]> Cypherpunks repositories - gostls13.git/commitdiff
go/types: consolidate verification logic
authorRobert Findley <rfindley@google.com>
Mon, 16 Aug 2021 20:01:42 +0000 (16:01 -0400)
committerRobert Findley <rfindley@google.com>
Fri, 20 Aug 2021 18:45:05 +0000 (18:45 +0000)
This is a straightforward port of CL 342149 to go/types.

Change-Id: I468c5154b7545b7816bb3f240b8db91e7a1fd3f6
Reviewed-on: https://go-review.googlesource.com/c/go/+/342488
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>
src/go/types/instantiate.go
src/go/types/typexpr.go

index 37184cb0ab09877098edebb85bec04a2c7ef86fc..eeb9b03050f93f06f2403091dedf64a35a094786 100644 (file)
@@ -25,12 +25,12 @@ import (
 // Any methods attached to a *Named are simply copied; they are not
 // instantiated.
 func (check *Checker) Instantiate(pos token.Pos, typ Type, targs []Type, posList []token.Pos, verify bool) (res Type) {
-       var tparams []*TypeName
+       var inst Type
        switch t := typ.(type) {
        case *Named:
-               return check.instantiateLazy(pos, t, targs, posList, verify)
+               inst = check.instantiateLazy(pos, t, targs)
        case *Signature:
-               tparams = t.TParams().list()
+               tparams := t.TParams().list()
                defer func() {
                        // If we had an unexpected failure somewhere don't panic below when
                        // asserting res.(*Signature). Check for *Signature in case Typ[Invalid]
@@ -49,18 +49,35 @@ func (check *Checker) Instantiate(pos token.Pos, typ Type, targs []Type, posList
                        // anymore; we need to set tparams to nil.
                        res.(*Signature).tparams = nil
                }()
+               inst = check.instantiate(pos, typ, tparams, targs, nil)
        default:
                // only types and functions can be generic
                panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ))
        }
-       inst := check.instantiate(pos, typ, tparams, targs, nil)
 
        if verify {
-               assert(len(posList) <= len(targs))
-               if len(tparams) == len(targs) {
-                       check.verify(pos, tparams, targs, posList)
+               if check == nil {
+                       panic("cannot have nil Checker if verifying constraints")
                }
+               assert(len(posList) <= len(targs))
+               check.later(func() {
+                       // Collect tparams again because lazily loaded *Named types may not have
+                       // had tparams set up above.
+                       var tparams []*TypeName
+                       switch t := typ.(type) {
+                       case *Named:
+                               tparams = t.TParams().list()
+                       case *Signature:
+                               tparams = t.TParams().list()
+                       }
+                       // Avoid duplicate errors; instantiate will have complained if tparams
+                       // and targs do not have the same length.
+                       if len(tparams) == len(targs) {
+                               check.verify(pos, tparams, targs, posList)
+                       }
+               })
        }
+
        return inst
 }
 
@@ -102,20 +119,7 @@ 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, 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)
-                       })
-               }
-       }
-
+func (check *Checker) instantiateLazy(pos token.Pos, orig *Named, targs []Type) Type {
        h := instantiatedHash(orig, targs)
        if check != nil {
                // typ may already have been instantiated with identical type arguments. In
@@ -138,9 +142,6 @@ func (check *Checker) instantiateLazy(pos token.Pos, orig *Named, targs []Type,
 }
 
 func (check *Checker) verify(pos token.Pos, tparams []*TypeName, targs []Type, posList []token.Pos) {
-       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 8af6570072fcc0f3872d99afdd5b6e1f193de2c3..def5871ce76a321db121f3bf1cb6eb8f467aa1dc 100644 (file)
@@ -433,7 +433,7 @@ func (check *Checker) instantiatedType(x ast.Expr, targsx []ast.Expr, def *Named
                posList[i] = arg.Pos()
        }
 
-       typ := check.instantiateLazy(x.Pos(), base, targs, posList, true)
+       typ := check.Instantiate(x.Pos(), base, targs, posList, true)
        def.setUnderlying(typ)
 
        // make sure we check instantiation works at least once