Follow-up on comment in CL 376914.
Also:
- add missing check != nil test in assignableTo
- use check.sprintf rather than fmt.Sprintf in missingMethodReason
For #48312.
Change-Id: Ie209b4101a7f2c279e42a59987d0068079c8b69f
Reviewed-on: https://go-review.googlesource.com/c/go/+/377375
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
var why string
if isInterfacePtr(x.typ) {
- why = check.sprintf("type %s is pointer to interface, not interface", x.typ)
+ why = check.interfacePtrError(x.typ)
} else {
why = check.sprintf("type %s has no field or method %s", x.typ, sel)
// Check if capitalization of sel matters and provide better error message in that case.
package types2
import (
- "fmt"
"strings"
)
if wrongType != nil {
if Identical(m.typ, wrongType.typ) {
if m.Name() == wrongType.Name() {
- r = fmt.Sprintf("(%s has pointer receiver)", mname)
+ r = check.sprintf("(%s has pointer receiver)", mname)
} else {
- r = fmt.Sprintf("(missing %s)\n\t\thave %s^^%s\n\t\twant %s^^%s",
+ r = check.sprintf("(missing %s)\n\t\thave %s^^%s\n\t\twant %s^^%s",
mname, wrongType.Name(), wrongType.typ, m.Name(), m.typ)
}
} else {
if check.conf.CompilerErrorMessages {
- r = fmt.Sprintf("(wrong type for %s)\n\t\thave %s^^%s\n\t\twant %s^^%s",
+ r = check.sprintf("(wrong type for %s)\n\t\thave %s^^%s\n\t\twant %s^^%s",
mname, wrongType.Name(), wrongType.typ, m.Name(), m.typ)
} else {
- r = fmt.Sprintf("(wrong type for %s: have %s, want %s)",
+ r = check.sprintf("(wrong type for %s: have %s, want %s)",
mname, wrongType.typ, m.typ)
}
}
r = strings.Replace(r, "^^func", "", -1)
} else if IsInterface(T) {
if isInterfacePtr(V) {
- r = fmt.Sprintf("(type %s is pointer to interface, not interface)", V)
+ r = "(" + check.interfacePtrError(V) + ")"
}
} else if isInterfacePtr(T) {
- r = fmt.Sprintf("(type %s is pointer to interface, not interface)", T)
+ r = "(" + check.interfacePtrError(T) + ")"
}
if r == "" {
- r = fmt.Sprintf("(missing %s)", mname)
+ r = check.sprintf("(missing %s)", mname)
}
return r
}
return p != nil && IsInterface(p.base)
}
+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 type parameter, not type parameter", T)
+ }
+ return check.sprintf("type %s is pointer to interface, not interface", T)
+}
+
// assertableTo reports whether a value of type V can be asserted to have type T.
// It returns (nil, false) as affirmative answer. Otherwise it returns a missing
// method required by V and whether it is missing or just has the wrong type.
if Ti, ok := Tu.(*Interface); ok && Tp == nil {
if m, wrongType := check.missingMethod(V, Ti, true); m != nil /* !Implements(V, Ti) */ {
if reason != nil {
- if check.conf.CompilerErrorMessages {
+ 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 {
x.m()
// (&x).m doesn't exist because &x is of type *P
// and pointers to type parameters don't have methods
- (&x).m /* ERROR type \*P is pointer to interface, not interface */ ()
+ (&x).m /* ERROR type \*P is pointer to type parameter, not type parameter */ ()
}
}
func _[P T](p *P) {
- p.m /* ERROR type \*P is pointer to interface, not interface */ ()
+ p.m /* ERROR type \*P is pointer to type parameter, not type parameter */ ()
}
var why string
if isInterfacePtr(x.typ) {
- why = check.sprintf("type %s is pointer to interface, not interface", x.typ)
+ why = check.interfacePtrError(x.typ)
} else {
why = check.sprintf("type %s has no field or method %s", x.typ, sel)
// Check if capitalization of sel matters and provide better error message in that case.
package types
import (
- "fmt"
"strings"
)
if wrongType != nil {
if Identical(m.typ, wrongType.typ) {
if m.Name() == wrongType.Name() {
- r = fmt.Sprintf("(%s has pointer receiver)", mname)
+ r = check.sprintf("(%s has pointer receiver)", mname)
} else {
- r = fmt.Sprintf("(missing %s)\n\t\thave %s^^%s\n\t\twant %s^^%s",
+ r = check.sprintf("(missing %s)\n\t\thave %s^^%s\n\t\twant %s^^%s",
mname, wrongType.Name(), wrongType.typ, m.Name(), m.typ)
}
} else {
if compilerErrorMessages {
- r = fmt.Sprintf("(wrong type for %s)\n\t\thave %s^^%s\n\t\twant %s^^%s",
+ r = check.sprintf("(wrong type for %s)\n\t\thave %s^^%s\n\t\twant %s^^%s",
mname, wrongType.Name(), wrongType.typ, m.Name(), m.typ)
} else {
- r = fmt.Sprintf("(wrong type for %s: have %s, want %s)",
+ r = check.sprintf("(wrong type for %s: have %s, want %s)",
mname, wrongType.typ, m.typ)
}
}
r = strings.Replace(r, "^^func", "", -1)
} else if IsInterface(T) {
if isInterfacePtr(V) {
- r = fmt.Sprintf("(type %s is pointer to interface, not interface)", V)
+ r = "(" + check.interfacePtrError(V) + ")"
}
} else if isInterfacePtr(T) {
- r = fmt.Sprintf("(type %s is pointer to interface, not interface)", T)
+ r = "(" + check.interfacePtrError(T) + ")"
}
if r == "" {
- r = fmt.Sprintf("(missing %s)", mname)
+ r = check.sprintf("(missing %s)", mname)
}
return r
}
return p != nil && IsInterface(p.base)
}
+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 type parameter, not type parameter", T)
+ }
+ return check.sprintf("type %s is pointer to interface, not interface", T)
+}
+
// assertableTo reports whether a value of type V can be asserted to have type T.
// It returns (nil, false) as affirmative answer. Otherwise it returns a missing
// method required by V and whether it is missing or just has the wrong type.
if Ti, ok := Tu.(*Interface); ok && Tp == nil {
if m, wrongType := check.missingMethod(V, Ti, true); m != nil /* Implements(V, Ti) */ {
if reason != nil {
- if compilerErrorMessages {
+ if check != nil && compilerErrorMessages {
*reason = check.sprintf("%s does not implement %s %s", x.typ, T,
check.missingMethodReason(x.typ, T, m, wrongType))
} else {
x.m()
// (&x).m doesn't exist because &x is of type *P
// and pointers to type parameters don't have methods
- (&x).m /* ERROR type \*P is pointer to interface, not interface */ ()
+ (&x).m /* ERROR type \*P is pointer to type parameter, not type parameter */ ()
}
}
func _[P T](p *P) {
- p.m /* ERROR type \*P is pointer to interface, not interface */ ()
+ p.m /* ERROR type \*P is pointer to type parameter, not type parameter */ ()
}