mirror of
https://github.com/golang/go
synced 2024-11-16 21:04:45 -07:00
go/types, types2: always use missingMethodReason in checker.Implements
Remove special case where we don't have a *Checker and always use Checker.missingMethodReason in Checker.implements. Look for zero methods rather than empty interface to exit early from Checker.missingMethod, and remove the extra test in Checker.implements. With this change we get consistent and more detailed error messages from all places where we do a form of the "implements" test. To make this possible, allow for the receiver to be nil in - Checker.sprintf - Checker.missingMethodReason - Checker.interfacePtrError - Checker.funcString Allowing Checker.sprintf with nil Checker permits further simplifying in a couple of places. Change-Id: I0ea7178c9efbcd4a25ded2a66e2b058db52dc4d4 Reviewed-on: https://go-review.googlesource.com/c/go/+/383054 Trust: Robert Griesemer <gri@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
parent
f1903fd4ec
commit
aadbfc30af
@ -167,8 +167,13 @@ func (check *Checker) markImports(pkg *Package) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check may be nil.
|
||||||
func (check *Checker) sprintf(format string, args ...interface{}) string {
|
func (check *Checker) sprintf(format string, args ...interface{}) string {
|
||||||
return sprintf(check.qualifier, false, format, args...)
|
var qf Qualifier
|
||||||
|
if check != nil {
|
||||||
|
qf = check.qualifier
|
||||||
|
}
|
||||||
|
return sprintf(qf, false, format, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (check *Checker) report(err *error_) {
|
func (check *Checker) report(err *error_) {
|
||||||
|
@ -160,21 +160,17 @@ func (check *Checker) implements(V, T Type) error {
|
|||||||
return nil // avoid follow-on errors (see issue #49541 for an example)
|
return nil // avoid follow-on errors (see issue #49541 for an example)
|
||||||
}
|
}
|
||||||
|
|
||||||
var qf Qualifier
|
|
||||||
if check != nil {
|
|
||||||
qf = check.qualifier
|
|
||||||
}
|
|
||||||
errorf := func(format string, args ...interface{}) error {
|
errorf := func(format string, args ...interface{}) error {
|
||||||
return errors.New(sprintf(qf, false, format, args...))
|
return errors.New(check.sprintf(format, args...))
|
||||||
}
|
}
|
||||||
|
|
||||||
Ti, _ := Tu.(*Interface)
|
Ti, _ := Tu.(*Interface)
|
||||||
if Ti == nil {
|
if Ti == nil {
|
||||||
var cause string
|
var cause string
|
||||||
if isInterfacePtr(Tu) {
|
if isInterfacePtr(Tu) {
|
||||||
cause = sprintf(qf, false, "type %s is pointer to interface, not interface", T)
|
cause = check.sprintf("type %s is pointer to interface, not interface", T)
|
||||||
} else {
|
} else {
|
||||||
cause = sprintf(qf, false, "%s is not an interface", T)
|
cause = check.sprintf("%s is not an interface", T)
|
||||||
}
|
}
|
||||||
return errorf("%s does not implement %s (%s)", V, T, cause)
|
return errorf("%s does not implement %s (%s)", V, T, cause)
|
||||||
}
|
}
|
||||||
@ -199,23 +195,8 @@ func (check *Checker) implements(V, T Type) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// V must implement T's methods, if any.
|
// V must implement T's methods, if any.
|
||||||
if Ti.NumMethods() > 0 {
|
if m, wrong := check.missingMethod(V, Ti, true); m != nil /* !Implements(V, Ti) */ {
|
||||||
if m, wrong := check.missingMethod(V, Ti, true); m != nil /* !Implements(V, Ti) */ {
|
return errorf("%s does not implement %s %s", V, T, check.missingMethodReason(V, T, m, wrong))
|
||||||
if check != nil && check.conf.CompilerErrorMessages {
|
|
||||||
return errorf("%s does not implement %s %s", V, T, check.missingMethodReason(V, T, m, wrong))
|
|
||||||
}
|
|
||||||
var cause string
|
|
||||||
if wrong != nil {
|
|
||||||
if Identical(m.typ, wrong.typ) {
|
|
||||||
cause = fmt.Sprintf("missing method %s (%s has pointer receiver)", m.name, m.name)
|
|
||||||
} else {
|
|
||||||
cause = fmt.Sprintf("wrong type for method %s (have %s, want %s)", m.Name(), wrong.typ, m.typ)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cause = "missing method " + m.Name()
|
|
||||||
}
|
|
||||||
return errorf("%s does not implement %s: %s", V, T, cause)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If T is comparable, V must be comparable.
|
// If T is comparable, V must be comparable.
|
||||||
|
@ -297,7 +297,7 @@ func MissingMethod(V Type, T *Interface, static bool) (method *Func, wrongType b
|
|||||||
// as the second result.
|
// as the second result.
|
||||||
func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, alt *Func) {
|
func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, alt *Func) {
|
||||||
// fast path for common case
|
// fast path for common case
|
||||||
if T.Empty() {
|
if T.NumMethods() == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -368,9 +368,10 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method,
|
|||||||
// and may include more have/want info after that. If non-nil, alt is a relevant
|
// and may include more have/want info after that. If non-nil, alt is a relevant
|
||||||
// method that matches in some way. It may have the correct name, but wrong type, or
|
// method that matches in some way. It may have the correct name, but wrong type, or
|
||||||
// it may have a pointer receiver, or it may have the correct name except wrong case.
|
// it may have a pointer receiver, or it may have the correct name except wrong case.
|
||||||
|
// check may be nil.
|
||||||
func (check *Checker) missingMethodReason(V, T Type, m, alt *Func) string {
|
func (check *Checker) missingMethodReason(V, T Type, m, alt *Func) string {
|
||||||
var mname string
|
var mname string
|
||||||
if check.conf.CompilerErrorMessages {
|
if check != nil && check.conf.CompilerErrorMessages {
|
||||||
mname = m.Name() + " method"
|
mname = m.Name() + " method"
|
||||||
} else {
|
} else {
|
||||||
mname = "method " + m.Name()
|
mname = "method " + m.Name()
|
||||||
@ -406,6 +407,7 @@ func isInterfacePtr(T Type) bool {
|
|||||||
return p != nil && IsInterface(p.base)
|
return p != nil && IsInterface(p.base)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check may be nil.
|
||||||
func (check *Checker) interfacePtrError(T Type) string {
|
func (check *Checker) interfacePtrError(T Type) string {
|
||||||
assert(isInterfacePtr(T))
|
assert(isInterfacePtr(T))
|
||||||
if p, _ := under(T).(*Pointer); isTypeParam(p.base) {
|
if p, _ := under(T).(*Pointer); isTypeParam(p.base) {
|
||||||
@ -415,9 +417,14 @@ func (check *Checker) interfacePtrError(T Type) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// funcString returns a string of the form name + signature for f.
|
// funcString returns a string of the form name + signature for f.
|
||||||
|
// check may be nil.
|
||||||
func (check *Checker) funcString(f *Func) string {
|
func (check *Checker) funcString(f *Func) string {
|
||||||
buf := bytes.NewBufferString(f.name)
|
buf := bytes.NewBufferString(f.name)
|
||||||
WriteSignature(buf, f.typ.(*Signature), check.qualifier)
|
var qf Qualifier
|
||||||
|
if check != nil {
|
||||||
|
qf = check.qualifier
|
||||||
|
}
|
||||||
|
WriteSignature(buf, f.typ.(*Signature), qf)
|
||||||
return buf.String()
|
return buf.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,7 +131,7 @@ func issue10260() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
var x I1
|
var x I1
|
||||||
x = T1 /* ERROR cannot use .*: missing method foo \(foo has pointer receiver\) */ {}
|
x = T1 /* ERROR cannot use T1{} .* as I1 value in assignment: T1 does not implement I1 \(method foo has pointer receiver\) */ {}
|
||||||
_ = x /* ERROR impossible type assertion: x\.\(T1\)\n\tT1 does not implement I1 \(method foo has pointer receiver\) */ .(T1)
|
_ = x /* ERROR impossible type assertion: x\.\(T1\)\n\tT1 does not implement I1 \(method foo has pointer receiver\) */ .(T1)
|
||||||
|
|
||||||
T1{}.foo /* ERROR cannot call pointer method foo on T1 */ ()
|
T1{}.foo /* ERROR cannot call pointer method foo on T1 */ ()
|
||||||
@ -139,34 +139,34 @@ func issue10260() {
|
|||||||
|
|
||||||
_ = i2 /* ERROR impossible type assertion: i2\.\(\*T1\)\n\t\*T1 does not implement I2 \(wrong type for method foo\)\n\t\thave foo\(\)\n\t\twant foo\(x int\) */ .(*T1)
|
_ = i2 /* ERROR impossible type assertion: i2\.\(\*T1\)\n\t\*T1 does not implement I2 \(wrong type for method foo\)\n\t\thave foo\(\)\n\t\twant foo\(x int\) */ .(*T1)
|
||||||
|
|
||||||
i1 = i0 /* ERROR cannot use .* missing method foo */
|
i1 = i0 /* ERROR cannot use i0 .* as I1 value in assignment: I0 does not implement I1 \(missing method foo\) */
|
||||||
i1 = t0 /* ERROR cannot use .* missing method foo */
|
i1 = t0 /* ERROR .* t0 .* as I1 .*: \*T0 does not implement I1 \(missing method foo\) */
|
||||||
i1 = i2 /* ERROR cannot use .* wrong type for method foo */
|
i1 = i2 /* ERROR .* i2 .* as I1 .*: I2 does not implement I1 \(wrong type for method foo\)\n\t\thave foo\(x int\)\n\t\twant foo\(\) */
|
||||||
i1 = t2 /* ERROR cannot use .* wrong type for method foo */
|
i1 = t2 /* ERROR .* t2 .* as I1 .*: \*T2 does not implement I1 \(wrong type for method foo\)\n\t\thave foo\(x int\)\n\t\twant foo\(\) */
|
||||||
i2 = i1 /* ERROR cannot use .* wrong type for method foo */
|
i2 = i1 /* ERROR .* i1 .* as I2 .*: I1 does not implement I2 \(wrong type for method foo\)\n\t\thave foo\(\)\n\t\twant foo\(x int\) */
|
||||||
i2 = t1 /* ERROR cannot use .* wrong type for method foo */
|
i2 = t1 /* ERROR .* t1 .* as I2 .*: \*T1 does not implement I2 \(wrong type for method foo\)\n\t\thave foo\(\)\n\t\twant foo\(x int\) */
|
||||||
|
|
||||||
_ = func() I1 { return i0 /* ERROR cannot use .* missing method foo */ }
|
_ = func() I1 { return i0 /* ERROR cannot use i0 .* as I1 value in return statement: I0 does not implement I1 \(missing method foo\) */ }
|
||||||
_ = func() I1 { return t0 /* ERROR cannot use .* missing method foo */ }
|
_ = func() I1 { return t0 /* ERROR .* t0 .* as I1 .*: \*T0 does not implement I1 \(missing method foo\) */ }
|
||||||
_ = func() I1 { return i2 /* ERROR cannot use .* wrong type for method foo */ }
|
_ = func() I1 { return i2 /* ERROR .* i2 .* as I1 .*: I2 does not implement I1 \(wrong type for method foo\)\n\t\thave foo\(x int\)\n\t\twant foo\(\) */ }
|
||||||
_ = func() I1 { return t2 /* ERROR cannot use .* wrong type for method foo */ }
|
_ = func() I1 { return t2 /* ERROR .* t2 .* as I1 .*: \*T2 does not implement I1 \(wrong type for method foo\)\n\t\thave foo\(x int\)\n\t\twant foo\(\) */ }
|
||||||
_ = func() I2 { return i1 /* ERROR cannot use .* wrong type for method foo */ }
|
_ = func() I2 { return i1 /* ERROR .* i1 .* as I2 .*: I1 does not implement I2 \(wrong type for method foo\)\n\t\thave foo\(\)\n\t\twant foo\(x int\) */ }
|
||||||
_ = func() I2 { return t1 /* ERROR cannot use .* wrong type for method foo */ }
|
_ = func() I2 { return t1 /* ERROR .* t1 .* as I2 .*: \*T1 does not implement I2 \(wrong type for method foo\)\n\t\thave foo\(\)\n\t\twant foo\(x int\) */ }
|
||||||
|
|
||||||
// a few more - less exhaustive now
|
// a few more - less exhaustive now
|
||||||
|
|
||||||
f := func(I1, I2){}
|
f := func(I1, I2){}
|
||||||
f(i0 /* ERROR cannot use .* missing method foo */ , i1 /* ERROR cannot use .* wrong type for method foo \(have func\(\), want func\(x int\)\) */ )
|
f(i0 /* ERROR missing method foo */ , i1 /* ERROR wrong type for method foo */ )
|
||||||
|
|
||||||
_ = [...]I1{i0 /* ERROR cannot use .* missing method foo */ }
|
_ = [...]I1{i0 /* ERROR cannot use i0 .* as I1 value in array or slice literal: I0 does not implement I1 \(missing method foo\) */ }
|
||||||
_ = [...]I1{i2 /* ERROR cannot use .* wrong type for method foo */ }
|
_ = [...]I1{i2 /* ERROR cannot use i2 .* as I1 value in array or slice literal: I2 does not implement I1 \(wrong type for method foo\)\n\t\thave foo\(x int\)\n\t\twant foo\(\) */ }
|
||||||
_ = []I1{i0 /* ERROR cannot use .* missing method foo */ }
|
_ = []I1{i0 /* ERROR missing method foo */ }
|
||||||
_ = []I1{i2 /* ERROR cannot use .* wrong type for method foo */ }
|
_ = []I1{i2 /* ERROR wrong type for method foo */ }
|
||||||
_ = map[int]I1{0: i0 /* ERROR cannot use .* missing method foo */ }
|
_ = map[int]I1{0: i0 /* ERROR missing method foo */ }
|
||||||
_ = map[int]I1{0: i2 /* ERROR cannot use .* wrong type for method foo */ }
|
_ = map[int]I1{0: i2 /* ERROR wrong type for method foo */ }
|
||||||
|
|
||||||
make(chan I1) <- i0 /* ERROR I0 does not implement I1: missing method foo */
|
make(chan I1) <- i0 /* ERROR missing method foo */
|
||||||
make(chan I1) <- i2 /* ERROR wrong type for method foo \(have func\(x int\), want func\(\)\) */
|
make(chan I1) <- i2 /* ERROR wrong type for method foo */
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that constants representable as integers are in integer form
|
// Check that constants representable as integers are in integer form
|
||||||
|
@ -9,7 +9,7 @@ type I[F any] interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func G[F any]() I[any] {
|
func G[F any]() I[any] {
|
||||||
return g /* ERROR "missing method Q \(Q has pointer receiver\)" */ [F]{}
|
return g /* ERROR cannot use g\[F\]{} .* as I\[any\] value in return statement: g\[F\] does not implement I\[any\] \(method Q has pointer receiver\) */ [F]{}
|
||||||
}
|
}
|
||||||
|
|
||||||
type g[F any] struct{}
|
type g[F any] struct{}
|
||||||
|
@ -63,8 +63,15 @@ func (check *Checker) markImports(pkg *Package) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check may be nil.
|
||||||
func (check *Checker) sprintf(format string, args ...any) string {
|
func (check *Checker) sprintf(format string, args ...any) string {
|
||||||
return sprintf(check.fset, check.qualifier, false, format, args...)
|
var fset *token.FileSet
|
||||||
|
var qf Qualifier
|
||||||
|
if check != nil {
|
||||||
|
fset = check.fset
|
||||||
|
qf = check.qualifier
|
||||||
|
}
|
||||||
|
return sprintf(fset, qf, false, format, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func sprintf(fset *token.FileSet, qf Qualifier, debug bool, format string, args ...any) string {
|
func sprintf(fset *token.FileSet, qf Qualifier, debug bool, format string, args ...any) string {
|
||||||
|
@ -160,25 +160,17 @@ func (check *Checker) implements(V, T Type) error {
|
|||||||
return nil // avoid follow-on errors (see issue #49541 for an example)
|
return nil // avoid follow-on errors (see issue #49541 for an example)
|
||||||
}
|
}
|
||||||
|
|
||||||
var qf Qualifier
|
|
||||||
if check != nil {
|
|
||||||
qf = check.qualifier
|
|
||||||
}
|
|
||||||
errorf := func(format string, args ...any) error {
|
errorf := func(format string, args ...any) error {
|
||||||
return errors.New(sprintf(nil, qf, false, format, args...))
|
return errors.New(check.sprintf(format, args...))
|
||||||
}
|
}
|
||||||
|
|
||||||
Ti, _ := Tu.(*Interface)
|
Ti, _ := Tu.(*Interface)
|
||||||
if Ti == nil {
|
if Ti == nil {
|
||||||
var fset *token.FileSet
|
|
||||||
if check != nil {
|
|
||||||
fset = check.fset
|
|
||||||
}
|
|
||||||
var cause string
|
var cause string
|
||||||
if isInterfacePtr(Tu) {
|
if isInterfacePtr(Tu) {
|
||||||
cause = sprintf(fset, qf, false, "type %s is pointer to interface, not interface", T)
|
cause = check.sprintf("type %s is pointer to interface, not interface", T)
|
||||||
} else {
|
} else {
|
||||||
cause = sprintf(fset, qf, false, "%s is not an interface", T)
|
cause = check.sprintf("%s is not an interface", T)
|
||||||
}
|
}
|
||||||
return errorf("%s does not implement %s (%s)", V, T, cause)
|
return errorf("%s does not implement %s (%s)", V, T, cause)
|
||||||
}
|
}
|
||||||
@ -203,23 +195,8 @@ func (check *Checker) implements(V, T Type) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// V must implement T's methods, if any.
|
// V must implement T's methods, if any.
|
||||||
if Ti.NumMethods() > 0 {
|
if m, wrong := check.missingMethod(V, Ti, true); m != nil /* !Implements(V, Ti) */ {
|
||||||
if m, wrong := check.missingMethod(V, Ti, true); m != nil /* !Implements(V, Ti) */ {
|
return errorf("%s does not implement %s %s", V, T, check.missingMethodReason(V, T, m, wrong))
|
||||||
if check != nil && compilerErrorMessages {
|
|
||||||
return errorf("%s does not implement %s %s", V, T, check.missingMethodReason(V, T, m, wrong))
|
|
||||||
}
|
|
||||||
var cause string
|
|
||||||
if wrong != nil {
|
|
||||||
if Identical(m.typ, wrong.typ) {
|
|
||||||
cause = fmt.Sprintf("missing method %s (%s has pointer receiver)", m.name, m.name)
|
|
||||||
} else {
|
|
||||||
cause = fmt.Sprintf("wrong type for method %s (have %s, want %s)", m.Name(), wrong.typ, m.typ)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cause = "missing method " + m.Name()
|
|
||||||
}
|
|
||||||
return errorf("%s does not implement %s: %s", V, T, cause)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If T is comparable, V must be comparable.
|
// If T is comparable, V must be comparable.
|
||||||
|
@ -298,7 +298,7 @@ func MissingMethod(V Type, T *Interface, static bool) (method *Func, wrongType b
|
|||||||
// Note: case-folding lookup is currently disabled
|
// Note: case-folding lookup is currently disabled
|
||||||
func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, alt *Func) {
|
func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, alt *Func) {
|
||||||
// fast path for common case
|
// fast path for common case
|
||||||
if T.Empty() {
|
if T.NumMethods() == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,9 +370,10 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method,
|
|||||||
// and may include more have/want info after that. If non-nil, alt is a relevant
|
// and may include more have/want info after that. If non-nil, alt is a relevant
|
||||||
// method that matches in some way. It may have the correct name, but wrong type, or
|
// method that matches in some way. It may have the correct name, but wrong type, or
|
||||||
// it may have a pointer receiver, or it may have the correct name except wrong case.
|
// it may have a pointer receiver, or it may have the correct name except wrong case.
|
||||||
|
// check may be nil.
|
||||||
func (check *Checker) missingMethodReason(V, T Type, m, alt *Func) string {
|
func (check *Checker) missingMethodReason(V, T Type, m, alt *Func) string {
|
||||||
var mname string
|
var mname string
|
||||||
if compilerErrorMessages {
|
if check != nil && compilerErrorMessages {
|
||||||
mname = m.Name() + " method"
|
mname = m.Name() + " method"
|
||||||
} else {
|
} else {
|
||||||
mname = "method " + m.Name()
|
mname = "method " + m.Name()
|
||||||
@ -408,6 +409,7 @@ func isInterfacePtr(T Type) bool {
|
|||||||
return p != nil && IsInterface(p.base)
|
return p != nil && IsInterface(p.base)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check may be nil.
|
||||||
func (check *Checker) interfacePtrError(T Type) string {
|
func (check *Checker) interfacePtrError(T Type) string {
|
||||||
assert(isInterfacePtr(T))
|
assert(isInterfacePtr(T))
|
||||||
if p, _ := under(T).(*Pointer); isTypeParam(p.base) {
|
if p, _ := under(T).(*Pointer); isTypeParam(p.base) {
|
||||||
@ -416,10 +418,14 @@ func (check *Checker) interfacePtrError(T Type) string {
|
|||||||
return check.sprintf("type %s is pointer to interface, not interface", T)
|
return check.sprintf("type %s is pointer to interface, not interface", T)
|
||||||
}
|
}
|
||||||
|
|
||||||
// funcString returns a string of the form name + signature for f.
|
// check may be nil.
|
||||||
func (check *Checker) funcString(f *Func) string {
|
func (check *Checker) funcString(f *Func) string {
|
||||||
buf := bytes.NewBufferString(f.name)
|
buf := bytes.NewBufferString(f.name)
|
||||||
WriteSignature(buf, f.typ.(*Signature), check.qualifier)
|
var qf Qualifier
|
||||||
|
if check != nil {
|
||||||
|
qf = check.qualifier
|
||||||
|
}
|
||||||
|
WriteSignature(buf, f.typ.(*Signature), qf)
|
||||||
return buf.String()
|
return buf.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
44
src/go/types/testdata/check/issues.src
vendored
44
src/go/types/testdata/check/issues.src
vendored
@ -131,7 +131,7 @@ func issue10260() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
var x I1
|
var x I1
|
||||||
x = T1 /* ERROR cannot use .*: missing method foo \(foo has pointer receiver\) */ {}
|
x = T1 /* ERROR cannot use \(T1 literal\) .* as I1 value in assignment: T1 does not implement I1 \(method foo has pointer receiver\) */ {}
|
||||||
_ = x /* ERROR impossible type assertion: x\.\(T1\)\n\tT1 does not implement I1 \(method foo has pointer receiver\) */ .(T1)
|
_ = x /* ERROR impossible type assertion: x\.\(T1\)\n\tT1 does not implement I1 \(method foo has pointer receiver\) */ .(T1)
|
||||||
|
|
||||||
T1{}.foo /* ERROR cannot call pointer method foo on T1 */ ()
|
T1{}.foo /* ERROR cannot call pointer method foo on T1 */ ()
|
||||||
@ -139,34 +139,34 @@ func issue10260() {
|
|||||||
|
|
||||||
_ = i2 /* ERROR impossible type assertion: i2\.\(\*T1\)\n\t\*T1 does not implement I2 \(wrong type for method foo\)\n\t\thave foo\(\)\n\t\twant foo\(x int\) */ .(*T1)
|
_ = i2 /* ERROR impossible type assertion: i2\.\(\*T1\)\n\t\*T1 does not implement I2 \(wrong type for method foo\)\n\t\thave foo\(\)\n\t\twant foo\(x int\) */ .(*T1)
|
||||||
|
|
||||||
i1 = i0 /* ERROR cannot use .* missing method foo */
|
i1 = i0 /* ERROR cannot use i0 .* as I1 value in assignment: I0 does not implement I1 \(missing method foo\) */
|
||||||
i1 = t0 /* ERROR cannot use .* missing method foo */
|
i1 = t0 /* ERROR .* t0 .* as I1 .*: \*T0 does not implement I1 \(missing method foo\) */
|
||||||
i1 = i2 /* ERROR cannot use .* wrong type for method foo */
|
i1 = i2 /* ERROR .* i2 .* as I1 .*: I2 does not implement I1 \(wrong type for method foo\)\n\t\thave foo\(x int\)\n\t\twant foo\(\) */
|
||||||
i1 = t2 /* ERROR cannot use .* wrong type for method foo */
|
i1 = t2 /* ERROR .* t2 .* as I1 .*: \*T2 does not implement I1 \(wrong type for method foo\)\n\t\thave foo\(x int\)\n\t\twant foo\(\) */
|
||||||
i2 = i1 /* ERROR cannot use .* wrong type for method foo */
|
i2 = i1 /* ERROR .* i1 .* as I2 .*: I1 does not implement I2 \(wrong type for method foo\)\n\t\thave foo\(\)\n\t\twant foo\(x int\) */
|
||||||
i2 = t1 /* ERROR cannot use .* wrong type for method foo */
|
i2 = t1 /* ERROR .* t1 .* as I2 .*: \*T1 does not implement I2 \(wrong type for method foo\)\n\t\thave foo\(\)\n\t\twant foo\(x int\) */
|
||||||
|
|
||||||
_ = func() I1 { return i0 /* ERROR cannot use .* missing method foo */ }
|
_ = func() I1 { return i0 /* ERROR cannot use i0 .* as I1 value in return statement: I0 does not implement I1 \(missing method foo\) */ }
|
||||||
_ = func() I1 { return t0 /* ERROR cannot use .* missing method foo */ }
|
_ = func() I1 { return t0 /* ERROR .* t0 .* as I1 .*: \*T0 does not implement I1 \(missing method foo\) */ }
|
||||||
_ = func() I1 { return i2 /* ERROR cannot use .* wrong type for method foo */ }
|
_ = func() I1 { return i2 /* ERROR .* i2 .* as I1 .*: I2 does not implement I1 \(wrong type for method foo\)\n\t\thave foo\(x int\)\n\t\twant foo\(\) */ }
|
||||||
_ = func() I1 { return t2 /* ERROR cannot use .* wrong type for method foo */ }
|
_ = func() I1 { return t2 /* ERROR .* t2 .* as I1 .*: \*T2 does not implement I1 \(wrong type for method foo\)\n\t\thave foo\(x int\)\n\t\twant foo\(\) */ }
|
||||||
_ = func() I2 { return i1 /* ERROR cannot use .* wrong type for method foo */ }
|
_ = func() I2 { return i1 /* ERROR .* i1 .* as I2 .*: I1 does not implement I2 \(wrong type for method foo\)\n\t\thave foo\(\)\n\t\twant foo\(x int\) */ }
|
||||||
_ = func() I2 { return t1 /* ERROR cannot use .* wrong type for method foo */ }
|
_ = func() I2 { return t1 /* ERROR .* t1 .* as I2 .*: \*T1 does not implement I2 \(wrong type for method foo\)\n\t\thave foo\(\)\n\t\twant foo\(x int\) */ }
|
||||||
|
|
||||||
// a few more - less exhaustive now
|
// a few more - less exhaustive now
|
||||||
|
|
||||||
f := func(I1, I2){}
|
f := func(I1, I2){}
|
||||||
f(i0 /* ERROR cannot use .* missing method foo */ , i1 /* ERROR cannot use .* wrong type for method foo \(have func\(\), want func\(x int\)\) */ )
|
f(i0 /* ERROR missing method foo */ , i1 /* ERROR wrong type for method foo */ )
|
||||||
|
|
||||||
_ = [...]I1{i0 /* ERROR cannot use .* missing method foo */ }
|
_ = [...]I1{i0 /* ERROR cannot use i0 .* as I1 value in array or slice literal: I0 does not implement I1 \(missing method foo\) */ }
|
||||||
_ = [...]I1{i2 /* ERROR cannot use .* wrong type for method foo */ }
|
_ = [...]I1{i2 /* ERROR cannot use i2 .* as I1 value in array or slice literal: I2 does not implement I1 \(wrong type for method foo\)\n\t\thave foo\(x int\)\n\t\twant foo\(\) */ }
|
||||||
_ = []I1{i0 /* ERROR cannot use .* missing method foo */ }
|
_ = []I1{i0 /* ERROR missing method foo */ }
|
||||||
_ = []I1{i2 /* ERROR cannot use .* wrong type for method foo */ }
|
_ = []I1{i2 /* ERROR wrong type for method foo */ }
|
||||||
_ = map[int]I1{0: i0 /* ERROR cannot use .* missing method foo */ }
|
_ = map[int]I1{0: i0 /* ERROR missing method foo */ }
|
||||||
_ = map[int]I1{0: i2 /* ERROR cannot use .* wrong type for method foo */ }
|
_ = map[int]I1{0: i2 /* ERROR wrong type for method foo */ }
|
||||||
|
|
||||||
make(chan I1) <- i0 /* ERROR I0 does not implement I1: missing method foo */
|
make(chan I1) <- i0 /* ERROR missing method foo */
|
||||||
make(chan I1) <- i2 /* ERROR wrong type for method foo \(have func\(x int\), want func\(\)\) */
|
make(chan I1) <- i2 /* ERROR wrong type for method foo */
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that constants representable as integers are in integer form
|
// Check that constants representable as integers are in integer form
|
||||||
|
@ -9,7 +9,7 @@ type I[F any] interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func G[F any]() I[any] {
|
func G[F any]() I[any] {
|
||||||
return g /* ERROR "missing method Q \(Q has pointer receiver\)" */ [F]{}
|
return g /* ERROR cannot use \(g\[F\] literal\) .* as I\[any\] value in return statement: g\[F\] does not implement I\[any\] \(method Q has pointer receiver\) */ [F]{}
|
||||||
}
|
}
|
||||||
|
|
||||||
type g[F any] struct{}
|
type g[F any] struct{}
|
||||||
|
Loading…
Reference in New Issue
Block a user