mirror of
https://github.com/golang/go
synced 2024-11-27 04:41:33 -07:00
go/types: determine hasPtrRecv property from source rather than type
LookupFieldOrMethod needs to know if a method receiver is a pointer type. Until now this was computed from the the method signature's receiver, which required the method signature to be type-checked. Furthermore, it required the receiver to be set before the method signature was fully type-checked in some cases (see issue #6638). This CL remembers this property during object resolution, when we know it from the source. With this CL, method signatures don't need to be type-checked before they can be looked up; this is a first step towards separating type checking of types and type-checking of associated methods. Updates #23203. Updates #26854. Change-Id: Ie3eb7976e8fe8176ea1b284fa7471a4b7000f80b Reviewed-on: https://go-review.googlesource.com/c/139422 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Alan Donovan <adonovan@google.com>
This commit is contained in:
parent
62e5215a2a
commit
d6ab653c78
@ -255,8 +255,17 @@ func (s methodSet) add(list []*Func, index []int, indirect bool, multiples bool)
|
||||
}
|
||||
|
||||
// ptrRecv reports whether the receiver is of the form *T.
|
||||
// The receiver must exist.
|
||||
func ptrRecv(f *Func) bool {
|
||||
_, isPtr := deref(f.typ.(*Signature).recv.typ)
|
||||
return isPtr
|
||||
// If a method's type is set, use that as the source of truth for the receiver.
|
||||
if f.typ != nil {
|
||||
_, isPtr := deref(f.typ.(*Signature).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
|
||||
}
|
||||
|
@ -294,6 +294,7 @@ 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
|
||||
hasPtrRecv bool // only valid for methods that don't have a type yet
|
||||
}
|
||||
|
||||
// NewFunc returns a new function with the given signature, representing
|
||||
@ -304,7 +305,7 @@ func NewFunc(pos token.Pos, pkg *Package, name string, sig *Signature) *Func {
|
||||
if sig != nil {
|
||||
typ = sig
|
||||
}
|
||||
return &Func{object{nil, pos, pkg, name, typ, 0, colorFor(typ), token.NoPos}}
|
||||
return &Func{object{nil, pos, pkg, name, typ, 0, colorFor(typ), token.NoPos}, false}
|
||||
}
|
||||
|
||||
// FullName returns the package- or receiver-type-qualified name of
|
||||
|
@ -465,6 +465,8 @@ func (check *Checker) collectObjects() {
|
||||
typ := unparen(list[0].Type)
|
||||
if ptr, _ := typ.(*ast.StarExpr); ptr != nil {
|
||||
typ = unparen(ptr.X)
|
||||
// TODO(gri): This may not be sufficient. See issue #27995.
|
||||
f.hasPtrRecv = true
|
||||
}
|
||||
if base, _ := typ.(*ast.Ident); base != nil {
|
||||
// base is a potential base type name; determine
|
||||
|
@ -558,9 +558,13 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d
|
||||
pos := name.Pos()
|
||||
// Don't type-check signature yet - use an
|
||||
// empty signature now and update it later.
|
||||
// Since we know the receiver, set it up now
|
||||
// (required to avoid crash in ptrRecv; see
|
||||
// e.g. test case for issue 6638).
|
||||
// But set up receiver since we know it and
|
||||
// its position, and because interface method
|
||||
// signatures don't get a receiver via regular
|
||||
// type-checking (there isn't a receiver in the
|
||||
// the method's AST). Setting the correct receiver
|
||||
// type is also important for ptrRecv() (see methodset.go).
|
||||
//
|
||||
// TODO(gri) Consider marking methods signatures
|
||||
// as incomplete, for better error messages. See
|
||||
// also the T4 and T5 tests in testdata/cycles2.src.
|
||||
|
Loading…
Reference in New Issue
Block a user