From 90182d0417061a5160948f003d4b6856e8b8cf58 Mon Sep 17 00:00:00 2001 From: Joe Groff Date: Tue, 9 Sep 2025 16:02:57 -0700 Subject: [PATCH] SILGen: Add missing FormalEvaluationScope when evaluating consumed noncopyable switch subjects. After #83959, we expect noncopyable OpenExistential evaluations to have an outer FormalEvaluationScope to forward to. However, there was no such FormalEvaluationScope while emitting a consuming switch subject, causing an assertion failure to trip. Add a FormalEvaluationScope tightly scoped around the evaluation in this case, fixing rdar://160080337. --- lib/SILGen/SILGenPattern.cpp | 6 +++++- ...consumed_subject_with_open_existential.swift | 17 +++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 test/SILGen/switch_noncopyable_consumed_subject_with_open_existential.swift diff --git a/lib/SILGen/SILGenPattern.cpp b/lib/SILGen/SILGenPattern.cpp index a201c94989b1d..18b31b4efb4d0 100644 --- a/lib/SILGen/SILGenPattern.cpp +++ b/lib/SILGen/SILGenPattern.cpp @@ -3500,7 +3500,7 @@ void SILGenFunction::emitSwitchStmt(SwitchStmt *S) { // exits out of the switch. // // When we break out of a case block, we take the subject's remnants with us - // in the former case, but not the latter.q + // in the former case, but not the latter. CleanupsDepth subjectDepth = Cleanups.getCleanupsDepth(); LexicalScope switchScope(*this, CleanupLocation(S)); std::optional switchFormalAccess; @@ -3563,6 +3563,10 @@ void SILGenFunction::emitSwitchStmt(SwitchStmt *S) { } case ValueOwnership::Owned: { // A consuming pattern match. Emit as a +1 rvalue. + // Create a tight evaluation scope for temporary borrows emitted during the + // evaluation. + FormalEvaluationScope limitedScope(*this); + subjectMV = emitRValueAsSingleValue(S->getSubjectExpr()); break; } diff --git a/test/SILGen/switch_noncopyable_consumed_subject_with_open_existential.swift b/test/SILGen/switch_noncopyable_consumed_subject_with_open_existential.swift new file mode 100644 index 0000000000000..30f381d85a8b9 --- /dev/null +++ b/test/SILGen/switch_noncopyable_consumed_subject_with_open_existential.swift @@ -0,0 +1,17 @@ +// RUN: %target-swift-emit-silgen -verify %s + +func fooify(p: any P) { + switch p.foo() { + case .success: + break + } +} + +enum Resoult: ~Copyable { + case success +} + +protocol P { + func foo() -> Resoult +} +