aboutsummaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
authorRobert Griesemer <gri@google.com>2026-01-21 15:11:13 -0800
committerGopher Robot <gobot@golang.org>2026-01-23 09:18:50 -0800
commit6d89ab44cc783abb68d511e88723c2b8ebf4ca3b (patch)
tree9969ee789e316ba3ca66e1428d465a2c69913538 /src/cmd
parent021d5ca042775537d707c6f5ae2f53f57dac243f (diff)
downloadgo-6d89ab44cc783abb68d511e88723c2b8ebf4ca3b.tar.xz
go/types, types: flip field/method selection logic inside out (cleanup)
By selecting on *Var/*Func first, the field/method selection logic becomes a bit cleaner, clearer, and a little bit simpler. No functional changes. Change-Id: I9860f98d52779b0f7ce4484ea77e74a3667d9e6b Reviewed-on: https://go-review.googlesource.com/c/go/+/738080 Reviewed-by: Alan Donovan <adonovan@google.com> Commit-Queue: Robert Griesemer <gri@google.com> Reviewed-by: Robert Griesemer <gri@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Robert Griesemer <gri@google.com>
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/compile/internal/types2/call.go114
1 files changed, 54 insertions, 60 deletions
diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go
index dfbb0a5491..c23a1048f2 100644
--- a/src/cmd/compile/internal/types2/call.go
+++ b/src/cmd/compile/internal/types2/call.go
@@ -837,71 +837,67 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr, wantType bool
}
// obj != nil
- // methods may not have a fully set up signature yet
- if m, _ := obj.(*Func); m != nil {
- check.objDecl(m)
- }
-
- if x.mode == typexpr {
- // method expression
- m, _ := obj.(*Func)
- if m == nil {
+ switch obj := obj.(type) {
+ case *Var:
+ if x.mode == typexpr {
check.errorf(e.X, MissingFieldOrMethod, "operand for field selector %s must be value of type %s", sel, x.typ)
goto Error
}
- check.recordSelection(e, MethodExpr, x.typ, m, index, indirect)
-
- sig := m.typ.(*Signature)
- if sig.recv == nil {
- check.error(e, InvalidDeclCycle, "illegal cycle in method declaration")
- goto Error
+ // field value
+ check.recordSelection(e, FieldVal, x.typ, obj, index, indirect)
+ if x.mode == variable || indirect {
+ x.mode = variable
+ } else {
+ x.mode = value
}
+ x.typ = obj.typ
- // The receiver type becomes the type of the first function
- // argument of the method expression's function type.
- var params []*Var
- if sig.params != nil {
- params = sig.params.vars
- }
- // Be consistent about named/unnamed parameters. This is not needed
- // for type-checking, but the newly constructed signature may appear
- // in an error message and then have mixed named/unnamed parameters.
- // (An alternative would be to not print parameter names in errors,
- // but it's useful to see them; this is cheap and method expressions
- // are rare.)
- name := ""
- if len(params) > 0 && params[0].name != "" {
- // name needed
- name = sig.recv.name
- if name == "" {
- name = "_"
- }
- }
- params = append([]*Var{NewParam(sig.recv.pos, sig.recv.pkg, name, x.typ)}, params...)
- x.mode = value
- x.typ = &Signature{
- tparams: sig.tparams,
- params: NewTuple(params...),
- results: sig.results,
- variadic: sig.variadic,
- }
+ case *Func:
+ check.objDecl(obj) // ensure fully set-up signature
+ check.addDeclDep(obj)
- check.addDeclDep(m)
+ if x.mode == typexpr {
+ // method expression
+ check.recordSelection(e, MethodExpr, x.typ, obj, index, indirect)
- } else {
- // regular selector
- switch obj := obj.(type) {
- case *Var:
- check.recordSelection(e, FieldVal, x.typ, obj, index, indirect)
- if x.mode == variable || indirect {
- x.mode = variable
- } else {
- x.mode = value
+ sig := obj.typ.(*Signature)
+ if sig.recv == nil {
+ check.error(e, InvalidDeclCycle, "illegal cycle in method declaration")
+ goto Error
+ }
+
+ // The receiver type becomes the type of the first function
+ // argument of the method expression's function type.
+ var params []*Var
+ if sig.params != nil {
+ params = sig.params.vars
+ }
+ // Be consistent about named/unnamed parameters. This is not needed
+ // for type-checking, but the newly constructed signature may appear
+ // in an error message and then have mixed named/unnamed parameters.
+ // (An alternative would be to not print parameter names in errors,
+ // but it's useful to see them; this is cheap and method expressions
+ // are rare.)
+ name := ""
+ if len(params) > 0 && params[0].name != "" {
+ // name needed
+ name = sig.recv.name
+ if name == "" {
+ name = "_"
+ }
+ }
+ params = append([]*Var{NewParam(sig.recv.pos, sig.recv.pkg, name, x.typ)}, params...)
+ x.mode = value
+ x.typ = &Signature{
+ tparams: sig.tparams,
+ params: NewTuple(params...),
+ results: sig.results,
+ variadic: sig.variadic,
}
- x.typ = obj.typ
+ } else {
+ // method value
- case *Func:
// TODO(gri) If we needed to take into account the receiver's
// addressability, should we report the type &(x.typ) instead?
check.recordSelection(e, MethodVal, x.typ, obj, index, indirect)
@@ -912,12 +908,10 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr, wantType bool
sig := *obj.typ.(*Signature)
sig.recv = nil
x.typ = &sig
-
- check.addDeclDep(obj)
-
- default:
- panic("unreachable")
}
+
+ default:
+ panic("unreachable")
}
// everything went well