mirror of
https://github.com/golang/go
synced 2024-11-26 16:26:49 -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
|
pos token.Pos // position of type instantiation; for error reporting only
|
||||||
base *Named // parameterized type to be instantiated
|
base *Named // parameterized type to be instantiated
|
||||||
targs []Type // type arguments
|
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
|
verify bool // if set, constraint satisfaction is verified
|
||||||
value Type // base[targs...] after instantiation or Typ[Invalid]; nil if not yet set
|
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 {
|
func (t *instance) expand() Type {
|
||||||
v := t.value
|
v := t.value
|
||||||
if v == nil {
|
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 {
|
if v == nil {
|
||||||
v = Typ[Invalid]
|
v = Typ[Invalid]
|
||||||
}
|
}
|
||||||
|
@ -113,8 +113,9 @@ func (check *Checker) Instantiate(pos token.Pos, typ Type, targs []Type, posList
|
|||||||
}
|
}
|
||||||
|
|
||||||
// InstantiateLazy is like Instantiate, but avoids actually
|
// InstantiateLazy is like Instantiate, but avoids actually
|
||||||
// instantiating the type until needed.
|
// instantiating the type until needed. typ must be a *Named
|
||||||
func (check *Checker) InstantiateLazy(pos token.Pos, typ Type, targs []Type, verify bool) (res Type) {
|
// type.
|
||||||
|
func (check *Checker) InstantiateLazy(pos token.Pos, typ Type, targs []Type, posList []token.Pos, verify bool) Type {
|
||||||
base := asNamed(typ)
|
base := asNamed(typ)
|
||||||
if base == nil {
|
if base == nil {
|
||||||
panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ))
|
panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ))
|
||||||
@ -125,6 +126,7 @@ func (check *Checker) InstantiateLazy(pos token.Pos, typ Type, targs []Type, ver
|
|||||||
pos: pos,
|
pos: pos,
|
||||||
base: base,
|
base: base,
|
||||||
targs: targs,
|
targs: targs,
|
||||||
|
posList: posList,
|
||||||
verify: verify,
|
verify: verify,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -264,7 +264,7 @@ func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) {
|
|||||||
case *ast.IndexExpr, *ast.MultiIndexExpr:
|
case *ast.IndexExpr, *ast.MultiIndexExpr:
|
||||||
ix := typeparams.UnpackIndexExpr(e)
|
ix := typeparams.UnpackIndexExpr(e)
|
||||||
// TODO(rfindley): type instantiation should require go1.18
|
// TODO(rfindley): type instantiation should require go1.18
|
||||||
return check.instantiatedType(ix, def)
|
return check.instantiatedType(ix.X, ix.Indices, def)
|
||||||
|
|
||||||
case *ast.ParenExpr:
|
case *ast.ParenExpr:
|
||||||
// Generic types must be instantiated before they can be used in any form.
|
// 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]
|
return Typ[Invalid]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (check *Checker) instantiatedType(ix *typeparams.IndexExpr, def *Named) Type {
|
func (check *Checker) instantiatedType(x ast.Expr, targsx []ast.Expr, def *Named) Type {
|
||||||
b := check.genericType(ix.X, true) // TODO(gri) what about cycles?
|
base := check.genericType(x, true)
|
||||||
if b == Typ[Invalid] {
|
if base == Typ[Invalid] {
|
||||||
return b // error already reported
|
return base // error already reported
|
||||||
}
|
|
||||||
base := asNamed(b)
|
|
||||||
if base == nil {
|
|
||||||
unreachable() // should have been caught by genericType
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a new type instance rather than instantiate the type
|
// evaluate arguments
|
||||||
// TODO(gri) should do argument number check here rather than
|
targs := check.typeList(targsx)
|
||||||
// when instantiating the type?
|
if targs == nil {
|
||||||
// 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 {
|
|
||||||
def.setUnderlying(Typ[Invalid]) // avoid later errors due to lazy instantiation
|
def.setUnderlying(Typ[Invalid]) // avoid later errors due to lazy instantiation
|
||||||
return Typ[Invalid]
|
return Typ[Invalid]
|
||||||
}
|
}
|
||||||
|
|
||||||
// determine argument positions (for error reporting)
|
// determine argument positions
|
||||||
typ.poslist = make([]token.Pos, len(ix.Indices))
|
posList := make([]token.Pos, len(targs))
|
||||||
for i, arg := range ix.Indices {
|
for i, arg := range targsx {
|
||||||
typ.poslist[i] = arg.Pos()
|
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
|
// make sure we check instantiation works at least once
|
||||||
// and that the resulting type is valid
|
// and that the resulting type is valid
|
||||||
check.later(func() {
|
check.later(func() {
|
||||||
t := typ.expand()
|
t := typ.(*instance).expand()
|
||||||
check.validType(t, nil)
|
check.validType(t, nil)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user