]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile/internal/types2: return an error from Instantiate on incorrect len(targs)
authorRobert Griesemer <gri@golang.org>
Tue, 16 Nov 2021 20:20:11 +0000 (12:20 -0800)
committerRobert Griesemer <gri@golang.org>
Wed, 17 Nov 2021 04:32:05 +0000 (04:32 +0000)
This CL is a clean port of CL 363635 from go/types to types2.

Updates #47916

Change-Id: Ib46758435c31ad9a6a4a63f552503d5afa66b5c0
Reviewed-on: https://go-review.googlesource.com/c/go/+/364534
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
src/cmd/compile/internal/types2/instantiate.go

index 35fcc7c0407532b9deeda34294d6e61dee0b6239..3f5fc56f5d20f843385cd9e4f2a61f40c7b8bfdd 100644 (file)
@@ -13,40 +13,50 @@ import (
        "fmt"
 )
 
-// Instantiate instantiates the type typ with the given type arguments targs.
-// typ must be a *Named or a *Signature type, and its number of type parameters
-// must match the number of provided type arguments. The result is a new,
-// instantiated (not parameterized) type of the same kind (either a *Named or a
-// *Signature). Any methods attached to a *Named are simply copied; they are
-// not instantiated.
+// Instantiate instantiates the type orig with the given type arguments targs.
+// orig must be a *Named or a *Signature type. If there is no error, the
+// resulting Type is a new, instantiated (not parameterized) type of the same
+// kind (either a *Named or a *Signature). Methods attached to a *Named type
+// are also instantiated, and associated with a new *Func that has the same
+// position as the original method, but nil function scope.
 //
-// If ctxt is non-nil, it may be used to de-dupe the instance against previous
-// instances with the same identity.
+// If ctxt is non-nil, it may be used to de-duplicate the instance against
+// previous instances with the same identity. As a special case, generic
+// *Signature origin types are only considered identical if they are pointer
+// equivalent, so that instantiating distinct (but possibly identical)
+// signatures will yield different instances.
 //
-// If verify is set and constraint satisfaction fails, the returned error may
-// wrap an *ArgumentError indicating which type argument did not satisfy its
-// corresponding type parameter constraint, and why.
+// If validate is set, Instantiate verifies that the number of type arguments
+// and parameters match, and that the type arguments satisfy their
+// corresponding type constraints. If verification fails, the resulting error
+// may wrap an *ArgumentError indicating which type argument did not satisfy
+// its corresponding type parameter constraint, and why.
 //
-// TODO(rfindley): change this function to also return an error if lengths of
-// tparams and targs do not match.
-func Instantiate(ctxt *Context, typ Type, targs []Type, validate bool) (Type, error) {
-       inst := (*Checker)(nil).instance(nopos, typ, targs, ctxt)
-
-       var err error
+// If validate is not set, Instantiate does not verify the type argument count
+// or whether the type arguments satisfy their constraints. Instantiate is
+// guaranteed to not return an error, but may panic. Specifically, for
+// *Signature types, Instantiate will panic immediately if the type argument
+// count is incorrect; for *Named types, a panic may occur later inside the
+// *Named API.
+func Instantiate(ctxt *Context, orig Type, targs []Type, validate bool) (Type, error) {
        if validate {
                var tparams []*TypeParam
-               switch t := typ.(type) {
+               switch t := orig.(type) {
                case *Named:
                        tparams = t.TypeParams().list()
                case *Signature:
                        tparams = t.TypeParams().list()
                }
+               if len(targs) != len(tparams) {
+                       return nil, fmt.Errorf("got %d type arguments but %s has %d type parameters", len(targs), orig, len(tparams))
+               }
                if i, err := (*Checker)(nil).verify(nopos, tparams, targs); err != nil {
-                       return inst, &ArgumentError{i, err}
+                       return nil, &ArgumentError{i, err}
                }
        }
 
-       return inst, err
+       inst := (*Checker)(nil).instance(nopos, orig, targs, ctxt)
+       return inst, nil
 }
 
 // instance creates a type or function instance using the given original type