if method == nil {
return
}
-
var msg string
if wrongType != nil {
- msg = fmt.Sprintf("wrong type for method %s (have %s, want %s)", method.name, wrongType.typ, method.typ)
+ if check.identical(method.typ, wrongType.typ) {
+ msg = fmt.Sprintf("missing method %s (%s has pointer receiver)", method.name, method.name)
+ } else {
+ msg = fmt.Sprintf("wrong type for method %s (have %s, want %s)", method.name, wrongType.typ, method.typ)
+ }
} else {
msg = "missing method " + method.name
}
// The receiver may be nil if missingMethod is invoked through
// an exported API call (such as MissingMethod), i.e., when all
// methods have been type-checked.
-// If the type has the correctly names method, but with the wrong
+// If the type has the correctly named method, but with the wrong
// signature, the existing method is returned as well.
+// To improve error messages, also report the wrong signature
+// when the method exists on *V instead of V.
func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, wrongType *Func) {
check.completeInterface(T)
for _, m := range T.allMethods {
obj, _, _ := check.rawLookupFieldOrMethod(V, false, m.pkg, m.name)
+ // Check if *V implements this method of T.
+ if obj == nil {
+ ptr := NewPointer(V)
+ obj, _, _ = check.rawLookupFieldOrMethod(ptr, false, m.pkg, m.name)
+ if obj != nil {
+ return m, obj.(*Func)
+ }
+ }
+
// we must have a method (not a field of matching function type)
f, _ := obj.(*Func)
if f == nil {
if m, wrongType := check.missingMethod(V, Ti, true); m != nil /* Implements(V, Ti) */ {
if reason != nil {
if wrongType != nil {
- *reason = fmt.Sprintf("wrong type for method %s (have %s, want %s)", m.Name(), wrongType.typ, m.typ)
+ if check.identical(m.typ, wrongType.typ) {
+ *reason = fmt.Sprintf("missing method %s (%s has pointer receiver)", m.name, m.name)
+ } else {
+ *reason = fmt.Sprintf("wrong type for method %s (have %s, want %s)", m.Name(), wrongType.typ, m.typ)
+ }
+
} else {
*reason = "missing method " + m.Name()
}
t2 *T2
)
+ var x I1 = T1 /* ERROR cannot use .*: missing method foo \(foo has pointer receiver\) */ {}
+ _ = x /* ERROR .* cannot have dynamic type T1 \(missing method foo \(foo has pointer receiver\)\) */ .(T1)
+
_ = i2 /* ERROR i2 .* cannot have dynamic type \*T1 \(wrong type for method foo \(have func\(\), want func\(x int\)\)\) */ .(*T1)
i1 = i0 /* ERROR cannot use .* missing method foo */
// Because both t1 and t2 have the same global package name (template),
// qualify packages with full path name in this case.
var _ t1.Template = t2 /* ERROR cannot use .* \(value of type "html/template".Template\) as "text/template".Template */ .Template{}
-}
\ No newline at end of file
+}