[Sema] Non-exhaustive switch statements are always an error in Swift 6.

This commit is contained in:
Holly Borla
2024-05-06 18:56:07 -07:00
parent 625436af05
commit 910bc35e85
4 changed files with 58 additions and 13 deletions

View File

@@ -7074,8 +7074,7 @@ WARNING(redundant_particular_literal_case,none,
NOTE(redundant_particular_literal_case_here,none,
"first occurrence of identical literal pattern is here", ())
WARNING(non_exhaustive_switch_warn,none, "switch must be exhaustive", ())
WARNING(non_exhaustive_switch_unknown_only,none,
ERROR(non_exhaustive_switch_unknown_only,none,
"switch covers known cases, but %0 may have additional unknown values"
"%select{|, possibly added in future versions}1", (Type, bool))

View File

@@ -1128,13 +1128,13 @@ namespace {
// Decide whether we want an error or a warning.
std::optional<decltype(diag::non_exhaustive_switch)> mainDiagType =
diag::non_exhaustive_switch;
bool downgrade = false;
if (unknownCase) {
switch (defaultReason) {
case RequiresDefault::EmptySwitchBody:
llvm_unreachable("there's an @unknown case; the body can't be empty");
case RequiresDefault::No:
if (!uncovered.isEmpty())
mainDiagType = diag::non_exhaustive_switch_warn;
downgrade = !uncovered.isEmpty();
break;
case RequiresDefault::UncoveredSwitch:
case RequiresDefault::SpaceTooLarge: {
@@ -1170,7 +1170,8 @@ namespace {
theEnum->getParentModule()->isSystemModule();
}
DE.diagnose(startLoc, diag::non_exhaustive_switch_unknown_only,
subjectType, shouldIncludeFutureVersionComment);
subjectType, shouldIncludeFutureVersionComment)
.warnUntilSwiftVersion(6);
mainDiagType = std::nullopt;
}
break;
@@ -1187,7 +1188,8 @@ namespace {
return;
case RequiresDefault::UncoveredSwitch: {
OS << tok::kw_default << ":\n" << placeholder << "\n";
DE.diagnose(startLoc, mainDiagType.value());
DE.diagnose(startLoc, mainDiagType.value())
.warnUntilSwiftVersionIf(downgrade, 6);
DE.diagnose(startLoc, diag::missing_several_cases, /*default*/true)
.fixItInsert(insertLoc, buffer.str());
}
@@ -1205,8 +1207,10 @@ namespace {
if (uncovered.isEmpty()) return;
// Check if we still have to emit the main diagnostic.
if (mainDiagType.has_value())
DE.diagnose(startLoc, mainDiagType.value());
if (mainDiagType.has_value()) {
DE.diagnose(startLoc, mainDiagType.value())
.warnUntilSwiftVersionIf(downgrade, 6);
}
// Add notes to explain what's missing.
auto processUncoveredSpaces =

View File

@@ -1,9 +1,13 @@
// RUN: %target-swift-frontend -typecheck %s -Xcc -isystem -Xcc %S/Inputs/custom-modules -verify -enable-nonfrozen-enum-exhaustivity-diagnostics
// RUN: %target-swift-frontend -typecheck %s -Xcc -isystem -Xcc %S/Inputs/custom-modules -verify -swift-version 5 -verify-additional-prefix swift5-
// RUN: %target-swift-frontend -typecheck %s -Xcc -isystem -Xcc %S/Inputs/custom-modules -verify -swift-version 6 -verify-additional-prefix swift6-
import EnumExhaustivity
func test(_ value: RegularEnum, _ exhaustiveValue: ExhaustiveEnum) {
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"}}
switch value {
// expected-swift5-warning@-1 {{switch covers known cases, but 'RegularEnum' may have additional unknown values, possibly added in future versions}}
// expected-swift6-error@-2 {{switch covers known cases, but 'RegularEnum' may have additional unknown values, possibly added in future versions}}
// expected-note@-3 {{handle unknown values using "@unknown default"}}
case .A: break
case .B: break
}
@@ -29,7 +33,11 @@ func testAttributes(
case .A, .B: break
}
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"}}
switch retetb {
// expected-swift5-warning@-1 {{switch covers known cases, but 'RegularEnumTurnedExhaustiveThenBackViaAPINotes' may have additional unknown values, possibly added in future versions}}
// expected-swift6-error@-2 {{switch covers known cases, but 'RegularEnumTurnedExhaustiveThenBackViaAPINotes' may have additional unknown values, possibly added in future versions}}
// expected-note@-3 {{handle unknown values using "@unknown default"}}
case .A, .B: break
}

View File

@@ -0,0 +1,34 @@
// RUN: %target-typecheck-verify-swift -swift-version 6 -enable-library-evolution
enum OverlyLargeSpaceEnum {
case case0
case case1
case case2
case case3
case case4
case case5
case case6
case case7
case case8
case case9
case case10
case case11
}
func testSwitch() -> Bool {
switch (OverlyLargeSpaceEnum.case1, OverlyLargeSpaceEnum.case2) { // expected-error {{switch must be exhaustive}}
// expected-note@-1 {{add missing case: '(.case11, _)'}}
case (.case0, _): return true
case (.case1, _): return true
case (.case2, _): return true
case (.case3, _): return true
case (.case4, _): return true
case (.case5, _): return true
case (.case6, _): return true
case (.case7, _): return true
case (.case8, _): return true
case (.case9, _): return true
case (.case10, _): return true
@unknown default: return false
}
}