mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
go/types: clean up panics in instantiation
This is a straightforward port of CL 341862 to go/types. Change-Id: I4214c08d2889e2daf40254385656c6beed79571d Reviewed-on: https://go-review.googlesource.com/c/go/+/342487 Trust: Robert Findley <rfindley@google.com> Run-TryBot: Robert Findley <rfindley@google.com> Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
parent
bacbc33439
commit
4d00fcbc43
2 changed files with 28 additions and 22 deletions
|
|
@ -53,15 +53,18 @@ func (check *Checker) Instantiate(pos token.Pos, typ Type, targs []Type, posList
|
||||||
// only types and functions can be generic
|
// only types and functions can be generic
|
||||||
panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ))
|
panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ))
|
||||||
}
|
}
|
||||||
|
inst := check.instantiate(pos, typ, tparams, targs, nil)
|
||||||
|
|
||||||
inst := check.instantiate(pos, typ, tparams, targs, posList, nil)
|
if verify {
|
||||||
if verify && len(tparams) == len(targs) {
|
assert(len(posList) <= len(targs))
|
||||||
|
if len(tparams) == len(targs) {
|
||||||
check.verify(pos, tparams, targs, posList)
|
check.verify(pos, tparams, targs, posList)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return inst
|
return inst
|
||||||
}
|
}
|
||||||
|
|
||||||
func (check *Checker) instantiate(pos token.Pos, typ Type, tparams []*TypeName, targs []Type, posList []token.Pos, typMap map[string]*Named) (res Type) {
|
func (check *Checker) instantiate(pos token.Pos, typ Type, tparams []*TypeName, targs []Type, typMap map[string]*Named) (res Type) {
|
||||||
// the number of supplied types must match the number of type parameters
|
// the number of supplied types must match the number of type parameters
|
||||||
if len(targs) != len(tparams) {
|
if len(targs) != len(tparams) {
|
||||||
// TODO(gri) provide better error message
|
// TODO(gri) provide better error message
|
||||||
|
|
@ -88,8 +91,6 @@ func (check *Checker) instantiate(pos token.Pos, typ Type, tparams []*TypeName,
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(len(posList) <= len(targs))
|
|
||||||
|
|
||||||
// TODO(gri) What is better here: work with TypeParams, or work with TypeNames?
|
// TODO(gri) What is better here: work with TypeParams, or work with TypeNames?
|
||||||
|
|
||||||
if len(tparams) == 0 {
|
if len(tparams) == 0 {
|
||||||
|
|
@ -101,14 +102,21 @@ func (check *Checker) instantiate(pos token.Pos, typ Type, tparams []*TypeName,
|
||||||
|
|
||||||
// instantiateLazy avoids actually instantiating the type until needed. typ
|
// instantiateLazy avoids actually instantiating the type until needed. typ
|
||||||
// must be a *Named type.
|
// must be a *Named type.
|
||||||
func (check *Checker) instantiateLazy(pos token.Pos, base *Named, targs []Type, posList []token.Pos, verify bool) Type {
|
func (check *Checker) instantiateLazy(pos token.Pos, orig *Named, targs []Type, posList []token.Pos, verify bool) Type {
|
||||||
if verify && base.TParams().Len() == len(targs) {
|
if verify {
|
||||||
// TODO: lift the nil check in verify to here.
|
if check == nil {
|
||||||
|
// Provide a more useful panic instead of panicking at check.later below.
|
||||||
|
panic("cannot have nil Checker if verifying constraints")
|
||||||
|
}
|
||||||
|
assert(len(posList) <= len(targs))
|
||||||
|
if orig.TParams().Len() == len(targs) {
|
||||||
check.later(func() {
|
check.later(func() {
|
||||||
check.verify(pos, base.tparams.list(), targs, posList)
|
check.verify(pos, orig.tparams.list(), targs, posList)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
h := instantiatedHash(base, targs)
|
}
|
||||||
|
|
||||||
|
h := instantiatedHash(orig, targs)
|
||||||
if check != nil {
|
if check != nil {
|
||||||
// typ may already have been instantiated with identical type arguments. In
|
// typ may already have been instantiated with identical type arguments. In
|
||||||
// that case, re-use the existing instance.
|
// that case, re-use the existing instance.
|
||||||
|
|
@ -117,10 +125,10 @@ func (check *Checker) instantiateLazy(pos token.Pos, base *Named, targs []Type,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tname := NewTypeName(pos, base.obj.pkg, base.obj.name, nil)
|
tname := NewTypeName(pos, orig.obj.pkg, orig.obj.name, nil)
|
||||||
named := check.newNamed(tname, base, nil, nil, nil) // methods and tparams are set when named is loaded.
|
named := check.newNamed(tname, orig, nil, nil, nil) // methods and tparams are set when named is loaded
|
||||||
named.targs = targs
|
named.targs = targs
|
||||||
named.instance = &instance{pos, posList}
|
named.instance = &instance{pos}
|
||||||
|
|
||||||
if check != nil {
|
if check != nil {
|
||||||
check.typMap[h] = named
|
check.typMap[h] = named
|
||||||
|
|
@ -133,7 +141,6 @@ func (check *Checker) verify(pos token.Pos, tparams []*TypeName, targs []Type, p
|
||||||
if check == nil {
|
if check == nil {
|
||||||
panic("cannot have nil Checker if verifying constraints")
|
panic("cannot have nil Checker if verifying constraints")
|
||||||
}
|
}
|
||||||
|
|
||||||
smap := makeSubstMap(tparams, targs)
|
smap := makeSubstMap(tparams, targs)
|
||||||
for i, tname := range tparams {
|
for i, tname := range tparams {
|
||||||
// best position for error reporting
|
// best position for error reporting
|
||||||
|
|
|
||||||
|
|
@ -248,11 +248,10 @@ func (n *Named) setUnderlying(typ Type) {
|
||||||
|
|
||||||
// instance holds position information for use in lazy instantiation.
|
// instance holds position information for use in lazy instantiation.
|
||||||
//
|
//
|
||||||
// TODO(rfindley): come up with a better name for this type, now that its usage
|
// TODO(rfindley): instance is probably unnecessary now. See if it can be
|
||||||
// has changed.
|
// eliminated.
|
||||||
type instance struct {
|
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
|
||||||
posList []token.Pos // position of each targ; for error reporting only
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// expand ensures that the underlying type of n is instantiated.
|
// expand ensures that the underlying type of n is instantiated.
|
||||||
|
|
@ -276,7 +275,7 @@ func (n *Named) expand(typMap map[string]*Named) *Named {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inst := n.check.instantiate(n.instance.pos, n.orig.underlying, n.TParams().list(), n.targs, n.instance.posList, typMap)
|
inst := n.check.instantiate(n.instance.pos, n.orig.underlying, n.TParams().list(), n.targs, typMap)
|
||||||
n.underlying = inst
|
n.underlying = inst
|
||||||
n.fromRHS = inst
|
n.fromRHS = inst
|
||||||
n.instance = nil
|
n.instance = nil
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue