mirror of
https://github.com/golang/go
synced 2024-11-11 23:20:24 -07:00
[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:
parent
4a72be87b3
commit
22f39ba208
@ -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]
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
})
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user