]> Cypherpunks.ru repositories - gostls13.git/commitdiff
cmd/compile/internal/types2: make ptrRecv a method hasPtrRecv of Func
authorRobert Griesemer <gri@golang.org>
Tue, 21 Sep 2021 17:54:08 +0000 (10:54 -0700)
committerRobert Griesemer <gri@golang.org>
Tue, 21 Sep 2021 20:28:55 +0000 (20:28 +0000)
Reading the Func.hasPtrRecv field directly (without consulting a
possibly existing signature) caused some issues in an earlier CL.
The function ptrRecv (in lookup.go) does the right thing but is
not easily discoverable.

Rename ptrRecv to hasPtrRecv and make it a method of Func; rename
Func.hasPtrRecv field to Func.hasPtrRecv_ to avoid name collisions.
Make it clear in field comment that it must not be read through the
hasPtrRecv method.

Change-Id: Ida9856c4789e499538eb34377be781655958fd5b
Reviewed-on: https://go-review.googlesource.com/c/go/+/351310
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
src/cmd/compile/internal/types2/lookup.go
src/cmd/compile/internal/types2/named.go
src/cmd/compile/internal/types2/object.go
src/cmd/compile/internal/types2/resolver.go

index eb460ca200a02ea7174dd20d1ebfc611e39a037d..e0fd74482ab04307272fb20b972e6a1811cc8ac4 100644 (file)
@@ -216,7 +216,7 @@ func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o
                        //        is shorthand for (&x).m()".
                        if f, _ := obj.(*Func); f != nil {
                                // determine if method has a pointer receiver
-                               hasPtrRecv := tpar == nil && ptrRecv(f)
+                               hasPtrRecv := tpar == nil && f.hasPtrRecv()
                                if hasPtrRecv && !indirect && !addressable {
                                        return nil, nil, true // pointer/addressable receiver required
                                }
@@ -474,22 +474,3 @@ func lookupMethod(methods []*Func, pkg *Package, name string) (int, *Func) {
        }
        return -1, nil
 }
-
-// ptrRecv reports whether the receiver is of the form *T.
-func ptrRecv(f *Func) bool {
-       // If a method's receiver type is set, use that as the source of truth for the receiver.
-       // Caution: Checker.funcDecl (decl.go) marks a function by setting its type to an empty
-       // signature. We may reach here before the signature is fully set up: we must explicitly
-       // check if the receiver is set (we cannot just look for non-nil f.typ).
-       if sig, _ := f.typ.(*Signature); sig != nil && sig.recv != nil {
-               _, isPtr := deref(sig.recv.typ)
-               return isPtr
-       }
-
-       // If a method's type is not set it may be a method/function that is:
-       // 1) client-supplied (via NewFunc with no signature), or
-       // 2) internally created but not yet type-checked.
-       // For case 1) we can't do anything; the client must know what they are doing.
-       // For case 2) we can use the information gathered by the resolver.
-       return f.hasPtrRecv
-}
index 36a8b88f252facad39893d4832683913721cdd6d..1db993afc90271aa959071e610b4953f8932baf7 100644 (file)
@@ -255,7 +255,7 @@ func expandNamed(env *Environment, n *Named, instPos syntax.Pos) (tparams *TypeP
                        // During type checking origm may not have a fully set up type, so defer
                        // instantiation of its signature until later.
                        m := NewFunc(origm.pos, origm.pkg, origm.name, nil)
-                       m.hasPtrRecv = ptrRecv(origm)
+                       m.hasPtrRecv_ = origm.hasPtrRecv()
                        // Setting instRecv here allows us to complete later (we need the
                        // instRecv to get targs and the original method).
                        m.instRecv = n
@@ -314,7 +314,7 @@ func (check *Checker) completeMethod(env *Environment, m *Func) {
                sig = &copy
        }
        var rtyp Type
-       if ptrRecv(m) {
+       if m.hasPtrRecv() {
                rtyp = NewPointer(rbase)
        } else {
                rtyp = rbase
index f44e1a93538940cafc63bfa3826b5510b6230b79..2e1cd7bff13e57026f5beff7ec936557ad172cac 100644 (file)
@@ -363,8 +363,8 @@ func (*Var) isDependency() {} // a variable may be a dependency of an initializa
 // An abstract method may belong to many interfaces due to embedding.
 type Func struct {
        object
-       instRecv   *Named // if non-nil, the receiver type for an incomplete instance method
-       hasPtrRecv bool   // only valid for methods that don't have a type yet
+       instRecv    *Named // if non-nil, the receiver type for an incomplete instance method
+       hasPtrRecv_ bool   // only valid for methods that don't have a type yet; use hasPtrRecv() to read
 }
 
 // NewFunc returns a new function with the given signature, representing
@@ -389,6 +389,25 @@ func (obj *Func) FullName() string {
 // Scope returns the scope of the function's body block.
 func (obj *Func) Scope() *Scope { return obj.typ.(*Signature).scope }
 
+// hasPtrRecv reports whether the receiver is of the form *T for the given method obj.
+func (obj *Func) hasPtrRecv() bool {
+       // If a method's receiver type is set, use that as the source of truth for the receiver.
+       // Caution: Checker.funcDecl (decl.go) marks a function by setting its type to an empty
+       // signature. We may reach here before the signature is fully set up: we must explicitly
+       // check if the receiver is set (we cannot just look for non-nil obj.typ).
+       if sig, _ := obj.typ.(*Signature); sig != nil && sig.recv != nil {
+               _, isPtr := deref(sig.recv.typ)
+               return isPtr
+       }
+
+       // If a method's type is not set it may be a method/function that is:
+       // 1) client-supplied (via NewFunc with no signature), or
+       // 2) internally created but not yet type-checked.
+       // For case 1) we can't do anything; the client must know what they are doing.
+       // For case 2) we can use the information gathered by the resolver.
+       return obj.hasPtrRecv_
+}
+
 func (*Func) isDependency() {} // a function may be a dependency of an initialization expression
 
 // A Label represents a declared label.
index 34fbc3d41b4693737acfde7c61af8e5f5318b394..a8cb244c55e6095c31bbb68d5dee0d427e35a789 100644 (file)
@@ -509,7 +509,7 @@ func (check *Checker) collectObjects() {
                        // Determine the receiver base type and associate m with it.
                        ptr, base := check.resolveBaseTypeName(m.ptr, m.recv)
                        if base != nil {
-                               m.obj.hasPtrRecv = ptr
+                               m.obj.hasPtrRecv_ = ptr
                                check.methods[base] = append(check.methods[base], m.obj)
                        }
                }