]> Cypherpunks repositories - gostls13.git/commitdiff
go/types: clean up panics in instantiation
authorRobert Findley <rfindley@google.com>
Mon, 16 Aug 2021 19:59:08 +0000 (15:59 -0400)
committerRobert Findley <rfindley@google.com>
Fri, 20 Aug 2021 18:44:58 +0000 (18:44 +0000)
This is a straightforward port of CL 341862 to go/types.

Change-Id: I4214c08d2889e2daf40254385656c6beed79571d
Reviewed-on: https://go-review.googlesource.com/c/go/+/342487
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
Reviewed-by: Robert Griesemer <gri@golang.org>
src/go/types/instantiate.go
src/go/types/named.go

index 81330672298c28fb1b6591a25d3a95928f57d7c3..37184cb0ab09877098edebb85bec04a2c7ef86fc 100644 (file)
@@ -53,15 +53,18 @@ func (check *Checker) Instantiate(pos token.Pos, typ Type, targs []Type, posList
                // only types and functions can be generic
                panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ))
        }
+       inst := check.instantiate(pos, typ, tparams, targs, nil)
 
-       inst := check.instantiate(pos, typ, tparams, targs, posList, nil)
-       if verify && len(tparams) == len(targs) {
-               check.verify(pos, tparams, targs, posList)
+       if verify {
+               assert(len(posList) <= len(targs))
+               if len(tparams) == len(targs) {
+                       check.verify(pos, tparams, targs, posList)
+               }
        }
        return inst
 }
 
-func (check *Checker) instantiate(pos token.Pos, typ Type, tparams []*TypeName, targs []Type, posList []token.Pos, typMap map[string]*Named) (res Type) {
+func (check *Checker) instantiate(pos token.Pos, typ Type, tparams []*TypeName, targs []Type, typMap map[string]*Named) (res Type) {
        // the number of supplied types must match the number of type parameters
        if len(targs) != len(tparams) {
                // TODO(gri) provide better error message
@@ -88,8 +91,6 @@ func (check *Checker) instantiate(pos token.Pos, typ Type, tparams []*TypeName,
                }()
        }
 
-       assert(len(posList) <= len(targs))
-
        // TODO(gri) What is better here: work with TypeParams, or work with TypeNames?
 
        if len(tparams) == 0 {
@@ -101,14 +102,21 @@ func (check *Checker) instantiate(pos token.Pos, typ Type, tparams []*TypeName,
 
 // instantiateLazy avoids actually instantiating the type until needed. typ
 // must be a *Named type.
-func (check *Checker) instantiateLazy(pos token.Pos, base *Named, targs []Type, posList []token.Pos, verify bool) Type {
-       if verify && base.TParams().Len() == len(targs) {
-               // TODO: lift the nil check in verify to here.
-               check.later(func() {
-                       check.verify(pos, base.tparams.list(), targs, posList)
-               })
-       }
-       h := instantiatedHash(base, targs)
+func (check *Checker) instantiateLazy(pos token.Pos, orig *Named, targs []Type, posList []token.Pos, verify bool) Type {
+       if verify {
+               if check == nil {
+                       // Provide a more useful panic instead of panicking at check.later below.
+                       panic("cannot have nil Checker if verifying constraints")
+               }
+               assert(len(posList) <= len(targs))
+               if orig.TParams().Len() == len(targs) {
+                       check.later(func() {
+                               check.verify(pos, orig.tparams.list(), targs, posList)
+                       })
+               }
+       }
+
+       h := instantiatedHash(orig, targs)
        if check != nil {
                // typ may already have been instantiated with identical type arguments. In
                // that case, re-use the existing instance.
@@ -117,10 +125,10 @@ func (check *Checker) instantiateLazy(pos token.Pos, base *Named, targs []Type,
                }
        }
 
-       tname := NewTypeName(pos, base.obj.pkg, base.obj.name, nil)
-       named := check.newNamed(tname, base, nil, nil, nil) // methods and tparams are set when named is loaded.
+       tname := NewTypeName(pos, orig.obj.pkg, orig.obj.name, nil)
+       named := check.newNamed(tname, orig, nil, nil, nil) // methods and tparams are set when named is loaded
        named.targs = targs
-       named.instance = &instance{pos, posList}
+       named.instance = &instance{pos}
 
        if check != nil {
                check.typMap[h] = named
@@ -133,7 +141,6 @@ func (check *Checker) verify(pos token.Pos, tparams []*TypeName, targs []Type, p
        if check == nil {
                panic("cannot have nil Checker if verifying constraints")
        }
-
        smap := makeSubstMap(tparams, targs)
        for i, tname := range tparams {
                // best position for error reporting
index 90abd117e28914e7ea109cf91151c163520def9b..d621e5ef21b17f8808aff4930cd1eba157a2d3d6 100644 (file)
@@ -248,11 +248,10 @@ func (n *Named) setUnderlying(typ Type) {
 
 // instance holds position information for use in lazy instantiation.
 //
-// TODO(rfindley): come up with a better name for this type, now that its usage
-// has changed.
+// TODO(rfindley): instance is probably unnecessary now. See if it can be
+// eliminated.
 type instance struct {
-       pos     token.Pos   // position of type instantiation; for error reporting only
-       posList []token.Pos // position of each targ; for error reporting only
+       pos token.Pos // position of type instantiation; for error reporting only
 }
 
 // expand ensures that the underlying type of n is instantiated.
@@ -276,7 +275,7 @@ func (n *Named) expand(typMap map[string]*Named) *Named {
                        }
                }
 
-               inst := n.check.instantiate(n.instance.pos, n.orig.underlying, n.TParams().list(), n.targs, n.instance.posList, typMap)
+               inst := n.check.instantiate(n.instance.pos, n.orig.underlying, n.TParams().list(), n.targs, typMap)
                n.underlying = inst
                n.fromRHS = inst
                n.instance = nil