// implements checks if V implements T and reports an error if it doesn't.
// If a qualifier is provided, it is used in error formatting.
+// The receiver may be nil if implements is called through an exported
+// API call such as AssignableTo.
func (check *Checker) implements(V, T Type, qf Qualifier) error {
Vu := under(V)
Tu := under(T)
return true, 0
}
- // T is an interface type and x implements T and T is not a type parameter
- if Ti, ok := Tu.(*Interface); ok && Tp == nil {
- if m, wrongType := check.missingMethod(V, Ti, true); m != nil /* !Implements(V, Ti) */ {
+ // T is an interface type and x implements T and T is not a type parameter.
+ // Also handle the case where T is a pointer to an interface.
+ if _, ok := Tu.(*Interface); ok && Tp == nil || isInterfacePtr(Tu) {
+ var qf Qualifier
+ if check != nil {
+ qf = check.qualifier
+ }
+ if err := check.implements(V, T, qf); err != nil {
if reason != nil {
- if check != nil && check.conf.CompilerErrorMessages {
- *reason = check.sprintf("%s does not implement %s %s", x.typ, T,
- check.missingMethodReason(x.typ, T, m, wrongType))
- } else {
- if wrongType != nil {
- if 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()
- }
- }
+ *reason = err.Error()
}
return false, _InvalidIfaceAssign
}
return true, 0
}
- // Provide extra detail in compiler error messages in some cases when T is
- // not an interface.
- if check != nil && check.conf.CompilerErrorMessages {
- if isInterfacePtr(Tu) {
+ // If V is an interface, check if a missing type assertion is the problem.
+ if Vi, _ := Vu.(*Interface); Vi != nil && Vp == nil {
+ if check.implements(T, V, nil) == nil {
+ // T implements V, so give hint about type assertion.
if reason != nil {
- *reason = check.sprintf("%s does not implement %s (type %s is pointer to interface, not interface)", x.typ, T, T)
- }
- return false, _InvalidIfaceAssign
- }
- if Vi, _ := Vu.(*Interface); Vi != nil && Vp == nil {
- if m, _ := check.missingMethod(T, Vi, true); m == nil {
- // T implements Vi, so give hint about type assertion.
- if reason != nil {
- *reason = check.sprintf("need type assertion")
- }
- return false, _IncompatibleAssign
+ *reason = "need type assertion"
}
+ return false, _IncompatibleAssign
}
}
_ = map[int]I1{0: i0 /* ERROR cannot use .* missing method foo */ }
_ = map[int]I1{0: i2 /* ERROR cannot use .* wrong type for method foo */ }
- make(chan I1) <- i0 /* ERROR cannot use .* in send: missing method foo */
- make(chan I1) <- i2 /* ERROR cannot use .* in send: wrong type for method foo */
+ make(chan I1) <- i0 /* ERROR I0 does not implement I1: missing method foo */
+ make(chan I1) <- i2 /* ERROR wrong type for method foo \(have func\(x int\), want func\(\)\) */
}
// Check that constants representable as integers are in integer form
// implements checks if V implements T and reports an error if it doesn't.
// If a qualifier is provided, it is used in error formatting.
+// The receiver may be nil if implements is called through an exported
+// API call such as AssignableTo.
func (check *Checker) implements(V, T Type, qf Qualifier) error {
Vu := under(V)
Tu := under(T)
import (
"bytes"
- "fmt"
"go/ast"
"go/constant"
"go/token"
return true, 0
}
- // T is an interface type and x implements T and T is not a type parameter
- if Ti, ok := Tu.(*Interface); ok && Tp == nil {
- if m, wrongType := check.missingMethod(V, Ti, true); m != nil /* Implements(V, Ti) */ {
+ // T is an interface type and x implements T and T is not a type parameter.
+ // Also handle the case where T is a pointer to an interface.
+ if _, ok := Tu.(*Interface); ok && Tp == nil || isInterfacePtr(Tu) {
+ var qf Qualifier
+ if check != nil {
+ qf = check.qualifier
+ }
+ if err := check.implements(V, T, qf); err != nil {
if reason != nil {
- if check != nil && compilerErrorMessages {
- *reason = check.sprintf("%s does not implement %s %s", x.typ, T,
- check.missingMethodReason(x.typ, T, m, wrongType))
- } else {
- if wrongType != nil {
- if 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()
- }
- }
+ *reason = err.Error()
}
return false, _InvalidIfaceAssign
}
return true, 0
}
- // Provide extra detail in compiler error messages in some cases when T is
- // not an interface.
- if check != nil && compilerErrorMessages {
- if isInterfacePtr(Tu) {
+ // If V is an interface, check if a missing type assertion is the problem.
+ if Vi, _ := Vu.(*Interface); Vi != nil && Vp == nil {
+ if check.implements(T, V, nil) == nil {
+ // T implements V, so give hint about type assertion.
if reason != nil {
- *reason = check.sprintf("%s does not implement %s (type %s is pointer to interface, not interface)", x.typ, T, T)
- }
- return false, _InvalidIfaceAssign
- }
- if Vi, _ := Vu.(*Interface); Vi != nil && Vp == nil {
- if m, _ := check.missingMethod(T, Vi, true); m == nil {
- // T implements Vi, so give hint about type assertion.
- if reason != nil {
- *reason = check.sprintf("need type assertion")
- }
- return false, _IncompatibleAssign
+ *reason = "need type assertion"
}
+ return false, _IncompatibleAssign
}
}
_ = map[int]I1{0: i0 /* ERROR cannot use .* missing method foo */ }
_ = map[int]I1{0: i2 /* ERROR cannot use .* wrong type for method foo */ }
- make(chan I1) <- i0 /* ERROR cannot use .* in send: missing method foo */
- make(chan I1) <- i2 /* ERROR cannot use .* in send: wrong type for method foo */
+ make(chan I1) <- i0 /* ERROR I0 does not implement I1: missing method foo */
+ make(chan I1) <- i2 /* ERROR wrong type for method foo \(have func\(x int\), want func\(\)\) */
}
// Check that constants representable as integers are in integer form