Skip to content

Commit 0e65410

Browse files
committed
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 <[email protected]> Run-TryBot: Robert Findley <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Robert Griesemer <[email protected]>
1 parent 1dc9af5 commit 0e65410

17 files changed

Lines changed: 142 additions & 51 deletions

src/go/types/assignments.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ func (check *Checker) assignment(x *operand, T Type, context string) {
7272

7373
// A generic (non-instantiated) function value cannot be assigned to a variable.
7474
if sig, _ := under(x.typ).(*Signature); sig != nil && sig.TypeParams().Len() > 0 {
75-
check.errorf(x, _Todo, "cannot use generic function %s without instantiation in %s", x, context)
75+
check.errorf(x, _WrongTypeArgCount, "cannot use generic function %s without instantiation in %s", x, context)
7676
}
7777

7878
// spec: "If a left-hand side is the blank identifier, any typed or

src/go/types/builtins.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
370370
return false
371371
}
372372
if key != nil && !Identical(map_.key, key) {
373-
check.invalidArg(x, _Todo, "maps of %s must have identical key types", x)
373+
check.invalidArg(x, _InvalidDelete, "maps of %s must have identical key types", x)
374374
return false
375375
}
376376
key = map_.key

src/go/types/call.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import (
1818
// The operand x must be the evaluation of inst.X and its type must be a signature.
1919
func (check *Checker) funcInst(x *operand, ix *typeparams.IndexExpr) {
2020
if !check.allowVersion(check.pkg, 1, 18) {
21-
check.softErrorf(inNode(ix.Orig, ix.Lbrack), _Todo, "function instantiation requires go1.18 or later")
21+
check.softErrorf(inNode(ix.Orig, ix.Lbrack), _UnsupportedFeature, "function instantiation requires go1.18 or later")
2222
}
2323

2424
targs := check.typeList(ix.Indices)
@@ -33,7 +33,7 @@ func (check *Checker) funcInst(x *operand, ix *typeparams.IndexExpr) {
3333
sig := x.typ.(*Signature)
3434
got, want := len(targs), sig.TypeParams().Len()
3535
if got > want {
36-
check.errorf(ix.Indices[got-1], _Todo, "got %d type arguments but want %d", got, want)
36+
check.errorf(ix.Indices[got-1], _WrongTypeArgCount, "got %d type arguments but want %d", got, want)
3737
x.mode = invalid
3838
x.expr = ix.Orig
3939
return
@@ -90,7 +90,7 @@ func (check *Checker) instantiateSignature(pos token.Pos, typ *Signature, targs
9090
if i < len(posList) {
9191
pos = posList[i]
9292
}
93-
check.softErrorf(atPos(pos), _Todo, err.Error())
93+
check.softErrorf(atPos(pos), _InvalidTypeArg, err.Error())
9494
} else {
9595
check.mono.recordInstance(check.pkg, pos, tparams, targs, posList)
9696
}
@@ -143,7 +143,7 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind {
143143
}
144144
if t, _ := under(T).(*Interface); t != nil {
145145
if !t.IsMethodSet() {
146-
check.errorf(call, _Todo, "cannot use interface %s in conversion (contains specific type constraints or is comparable)", T)
146+
check.errorf(call, _MisplacedConstraintIface, "cannot use interface %s in conversion (contains specific type constraints or is comparable)", T)
147147
break
148148
}
149149
}
@@ -198,7 +198,7 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind {
198198
// check number of type arguments (got) vs number of type parameters (want)
199199
got, want := len(targs), sig.TypeParams().Len()
200200
if got > want {
201-
check.errorf(ix.Indices[want], _Todo, "got %d type arguments but want %d", got, want)
201+
check.errorf(ix.Indices[want], _WrongTypeArgCount, "got %d type arguments but want %d", got, want)
202202
check.use(call.Args...)
203203
x.mode = invalid
204204
x.expr = call
@@ -370,9 +370,9 @@ func (check *Checker) arguments(call *ast.CallExpr, sig *Signature, targs []Type
370370
switch call.Fun.(type) {
371371
case *ast.IndexExpr, *ast.IndexListExpr:
372372
ix := typeparams.UnpackIndexExpr(call.Fun)
373-
check.softErrorf(inNode(call.Fun, ix.Lbrack), _Todo, "function instantiation requires go1.18 or later")
373+
check.softErrorf(inNode(call.Fun, ix.Lbrack), _UnsupportedFeature, "function instantiation requires go1.18 or later")
374374
default:
375-
check.softErrorf(inNode(call, call.Lparen), _Todo, "implicit function instantiation requires go1.18 or later")
375+
check.softErrorf(inNode(call, call.Lparen), _UnsupportedFeature, "implicit function instantiation requires go1.18 or later")
376376
}
377377
}
378378
// TODO(gri) provide position information for targs so we can feed

src/go/types/decl.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -623,15 +623,15 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) {
623623
check.validType(obj.typ, nil)
624624
// If typ is local, an error was already reported where typ is specified/defined.
625625
if check.isImportedConstraint(rhs) && !check.allowVersion(check.pkg, 1, 18) {
626-
check.errorf(tdecl.Type, _Todo, "using type constraint %s requires go1.18 or later", rhs)
626+
check.errorf(tdecl.Type, _UnsupportedFeature, "using type constraint %s requires go1.18 or later", rhs)
627627
}
628628
}).describef(obj, "validType(%s)", obj.Name())
629629

630630
alias := tdecl.Assign.IsValid()
631631
if alias && tdecl.TypeParams.NumFields() != 0 {
632632
// The parser will ensure this but we may still get an invalid AST.
633633
// Complain and continue as regular type definition.
634-
check.error(atPos(tdecl.Assign), _Todo, "generic type cannot be alias")
634+
check.error(atPos(tdecl.Assign), _BadDecl, "generic type cannot be alias")
635635
alias = false
636636
}
637637

@@ -673,7 +673,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) {
673673
// type (underlying not fully resolved yet) it cannot become a type parameter due
674674
// to this very restriction.
675675
if tpar, _ := named.underlying.(*TypeParam); tpar != nil {
676-
check.error(tdecl.Type, _Todo, "cannot use a type parameter as RHS in type declaration")
676+
check.error(tdecl.Type, _MisplacedTypeParam, "cannot use a type parameter as RHS in type declaration")
677677
named.underlying = Typ[Invalid]
678678
}
679679
}
@@ -724,7 +724,7 @@ func (check *Checker) collectTypeParams(dst **TypeParamList, list *ast.FieldList
724724
check.later(func() {
725725
for i, bound := range bounds {
726726
if _, ok := under(bound).(*TypeParam); ok {
727-
check.error(posns[i], _Todo, "cannot use a type parameter as constraint")
727+
check.error(posns[i], _MisplacedTypeParam, "cannot use a type parameter as constraint")
728728
}
729729
}
730730
for _, tpar := range tparams {
@@ -861,7 +861,7 @@ func (check *Checker) funcDecl(obj *Func, decl *declInfo) {
861861
obj.color_ = saved
862862

863863
if fdecl.Type.TypeParams.NumFields() > 0 && fdecl.Body == nil {
864-
check.softErrorf(fdecl.Name, _Todo, "parameterized function is missing function body")
864+
check.softErrorf(fdecl.Name, _BadDecl, "parameterized function is missing function body")
865865
}
866866

867867
// function body must be type-checked after global declarations

src/go/types/errorcodes.go

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1301,13 +1301,97 @@ const (
13011301
// var _ = unsafe.Slice(&x, uint64(1) << 63)
13021302
_InvalidUnsafeSlice
13031303

1304+
// All codes below were added in Go 1.18.
1305+
1306+
// _UnsupportedFeature occurs when a language feature is used that is not
1307+
// supported at this Go version.
1308+
_UnsupportedFeature
1309+
1310+
// _WrongTypeArgCount occurs when a type or function is instantiated with an
1311+
// incorrent number of type arguments, including when a generic type or
1312+
// function is used without instantiation.
1313+
//
1314+
// Errors inolving failed type inference are assigned other error codes.
1315+
//
1316+
// Example:
1317+
// type T[p any] int
1318+
//
1319+
// var _ T[int, string]
1320+
//
1321+
// Example:
1322+
// func f[T any]() {}
1323+
//
1324+
// var x = f
1325+
_WrongTypeArgCount
1326+
1327+
// _CannotInferTypeArgs occurs when type or function type argument inference
1328+
// fails to infer all type arguments.
1329+
//
1330+
// Example:
1331+
// func f[T any]() {}
1332+
//
1333+
// func _() {
1334+
// f()
1335+
// }
1336+
//
1337+
// Example:
1338+
// type N[P, Q any] struct{}
1339+
//
1340+
// var _ N[int]
1341+
_CannotInferTypeArgs
1342+
1343+
// _InvalidTypeArg occurs when a type argument does not satisfy its
1344+
// corresponding type parameter constraints.
1345+
//
1346+
// Example:
1347+
// type T[P ~int] struct{}
1348+
//
1349+
// var _ T[string]
1350+
_InvalidTypeArg // arguments? InferenceFailed
1351+
13041352
// _InvalidInstanceCycle occurs when an invalid cycle is detected
13051353
// within the instantiation graph.
13061354
//
13071355
// Example:
13081356
// func f[T any]() { f[*T]() }
13091357
_InvalidInstanceCycle
13101358

1359+
// _InvalidUnion occurs when an embedded union or approximation element is
1360+
// not valid.
1361+
//
1362+
// Example:
1363+
// type _ interface {
1364+
// ~int | interface{ m() }
1365+
// }
1366+
_InvalidUnion
1367+
1368+
// _MisplacedConstraintIface occurs when a constraint-type interface is used
1369+
// outside of constraint position.
1370+
//
1371+
// Example:
1372+
// type I interface { ~int }
1373+
//
1374+
// var _ I
1375+
_MisplacedConstraintIface
1376+
1377+
// _InvalidMethodTypeParams occurs when methods have type parameters.
1378+
//
1379+
// Example:
1380+
// type T int
1381+
//
1382+
// func (T) m[P any]() {}
1383+
_InvalidMethodTypeParams
1384+
1385+
// _MisplacedTypeParam occurs when a type parameter is used in a place where
1386+
// it is not permitted.
1387+
//
1388+
// Example:
1389+
// type T[P any] P
1390+
//
1391+
// Example:
1392+
// type T[P any] struct{ *P }
1393+
_MisplacedTypeParam
1394+
13111395
// _Todo is a placeholder for error codes that have not been decided.
13121396
// TODO(rFindley) remove this error code after deciding on errors for generics code.
13131397
_Todo

src/go/types/errorcodes_test.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,10 @@ func TestErrorCodeStyle(t *testing.T) {
171171
}
172172
}
173173
doc := spec.Doc.Text()
174-
if !strings.HasPrefix(doc, name) {
175-
t.Errorf("doc for %q does not start with identifier", name)
174+
if doc == "" {
175+
t.Errorf("%q is undocumented", name)
176+
} else if !strings.HasPrefix(doc, name) {
177+
t.Errorf("doc for %q does not start with the error code name", name)
176178
}
177179
lowerComment := strings.ToLower(strings.TrimPrefix(doc, name))
178180
for _, bad := range forbiddenInComment {

src/go/types/expr.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ func (check *Checker) unary(x *operand, e *ast.UnaryExpr) {
186186
return false
187187
}
188188
if elem != nil && !Identical(ch.elem, elem) {
189-
check.invalidOp(x, _Todo, "channels of %s must have the same element type", x)
189+
check.invalidOp(x, _InvalidReceive, "channels of %s must have the same element type", x)
190190
return false
191191
}
192192
elem = ch.elem
@@ -1116,7 +1116,7 @@ func (check *Checker) nonGeneric(x *operand) {
11161116
}
11171117
}
11181118
if what != "" {
1119-
check.errorf(x.expr, _Todo, "cannot use generic %s %s without instantiation", what, x.expr)
1119+
check.errorf(x.expr, _WrongTypeArgCount, "cannot use generic %s %s without instantiation", what, x.expr)
11201120
x.mode = invalid
11211121
x.typ = Typ[Invalid]
11221122
}
@@ -1233,7 +1233,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
12331233
// Prevent crash if the struct referred to is not yet set up.
12341234
// See analogous comment for *Array.
12351235
if utyp.fields == nil {
1236-
check.error(e, _Todo, "illegal cycle in type declaration")
1236+
check.error(e, _InvalidDeclCycle, "illegal cycle in type declaration")
12371237
goto Error
12381238
}
12391239
if len(e.Elts) == 0 {
@@ -1472,7 +1472,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
14721472
return false
14731473
}
14741474
if base != nil && !Identical(p.base, base) {
1475-
check.invalidOp(x, _Todo, "pointers of %s must have identical base types", x)
1475+
check.invalidOp(x, _InvalidIndirection, "pointers of %s must have identical base types", x)
14761476
return false
14771477
}
14781478
base = p.base

src/go/types/infer.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -118,17 +118,21 @@ func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type,
118118
}
119119
}
120120
if allFailed {
121-
check.errorf(arg, _Todo, "%s %s of %s does not match %s (cannot infer %s)", kind, targ, arg.expr, tpar, typeParamsString(tparams))
121+
check.errorf(arg, _CannotInferTypeArgs, "%s %s of %s does not match %s (cannot infer %s)", kind, targ, arg.expr, tpar, typeParamsString(tparams))
122122
return
123123
}
124124
}
125125
smap := makeSubstMap(tparams, targs)
126126
// TODO(rFindley): pass a positioner here, rather than arg.Pos().
127127
inferred := check.subst(arg.Pos(), tpar, smap, nil)
128+
// _CannotInferTypeArgs indicates a failure of inference, though the actual
129+
// error may be better attributed to a user-provided type argument (hence
130+
// _InvalidTypeArg). We can't differentiate these cases, so fall back on
131+
// the more general _CannotInferTypeArgs.
128132
if inferred != tpar {
129-
check.errorf(arg, _Todo, "%s %s of %s does not match inferred type %s for %s", kind, targ, arg.expr, inferred, tpar)
133+
check.errorf(arg, _CannotInferTypeArgs, "%s %s of %s does not match inferred type %s for %s", kind, targ, arg.expr, inferred, tpar)
130134
} else {
131-
check.errorf(arg, _Todo, "%s %s of %s does not match %s", kind, targ, arg.expr, tpar)
135+
check.errorf(arg, _CannotInferTypeArgs, "%s %s of %s does not match %s", kind, targ, arg.expr, tpar)
132136
}
133137
}
134138

@@ -214,7 +218,7 @@ func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type,
214218
// At least one type argument couldn't be inferred.
215219
assert(index >= 0 && targs[index] == nil)
216220
tpar := tparams[index]
217-
check.errorf(posn, _Todo, "cannot infer %s (%v)", tpar.obj.name, tpar.obj.pos)
221+
check.errorf(posn, _CannotInferTypeArgs, "cannot infer %s (%v)", tpar.obj.name, tpar.obj.pos)
218222
return nil
219223
}
220224

@@ -383,7 +387,7 @@ func (check *Checker) inferB(tparams []*TypeParam, targs []Type) (types []Type,
383387
if !u.unify(tpar, sbound) {
384388
// TODO(gri) improve error message by providing the type arguments
385389
// which we know already
386-
check.errorf(tpar.obj, _Todo, "%s does not match %s", tpar, sbound)
390+
check.errorf(tpar.obj, _InvalidTypeArg, "%s does not match %s", tpar, sbound)
387391
return nil, 0
388392
}
389393
}

src/go/types/instantiate.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ func (check *Checker) validateTArgLen(pos token.Pos, ntparams, ntargs int) bool
124124
if ntargs != ntparams {
125125
// TODO(gri) provide better error message
126126
if check != nil {
127-
check.errorf(atPos(pos), _Todo, "got %d arguments but %d type parameters", ntargs, ntparams)
127+
check.errorf(atPos(pos), _WrongTypeArgCount, "got %d arguments but %d type parameters", ntargs, ntparams)
128128
return false
129129
}
130130
panic(fmt.Sprintf("%v: got %d arguments but %d type parameters", pos, ntargs, ntparams))

src/go/types/interface.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d
181181
if ftyp, _ := f.Type.(*ast.FuncType); ftyp != nil && ftyp.TypeParams != nil {
182182
at = ftyp.TypeParams
183183
}
184-
check.errorf(at, _Todo, "methods cannot have type parameters")
184+
check.errorf(at, _InvalidMethodTypeParams, "methods cannot have type parameters")
185185
}
186186

187187
// use named receiver type if available (for better error messages)

0 commit comments

Comments
 (0)