mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[Sema] Non-exhaustive switch statements are always an error in Swift 6.
This commit is contained in:
@@ -7074,10 +7074,9 @@ WARNING(redundant_particular_literal_case,none,
|
|||||||
NOTE(redundant_particular_literal_case_here,none,
|
NOTE(redundant_particular_literal_case_here,none,
|
||||||
"first occurrence of identical literal pattern is here", ())
|
"first occurrence of identical literal pattern is here", ())
|
||||||
|
|
||||||
WARNING(non_exhaustive_switch_warn,none, "switch must be exhaustive", ())
|
ERROR(non_exhaustive_switch_unknown_only,none,
|
||||||
WARNING(non_exhaustive_switch_unknown_only,none,
|
"switch covers known cases, but %0 may have additional unknown values"
|
||||||
"switch covers known cases, but %0 may have additional unknown values"
|
"%select{|, possibly added in future versions}1", (Type, bool))
|
||||||
"%select{|, possibly added in future versions}1", (Type, bool))
|
|
||||||
|
|
||||||
ERROR(override_nsobject_hashvalue_error,none,
|
ERROR(override_nsobject_hashvalue_error,none,
|
||||||
"'NSObject.hashValue' is not overridable; "
|
"'NSObject.hashValue' is not overridable; "
|
||||||
|
|||||||
@@ -1128,13 +1128,13 @@ namespace {
|
|||||||
// Decide whether we want an error or a warning.
|
// Decide whether we want an error or a warning.
|
||||||
std::optional<decltype(diag::non_exhaustive_switch)> mainDiagType =
|
std::optional<decltype(diag::non_exhaustive_switch)> mainDiagType =
|
||||||
diag::non_exhaustive_switch;
|
diag::non_exhaustive_switch;
|
||||||
|
bool downgrade = false;
|
||||||
if (unknownCase) {
|
if (unknownCase) {
|
||||||
switch (defaultReason) {
|
switch (defaultReason) {
|
||||||
case RequiresDefault::EmptySwitchBody:
|
case RequiresDefault::EmptySwitchBody:
|
||||||
llvm_unreachable("there's an @unknown case; the body can't be empty");
|
llvm_unreachable("there's an @unknown case; the body can't be empty");
|
||||||
case RequiresDefault::No:
|
case RequiresDefault::No:
|
||||||
if (!uncovered.isEmpty())
|
downgrade = !uncovered.isEmpty();
|
||||||
mainDiagType = diag::non_exhaustive_switch_warn;
|
|
||||||
break;
|
break;
|
||||||
case RequiresDefault::UncoveredSwitch:
|
case RequiresDefault::UncoveredSwitch:
|
||||||
case RequiresDefault::SpaceTooLarge: {
|
case RequiresDefault::SpaceTooLarge: {
|
||||||
@@ -1170,7 +1170,8 @@ namespace {
|
|||||||
theEnum->getParentModule()->isSystemModule();
|
theEnum->getParentModule()->isSystemModule();
|
||||||
}
|
}
|
||||||
DE.diagnose(startLoc, diag::non_exhaustive_switch_unknown_only,
|
DE.diagnose(startLoc, diag::non_exhaustive_switch_unknown_only,
|
||||||
subjectType, shouldIncludeFutureVersionComment);
|
subjectType, shouldIncludeFutureVersionComment)
|
||||||
|
.warnUntilSwiftVersion(6);
|
||||||
mainDiagType = std::nullopt;
|
mainDiagType = std::nullopt;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1187,7 +1188,8 @@ namespace {
|
|||||||
return;
|
return;
|
||||||
case RequiresDefault::UncoveredSwitch: {
|
case RequiresDefault::UncoveredSwitch: {
|
||||||
OS << tok::kw_default << ":\n" << placeholder << "\n";
|
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)
|
DE.diagnose(startLoc, diag::missing_several_cases, /*default*/true)
|
||||||
.fixItInsert(insertLoc, buffer.str());
|
.fixItInsert(insertLoc, buffer.str());
|
||||||
}
|
}
|
||||||
@@ -1205,8 +1207,10 @@ namespace {
|
|||||||
if (uncovered.isEmpty()) return;
|
if (uncovered.isEmpty()) return;
|
||||||
|
|
||||||
// Check if we still have to emit the main diagnostic.
|
// Check if we still have to emit the main diagnostic.
|
||||||
if (mainDiagType.has_value())
|
if (mainDiagType.has_value()) {
|
||||||
DE.diagnose(startLoc, mainDiagType.value());
|
DE.diagnose(startLoc, mainDiagType.value())
|
||||||
|
.warnUntilSwiftVersionIf(downgrade, 6);
|
||||||
|
}
|
||||||
|
|
||||||
// Add notes to explain what's missing.
|
// Add notes to explain what's missing.
|
||||||
auto processUncoveredSpaces =
|
auto processUncoveredSpaces =
|
||||||
|
|||||||
@@ -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
|
import EnumExhaustivity
|
||||||
|
|
||||||
func test(_ value: RegularEnum, _ exhaustiveValue: ExhaustiveEnum) {
|
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 .A: break
|
||||||
case .B: break
|
case .B: break
|
||||||
}
|
}
|
||||||
@@ -29,7 +33,11 @@ func testAttributes(
|
|||||||
case .A, .B: break
|
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
|
case .A, .B: break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
34
test/Compatibility/exhaustive_switch_swift_6.swift
Normal file
34
test/Compatibility/exhaustive_switch_swift_6.swift
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user