[SILGen] Fix load ownership for trivial tuple elements in consuming switch

In consuming switch when emitting case block that destructures a tuple payload,
it was unconditionally issuing load [take] even if the element was a trivial type.
Later code assumes loads for trivial types have trivial ownership.

The fix uses TypeLowering::emitLoad() instead of directly creating the
load, which handles setting ownership to trivial if the type is trivial.

Fixes #85743
This commit is contained in:
Benjamin Levine
2025-11-30 17:10:27 -05:00
parent a69dbb3366
commit e93ea1db26
2 changed files with 26 additions and 1 deletions

View File

@@ -2672,7 +2672,9 @@ void PatternMatchEmission::emitDestructiveCaseBlocks() {
for (unsigned i = 0, e = p->getNumElements(); i < e; ++i) {
SILValue element = SGF.B.createTupleElementAddr(p, baseAddr, i);
if (element->getType().isLoadable(SGF.F)) {
element = SGF.B.createLoad(p, element, LoadOwnershipQualifier::Take);
element =
SGF.getTypeLowering(element->getType())
.emitLoad(SGF.B, p, element, LoadOwnershipQualifier::Take);
}
visit(p->getElement(i).getPattern(),
SGF.emitManagedRValueWithCleanup(element));

View File

@@ -0,0 +1,23 @@
// RUN: %target-swift-emit-silgen %s | %FileCheck %s
// RUN: %target-swift-emit-sil %s -sil-verify-all
// Test that consuming switch on address only enum with trivial payload case correctly use load [trivial]
// instead of load [take].
protocol AProtocol {}
enum AddressOnly: ~Copyable {
case unloadableAndInt(any AProtocol, Int)
}
// CHECK-LABEL: sil hidden [ossa] @$s33address_only_enum_trivial_payload14consumeTheEnum
func consumeTheEnum(_ value: consuming AddressOnly) -> Int {
// CHECK: switch_enum_addr {{.*}}AddressOnly.unloadableAndInt
switch consume value {
case .unloadableAndInt(_, let count):
// CHECK: [[ADDR:%[0-9]+]] = unchecked_take_enum_data_addr
// CHECK: [[TRIVIAL_ADDR:%[0-9]+]] = tuple_element_addr [[ADDR]], 1
// CHECK: load [trivial] [[TRIVIAL_ADDR]]
return count
}
}