mirror of
https://github.com/golang/go
synced 2024-11-16 21:04:45 -07:00
go/types, types2: use Checker.implements in operand.assignableTo
Now that we have the detailed error reporting in Checker.implements we don't need it anymore in operand.assignableTo and can simply call Checker.implements. This also more directly matches the spec. For #50646. Change-Id: Ic44ced999c75be6cc9edaab01177ee0495147ea1 Reviewed-on: https://go-review.googlesource.com/c/go/+/381435 Trust: Robert Griesemer <gri@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
parent
2e30c4b4bb
commit
25b4b862f2
@ -157,6 +157,8 @@ func (check *Checker) verify(pos syntax.Pos, tparams []*TypeParam, targs []Type)
|
||||
|
||||
// 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)
|
||||
|
@ -288,47 +288,30 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -165,8 +165,8 @@ func issue10260() {
|
||||
_ = 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
|
||||
|
@ -157,6 +157,8 @@ func (check *Checker) verify(pos token.Pos, tparams []*TypeParam, targs []Type)
|
||||
|
||||
// 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)
|
||||
|
@ -8,7 +8,6 @@ package types
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
@ -278,48 +277,30 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
4
src/go/types/testdata/check/issues.src
vendored
4
src/go/types/testdata/check/issues.src
vendored
@ -165,8 +165,8 @@ func issue10260() {
|
||||
_ = 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
|
||||
|
Loading…
Reference in New Issue
Block a user