1
0
mirror of https://github.com/golang/go synced 2024-07-03 00:40:45 +00:00

[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 {

View File

@ -0,0 +1,30 @@
// run -gcflags=-G=3
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
func f[T any](i interface{}) {
switch i.(type) {
case T:
println("T")
case int:
println("int")
default:
println("other")
}
}
type myint int
func (myint) foo() {
}
func main() {
f[interface{}](nil)
f[interface{}](6)
f[interface{foo()}](nil)
f[interface{foo()}](7)
f[interface{foo()}](myint(8))
}

View File

@ -0,0 +1,5 @@
other
T
other
int
T

View File

@ -0,0 +1,37 @@
// run -gcflags=-G=3
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
func f[T any](i interface{foo()}) {
switch i.(type) {
case interface{bar() T}:
println("barT")
case myint:
println("myint")
case myfloat:
println("myfloat")
default:
println("other")
}
}
type myint int
func (myint) foo() {
}
func (x myint) bar() int {
return int(x)
}
type myfloat float64
func (myfloat) foo() {
}
func main() {
f[int](nil)
f[int](myint(6))
f[int](myfloat(7))
}

View File

@ -0,0 +1,3 @@
other
barT
myfloat