Skip to content

Commit 3cc5628

Browse files
authored
Merge pull request #63129 from eeckstein/fix-walk-utils
WalkUtils: fix a crash when visiting mismatching types
2 parents 3be2302 + b5e731d commit 3cc5628

File tree

2 files changed

+45
-1
lines changed

2 files changed

+45
-1
lines changed

SwiftCompilerSources/Sources/Optimizer/Utilities/WalkUtils.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,11 @@ extension ValueUseDefWalker {
569569
switch def {
570570
case let str as StructInst:
571571
if let (index, path) = path.pop(kind: .structField) {
572+
if index >= str.operands.count {
573+
// This can happen if there is a type mismatch, e.g. two different concrete types of an existential
574+
// are visited for the same path.
575+
return unmatchedPath(value: str, path: path)
576+
}
572577
return walkUp(value: str.operands[index].value, path: path)
573578
} else if path.popIfMatches(.anyValueFields, index: nil) != nil {
574579
return walkUpAllOperands(of: str, path: path)
@@ -577,6 +582,11 @@ extension ValueUseDefWalker {
577582
}
578583
case let t as TupleInst:
579584
if let (index, path) = path.pop(kind: .tupleField) {
585+
if index >= t.operands.count {
586+
// This can happen if there is a type mismatch, e.g. two different concrete types of an existential
587+
// are visited for the same path.
588+
return unmatchedPath(value: t, path: path)
589+
}
580590
return walkUp(value: t.operands[index].value, path: path)
581591
} else if path.popIfMatches(.anyValueFields, index: nil) != nil {
582592
return walkUpAllOperands(of: t, path: path)

test/SILOptimizer/escape_info.sil

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,14 @@ final class F {
4141
@_hasStorage var y: Y
4242
}
4343

44-
struct TwoF {
44+
protocol P {
45+
}
46+
47+
struct OneF : P {
48+
@_hasStorage var a: F
49+
}
50+
51+
struct TwoF : P {
4552
@_hasStorage var a: F
4653
@_hasStorage var b: F
4754
}
@@ -1343,3 +1350,30 @@ bb0:
13431350
return %13 : $()
13441351
}
13451352

1353+
// CHECK-LABEL: Escape information for test_mismatching_existential_types:
1354+
// CHECK: - : %1 = alloc_ref $Y
1355+
// CHECK: End function test_mismatching_existential_types
1356+
sil @test_mismatching_existential_types : $@convention(thin) (@guaranteed F) -> () {
1357+
bb0(%0 : $F):
1358+
%1 = alloc_ref $Y
1359+
1360+
%2 = alloc_stack $any P
1361+
1362+
%3 = init_existential_addr %2 : $*any P, $OneF
1363+
%4 = struct $OneF (%0 : $F)
1364+
store %4 to %3 : $*OneF
1365+
1366+
// Strictly speaking it's illegal to re-initialize an existential with a different concrete type.
1367+
// But for this test this doesn't matter.
1368+
%6 = init_existential_addr %2 : $*any P, $TwoF
1369+
%7 = struct_element_addr %6 : $*TwoF, #TwoF.b
1370+
%8 = load %7 : $*F
1371+
1372+
%9 = ref_element_addr %8 : $F, #F.y
1373+
store %1 to %9 : $*Y
1374+
1375+
dealloc_stack %2 : $*any P
1376+
%r = tuple()
1377+
return %r : $()
1378+
}
1379+

0 commit comments

Comments
 (0)