compiler: fix crash on type assert on interfaces with no methods
Этот коммит содержится в:
родитель
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
предоставленный
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
предоставленный
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
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче