mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
We used to emit this: checked_cast_br [exact] %0 : $Foo to $Bar, bb1, bb2 bb1(%1 : $Bar): %2 = unchecked_ref_cast %0 : $Foo to %1 : $Bar apply ...(..., %2) br ... bb2: ... This is not ownership SIL-safe, because we're re-using the original operand, which will have already been consumed at that point. The more immediate problem here is that this is actually not safe when combined with other optimizations. Suppose that after the speculative devirtualization, our function is inlined into another function where the operand was an upcast. Now we have this code: %0 = upcast ... checked_cast_br [exact] %0 : $Foo to $Bar, bb1, bb2 bb1(%1 : $Bar): %2 = unchecked_ref_cast %0 : $Foo to %1 : $Bar apply ...(..., %2) br ... bb2: ... The SILCombiner will simplify the unchecked_ref_cast of the upcast into an unchecked_ref_cast of the upcast's original operand. At this point, we have an unchecked_ref_cast between two unrelated class types. While this means the block bb1 is unreachable, we might perform further optimizations on it before we run the cast optimizer and delete it altogether. In particular, the devirtualizer follows chains of reference cast instructions, and it will get very confused if it finds this invalid cast between unrelated types. Fixes <rdar://problem/57712094>, <https://bugs.swift.org/browse/SR-11916>.