Skip to content

Commit c78a267

Browse files
committed
go/types: return an error from Instantiate on incorrect len(targs)
Instantiate already returns an error when validation fails. Panicking on an incorrect number of type arguments means that callers must both pre-validate the number of type arguments and handle resulting errors. Returning an error rather than panicking allows eliminating pre-validation at the call-site. Also update the Instantiate docstring to correct some stale/inaccurate information, and to clarify its behavior more precisely. Updates #47916 Change-Id: I997ef30b3486760a90b0db4c3ea7111280d74a81 Reviewed-on: https://go-review.googlesource.com/c/go/+/363635 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 e658c42 commit c78a267

File tree

1 file changed

+30
-20
lines changed

1 file changed

+30
-20
lines changed

Diff for: src/go/types/instantiate.go

+30-20
Original file line numberDiff line numberDiff line change
@@ -13,40 +13,50 @@ import (
1313
"go/token"
1414
)
1515

16-
// Instantiate instantiates the type typ with the given type arguments targs.
17-
// typ must be a *Named or a *Signature type, and its number of type parameters
18-
// must match the number of provided type arguments. The result is a new,
19-
// instantiated (not parameterized) type of the same kind (either a *Named or a
20-
// *Signature). Any methods attached to a *Named are simply copied; they are
21-
// not instantiated.
16+
// Instantiate instantiates the type orig with the given type arguments targs.
17+
// orig must be a *Named or a *Signature type. If there is no error, the
18+
// resulting Type is a new, instantiated (not parameterized) type of the same
19+
// kind (either a *Named or a *Signature). Methods attached to a *Named type
20+
// are also instantiated, and associated with a new *Func that has the same
21+
// position as the original method, but nil function scope.
2222
//
23-
// If ctxt is non-nil, it may be used to de-dupe the instance against previous
24-
// instances with the same identity.
23+
// If ctxt is non-nil, it may be used to de-duplicate the instance against
24+
// previous instances with the same identity. As a special case, generic
25+
// *Signature origin types are only considered identical if they are pointer
26+
// equivalent, so that instantiating distinct (but possibly identical)
27+
// signatures will yield different instances.
2528
//
26-
// If verify is set and constraint satisfaction fails, the returned error may
27-
// wrap an *ArgumentError indicating which type argument did not satisfy its
28-
// corresponding type parameter constraint, and why.
29+
// If validate is set, Instantiate verifies that the number of type arguments
30+
// and parameters match, and that the type arguments satisfy their
31+
// corresponding type constraints. If verification fails, the resulting error
32+
// may wrap an *ArgumentError indicating which type argument did not satisfy
33+
// its corresponding type parameter constraint, and why.
2934
//
30-
// TODO(rfindley): change this function to also return an error if lengths of
31-
// tparams and targs do not match.
32-
func Instantiate(ctxt *Context, typ Type, targs []Type, validate bool) (Type, error) {
33-
inst := (*Checker)(nil).instance(token.NoPos, typ, targs, ctxt)
34-
35-
var err error
35+
// If validate is not set, Instantiate does not verify the type argument count
36+
// or whether the type arguments satisfy their constraints. Instantiate is
37+
// guaranteed to not return an error, but may panic. Specifically, for
38+
// *Signature types, Instantiate will panic immediately if the type argument
39+
// count is incorrect; for *Named types, a panic may occur later inside the
40+
// *Named API.
41+
func Instantiate(ctxt *Context, orig Type, targs []Type, validate bool) (Type, error) {
3642
if validate {
3743
var tparams []*TypeParam
38-
switch t := typ.(type) {
44+
switch t := orig.(type) {
3945
case *Named:
4046
tparams = t.TypeParams().list()
4147
case *Signature:
4248
tparams = t.TypeParams().list()
4349
}
50+
if len(targs) != len(tparams) {
51+
return nil, fmt.Errorf("got %d type arguments but %s has %d type parameters", len(targs), orig, len(tparams))
52+
}
4453
if i, err := (*Checker)(nil).verify(token.NoPos, tparams, targs); err != nil {
45-
return inst, &ArgumentError{i, err}
54+
return nil, &ArgumentError{i, err}
4655
}
4756
}
4857

49-
return inst, err
58+
inst := (*Checker)(nil).instance(token.NoPos, orig, targs, ctxt)
59+
return inst, nil
5060
}
5161

5262
// instance creates a type or function instance using the given original type

0 commit comments

Comments
 (0)