go/types: assign error codes to new errors for Go 1.18

During development, we used placeholder _Todo error codes for new
errors related to generics. Add real error codes in these places.

As a result, 9 new error codes are added for ~50 call sites.

Change-Id: Ib57b4cd9f0a2e160971a3aeea18f9fe26fc0f835
Reviewed-on: https://go-review.googlesource.com/c/go/+/363874
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
Robert Findley 2021-11-14 20:34:58 -05:00
parent 1dc9af5cdc
commit 0e65410038
17 changed files with 142 additions and 51 deletions

View File

@ -72,7 +72,7 @@ func (check *Checker) assignment(x *operand, T Type, context string) {
// A generic (non-instantiated) function value cannot be assigned to a variable.
if sig, _ := under(x.typ).(*Signature); sig != nil && sig.TypeParams().Len() > 0 {
check.errorf(x, _Todo, "cannot use generic function %s without instantiation in %s", x, context)
check.errorf(x, _WrongTypeArgCount, "cannot use generic function %s without instantiation in %s", x, context)
}
// spec: "If a left-hand side is the blank identifier, any typed or

View File

@ -370,7 +370,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
return false
}
if key != nil && !Identical(map_.key, key) {
check.invalidArg(x, _Todo, "maps of %s must have identical key types", x)
check.invalidArg(x, _InvalidDelete, "maps of %s must have identical key types", x)
return false
}
key = map_.key

View File

@ -18,7 +18,7 @@ import (
// The operand x must be the evaluation of inst.X and its type must be a signature.
func (check *Checker) funcInst(x *operand, ix *typeparams.IndexExpr) {
if !check.allowVersion(check.pkg, 1, 18) {
check.softErrorf(inNode(ix.Orig, ix.Lbrack), _Todo, "function instantiation requires go1.18 or later")
check.softErrorf(inNode(ix.Orig, ix.Lbrack), _UnsupportedFeature, "function instantiation requires go1.18 or later")
}
targs := check.typeList(ix.Indices)
@ -33,7 +33,7 @@ func (check *Checker) funcInst(x *operand, ix *typeparams.IndexExpr) {
sig := x.typ.(*Signature)
got, want := len(targs), sig.TypeParams().Len()
if got > want {
check.errorf(ix.Indices[got-1], _Todo, "got %d type arguments but want %d", got, want)
check.errorf(ix.Indices[got-1], _WrongTypeArgCount, "got %d type arguments but want %d", got, want)
x.mode = invalid
x.expr = ix.Orig
return
@ -90,7 +90,7 @@ func (check *Checker) instantiateSignature(pos token.Pos, typ *Signature, targs
if i < len(posList) {
pos = posList[i]
}
check.softErrorf(atPos(pos), _Todo, err.Error())
check.softErrorf(atPos(pos), _InvalidTypeArg, err.Error())
} else {
check.mono.recordInstance(check.pkg, pos, tparams, targs, posList)
}
@ -143,7 +143,7 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind {
}
if t, _ := under(T).(*Interface); t != nil {
if !t.IsMethodSet() {
check.errorf(call, _Todo, "cannot use interface %s in conversion (contains specific type constraints or is comparable)", T)
check.errorf(call, _MisplacedConstraintIface, "cannot use interface %s in conversion (contains specific type constraints or is comparable)", T)
break
}
}
@ -198,7 +198,7 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind {
// check number of type arguments (got) vs number of type parameters (want)
got, want := len(targs), sig.TypeParams().Len()
if got > want {
check.errorf(ix.Indices[want], _Todo, "got %d type arguments but want %d", got, want)
check.errorf(ix.Indices[want], _WrongTypeArgCount, "got %d type arguments but want %d", got, want)
check.use(call.Args...)
x.mode = invalid
x.expr = call
@ -370,9 +370,9 @@ func (check *Checker) arguments(call *ast.CallExpr, sig *Signature, targs []Type
switch call.Fun.(type) {
case *ast.IndexExpr, *ast.IndexListExpr:
ix := typeparams.UnpackIndexExpr(call.Fun)
check.softErrorf(inNode(call.Fun, ix.Lbrack), _Todo, "function instantiation requires go1.18 or later")
check.softErrorf(inNode(call.Fun, ix.Lbrack), _UnsupportedFeature, "function instantiation requires go1.18 or later")
default:
check.softErrorf(inNode(call, call.Lparen), _Todo, "implicit function instantiation requires go1.18 or later")
check.softErrorf(inNode(call, call.Lparen), _UnsupportedFeature, "implicit function instantiation requires go1.18 or later")
}
}
// TODO(gri) provide position information for targs so we can feed

View File

@ -623,7 +623,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) {
check.validType(obj.typ, nil)
// If typ is local, an error was already reported where typ is specified/defined.
if check.isImportedConstraint(rhs) && !check.allowVersion(check.pkg, 1, 18) {
check.errorf(tdecl.Type, _Todo, "using type constraint %s requires go1.18 or later", rhs)
check.errorf(tdecl.Type, _UnsupportedFeature, "using type constraint %s requires go1.18 or later", rhs)
}
}).describef(obj, "validType(%s)", obj.Name())
@ -631,7 +631,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) {
if alias && tdecl.TypeParams.NumFields() != 0 {
// The parser will ensure this but we may still get an invalid AST.
// Complain and continue as regular type definition.
check.error(atPos(tdecl.Assign), _Todo, "generic type cannot be alias")
check.error(atPos(tdecl.Assign), _BadDecl, "generic type cannot be alias")
alias = false
}
@ -673,7 +673,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) {
// type (underlying not fully resolved yet) it cannot become a type parameter due
// to this very restriction.
if tpar, _ := named.underlying.(*TypeParam); tpar != nil {
check.error(tdecl.Type, _Todo, "cannot use a type parameter as RHS in type declaration")
check.error(tdecl.Type, _MisplacedTypeParam, "cannot use a type parameter as RHS in type declaration")
named.underlying = Typ[Invalid]
}
}
@ -724,7 +724,7 @@ func (check *Checker) collectTypeParams(dst **TypeParamList, list *ast.FieldList
check.later(func() {
for i, bound := range bounds {
if _, ok := under(bound).(*TypeParam); ok {
check.error(posns[i], _Todo, "cannot use a type parameter as constraint")
check.error(posns[i], _MisplacedTypeParam, "cannot use a type parameter as constraint")
}
}
for _, tpar := range tparams {
@ -861,7 +861,7 @@ func (check *Checker) funcDecl(obj *Func, decl *declInfo) {
obj.color_ = saved
if fdecl.Type.TypeParams.NumFields() > 0 && fdecl.Body == nil {
check.softErrorf(fdecl.Name, _Todo, "parameterized function is missing function body")
check.softErrorf(fdecl.Name, _BadDecl, "parameterized function is missing function body")
}
// function body must be type-checked after global declarations

View File

@ -1301,6 +1301,54 @@ const (
// var _ = unsafe.Slice(&x, uint64(1) << 63)
_InvalidUnsafeSlice
// All codes below were added in Go 1.18.
// _UnsupportedFeature occurs when a language feature is used that is not
// supported at this Go version.
_UnsupportedFeature
// _WrongTypeArgCount occurs when a type or function is instantiated with an
// incorrent number of type arguments, including when a generic type or
// function is used without instantiation.
//
// Errors inolving failed type inference are assigned other error codes.
//
// Example:
// type T[p any] int
//
// var _ T[int, string]
//
// Example:
// func f[T any]() {}
//
// var x = f
_WrongTypeArgCount
// _CannotInferTypeArgs occurs when type or function type argument inference
// fails to infer all type arguments.
//
// Example:
// func f[T any]() {}
//
// func _() {
// f()
// }
//
// Example:
// type N[P, Q any] struct{}
//
// var _ N[int]
_CannotInferTypeArgs
// _InvalidTypeArg occurs when a type argument does not satisfy its
// corresponding type parameter constraints.
//
// Example:
// type T[P ~int] struct{}
//
// var _ T[string]
_InvalidTypeArg // arguments? InferenceFailed
// _InvalidInstanceCycle occurs when an invalid cycle is detected
// within the instantiation graph.
//
@ -1308,6 +1356,42 @@ const (
// func f[T any]() { f[*T]() }
_InvalidInstanceCycle
// _InvalidUnion occurs when an embedded union or approximation element is
// not valid.
//
// Example:
// type _ interface {
// ~int | interface{ m() }
// }
_InvalidUnion
// _MisplacedConstraintIface occurs when a constraint-type interface is used
// outside of constraint position.
//
// Example:
// type I interface { ~int }
//
// var _ I
_MisplacedConstraintIface
// _InvalidMethodTypeParams occurs when methods have type parameters.
//
// Example:
// type T int
//
// func (T) m[P any]() {}
_InvalidMethodTypeParams
// _MisplacedTypeParam occurs when a type parameter is used in a place where
// it is not permitted.
//
// Example:
// type T[P any] P
//
// Example:
// type T[P any] struct{ *P }
_MisplacedTypeParam
// _Todo is a placeholder for error codes that have not been decided.
// TODO(rFindley) remove this error code after deciding on errors for generics code.
_Todo

View File

@ -171,8 +171,10 @@ func TestErrorCodeStyle(t *testing.T) {
}
}
doc := spec.Doc.Text()
if !strings.HasPrefix(doc, name) {
t.Errorf("doc for %q does not start with identifier", name)
if doc == "" {
t.Errorf("%q is undocumented", name)
} else if !strings.HasPrefix(doc, name) {
t.Errorf("doc for %q does not start with the error code name", name)
}
lowerComment := strings.ToLower(strings.TrimPrefix(doc, name))
for _, bad := range forbiddenInComment {

View File

@ -186,7 +186,7 @@ func (check *Checker) unary(x *operand, e *ast.UnaryExpr) {
return false
}
if elem != nil && !Identical(ch.elem, elem) {
check.invalidOp(x, _Todo, "channels of %s must have the same element type", x)
check.invalidOp(x, _InvalidReceive, "channels of %s must have the same element type", x)
return false
}
elem = ch.elem
@ -1116,7 +1116,7 @@ func (check *Checker) nonGeneric(x *operand) {
}
}
if what != "" {
check.errorf(x.expr, _Todo, "cannot use generic %s %s without instantiation", what, x.expr)
check.errorf(x.expr, _WrongTypeArgCount, "cannot use generic %s %s without instantiation", what, x.expr)
x.mode = invalid
x.typ = Typ[Invalid]
}
@ -1233,7 +1233,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
// Prevent crash if the struct referred to is not yet set up.
// See analogous comment for *Array.
if utyp.fields == nil {
check.error(e, _Todo, "illegal cycle in type declaration")
check.error(e, _InvalidDeclCycle, "illegal cycle in type declaration")
goto Error
}
if len(e.Elts) == 0 {
@ -1472,7 +1472,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
return false
}
if base != nil && !Identical(p.base, base) {
check.invalidOp(x, _Todo, "pointers of %s must have identical base types", x)
check.invalidOp(x, _InvalidIndirection, "pointers of %s must have identical base types", x)
return false
}
base = p.base

View File

@ -118,17 +118,21 @@ func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type,
}
}
if allFailed {
check.errorf(arg, _Todo, "%s %s of %s does not match %s (cannot infer %s)", kind, targ, arg.expr, tpar, typeParamsString(tparams))
check.errorf(arg, _CannotInferTypeArgs, "%s %s of %s does not match %s (cannot infer %s)", kind, targ, arg.expr, tpar, typeParamsString(tparams))
return
}
}
smap := makeSubstMap(tparams, targs)
// TODO(rFindley): pass a positioner here, rather than arg.Pos().
inferred := check.subst(arg.Pos(), tpar, smap, nil)
// _CannotInferTypeArgs indicates a failure of inference, though the actual
// error may be better attributed to a user-provided type argument (hence
// _InvalidTypeArg). We can't differentiate these cases, so fall back on
// the more general _CannotInferTypeArgs.
if inferred != tpar {
check.errorf(arg, _Todo, "%s %s of %s does not match inferred type %s for %s", kind, targ, arg.expr, inferred, tpar)
check.errorf(arg, _CannotInferTypeArgs, "%s %s of %s does not match inferred type %s for %s", kind, targ, arg.expr, inferred, tpar)
} else {
check.errorf(arg, _Todo, "%s %s of %s does not match %s", kind, targ, arg.expr, tpar)
check.errorf(arg, _CannotInferTypeArgs, "%s %s of %s does not match %s", kind, targ, arg.expr, tpar)
}
}
@ -214,7 +218,7 @@ func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type,
// At least one type argument couldn't be inferred.
assert(index >= 0 && targs[index] == nil)
tpar := tparams[index]
check.errorf(posn, _Todo, "cannot infer %s (%v)", tpar.obj.name, tpar.obj.pos)
check.errorf(posn, _CannotInferTypeArgs, "cannot infer %s (%v)", tpar.obj.name, tpar.obj.pos)
return nil
}
@ -383,7 +387,7 @@ func (check *Checker) inferB(tparams []*TypeParam, targs []Type) (types []Type,
if !u.unify(tpar, sbound) {
// TODO(gri) improve error message by providing the type arguments
// which we know already
check.errorf(tpar.obj, _Todo, "%s does not match %s", tpar, sbound)
check.errorf(tpar.obj, _InvalidTypeArg, "%s does not match %s", tpar, sbound)
return nil, 0
}
}

View File

@ -124,7 +124,7 @@ func (check *Checker) validateTArgLen(pos token.Pos, ntparams, ntargs int) bool
if ntargs != ntparams {
// TODO(gri) provide better error message
if check != nil {
check.errorf(atPos(pos), _Todo, "got %d arguments but %d type parameters", ntargs, ntparams)
check.errorf(atPos(pos), _WrongTypeArgCount, "got %d arguments but %d type parameters", ntargs, ntparams)
return false
}
panic(fmt.Sprintf("%v: got %d arguments but %d type parameters", pos, ntargs, ntparams))

View File

@ -181,7 +181,7 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d
if ftyp, _ := f.Type.(*ast.FuncType); ftyp != nil && ftyp.TypeParams != nil {
at = ftyp.TypeParams
}
check.errorf(at, _Todo, "methods cannot have type parameters")
check.errorf(at, _InvalidMethodTypeParams, "methods cannot have type parameters")
}
// use named receiver type if available (for better error messages)

View File

@ -382,7 +382,7 @@ func (check *Checker) collectObjects() {
}
case typeDecl:
if d.spec.TypeParams.NumFields() != 0 && !check.allowVersion(pkg, 1, 18) {
check.softErrorf(d.spec.TypeParams.List[0], _Todo, "type parameters require go1.18 or later")
check.softErrorf(d.spec.TypeParams.List[0], _UnsupportedFeature, "type parameters require go1.18 or later")
}
obj := NewTypeName(d.spec.Name.Pos(), pkg, d.spec.Name.Name, nil)
check.declarePkgObj(d.spec.Name, obj, &declInfo{file: fileScope, tdecl: d.spec})
@ -440,7 +440,7 @@ func (check *Checker) collectObjects() {
check.recordDef(d.decl.Name, obj)
}
if d.decl.Type.TypeParams.NumFields() != 0 && !check.allowVersion(pkg, 1, 18) && !hasTParamError {
check.softErrorf(d.decl.Type.TypeParams.List[0], _Todo, "type parameters require go1.18 or later")
check.softErrorf(d.decl.Type.TypeParams.List[0], _UnsupportedFeature, "type parameters require go1.18 or later")
}
info := &declInfo{file: fileScope, fdecl: d.decl}
// Methods are not package-level objects but we still track them in the
@ -527,7 +527,7 @@ L: // unpack receiver type
case nil:
check.invalidAST(ix.Orig, "parameterized receiver contains nil parameters")
default:
check.errorf(arg, _Todo, "receiver type parameter %s must be an identifier", arg)
check.errorf(arg, _BadDecl, "receiver type parameter %s must be an identifier", arg)
}
if par == nil {
par = &ast.Ident{NamePos: arg.Pos(), Name: "_"}

View File

@ -168,7 +168,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast
// (A separate check is needed when type-checking interface method signatures because
// they don't have a receiver specification.)
if recvPar != nil {
check.errorf(ftyp.TypeParams, _Todo, "methods cannot have type parameters")
check.errorf(ftyp.TypeParams, _InvalidMethodTypeParams, "methods cannot have type parameters")
}
}
@ -215,7 +215,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast
// The receiver type may be an instantiated type referred to
// by an alias (which cannot have receiver parameters for now).
if T.TypeArgs() != nil && sig.RecvTypeParams() == nil {
check.errorf(atPos(recv.pos), _Todo, "cannot define methods on instantiated type %s", recv.typ)
check.errorf(atPos(recv.pos), _InvalidRecv, "cannot define methods on instantiated type %s", recv.typ)
break
}
// spec: "The type denoted by T is called the receiver base type; it must not

View File

@ -429,7 +429,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
return false
}
if elem != nil && !Identical(uch.elem, elem) {
check.invalidOp(inNode(s, s.Arrow), _Todo, "channels of %s must have the same element type", &ch)
check.invalidOp(inNode(s, s.Arrow), _InvalidSend, "channels of %s must have the same element type", &ch)
return false
}
elem = uch.elem

View File

@ -124,9 +124,7 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType) {
pos := f.Type.Pos()
name := embeddedFieldIdent(f.Type)
if name == nil {
// TODO(rFindley): using invalidAST here causes test failures (all
// errors should have codes). Clean this up.
check.errorf(f.Type, _Todo, "invalid AST: embedded field type %s has no name", f.Type)
check.invalidAST(f.Type, "embedded field type %s has no name", f.Type)
name = ast.NewIdent("_")
name.NamePos = pos
addInvalid(name, pos)
@ -158,7 +156,10 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType) {
case *Pointer:
check.error(embeddedPos, _InvalidPtrEmbed, "embedded field type cannot be a pointer")
case *TypeParam:
check.error(embeddedPos, _InvalidPtrEmbed, "embedded field type cannot be a (pointer to a) type parameter")
// This error code here is inconsistent with other error codes for
// invalid embedding, because this restriction may be relaxed in the
// future, and so it did not warrant a new error code.
check.error(embeddedPos, _MisplacedTypeParam, "embedded field type cannot be a (pointer to a) type parameter")
case *Interface:
if isPtr {
check.error(embeddedPos, _InvalidPtrEmbed, "embedded field type cannot be a pointer to an interface")

View File

@ -269,7 +269,7 @@ func computeInterfaceTypeSet(check *Checker, pos token.Pos, ityp *Interface) *_T
tset := computeInterfaceTypeSet(check, pos, u)
// If typ is local, an error was already reported where typ is specified/defined.
if check != nil && check.isImportedConstraint(typ) && !check.allowVersion(check.pkg, 1, 18) {
check.errorf(atPos(pos), _Todo, "embedding constraint interface %s requires go1.18 or later", typ)
check.errorf(atPos(pos), _UnsupportedFeature, "embedding constraint interface %s requires go1.18 or later", typ)
continue
}
if tset.comparable {
@ -281,7 +281,7 @@ func computeInterfaceTypeSet(check *Checker, pos token.Pos, ityp *Interface) *_T
terms = tset.terms
case *Union:
if check != nil && !check.allowVersion(check.pkg, 1, 18) {
check.errorf(atPos(pos), _Todo, "embedding interface element %s requires go1.18 or later", u)
check.errorf(atPos(pos), _InvalidIfaceEmbed, "embedding interface element %s requires go1.18 or later", u)
continue
}
tset := computeUnionTypeSet(check, pos, u)
@ -385,7 +385,7 @@ func computeUnionTypeSet(check *Checker, pos token.Pos, utyp *Union) *_TypeSet {
allTerms = allTerms.union(terms)
if len(allTerms) > maxTermCount {
if check != nil {
check.errorf(atPos(pos), _Todo, "cannot handle more than %d union terms (implementation limitation)", maxTermCount)
check.errorf(atPos(pos), _InvalidUnion, "cannot handle more than %d union terms (implementation limitation)", maxTermCount)
}
utyp.tset = &invalidTypeSet
return utyp.tset

View File

@ -149,9 +149,9 @@ func (check *Checker) varType(e ast.Expr) Type {
tset := computeInterfaceTypeSet(check, e.Pos(), t) // TODO(gri) is this the correct position?
if !tset.IsMethodSet() {
if tset.comparable {
check.softErrorf(e, _Todo, "interface is (or embeds) comparable")
check.softErrorf(e, _MisplacedConstraintIface, "interface is (or embeds) comparable")
} else {
check.softErrorf(e, _Todo, "interface contains type constraints")
check.softErrorf(e, _MisplacedConstraintIface, "interface contains type constraints")
}
}
}
@ -169,7 +169,7 @@ func (check *Checker) definedType(e ast.Expr, def *Named) Type {
typ := check.typInternal(e, def)
assert(isTyped(typ))
if isGeneric(typ) {
check.errorf(e, _Todo, "cannot use generic type %s without instantiation", typ)
check.errorf(e, _WrongTypeArgCount, "cannot use generic type %s without instantiation", typ)
typ = Typ[Invalid]
}
check.recordTypeAndValue(e, typexpr, typ, nil)
@ -261,7 +261,7 @@ func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) {
case *ast.IndexExpr, *ast.IndexListExpr:
ix := typeparams.UnpackIndexExpr(e)
if !check.allowVersion(check.pkg, 1, 18) {
check.softErrorf(inNode(e, ix.Lbrack), _Todo, "type instantiation requires go1.18 or later")
check.softErrorf(inNode(e, ix.Lbrack), _UnsupportedFeature, "type instantiation requires go1.18 or later")
}
return check.instantiatedType(ix.X, ix.Indices, def)
@ -459,7 +459,7 @@ func (check *Checker) instantiatedType(x ast.Expr, targsx []ast.Expr, def *Named
if i < len(posList) {
pos = posList[i]
}
check.softErrorf(atPos(pos), _Todo, err.Error())
check.softErrorf(atPos(pos), _InvalidTypeArg, err.Error())
} else {
check.mono.recordInstance(check.pkg, x.Pos(), inst.tparams.list(), inst.targs.list(), posList)
}

View File

@ -63,7 +63,7 @@ func parseUnion(check *Checker, tlist []ast.Expr) Type {
return typ
}
if len(terms) >= maxTermCount {
check.errorf(x, _Todo, "cannot handle more than %d union terms (implementation limitation)", maxTermCount)
check.errorf(x, _InvalidUnion, "cannot handle more than %d union terms (implementation limitation)", maxTermCount)
return Typ[Invalid]
}
terms = append(terms, NewTerm(tilde, typ))
@ -82,12 +82,12 @@ func parseUnion(check *Checker, tlist []ast.Expr) Type {
f, _ := u.(*Interface)
if t.tilde {
if f != nil {
check.errorf(tlist[i], _Todo, "invalid use of ~ (%s is an interface)", t.typ)
check.errorf(tlist[i], _InvalidUnion, "invalid use of ~ (%s is an interface)", t.typ)
continue // don't report another error for t
}
if !Identical(u, t.typ) {
check.errorf(tlist[i], _Todo, "invalid use of ~ (underlying type of %s is %s)", t.typ, u)
check.errorf(tlist[i], _InvalidUnion, "invalid use of ~ (underlying type of %s is %s)", t.typ, u)
continue // don't report another error for t
}
}
@ -96,14 +96,14 @@ func parseUnion(check *Checker, tlist []ast.Expr) Type {
// in the beginning. Embedded interfaces with tilde are excluded above. If we reach
// here, we must have at least two terms in the union.
if f != nil && !f.typeSet().IsTypeSet() {
check.errorf(tlist[i], _Todo, "cannot use %s in union (interface contains methods)", t)
check.errorf(tlist[i], _InvalidUnion, "cannot use %s in union (interface contains methods)", t)
continue // don't report another error for t
}
// Report overlapping (non-disjoint) terms such as
// a|a, a|~a, ~a|~a, and ~a|A (where under(A) == a).
if j := overlappingTerm(terms[:i], t); j >= 0 {
check.softErrorf(tlist[i], _Todo, "overlapping terms %s and %s", t, terms[j])
check.softErrorf(tlist[i], _InvalidUnion, "overlapping terms %s and %s", t, terms[j])
}
}
})
@ -124,7 +124,7 @@ func parseTilde(check *Checker, x ast.Expr) (tilde bool, typ Type) {
// check to later and could return Typ[Invalid] instead.
check.later(func() {
if _, ok := under(typ).(*TypeParam); ok {
check.error(x, _Todo, "cannot embed a type parameter")
check.error(x, _MisplacedTypeParam, "cannot embed a type parameter")
}
})
return