diff options
author | Robert Griesemer <gri@golang.org> | 2021-07-28 13:50:09 -0700 |
---|---|---|
committer | Robert Griesemer <gri@golang.org> | 2021-07-29 19:45:50 +0000 |
commit | c079b6baaa781e71a48661c05063d1d2754937f8 (patch) | |
tree | 55c52c63513c657ab611f0d3f9b2c7cbf4834cc4 | |
parent | ff0c0dbca6a7a3a3d6528481829679be4c9d7e94 (diff) | |
download | go-c079b6baaa781e71a48661c05063d1d2754937f8.tar.gz go-c079b6baaa781e71a48661c05063d1d2754937f8.zip |
[dev.typeparams] cmd/compile/internal/types2: trigger verification while resolving instance
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>
-rw-r--r-- | src/cmd/compile/internal/types2/instance.go | 2 | ||||
-rw-r--r-- | src/cmd/compile/internal/types2/instantiate.go | 59 | ||||
-rw-r--r-- | src/cmd/compile/internal/types2/testdata/check/issues.go2 | 4 |
3 files changed, 37 insertions, 28 deletions
diff --git a/src/cmd/compile/internal/types2/instance.go b/src/cmd/compile/internal/types2/instance.go index df0fc17ba7..711d7de53c 100644 --- a/src/cmd/compile/internal/types2/instance.go +++ b/src/cmd/compile/internal/types2/instance.go @@ -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 diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index 1294b08490..7a40cea889 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -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. diff --git a/src/cmd/compile/internal/types2/testdata/check/issues.go2 b/src/cmd/compile/internal/types2/testdata/check/issues.go2 index e29357de0b..1ede383ebe 100644 --- a/src/cmd/compile/internal/types2/testdata/check/issues.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/issues.go2 @@ -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 _() { |