]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.typeparams] cmd/compile/internal/types2: trigger verification while resolving...
authorRobert Griesemer <gri@golang.org>
Wed, 28 Jul 2021 20:50:09 +0000 (13:50 -0700)
committerRobert Griesemer <gri@golang.org>
Thu, 29 Jul 2021 19:45:50 +0000 (19:45 +0000)
This is a straight port of CL 335978 with minor adjustements to
white space and an error message.

Change-Id: Icfcb562f75802a119ce5d02427bffecf7e279b2f
Reviewed-on: https://go-review.googlesource.com/c/go/+/338097
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
src/cmd/compile/internal/types2/instance.go
src/cmd/compile/internal/types2/instantiate.go
src/cmd/compile/internal/types2/testdata/check/issues.go2

index df0fc17ba7acc7f077c09ee7b62466cde92c6e26..711d7de53cac9c723db9b898bbef0644c2fb7a5a 100644 (file)
@@ -26,7 +26,7 @@ func (n *Named) expand() {
                // tparams. This is done implicitly by the call to n.TParams, but making it
                // explicit is harmless: load is idempotent.
                n.load()
-               inst := n.check.instantiate(n.instance.pos, n.orig.underlying, n.TParams(), n.targs, n.instance.posList, n.instance.verify)
+               inst := n.check.instantiate(n.instance.pos, n.orig.underlying, n.TParams(), n.targs, n.instance.posList)
                n.underlying = inst
                n.fromRHS = inst
                n.instance = nil
index 1294b08490de20c2c5972e99325e6a0fe60898c2..7a40cea88942263bc1af386f823c38561e4110f6 100644 (file)
@@ -54,10 +54,15 @@ func (check *Checker) Instantiate(pos syntax.Pos, typ Type, targs []Type, posLis
                // only types and functions can be generic
                panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ))
        }
-       return check.instantiate(pos, typ, tparams, targs, posList, verify)
+
+       inst := check.instantiate(pos, typ, tparams, targs, posList)
+       if verify && len(tparams) == len(targs) {
+               check.verify(pos, tparams, targs, posList)
+       }
+       return inst
 }
 
-func (check *Checker) instantiate(pos syntax.Pos, typ Type, tparams []*TypeName, targs []Type, posList []syntax.Pos, verify bool) (res Type) {
+func (check *Checker) instantiate(pos syntax.Pos, typ Type, tparams []*TypeName, targs []Type, posList []syntax.Pos) (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
@@ -67,9 +72,6 @@ func (check *Checker) instantiate(pos syntax.Pos, typ Type, tparams []*TypeName,
                }
                panic(fmt.Sprintf("%v: got %d arguments but %d type parameters", pos, len(targs), len(tparams)))
        }
-       if verify && check == nil {
-               panic("cannot have nil receiver if verify is set")
-       }
 
        if check != nil && check.conf.Trace {
                check.trace(pos, "-- instantiating %s with %s", typ, typeListString(targs))
@@ -93,24 +95,7 @@ func (check *Checker) instantiate(pos syntax.Pos, typ Type, tparams []*TypeName,
                return typ // nothing to do (minor optimization)
        }
 
-       smap := makeSubstMap(tparams, targs)
-
-       // check bounds
-       if verify {
-               for i, tname := range tparams {
-                       // best position for error reporting
-                       pos := pos
-                       if i < len(posList) {
-                               pos = posList[i]
-                       }
-                       // stop checking bounds after the first failure
-                       if !check.satisfies(pos, targs[i], tname.typ.(*TypeParam), smap) {
-                               break
-                       }
-               }
-       }
-
-       return check.subst(pos, typ, smap)
+       return check.subst(pos, typ, makeSubstMap(tparams, targs))
 }
 
 // InstantiateLazy is like Instantiate, but avoids actually
@@ -120,10 +105,16 @@ func (check *Checker) InstantiateLazy(pos syntax.Pos, typ Type, targs []Type, po
        // Don't use asNamed here: we don't want to expand the base during lazy
        // instantiation.
        base := typ.(*Named)
-
        if base == nil {
                panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ))
        }
+
+       if verify && len(base.tparams) == len(targs) {
+               check.later(func() {
+                       check.verify(pos, base.tparams, targs, posList)
+               })
+       }
+
        h := instantiatedHash(base, targs)
        if check != nil {
                // typ may already have been instantiated with identical type arguments. In
@@ -148,6 +139,26 @@ func (check *Checker) InstantiateLazy(pos syntax.Pos, typ Type, targs []Type, po
        return named
 }
 
+func (check *Checker) verify(pos syntax.Pos, tparams []*TypeName, targs []Type, posList []syntax.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
+               pos := pos
+               if i < len(posList) {
+                       pos = posList[i]
+               }
+
+               // stop checking bounds after the first failure
+               if !check.satisfies(pos, targs[i], tname.typ.(*TypeParam), smap) {
+                       break
+               }
+       }
+}
+
 // satisfies reports whether the type argument targ satisfies the constraint of type parameter
 // parameter tpar (after any of its type parameters have been substituted through smap).
 // A suitable error is reported if the result is false.
index e29357de0b8857d4e355f9381a58f293ea54457f..1ede383ebe551cd413a5f7ffc5addade72d65411 100644 (file)
@@ -74,10 +74,8 @@ func (u T2[U]) Add1() U {
     return u.s + 1
 }
 
-// TODO(rfindley): we should probably report an error here as well, not
-//                 just when the type is first instantiated.
 func NewT2[U any]() T2[U /* ERROR U has no constraints */ ] {
-    return T2[U]{}
+    return T2[U /* ERROR U has no constraints */ ]{}
 }
 
 func _() {