[dev.typeparams] cmd/compile: handle interface type parameters in type switches

Change-Id: I9bba21a64d7e9f42395b6fcdf8aa3ca01cf131dc
Reviewed-on: https://go-review.googlesource.com/c/go/+/340912
Trust: Keith Randall <khr@golang.org>
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Dan Scales <danscales@google.com>
This commit is contained in:
Keith Randall 2021-08-09 11:40:46 -07:00
parent e4cfa2f6da
commit 2fbf6aafe7
5 changed files with 93 additions and 12 deletions

View file

@ -1157,19 +1157,21 @@ func (subst *subster) node(n ir.Node) ir.Node {
assert(ix >= 0)
dt := ir.NewDynamicType(c.Pos(), getDictionaryEntry(c.Pos(), subst.info.dictParam, ix, subst.info.dictLen))
// For type switch from nonemoty interfaces to non-interfaces, we need an itab as well.
if _, ok := subst.info.gfInfo.type2switchType[c]; ok {
// Type switch from nonempty interface. We need a *runtime.itab
// for the dynamic type.
ix := -1
for i, ic := range subst.info.gfInfo.itabConvs {
if ic == c {
ix = subst.info.startItabConv + i
break
// For type switch from nonempty interfaces to non-interfaces, we need an itab as well.
if !m.List[i].Type().IsInterface() {
if _, ok := subst.info.gfInfo.type2switchType[c]; ok {
// Type switch from nonempty interface. We need a *runtime.itab
// for the dynamic type.
ix := -1
for i, ic := range subst.info.gfInfo.itabConvs {
if ic == c {
ix = subst.info.startItabConv + i
break
}
}
assert(ix >= 0)
dt.ITab = getDictionaryEntry(c.Pos(), subst.info.dictParam, ix, subst.info.dictLen)
}
assert(ix >= 0)
dt.ITab = getDictionaryEntry(c.Pos(), subst.info.dictParam, ix, subst.info.dictLen)
}
typed(m.List[i].Type(), dt)
m.List[i] = dt
@ -1484,6 +1486,8 @@ func (g *irgen) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool)
// instantiations have been created.
func (g *irgen) finalizeSyms() {
for _, d := range g.dictSymsToFinalize {
infoPrint("=== Finalizing dictionary %s\n", d.sym.Name)
lsym := d.sym.Linksym()
info := g.getGfInfo(d.gf)
@ -1528,9 +1532,11 @@ func (g *irgen) finalizeSyms() {
// No itab is wanted if src type is an interface. We
// will use a type assert instead.
d.off = objw.Uintptr(lsym, d.off, 0)
infoPrint(" + Unused itab entry for %v\n", srctype)
} else {
itabLsym := reflectdata.ITabLsym(srctype, dsttype)
d.off = objw.SymPtr(lsym, d.off, itabLsym, 0)
infoPrint(" + Itab for (%v,%v)\n", srctype, dsttype)
}
}
@ -1694,7 +1700,7 @@ func (g *irgen) getGfInfo(gn *ir.Name) *gfInfo {
for _, cc := range n.(*ir.SwitchStmt).Cases {
for _, c := range cc.List {
if c.Op() == ir.OTYPE && c.Type().HasTParam() {
// Type switch from a non-empty interface to a noninterface.
// Type switch from a non-empty interface - might need an itab.
infoPrint(" Itab for type switch: %v\n", c)
info.itabConvs = append(info.itabConvs, c)
if info.type2switchType == nil {