[dev.typeparams] go/types: use InstantiateLazy to create instance types (cleanup)

This is a port of CL 333669 to go/types, adjusted for the position and
IndexExpr APIs, and excluding the noder changes.

Change-Id: I3ac4bbf271947c3cf80ab04c462a91657316f4fe
Reviewed-on: https://go-review.googlesource.com/c/go/+/335073
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>
This commit is contained in:
Rob Findley 2021-07-16 19:58:59 -04:00 committed by Robert Findley
parent 4a72be87b3
commit 22f39ba208
3 changed files with 27 additions and 38 deletions

View File

@ -15,7 +15,7 @@ type instance struct {
pos token.Pos // position of type instantiation; for error reporting only
base *Named // parameterized type to be instantiated
targs []Type // type arguments
poslist []token.Pos // position of each targ; for error reporting only
posList []token.Pos // position of each targ; for error reporting only
verify bool // if set, constraint satisfaction is verified
value Type // base[targs...] after instantiation or Typ[Invalid]; nil if not yet set
}
@ -26,7 +26,7 @@ type instance struct {
func (t *instance) expand() Type {
v := t.value
if v == nil {
v = t.check.Instantiate(t.pos, t.base, t.targs, t.poslist, t.verify)
v = t.check.Instantiate(t.pos, t.base, t.targs, t.posList, t.verify)
if v == nil {
v = Typ[Invalid]
}

View File

@ -113,19 +113,21 @@ func (check *Checker) Instantiate(pos token.Pos, typ Type, targs []Type, posList
}
// InstantiateLazy is like Instantiate, but avoids actually
// instantiating the type until needed.
func (check *Checker) InstantiateLazy(pos token.Pos, typ Type, targs []Type, verify bool) (res Type) {
// instantiating the type until needed. typ must be a *Named
// type.
func (check *Checker) InstantiateLazy(pos token.Pos, typ Type, targs []Type, posList []token.Pos, verify bool) Type {
base := asNamed(typ)
if base == nil {
panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ))
}
return &instance{
check: check,
pos: pos,
base: base,
targs: targs,
verify: verify,
check: check,
pos: pos,
base: base,
targs: targs,
posList: posList,
verify: verify,
}
}

View File

@ -264,7 +264,7 @@ func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) {
case *ast.IndexExpr, *ast.MultiIndexExpr:
ix := typeparams.UnpackIndexExpr(e)
// TODO(rfindley): type instantiation should require go1.18
return check.instantiatedType(ix, def)
return check.instantiatedType(ix.X, ix.Indices, def)
case *ast.ParenExpr:
// Generic types must be instantiated before they can be used in any form.
@ -400,45 +400,32 @@ func (check *Checker) typeOrNil(e ast.Expr) Type {
return Typ[Invalid]
}
func (check *Checker) instantiatedType(ix *typeparams.IndexExpr, def *Named) Type {
b := check.genericType(ix.X, true) // TODO(gri) what about cycles?
if b == Typ[Invalid] {
return b // error already reported
}
base := asNamed(b)
if base == nil {
unreachable() // should have been caught by genericType
func (check *Checker) instantiatedType(x ast.Expr, targsx []ast.Expr, def *Named) Type {
base := check.genericType(x, true)
if base == Typ[Invalid] {
return base // error already reported
}
// create a new type instance rather than instantiate the type
// TODO(gri) should do argument number check here rather than
// when instantiating the type?
// TODO(gri) use InstantiateLazy here (cleanup)
typ := new(instance)
def.setUnderlying(typ)
typ.check = check
typ.pos = ix.X.Pos()
typ.base = base
typ.verify = true
// evaluate arguments (always)
typ.targs = check.typeList(ix.Indices)
if typ.targs == nil {
// evaluate arguments
targs := check.typeList(targsx)
if targs == nil {
def.setUnderlying(Typ[Invalid]) // avoid later errors due to lazy instantiation
return Typ[Invalid]
}
// determine argument positions (for error reporting)
typ.poslist = make([]token.Pos, len(ix.Indices))
for i, arg := range ix.Indices {
typ.poslist[i] = arg.Pos()
// determine argument positions
posList := make([]token.Pos, len(targs))
for i, arg := range targsx {
posList[i] = arg.Pos()
}
typ := check.InstantiateLazy(x.Pos(), base, targs, posList, true)
def.setUnderlying(typ)
// make sure we check instantiation works at least once
// and that the resulting type is valid
check.later(func() {
t := typ.expand()
t := typ.(*instance).expand()
check.validType(t, nil)
})