}
// 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
}
// 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
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
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
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.