}
}
+// check may be nil.
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_) {
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 {
- return errors.New(sprintf(qf, false, format, args...))
+ return errors.New(check.sprintf(format, args...))
}
Ti, _ := Tu.(*Interface)
if Ti == nil {
var cause string
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 {
- 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)
}
}
// 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 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 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 T is comparable, V must be comparable.
// as the second result.
func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, alt *Func) {
// fast path for common case
- if T.Empty() {
+ if T.NumMethods() == 0 {
return
}
// 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
// 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 {
var mname string
- if check.conf.CompilerErrorMessages {
+ if check != nil && check.conf.CompilerErrorMessages {
mname = m.Name() + " method"
} else {
mname = "method " + m.Name()
return p != nil && IsInterface(p.base)
}
+// check may be nil.
func (check *Checker) interfacePtrError(T Type) string {
assert(isInterfacePtr(T))
if p, _ := under(T).(*Pointer); isTypeParam(p.base) {
}
// funcString returns a string of the form name + signature for f.
+// check may be nil.
func (check *Checker) funcString(f *Func) string {
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()
}
)
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)
T1{}.foo /* ERROR cannot call pointer method foo on 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 = t0 /* ERROR cannot use .* missing method foo */
- i1 = i2 /* ERROR cannot use .* wrong type for method foo */
- i1 = t2 /* ERROR cannot use .* wrong type for method foo */
- i2 = i1 /* ERROR cannot use .* wrong type for method foo */
- i2 = t1 /* ERROR cannot use .* wrong type for method foo */
+ i1 = i0 /* ERROR cannot use i0 .* as I1 value in assignment: I0 does not implement I1 \(missing method foo\) */
+ i1 = t0 /* ERROR .* t0 .* as I1 .*: \*T0 does not implement I1 \(missing 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 .* 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 .* 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 .* 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 t0 /* ERROR cannot use .* missing method foo */ }
- _ = func() I1 { return i2 /* ERROR cannot use .* wrong type for method foo */ }
- _ = func() I1 { return t2 /* ERROR cannot use .* wrong type for method foo */ }
- _ = func() I2 { return i1 /* ERROR cannot use .* wrong type for method foo */ }
- _ = func() I2 { return t1 /* ERROR cannot use .* wrong type for 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 .* t0 .* as I1 .*: \*T0 does not implement I1 \(missing 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 .* 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 .* 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 .* 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
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{i2 /* ERROR cannot use .* wrong type for method foo */ }
- _ = []I1{i0 /* ERROR cannot use .* missing method foo */ }
- _ = []I1{i2 /* ERROR cannot use .* wrong type for method foo */ }
- _ = map[int]I1{0: i0 /* ERROR cannot use .* missing method foo */ }
- _ = map[int]I1{0: i2 /* ERROR cannot use .* wrong type for 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 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 missing method foo */ }
+ _ = []I1{i2 /* ERROR wrong type for method foo */ }
+ _ = map[int]I1{0: i0 /* ERROR missing 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) <- i2 /* ERROR wrong type for method foo \(have func\(x int\), want func\(\)\) */
+ make(chan I1) <- i0 /* ERROR missing method foo */
+ make(chan I1) <- i2 /* ERROR wrong type for method foo */
}
// Check that constants representable as integers are in integer form
}
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{}
}
}
+// check may be nil.
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 {
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 {
- return errors.New(sprintf(nil, qf, false, format, args...))
+ return errors.New(check.sprintf(format, args...))
}
Ti, _ := Tu.(*Interface)
if Ti == nil {
- var fset *token.FileSet
- if check != nil {
- fset = check.fset
- }
var cause string
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 {
- 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)
}
}
// 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 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 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 T is comparable, V must be comparable.
// Note: case-folding lookup is currently disabled
func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, alt *Func) {
// fast path for common case
- if T.Empty() {
+ if T.NumMethods() == 0 {
return
}
// 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
// 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 {
var mname string
- if compilerErrorMessages {
+ if check != nil && compilerErrorMessages {
mname = m.Name() + " method"
} else {
mname = "method " + m.Name()
return p != nil && IsInterface(p.base)
}
+// check may be nil.
func (check *Checker) interfacePtrError(T Type) string {
assert(isInterfacePtr(T))
if p, _ := under(T).(*Pointer); isTypeParam(p.base) {
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 {
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()
}
)
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)
T1{}.foo /* ERROR cannot call pointer method foo on 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 = t0 /* ERROR cannot use .* missing method foo */
- i1 = i2 /* ERROR cannot use .* wrong type for method foo */
- i1 = t2 /* ERROR cannot use .* wrong type for method foo */
- i2 = i1 /* ERROR cannot use .* wrong type for method foo */
- i2 = t1 /* ERROR cannot use .* wrong type for method foo */
+ i1 = i0 /* ERROR cannot use i0 .* as I1 value in assignment: I0 does not implement I1 \(missing method foo\) */
+ i1 = t0 /* ERROR .* t0 .* as I1 .*: \*T0 does not implement I1 \(missing 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 .* 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 .* 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 .* 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 t0 /* ERROR cannot use .* missing method foo */ }
- _ = func() I1 { return i2 /* ERROR cannot use .* wrong type for method foo */ }
- _ = func() I1 { return t2 /* ERROR cannot use .* wrong type for method foo */ }
- _ = func() I2 { return i1 /* ERROR cannot use .* wrong type for method foo */ }
- _ = func() I2 { return t1 /* ERROR cannot use .* wrong type for 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 .* t0 .* as I1 .*: \*T0 does not implement I1 \(missing 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 .* 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 .* 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 .* 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
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{i2 /* ERROR cannot use .* wrong type for method foo */ }
- _ = []I1{i0 /* ERROR cannot use .* missing method foo */ }
- _ = []I1{i2 /* ERROR cannot use .* wrong type for method foo */ }
- _ = map[int]I1{0: i0 /* ERROR cannot use .* missing method foo */ }
- _ = map[int]I1{0: i2 /* ERROR cannot use .* wrong type for 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 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 missing method foo */ }
+ _ = []I1{i2 /* ERROR wrong type for method foo */ }
+ _ = map[int]I1{0: i0 /* ERROR missing 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) <- i2 /* ERROR wrong type for method foo \(have func\(x int\), want func\(\)\) */
+ make(chan I1) <- i0 /* ERROR missing method foo */
+ make(chan I1) <- i2 /* ERROR wrong type for method foo */
}
// Check that constants representable as integers are in integer form
}
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{}