compiler: fix crash on type assert on interfaces with no methods

Этот коммит содержится в:
Damian Gryski 2023-11-04 10:14:08 -07:00 коммит произвёл Ron Evans
родитель 2b215955ca
коммит 777048cfa9
3 изменённых файлов: 28 добавлений и 12 удалений

Просмотреть файл

@ -684,8 +684,14 @@ func (b *builder) createTypeAssert(expr *ssa.TypeAssert) llvm.Value {
actualTypeNum := b.CreateExtractValue(itf, 0, "interface.type") actualTypeNum := b.CreateExtractValue(itf, 0, "interface.type")
commaOk := llvm.Value{} commaOk := llvm.Value{}
if _, ok := expr.AssertedType.Underlying().(*types.Interface); ok {
// Type assert on interface type. if intf, ok := expr.AssertedType.Underlying().(*types.Interface); ok {
if intf.Empty() {
// intf is the empty interface => no methods
// This type assertion always succeeds, so we can just set commaOk to true.
commaOk = llvm.ConstInt(b.ctx.Int1Type(), 1, true)
} else {
// Type assert on interface type with methods.
// This is a call to an interface type assert function. // This is a call to an interface type assert function.
// The interface lowering pass will define this function by filling it // The interface lowering pass will define this function by filling it
// with a type switch over all concrete types that implement this // with a type switch over all concrete types that implement this
@ -696,7 +702,7 @@ func (b *builder) createTypeAssert(expr *ssa.TypeAssert) llvm.Value {
// https://research.swtch.com/interfaces // https://research.swtch.com/interfaces
fn := b.getInterfaceImplementsFunc(expr.AssertedType) fn := b.getInterfaceImplementsFunc(expr.AssertedType)
commaOk = b.CreateCall(fn.GlobalValueType(), fn, []llvm.Value{actualTypeNum}, "") commaOk = b.CreateCall(fn.GlobalValueType(), fn, []llvm.Value{actualTypeNum}, "")
}
} else { } else {
name, _ := getTypeCodeName(expr.AssertedType) name, _ := getTypeCodeName(expr.AssertedType)
globalName := "reflect/types.typeid:" + name globalName := "reflect/types.typeid:" + name

9
testdata/interface.go предоставленный
Просмотреть файл

@ -116,6 +116,9 @@ func main() {
// check that pointer-to-pointer type switches work // check that pointer-to-pointer type switches work
ptrptrswitch() ptrptrswitch()
// check that type asserts to interfaces with no methods work
emptyintfcrash()
} }
func printItf(val interface{}) { func printItf(val interface{}) {
@ -334,3 +337,9 @@ func identify(itf any) {
println("other type??") println("other type??")
} }
} }
func emptyintfcrash() {
if x, ok := any(5).(any); ok {
println("x is", x.(int))
}
}

1
testdata/interface.txt предоставленный
Просмотреть файл

@ -27,3 +27,4 @@ slept 1ms
type is int type is int
type is *int type is *int
type is **int type is **int
x is 5