Skip to content

Commit 910bc35

Browse files
committed
[Sema] Non-exhaustive switch statements are always an error in Swift 6.
1 parent 625436a commit 910bc35

File tree

4 files changed

+58
-13
lines changed

4 files changed

+58
-13
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7074,10 +7074,9 @@ WARNING(redundant_particular_literal_case,none,
70747074
NOTE(redundant_particular_literal_case_here,none,
70757075
"first occurrence of identical literal pattern is here", ())
70767076

7077-
WARNING(non_exhaustive_switch_warn,none, "switch must be exhaustive", ())
7078-
WARNING(non_exhaustive_switch_unknown_only,none,
7079-
"switch covers known cases, but %0 may have additional unknown values"
7080-
"%select{|, possibly added in future versions}1", (Type, bool))
7077+
ERROR(non_exhaustive_switch_unknown_only,none,
7078+
"switch covers known cases, but %0 may have additional unknown values"
7079+
"%select{|, possibly added in future versions}1", (Type, bool))
70817080

70827081
ERROR(override_nsobject_hashvalue_error,none,
70837082
"'NSObject.hashValue' is not overridable; "

lib/Sema/TypeCheckSwitchStmt.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1128,13 +1128,13 @@ namespace {
11281128
// Decide whether we want an error or a warning.
11291129
std::optional<decltype(diag::non_exhaustive_switch)> mainDiagType =
11301130
diag::non_exhaustive_switch;
1131+
bool downgrade = false;
11311132
if (unknownCase) {
11321133
switch (defaultReason) {
11331134
case RequiresDefault::EmptySwitchBody:
11341135
llvm_unreachable("there's an @unknown case; the body can't be empty");
11351136
case RequiresDefault::No:
1136-
if (!uncovered.isEmpty())
1137-
mainDiagType = diag::non_exhaustive_switch_warn;
1137+
downgrade = !uncovered.isEmpty();
11381138
break;
11391139
case RequiresDefault::UncoveredSwitch:
11401140
case RequiresDefault::SpaceTooLarge: {
@@ -1170,7 +1170,8 @@ namespace {
11701170
theEnum->getParentModule()->isSystemModule();
11711171
}
11721172
DE.diagnose(startLoc, diag::non_exhaustive_switch_unknown_only,
1173-
subjectType, shouldIncludeFutureVersionComment);
1173+
subjectType, shouldIncludeFutureVersionComment)
1174+
.warnUntilSwiftVersion(6);
11741175
mainDiagType = std::nullopt;
11751176
}
11761177
break;
@@ -1187,7 +1188,8 @@ namespace {
11871188
return;
11881189
case RequiresDefault::UncoveredSwitch: {
11891190
OS << tok::kw_default << ":\n" << placeholder << "\n";
1190-
DE.diagnose(startLoc, mainDiagType.value());
1191+
DE.diagnose(startLoc, mainDiagType.value())
1192+
.warnUntilSwiftVersionIf(downgrade, 6);
11911193
DE.diagnose(startLoc, diag::missing_several_cases, /*default*/true)
11921194
.fixItInsert(insertLoc, buffer.str());
11931195
}
@@ -1205,8 +1207,10 @@ namespace {
12051207
if (uncovered.isEmpty()) return;
12061208

12071209
// Check if we still have to emit the main diagnostic.
1208-
if (mainDiagType.has_value())
1209-
DE.diagnose(startLoc, mainDiagType.value());
1210+
if (mainDiagType.has_value()) {
1211+
DE.diagnose(startLoc, mainDiagType.value())
1212+
.warnUntilSwiftVersionIf(downgrade, 6);
1213+
}
12101214

12111215
// Add notes to explain what's missing.
12121216
auto processUncoveredSpaces =

test/ClangImporter/enum-exhaustivity-system.swift

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1-
// RUN: %target-swift-frontend -typecheck %s -Xcc -isystem -Xcc %S/Inputs/custom-modules -verify -enable-nonfrozen-enum-exhaustivity-diagnostics
1+
// RUN: %target-swift-frontend -typecheck %s -Xcc -isystem -Xcc %S/Inputs/custom-modules -verify -swift-version 5 -verify-additional-prefix swift5-
2+
// RUN: %target-swift-frontend -typecheck %s -Xcc -isystem -Xcc %S/Inputs/custom-modules -verify -swift-version 6 -verify-additional-prefix swift6-
23

34
import EnumExhaustivity
45

56
func test(_ value: RegularEnum, _ exhaustiveValue: ExhaustiveEnum) {
6-
switch value { // expected-warning {{switch covers known cases, but 'RegularEnum' may have additional unknown values, possibly added in future versions}} expected-note {{handle unknown values using "@unknown default"}}
7+
switch value {
8+
// expected-swift5-warning@-1 {{switch covers known cases, but 'RegularEnum' may have additional unknown values, possibly added in future versions}}
9+
// expected-swift6-error@-2 {{switch covers known cases, but 'RegularEnum' may have additional unknown values, possibly added in future versions}}
10+
// expected-note@-3 {{handle unknown values using "@unknown default"}}
711
case .A: break
812
case .B: break
913
}
@@ -29,7 +33,11 @@ func testAttributes(
2933
case .A, .B: break
3034
}
3135

32-
switch retetb { // expected-warning {{switch covers known cases, but 'RegularEnumTurnedExhaustiveThenBackViaAPINotes' may have additional unknown values, possibly added in future versions}} expected-note {{handle unknown values using "@unknown default"}}
36+
switch retetb {
37+
// expected-swift5-warning@-1 {{switch covers known cases, but 'RegularEnumTurnedExhaustiveThenBackViaAPINotes' may have additional unknown values, possibly added in future versions}}
38+
// expected-swift6-error@-2 {{switch covers known cases, but 'RegularEnumTurnedExhaustiveThenBackViaAPINotes' may have additional unknown values, possibly added in future versions}}
39+
// expected-note@-3 {{handle unknown values using "@unknown default"}}
40+
3341
case .A, .B: break
3442
}
3543

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// RUN: %target-typecheck-verify-swift -swift-version 6 -enable-library-evolution
2+
3+
enum OverlyLargeSpaceEnum {
4+
case case0
5+
case case1
6+
case case2
7+
case case3
8+
case case4
9+
case case5
10+
case case6
11+
case case7
12+
case case8
13+
case case9
14+
case case10
15+
case case11
16+
}
17+
18+
func testSwitch() -> Bool {
19+
switch (OverlyLargeSpaceEnum.case1, OverlyLargeSpaceEnum.case2) { // expected-error {{switch must be exhaustive}}
20+
// expected-note@-1 {{add missing case: '(.case11, _)'}}
21+
case (.case0, _): return true
22+
case (.case1, _): return true
23+
case (.case2, _): return true
24+
case (.case3, _): return true
25+
case (.case4, _): return true
26+
case (.case5, _): return true
27+
case (.case6, _): return true
28+
case (.case7, _): return true
29+
case (.case8, _): return true
30+
case (.case9, _): return true
31+
case (.case10, _): return true
32+
@unknown default: return false
33+
}
34+
}

0 commit comments

Comments
 (0)