Skip to content

Commit 72eaf25

Browse files
committed
SILGen: Diagnose unsupported shared case blocks for noncopyable switch subjects.
This isn't fully implemented yet so it would crash eventually, so instead of letting the compiler crash put up a proper diagnostic indicating this isn't yet implemented. rdar://129034189
1 parent cb2f23f commit 72eaf25

File tree

3 files changed

+50
-3
lines changed

3 files changed

+50
-3
lines changed

include/swift/AST/DiagnosticsSIL.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,5 +1038,8 @@ NOTE(lifetime_outside_scope_use, none,
10381038
NOTE(lifetime_outside_scope_escape, none,
10391039
"this use causes the lifetime-dependent value to escape", ())
10401040

1041+
ERROR(noncopyable_shared_case_block_unimplemented, none,
1042+
"matching a non-'Copyable' value using a case label that has multiple patterns is not implemented", ())
1043+
10411044
#define UNDEFINE_DIAGNOSTIC_MACROS
10421045
#include "DefineDiagnosticMacros.h"

lib/SILGen/SILGenPattern.cpp

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,8 @@ class PatternMatchEmission {
457457
void emitDestructiveCaseBlocks();
458458

459459
JumpDest getSharedCaseBlockDest(CaseStmt *caseStmt);
460-
void emitSharedCaseBlocks(llvm::function_ref<void(CaseStmt *)> bodyEmitter);
460+
void emitSharedCaseBlocks(ValueOwnership ownership,
461+
llvm::function_ref<void(CaseStmt *)> bodyEmitter);
461462

462463
void emitCaseBody(CaseStmt *caseBlock);
463464

@@ -2899,7 +2900,21 @@ emitAddressOnlyInitialization(VarDecl *dest, SILValue value) {
28992900

29002901
/// Emit all the shared case statements.
29012902
void PatternMatchEmission::emitSharedCaseBlocks(
2903+
ValueOwnership ownership,
29022904
llvm::function_ref<void(CaseStmt *)> bodyEmitter) {
2905+
if (ownership >= ValueOwnership::Shared
2906+
&& !SharedCases.empty()) {
2907+
SGF.SGM.diagnose(SharedCases.front().first,
2908+
diag::noncopyable_shared_case_block_unimplemented);
2909+
2910+
for (auto &entry : SharedCases) {
2911+
SILBasicBlock *caseBB = entry.second.first;
2912+
SGF.B.setInsertionPoint(caseBB);
2913+
SGF.B.createUnreachable(entry.first);
2914+
}
2915+
2916+
return;
2917+
}
29032918
for (auto &entry : SharedCases) {
29042919
CaseStmt *caseBlock = entry.first;
29052920
SILBasicBlock *caseBB = entry.second.first;
@@ -3742,7 +3757,7 @@ void SILGenFunction::emitSwitchStmt(SwitchStmt *S) {
37423757
}
37433758

37443759
// Then emit the case blocks shared by multiple pattern cases.
3745-
emission.emitSharedCaseBlocks(
3760+
emission.emitSharedCaseBlocks(ownership,
37463761
[&](CaseStmt *caseStmt) { emission.emitCaseBody(caseStmt); });
37473762

37483763
// Bookkeeping.
@@ -4015,7 +4030,8 @@ void SILGenFunction::emitCatchDispatch(DoCatchStmt *S, ManagedValue exn,
40154030
stmtScope.pop();
40164031

40174032
// Then emit the case blocks shared by multiple pattern cases.
4018-
emission.emitSharedCaseBlocks([&](CaseStmt *caseStmt) {
4033+
emission.emitSharedCaseBlocks(ValueOwnership::Default,
4034+
[&](CaseStmt *caseStmt) {
40194035
emitStmt(caseStmt->getBody());
40204036

40214037
// If we fell out of the catch clause, branch to the fallthrough dest.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// RUN: %target-swift-emit-silgen -verify %s
2+
3+
struct Inner: ~Copyable {}
4+
enum Outer: ~Copyable { case value(Inner, Int) }
5+
6+
func borrow(_: borrowing Inner) {}
7+
func consume(_: consuming Inner) {}
8+
9+
func foo(x: borrowing Outer) {
10+
switch x {
11+
case .value(let y, 0), // expected-error{{not implemented}}
12+
.value(let y, _):
13+
borrow(y)
14+
}
15+
16+
}
17+
18+
func bar(x: borrowing Outer) {
19+
switch x {
20+
case .value(let y, 0):
21+
borrow(y)
22+
fallthrough
23+
24+
case .value(let y, _): // expected-error{{not implemented}}
25+
borrow(y)
26+
}
27+
28+
}

0 commit comments

Comments
 (0)