Skip to content

Commit ff790c6

Browse files
authored
Merge pull request #81176 from xedin/pre-enum-extensibility
[AST/Sema] Add `@preEnumExtensibility` attribute to downgrade warning…
2 parents e7bbd4b + 498430a commit ff790c6

File tree

12 files changed

+102
-10
lines changed

12 files changed

+102
-10
lines changed

include/swift/AST/DeclAttr.def

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -887,7 +887,13 @@ SIMPLE_DECL_ATTR(concurrent, Concurrent,
887887
ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove | UnconstrainedInABIAttr,
888888
170)
889889

890-
LAST_DECL_ATTR(Concurrent)
890+
SIMPLE_DECL_ATTR(preEnumExtensibility, PreEnumExtensibility,
891+
OnEnum,
892+
ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIBreakingToRemove | UnconstrainedInABIAttr,
893+
171)
894+
DECL_ATTR_FEATURE_REQUIREMENT(PreEnumExtensibility, ExtensibleAttribute)
895+
896+
LAST_DECL_ATTR(PreEnumExtensibility)
891897

892898
#undef DECL_ATTR_ALIAS
893899
#undef CONTEXTUAL_DECL_ATTR_ALIAS

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8702,7 +8702,7 @@ GROUPED_WARNING(
87028702
(StringRef, DeclAttribute))
87038703
87048704
//===----------------------------------------------------------------------===//
8705-
// MARK: @extensible Attribute
8705+
// MARK: @extensible and @preEnumExtensibility Attributes
87068706
//===----------------------------------------------------------------------===//
87078707
87088708
ERROR(extensible_attr_on_frozen_type,none,
@@ -8714,6 +8714,9 @@ ERROR(extensible_attr_on_internal_type,none,
87148714
"%select{private|fileprivate|internal|%error|%error|%error}1",
87158715
(DeclName, AccessLevel))
87168716
8717+
ERROR(pre_enum_extensibility_without_extensible,none,
8718+
"%0 can only be used together with '@extensible' attribute", (DeclAttribute))
8719+
87178720
//===----------------------------------------------------------------------===//
87188721
// MARK: SwiftSettings
87198722
//===----------------------------------------------------------------------===//

lib/AST/ASTDumper.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5062,6 +5062,7 @@ class PrintAttribute : public AttributeVisitor<PrintAttribute, void, Label>,
50625062
TRIVIAL_ATTR_PRINTER(WeakLinked, weak_linked)
50635063
TRIVIAL_ATTR_PRINTER(Extensible, extensible)
50645064
TRIVIAL_ATTR_PRINTER(Concurrent, concurrent)
5065+
TRIVIAL_ATTR_PRINTER(PreEnumExtensibility, preEnumExtensibility)
50655066

50665067
#undef TRIVIAL_ATTR_PRINTER
50675068

lib/AST/ASTPrinter.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3301,7 +3301,8 @@ suppressingFeatureAddressableTypes(PrintOptions &options,
33013301
static void
33023302
suppressingFeatureExtensibleAttribute(PrintOptions &options,
33033303
llvm::function_ref<void()> action) {
3304-
ExcludeAttrRAII scope(options.ExcludeAttrList, DeclAttrKind::Extensible);
3304+
ExcludeAttrRAII scope1(options.ExcludeAttrList, DeclAttrKind::Extensible);
3305+
ExcludeAttrRAII scope2(options.ExcludeAttrList, DeclAttrKind::PreEnumExtensibility);
33053306
action();
33063307
}
33073308

lib/ASTGen/Sources/ASTGen/DeclAttrs.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ extension ASTGenVisitor {
229229
.eagerMove,
230230
.exported,
231231
.extensible,
232+
.preEnumExtensibility,
232233
.discardableResult,
233234
.disfavoredOverload,
234235
.dynamicMemberLookup,

lib/Sema/TypeCheckAttr.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,14 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
258258
}
259259
}
260260

261+
void visitPreEnumExtensibilityAttr(PreEnumExtensibilityAttr *attr) {
262+
if (!D->getAttrs().hasAttribute<ExtensibleAttr>()) {
263+
diagnoseAndRemoveAttr(
264+
attr, diag::pre_enum_extensibility_without_extensible, attr);
265+
return;
266+
}
267+
}
268+
261269
void visitConcurrentAttr(ConcurrentAttr *attr) {
262270
checkExecutionBehaviorAttribute(attr);
263271

lib/Sema/TypeCheckDeclOverride.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1611,6 +1611,7 @@ namespace {
16111611
UNINTERESTING_ATTR(Optimize)
16121612
UNINTERESTING_ATTR(Exclusivity)
16131613
UNINTERESTING_ATTR(Extensible)
1614+
UNINTERESTING_ATTR(PreEnumExtensibility)
16141615
UNINTERESTING_ATTR(NoLocks)
16151616
UNINTERESTING_ATTR(NoAllocation)
16161617
UNINTERESTING_ATTR(NoRuntime)

lib/Sema/TypeCheckSwitchStmt.cpp

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,16 +1154,28 @@ namespace {
11541154
assert(defaultReason == RequiresDefault::No);
11551155
Type subjectType = Switch->getSubjectExpr()->getType();
11561156
bool shouldIncludeFutureVersionComment = false;
1157-
bool shouldDowngradeToWarning = true;
1158-
if (auto *theEnum = subjectType->getEnumOrBoundGenericEnum()) {
1157+
auto *theEnum = subjectType->getEnumOrBoundGenericEnum();
1158+
1159+
if (theEnum) {
11591160
auto *enumModule = theEnum->getParentModule();
11601161
shouldIncludeFutureVersionComment =
11611162
enumModule->isSystemModule() ||
11621163
theEnum->getAttrs().hasAttribute<ExtensibleAttr>();
11631164
}
1164-
DE.diagnose(startLoc, diag::non_exhaustive_switch_unknown_only,
1165-
subjectType, shouldIncludeFutureVersionComment)
1166-
.warnUntilSwiftVersionIf(shouldDowngradeToWarning, 6);
1165+
1166+
auto diag =
1167+
DE.diagnose(startLoc, diag::non_exhaustive_switch_unknown_only,
1168+
subjectType, shouldIncludeFutureVersionComment);
1169+
1170+
// Presence of `@preEnumExtensibility` pushed the warning farther
1171+
// into the future.
1172+
if (theEnum &&
1173+
theEnum->getAttrs().hasAttribute<PreEnumExtensibilityAttr>()) {
1174+
diag.warnUntilFutureSwiftVersion();
1175+
} else {
1176+
diag.warnUntilSwiftVersion(6);
1177+
}
1178+
11671179
mainDiagType = std::nullopt;
11681180
}
11691181
break;

lib/Serialization/ModuleFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5858
/// describe what change you made. The content of this comment isn't important;
5959
/// it just ensures a conflict if two people change the module format.
6060
/// Don't worry about adhering to the 80-column limit for this line.
61-
const uint16_t SWIFTMODULE_VERSION_MINOR = 946; // end_cow_mutation_addr
61+
const uint16_t SWIFTMODULE_VERSION_MINOR = 947; // @preEnumExtensibility attribute
6262

6363
/// A standard hash seed used for all string hashes in a serialized module.
6464
///

test/ModuleInterface/extensible_attr.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,14 @@
1616
@extensible
1717
public enum E {
1818
}
19+
20+
// CHECK: #if compiler(>=5.3) && $ExtensibleAttribute
21+
// CHECK-NEXT: @preEnumExtensibility @extensible public enum F {
22+
// CHECK: #else
23+
// CHECK-NEXT: public enum F {
24+
// CHECK: #endif
25+
@preEnumExtensibility
26+
@extensible
27+
public enum F {
28+
case a
29+
}

test/ModuleInterface/extensible_enums.swift

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@
2929
// RUN: -package-name Test \
3030
// RUN: -verify
3131

32+
// Different module but the same package
33+
// RUN: %target-swift-frontend -typecheck %t/src/TestSwift6.swift \
34+
// RUN: -swift-version 6 -module-name Client -I %t \
35+
// RUN: -verify
36+
3237
// REQUIRES: swift_feature_ExtensibleAttribute
3338

3439
//--- Lib.swift
@@ -38,6 +43,12 @@ public enum E {
3843
case a
3944
}
4045

46+
@preEnumExtensibility
47+
@extensible
48+
public enum PE {
49+
case a
50+
}
51+
4152
@frozen
4253
public enum F {
4354
case a
@@ -58,7 +69,7 @@ func test_same_module(e: E, f: F) {
5869
//--- TestChecking.swift
5970
import Lib
6071

61-
func test(e: E, f: F) {
72+
func test(e: E, pe: PE, f: F) {
6273
// `E` is marked as `@extensible` which means it gets new semantics
6374

6475
switch e {
@@ -72,6 +83,12 @@ func test(e: E, f: F) {
7283
@unknown default: break
7384
}
7485

86+
switch pe {
87+
// expected-warning@-1 {{switch covers known cases, but 'PE' may have additional unknown values, possibly added in future versions; this will be an error in a future Swift language mode}}
88+
// expected-note@-2 {{handle unknown values using "@unknown default"}}
89+
case .a: break
90+
}
91+
7592
// `F` is marked as `@frozen` which means regular rules apply.
7693

7794
switch f { // Ok (no errors because `F` is `@frozen`)
@@ -110,3 +127,25 @@ func test_no_default(e: E, f: F) {
110127
@unknown default: break
111128
}
112129
}
130+
131+
//--- TestSwift6.swift
132+
import Lib
133+
134+
func test(e: E, pe: PE, f: F) {
135+
switch e {
136+
// expected-error@-1 {{switch covers known cases, but 'E' may have additional unknown values, possibly added in future versions}}
137+
// expected-note@-2 {{handle unknown values using "@unknown default"}}
138+
case .a: break
139+
}
140+
141+
switch e { // Ok (no warnings)
142+
case .a: break
143+
@unknown default: break
144+
}
145+
146+
switch pe {
147+
// expected-warning@-1 {{switch covers known cases, but 'PE' may have additional unknown values, possibly added in future versions; this will be an error in a future Swift language mode}}
148+
// expected-note@-2 {{handle unknown values using "@unknown default"}}
149+
case .a: break
150+
}
151+
}

test/attr/attr_extensible.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,12 @@ struct Test {
3838
set { }
3939
}
4040
}
41+
42+
@preEnumExtensibility
43+
@extensible
44+
public enum PE {
45+
}
46+
47+
@preEnumExtensibility // expected-error {{@preEnumExtensibility can only be used together with '@extensible' attribute}}
48+
public enum WrongPreE {
49+
}

0 commit comments

Comments
 (0)