1
0
mirror of https://github.com/golang/go synced 2024-11-18 06:24:47 -07:00

go/types, types2: consistently use "cause" instead of "reason" for error details (cleanup)

There were many more uses of the variable name "cause" than "reason"
to hold error message details. Consistently use "cause" throughout.

Accordingly, s/MissingMethodReason/MissingMethodCause/.

Change-Id: I171d784faabc66a4c58ba8944784204687595203
Reviewed-on: https://go-review.googlesource.com/c/go/+/435418
Run-TryBot: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
Auto-Submit: Robert Griesemer <gri@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@google.com>
This commit is contained in:
Robert Griesemer 2022-09-28 14:59:16 -07:00 committed by Gopher Robot
parent 5612215d32
commit ffdfa9ff41
10 changed files with 90 additions and 90 deletions

View File

@ -1764,7 +1764,7 @@ func (check *Checker) typeAssertion(e syntax.Expr, x *operand, T Type, typeSwitc
return // success return // success
} }
cause := check.missingMethodReason(T, x.typ, method, alt) cause := check.missingMethodCause(T, x.typ, method, alt)
if typeSwitch { if typeSwitch {
check.errorf(e, _ImpossibleAssert, "impossible type switch case: %s\n\t%s cannot have dynamic type %s %s", e, x, T, cause) check.errorf(e, _ImpossibleAssert, "impossible type switch case: %s\n\t%s cannot have dynamic type %s %s", e, x, T, cause)

View File

@ -174,9 +174,9 @@ func (check *Checker) verify(pos syntax.Pos, tparams []*TypeParam, targs []Type,
// need to instantiate it with the type arguments with which we instantiated // need to instantiate it with the type arguments with which we instantiated
// the parameterized type. // the parameterized type.
bound := check.subst(pos, tpar.bound, smap, nil, ctxt) bound := check.subst(pos, tpar.bound, smap, nil, ctxt)
var reason string var cause string
if !check.implements(targs[i], bound, &reason) { if !check.implements(targs[i], bound, &cause) {
return i, errors.New(reason) return i, errors.New(cause)
} }
} }
return -1, nil return -1, nil
@ -185,9 +185,9 @@ func (check *Checker) verify(pos syntax.Pos, tparams []*TypeParam, targs []Type,
// implements checks if V implements T. The receiver may be nil if implements // implements checks if V implements T. The receiver may be nil if implements
// is called through an exported API call such as AssignableTo. // is called through an exported API call such as AssignableTo.
// //
// If the provided reason is non-nil, it may be set to an error string // If the provided cause is non-nil, it may be set to an error string
// explaining why V does not implement T. // explaining why V does not implement T.
func (check *Checker) implements(V, T Type, reason *string) bool { func (check *Checker) implements(V, T Type, cause *string) bool {
Vu := under(V) Vu := under(V)
Tu := under(T) Tu := under(T)
if Vu == Typ[Invalid] || Tu == Typ[Invalid] { if Vu == Typ[Invalid] || Tu == Typ[Invalid] {
@ -199,14 +199,14 @@ func (check *Checker) implements(V, T Type, reason *string) bool {
Ti, _ := Tu.(*Interface) Ti, _ := Tu.(*Interface)
if Ti == nil { if Ti == nil {
var cause string var detail string
if isInterfacePtr(Tu) { if isInterfacePtr(Tu) {
cause = check.sprintf("type %s is pointer to interface, not interface", T) detail = check.sprintf("type %s is pointer to interface, not interface", T)
} else { } else {
cause = check.sprintf("%s is not an interface", T) detail = check.sprintf("%s is not an interface", T)
} }
if reason != nil { if cause != nil {
*reason = check.sprintf("%s does not implement %s (%s)", V, T, cause) *cause = check.sprintf("%s does not implement %s (%s)", V, T, detail)
} }
return false return false
} }
@ -227,16 +227,16 @@ func (check *Checker) implements(V, T Type, reason *string) bool {
// No type with non-empty type set satisfies the empty type set. // No type with non-empty type set satisfies the empty type set.
if Ti.typeSet().IsEmpty() { if Ti.typeSet().IsEmpty() {
if reason != nil { if cause != nil {
*reason = check.sprintf("cannot implement %s (empty type set)", T) *cause = check.sprintf("cannot implement %s (empty type set)", T)
} }
return false return false
} }
// V must implement T's methods, if any. // V must implement T's methods, if any.
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) */ {
if reason != nil { if cause != nil {
*reason = check.sprintf("%s does not implement %s %s", V, T, check.missingMethodReason(V, T, m, wrong)) *cause = check.sprintf("%s does not implement %s %s", V, T, check.missingMethodCause(V, T, m, wrong))
} }
return false return false
} }
@ -245,8 +245,8 @@ func (check *Checker) implements(V, T Type, reason *string) bool {
checkComparability := func() bool { checkComparability := func() bool {
// If T is comparable, V must be comparable. // If T is comparable, V must be comparable.
if Ti.IsComparable() && !comparable(V, false, nil, nil) { if Ti.IsComparable() && !comparable(V, false, nil, nil) {
if reason != nil { if cause != nil {
*reason = check.sprintf("%s does not implement comparable", V) *cause = check.sprintf("%s does not implement comparable", V)
} }
return false return false
} }
@ -265,8 +265,8 @@ func (check *Checker) implements(V, T Type, reason *string) bool {
if Vi != nil { if Vi != nil {
if !Vi.typeSet().subsetOf(Ti.typeSet()) { if !Vi.typeSet().subsetOf(Ti.typeSet()) {
// TODO(gri) report which type is missing // TODO(gri) report which type is missing
if reason != nil { if cause != nil {
*reason = check.sprintf("%s does not implement %s", V, T) *cause = check.sprintf("%s does not implement %s", V, T)
} }
return false return false
} }
@ -291,11 +291,11 @@ func (check *Checker) implements(V, T Type, reason *string) bool {
} }
return false return false
}) { }) {
if reason != nil { if cause != nil {
if alt != nil { if alt != nil {
*reason = check.sprintf("%s does not implement %s (possibly missing ~ for %s in constraint %s)", V, T, alt, T) *cause = check.sprintf("%s does not implement %s (possibly missing ~ for %s in constraint %s)", V, T, alt, T)
} else { } else {
*reason = check.sprintf("%s does not implement %s (%s missing in %s)", V, T, V, Ti.typeSet().terms) *cause = check.sprintf("%s does not implement %s (%s missing in %s)", V, T, V, Ti.typeSet().terms)
} }
} }
return false return false

View File

@ -364,13 +364,13 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method,
return return
} }
// missingMethodReason returns a string giving the detailed reason for a missing method m, // missingMethodCause returns a string giving the detailed cause for a missing method m,
// where m is missing from V, but required by T. It puts the reason in parentheses, // where m is missing from V, but required by T. It puts the cause in parentheses,
// 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. // check may be nil.
func (check *Checker) missingMethodReason(V, T Type, m, alt *Func) string { func (check *Checker) missingMethodCause(V, T Type, m, alt *Func) string {
mname := "method " + m.Name() mname := "method " + m.Name()
if alt != nil { if alt != nil {

View File

@ -234,12 +234,12 @@ func (x *operand) setConst(k syntax.LitKind, lit string) {
func (x *operand) isNil() bool { return x.mode == nilvalue } func (x *operand) isNil() bool { return x.mode == nilvalue }
// assignableTo reports whether x is assignable to a variable of type T. If the // assignableTo reports whether x is assignable to a variable of type T. If the
// result is false and a non-nil reason is provided, it may be set to a more // result is false and a non-nil cause is provided, it may be set to a more
// detailed explanation of the failure (result != ""). The returned error code // detailed explanation of the failure (result != ""). The returned error code
// is only valid if the (first) result is false. The check parameter may be nil // is only valid if the (first) result is false. The check parameter may be nil
// if assignableTo is invoked through an exported API call, i.e., when all // if assignableTo is invoked through an exported API call, i.e., when all
// methods have been type-checked. // methods have been type-checked.
func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, errorCode) { func (x *operand) assignableTo(check *Checker, T Type, cause *string) (bool, errorCode) {
if x.mode == invalid || T == Typ[Invalid] { if x.mode == invalid || T == Typ[Invalid] {
return true, 0 // avoid spurious errors return true, 0 // avoid spurious errors
} }
@ -288,7 +288,7 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er
// T is an interface type and x implements T and T is not a type parameter. // 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. // Also handle the case where T is a pointer to an interface.
if _, ok := Tu.(*Interface); ok && Tp == nil || isInterfacePtr(Tu) { if _, ok := Tu.(*Interface); ok && Tp == nil || isInterfacePtr(Tu) {
if !check.implements(V, T, reason) { if !check.implements(V, T, cause) {
return false, _InvalidIfaceAssign return false, _InvalidIfaceAssign
} }
return true, 0 return true, 0
@ -298,8 +298,8 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er
if Vi, _ := Vu.(*Interface); Vi != nil && Vp == nil { if Vi, _ := Vu.(*Interface); Vi != nil && Vp == nil {
if check.implements(T, V, nil) { if check.implements(T, V, nil) {
// T implements V, so give hint about type assertion. // T implements V, so give hint about type assertion.
if reason != nil { if cause != nil {
*reason = "need type assertion" *cause = "need type assertion"
} }
return false, _IncompatibleAssign return false, _IncompatibleAssign
} }
@ -320,12 +320,12 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er
} }
errorf := func(format string, args ...interface{}) { errorf := func(format string, args ...interface{}) {
if check != nil && reason != nil { if check != nil && cause != nil {
msg := check.sprintf(format, args...) msg := check.sprintf(format, args...)
if *reason != "" { if *cause != "" {
msg += "\n\t" + *reason msg += "\n\t" + *cause
} }
*reason = msg *cause = msg
} }
} }
@ -338,7 +338,7 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er
if T == nil { if T == nil {
return false // no specific types return false // no specific types
} }
ok, code = x.assignableTo(check, T.typ, reason) ok, code = x.assignableTo(check, T.typ, cause)
if !ok { if !ok {
errorf("cannot assign %s to %s (in %s)", x.typ, T.typ, Tp) errorf("cannot assign %s to %s (in %s)", x.typ, T.typ, Tp)
return false return false
@ -360,7 +360,7 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er
return false // no specific types return false // no specific types
} }
x.typ = V.typ x.typ = V.typ
ok, code = x.assignableTo(check, T, reason) ok, code = x.assignableTo(check, T, cause)
if !ok { if !ok {
errorf("cannot assign %s (in %s) to %s", V.typ, Vp, T) errorf("cannot assign %s (in %s) to %s", V.typ, Vp, T)
return false return false

View File

@ -188,14 +188,14 @@ func (check *Checker) definedType(e syntax.Expr, def *Named) Type {
} }
// genericType is like typ but the type must be an (uninstantiated) generic // genericType is like typ but the type must be an (uninstantiated) generic
// type. If reason is non-nil and the type expression was a valid type but not // type. If cause is non-nil and the type expression was a valid type but not
// generic, reason will be populated with a message describing the error. // generic, cause will be populated with a message describing the error.
func (check *Checker) genericType(e syntax.Expr, reason *string) Type { func (check *Checker) genericType(e syntax.Expr, cause *string) Type {
typ := check.typInternal(e, nil) typ := check.typInternal(e, nil)
assert(isTyped(typ)) assert(isTyped(typ))
if typ != Typ[Invalid] && !isGeneric(typ) { if typ != Typ[Invalid] && !isGeneric(typ) {
if reason != nil { if cause != nil {
*reason = check.sprintf("%s is not a generic type", typ) *cause = check.sprintf("%s is not a generic type", typ)
} }
typ = Typ[Invalid] typ = Typ[Invalid]
} }
@ -413,10 +413,10 @@ func (check *Checker) instantiatedType(x syntax.Expr, xlist []syntax.Expr, def *
}() }()
} }
var reason string var cause string
gtyp := check.genericType(x, &reason) gtyp := check.genericType(x, &cause)
if reason != "" { if cause != "" {
check.errorf(x, _NotAGenericType, invalidOp+"%s%s (%s)", x, xlist, reason) check.errorf(x, _NotAGenericType, invalidOp+"%s%s (%s)", x, xlist, cause)
} }
if gtyp == Typ[Invalid] { if gtyp == Typ[Invalid] {
return gtyp // error already reported return gtyp // error already reported

View File

@ -1711,7 +1711,7 @@ func (check *Checker) typeAssertion(e ast.Expr, x *operand, T Type, typeSwitch b
return // success return // success
} }
cause := check.missingMethodReason(T, x.typ, method, alt) cause := check.missingMethodCause(T, x.typ, method, alt)
if typeSwitch { if typeSwitch {
check.errorf(e, _ImpossibleAssert, "impossible type switch case: %s\n\t%s cannot have dynamic type %s %s", e, x, T, cause) check.errorf(e, _ImpossibleAssert, "impossible type switch case: %s\n\t%s cannot have dynamic type %s %s", e, x, T, cause)

View File

@ -174,9 +174,9 @@ func (check *Checker) verify(pos token.Pos, tparams []*TypeParam, targs []Type,
// need to instantiate it with the type arguments with which we instantiated // need to instantiate it with the type arguments with which we instantiated
// the parameterized type. // the parameterized type.
bound := check.subst(pos, tpar.bound, smap, nil, ctxt) bound := check.subst(pos, tpar.bound, smap, nil, ctxt)
var reason string var cause string
if !check.implements(targs[i], bound, &reason) { if !check.implements(targs[i], bound, &cause) {
return i, errors.New(reason) return i, errors.New(cause)
} }
} }
return -1, nil return -1, nil
@ -185,9 +185,9 @@ func (check *Checker) verify(pos token.Pos, tparams []*TypeParam, targs []Type,
// implements checks if V implements T. The receiver may be nil if implements // implements checks if V implements T. The receiver may be nil if implements
// is called through an exported API call such as AssignableTo. // is called through an exported API call such as AssignableTo.
// //
// If the provided reason is non-nil, it may be set to an error string // If the provided cause is non-nil, it may be set to an error string
// explaining why V does not implement T. // explaining why V does not implement T.
func (check *Checker) implements(V, T Type, reason *string) bool { func (check *Checker) implements(V, T Type, cause *string) bool {
Vu := under(V) Vu := under(V)
Tu := under(T) Tu := under(T)
if Vu == Typ[Invalid] || Tu == Typ[Invalid] { if Vu == Typ[Invalid] || Tu == Typ[Invalid] {
@ -199,14 +199,14 @@ func (check *Checker) implements(V, T Type, reason *string) bool {
Ti, _ := Tu.(*Interface) Ti, _ := Tu.(*Interface)
if Ti == nil { if Ti == nil {
var cause string var detail string
if isInterfacePtr(Tu) { if isInterfacePtr(Tu) {
cause = check.sprintf("type %s is pointer to interface, not interface", T) detail = check.sprintf("type %s is pointer to interface, not interface", T)
} else { } else {
cause = check.sprintf("%s is not an interface", T) detail = check.sprintf("%s is not an interface", T)
} }
if reason != nil { if cause != nil {
*reason = check.sprintf("%s does not implement %s (%s)", V, T, cause) *cause = check.sprintf("%s does not implement %s (%s)", V, T, detail)
} }
return false return false
} }
@ -227,16 +227,16 @@ func (check *Checker) implements(V, T Type, reason *string) bool {
// No type with non-empty type set satisfies the empty type set. // No type with non-empty type set satisfies the empty type set.
if Ti.typeSet().IsEmpty() { if Ti.typeSet().IsEmpty() {
if reason != nil { if cause != nil {
*reason = check.sprintf("cannot implement %s (empty type set)", T) *cause = check.sprintf("cannot implement %s (empty type set)", T)
} }
return false return false
} }
// V must implement T's methods, if any. // V must implement T's methods, if any.
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) */ {
if reason != nil { if cause != nil {
*reason = check.sprintf("%s does not implement %s %s", V, T, check.missingMethodReason(V, T, m, wrong)) *cause = check.sprintf("%s does not implement %s %s", V, T, check.missingMethodCause(V, T, m, wrong))
} }
return false return false
} }
@ -245,8 +245,8 @@ func (check *Checker) implements(V, T Type, reason *string) bool {
checkComparability := func() bool { checkComparability := func() bool {
// If T is comparable, V must be comparable. // If T is comparable, V must be comparable.
if Ti.IsComparable() && !comparable(V, false, nil, nil) { if Ti.IsComparable() && !comparable(V, false, nil, nil) {
if reason != nil { if cause != nil {
*reason = check.sprintf("%s does not implement comparable", V) *cause = check.sprintf("%s does not implement comparable", V)
} }
return false return false
} }
@ -265,8 +265,8 @@ func (check *Checker) implements(V, T Type, reason *string) bool {
if Vi != nil { if Vi != nil {
if !Vi.typeSet().subsetOf(Ti.typeSet()) { if !Vi.typeSet().subsetOf(Ti.typeSet()) {
// TODO(gri) report which type is missing // TODO(gri) report which type is missing
if reason != nil { if cause != nil {
*reason = check.sprintf("%s does not implement %s", V, T) *cause = check.sprintf("%s does not implement %s", V, T)
} }
return false return false
} }
@ -291,11 +291,11 @@ func (check *Checker) implements(V, T Type, reason *string) bool {
} }
return false return false
}) { }) {
if reason != nil { if cause != nil {
if alt != nil { if alt != nil {
*reason = check.sprintf("%s does not implement %s (possibly missing ~ for %s in constraint %s)", V, T, alt, T) *cause = check.sprintf("%s does not implement %s (possibly missing ~ for %s in constraint %s)", V, T, alt, T)
} else { } else {
*reason = check.sprintf("%s does not implement %s (%s missing in %s)", V, T, V, Ti.typeSet().terms) *cause = check.sprintf("%s does not implement %s (%s missing in %s)", V, T, V, Ti.typeSet().terms)
} }
} }
return false return false

View File

@ -364,13 +364,13 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method,
return return
} }
// missingMethodReason returns a string giving the detailed reason for a missing method m, // missingMethodCause returns a string giving the detailed cause for a missing method m,
// where m is missing from V, but required by T. It puts the reason in parentheses, // where m is missing from V, but required by T. It puts the cause in parentheses,
// 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. // check may be nil.
func (check *Checker) missingMethodReason(V, T Type, m, alt *Func) string { func (check *Checker) missingMethodCause(V, T Type, m, alt *Func) string {
mname := "method " + m.Name() mname := "method " + m.Name()
if alt != nil { if alt != nil {

View File

@ -223,12 +223,12 @@ func (x *operand) isNil() bool {
} }
// assignableTo reports whether x is assignable to a variable of type T. If the // assignableTo reports whether x is assignable to a variable of type T. If the
// result is false and a non-nil reason is provided, it may be set to a more // result is false and a non-nil cause is provided, it may be set to a more
// detailed explanation of the failure (result != ""). The returned error code // detailed explanation of the failure (result != ""). The returned error code
// is only valid if the (first) result is false. The check parameter may be nil // is only valid if the (first) result is false. The check parameter may be nil
// if assignableTo is invoked through an exported API call, i.e., when all // if assignableTo is invoked through an exported API call, i.e., when all
// methods have been type-checked. // methods have been type-checked.
func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, errorCode) { func (x *operand) assignableTo(check *Checker, T Type, cause *string) (bool, errorCode) {
if x.mode == invalid || T == Typ[Invalid] { if x.mode == invalid || T == Typ[Invalid] {
return true, 0 // avoid spurious errors return true, 0 // avoid spurious errors
} }
@ -277,7 +277,7 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er
// T is an interface type and x implements T and T is not a type parameter. // 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. // Also handle the case where T is a pointer to an interface.
if _, ok := Tu.(*Interface); ok && Tp == nil || isInterfacePtr(Tu) { if _, ok := Tu.(*Interface); ok && Tp == nil || isInterfacePtr(Tu) {
if !check.implements(V, T, reason) { if !check.implements(V, T, cause) {
return false, _InvalidIfaceAssign return false, _InvalidIfaceAssign
} }
return true, 0 return true, 0
@ -287,8 +287,8 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er
if Vi, _ := Vu.(*Interface); Vi != nil && Vp == nil { if Vi, _ := Vu.(*Interface); Vi != nil && Vp == nil {
if check.implements(T, V, nil) { if check.implements(T, V, nil) {
// T implements V, so give hint about type assertion. // T implements V, so give hint about type assertion.
if reason != nil { if cause != nil {
*reason = "need type assertion" *cause = "need type assertion"
} }
return false, _IncompatibleAssign return false, _IncompatibleAssign
} }
@ -309,12 +309,12 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er
} }
errorf := func(format string, args ...any) { errorf := func(format string, args ...any) {
if check != nil && reason != nil { if check != nil && cause != nil {
msg := check.sprintf(format, args...) msg := check.sprintf(format, args...)
if *reason != "" { if *cause != "" {
msg += "\n\t" + *reason msg += "\n\t" + *cause
} }
*reason = msg *cause = msg
} }
} }
@ -327,7 +327,7 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er
if T == nil { if T == nil {
return false // no specific types return false // no specific types
} }
ok, code = x.assignableTo(check, T.typ, reason) ok, code = x.assignableTo(check, T.typ, cause)
if !ok { if !ok {
errorf("cannot assign %s to %s (in %s)", x.typ, T.typ, Tp) errorf("cannot assign %s to %s (in %s)", x.typ, T.typ, Tp)
return false return false
@ -349,7 +349,7 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er
return false // no specific types return false // no specific types
} }
x.typ = V.typ x.typ = V.typ
ok, code = x.assignableTo(check, T, reason) ok, code = x.assignableTo(check, T, cause)
if !ok { if !ok {
errorf("cannot assign %s (in %s) to %s", V.typ, Vp, T) errorf("cannot assign %s (in %s) to %s", V.typ, Vp, T)
return false return false

View File

@ -188,14 +188,14 @@ func (check *Checker) definedType(e ast.Expr, def *Named) Type {
} }
// genericType is like typ but the type must be an (uninstantiated) generic // genericType is like typ but the type must be an (uninstantiated) generic
// type. If reason is non-nil and the type expression was a valid type but not // type. If cause is non-nil and the type expression was a valid type but not
// generic, reason will be populated with a message describing the error. // generic, cause will be populated with a message describing the error.
func (check *Checker) genericType(e ast.Expr, reason *string) Type { func (check *Checker) genericType(e ast.Expr, cause *string) Type {
typ := check.typInternal(e, nil) typ := check.typInternal(e, nil)
assert(isTyped(typ)) assert(isTyped(typ))
if typ != Typ[Invalid] && !isGeneric(typ) { if typ != Typ[Invalid] && !isGeneric(typ) {
if reason != nil { if cause != nil {
*reason = check.sprintf("%s is not a generic type", typ) *cause = check.sprintf("%s is not a generic type", typ)
} }
typ = Typ[Invalid] typ = Typ[Invalid]
} }
@ -404,10 +404,10 @@ func (check *Checker) instantiatedType(ix *typeparams.IndexExpr, def *Named) (re
}() }()
} }
var reason string var cause string
gtyp := check.genericType(ix.X, &reason) gtyp := check.genericType(ix.X, &cause)
if reason != "" { if cause != "" {
check.invalidOp(ix.Orig, _NotAGenericType, "%s (%s)", ix.Orig, reason) check.invalidOp(ix.Orig, _NotAGenericType, "%s (%s)", ix.Orig, cause)
} }
if gtyp == Typ[Invalid] { if gtyp == Typ[Invalid] {
return gtyp // error already reported return gtyp // error already reported