From 66e718525b7668367a5a8505edc0ba333d314f17 Mon Sep 17 00:00:00 2001 From: Erik Eckstein Date: Mon, 13 Oct 2025 19:23:14 +0200 Subject: [PATCH] SILCombine: don't fold `unchecked_take_enum_data_addr` - `destroy_addr` of enums with deinit Destroying whole non-copyable enums with a deinit would wrongly trigger calling its deinit. --- .../SILCombiner/SILCombinerMiscVisitors.cpp | 4 +++ test/SILOptimizer/sil_combine_moveonly.sil | 26 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp b/lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp index e5cf557d72a..a58e475082a 100644 --- a/lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp +++ b/lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp @@ -1146,6 +1146,10 @@ SILInstruction *SILCombiner::visitUncheckedTakeEnumDataAddrInst( } if (onlyDestroys) { + // Destroying whole non-copyable enums with a deinit would wrongly trigger calling its deinit. + if (tedai->getOperand()->getType().isValueTypeWithDeinit()) + return nullptr; + // The unchecked_take_enum_data_addr is dead: remove it and replace all // destroys with a destroy of its operand. while (!tedai->use_empty()) { diff --git a/test/SILOptimizer/sil_combine_moveonly.sil b/test/SILOptimizer/sil_combine_moveonly.sil index df42158c3c1..1a39bc99847 100644 --- a/test/SILOptimizer/sil_combine_moveonly.sil +++ b/test/SILOptimizer/sil_combine_moveonly.sil @@ -185,3 +185,29 @@ bb0(%0 : @owned $S2): return %r } +// CHECK-LABEL: sil [ossa] @dont_fold_destroy_of_take_enum_with_deinit_ossa : +// CHECK: bb0(%0 : $*MaybeFileDescriptor): +// CHECK-NEXT: %1 = unchecked_take_enum_data_addr %0 +// CHECK-NEXT: destroy_addr %1 +// CHECK: } // end sil function 'dont_fold_destroy_of_take_enum_with_deinit_ossa' +sil [ossa] @dont_fold_destroy_of_take_enum_with_deinit_ossa : $@convention(thin) (@in MaybeFileDescriptor) -> () { +bb0(%0 : $*MaybeFileDescriptor): + %1 = unchecked_take_enum_data_addr %0, #MaybeFileDescriptor.some!enumelt + destroy_addr %1 + %r = tuple () + return %r : $() +} + +// CHECK-LABEL: sil @dont_fold_destroy_of_take_enum_with_deinit : +// CHECK: bb0(%0 : $*MaybeFileDescriptor): +// CHECK-NEXT: %1 = unchecked_take_enum_data_addr %0 +// CHECK-NEXT: destroy_addr %1 +// CHECK: } // end sil function 'dont_fold_destroy_of_take_enum_with_deinit' +sil @dont_fold_destroy_of_take_enum_with_deinit : $@convention(thin) (@in MaybeFileDescriptor) -> () { +bb0(%0 : $*MaybeFileDescriptor): + %1 = unchecked_take_enum_data_addr %0, #MaybeFileDescriptor.some!enumelt + destroy_addr %1 + %r = tuple () + return %r : $() +} +