mirror of
https://github.com/golang/go
synced 2024-11-17 04:04:46 -07:00
go/types: make ptrRecv a method hasPtrRecv of Func
This is a clean port of CL 351310 from types2 to go/types with the necessary changes to methodset.go which doesn't exist in types2. Change-Id: Ifdac820d3be14c7bfa778b7bca3f6ba58d220b2e Reviewed-on: https://go-review.googlesource.com/c/go/+/351311 Trust: Robert Griesemer <gri@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
parent
5efa8ff340
commit
f6f6621312
@ -212,7 +212,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
|
||||
}
|
||||
|
@ -232,10 +232,10 @@ func (s methodSet) add(list []*Func, index []int, indirect bool, multiples bool)
|
||||
// if f is not in the set, add it
|
||||
if !multiples {
|
||||
// TODO(gri) A found method may not be added because it's not in the method set
|
||||
// (!indirect && ptrRecv(f)). A 2nd method on the same level may be in the method
|
||||
// (!indirect && f.hasPtrRecv()). A 2nd method on the same level may be in the method
|
||||
// set and may not collide with the first one, thus leading to a false positive.
|
||||
// Is that possible? Investigate.
|
||||
if _, found := s[key]; !found && (indirect || !ptrRecv(f)) {
|
||||
if _, found := s[key]; !found && (indirect || !f.hasPtrRecv()) {
|
||||
s[key] = &Selection{MethodVal, nil, f, concat(index, i), indirect}
|
||||
continue
|
||||
}
|
||||
@ -244,22 +244,3 @@ func (s methodSet) add(list []*Func, index []int, indirect bool, multiples bool)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
@ -257,7 +257,7 @@ func expandNamed(env *Environment, n *Named, instPos token.Pos) (tparams *TypePa
|
||||
// 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
|
||||
@ -316,7 +316,7 @@ func (check *Checker) completeMethod(env *Environment, m *Func) {
|
||||
sig = ©
|
||||
}
|
||||
var rtyp Type
|
||||
if ptrRecv(m) {
|
||||
if m.hasPtrRecv() {
|
||||
rtyp = NewPointer(rbase)
|
||||
} else {
|
||||
rtyp = rbase
|
||||
|
@ -317,8 +317,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
|
||||
@ -343,6 +343,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.
|
||||
|
@ -483,7 +483,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)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user