Skip to content

Commit cefa0b2

Browse files
committed
[AST/Sema] Add @preEnumExtensibility attribute to downgrade warnings for extensible enums
Just like `@preconcurrency` for concurrency, this attribute is going to allow exhaustiveness error downgrades for enums that were retroactively marked as `@extensible`. (cherry picked from commit 498430a)
1 parent 58988a0 commit cefa0b2

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
@@ -8712,7 +8712,7 @@ GROUPED_WARNING(
87128712
(StringRef))
87138713

87148714
//===----------------------------------------------------------------------===//
8715-
// MARK: @extensible Attribute
8715+
// MARK: @extensible and @preEnumExtensibility Attributes
87168716
//===----------------------------------------------------------------------===//
87178717

87188718
ERROR(extensible_attr_on_frozen_type,none,
@@ -8724,6 +8724,9 @@ ERROR(extensible_attr_on_internal_type,none,
87248724
"%select{private|fileprivate|internal|%error|%error|%error}1",
87258725
(DeclName, AccessLevel))
87268726

8727+
ERROR(pre_enum_extensibility_without_extensible,none,
8728+
"%0 can only be used together with '@extensible' attribute", (DeclAttribute))
8729+
87278730
//===----------------------------------------------------------------------===//
87288731
// MARK: `using` declaration
87298732
//===----------------------------------------------------------------------===//

lib/AST/ASTDumper.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5066,6 +5066,7 @@ class PrintAttribute : public AttributeVisitor<PrintAttribute, void, Label>,
50665066
TRIVIAL_ATTR_PRINTER(WeakLinked, weak_linked)
50675067
TRIVIAL_ATTR_PRINTER(Extensible, extensible)
50685068
TRIVIAL_ATTR_PRINTER(Concurrent, concurrent)
5069+
TRIVIAL_ATTR_PRINTER(PreEnumExtensibility, preEnumExtensibility)
50695070

50705071
#undef TRIVIAL_ATTR_PRINTER
50715072

lib/AST/ASTPrinter.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3328,7 +3328,8 @@ suppressingFeatureAddressableTypes(PrintOptions &options,
33283328
static void
33293329
suppressingFeatureExtensibleAttribute(PrintOptions &options,
33303330
llvm::function_ref<void()> action) {
3331-
ExcludeAttrRAII scope(options.ExcludeAttrList, DeclAttrKind::Extensible);
3331+
ExcludeAttrRAII scope1(options.ExcludeAttrList, DeclAttrKind::Extensible);
3332+
ExcludeAttrRAII scope2(options.ExcludeAttrList, DeclAttrKind::PreEnumExtensibility);
33323333
action();
33333334
}
33343335

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
@@ -262,6 +262,14 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
262262
}
263263
}
264264

265+
void visitPreEnumExtensibilityAttr(PreEnumExtensibilityAttr *attr) {
266+
if (!D->getAttrs().hasAttribute<ExtensibleAttr>()) {
267+
diagnoseAndRemoveAttr(
268+
attr, diag::pre_enum_extensibility_without_extensible, attr);
269+
return;
270+
}
271+
}
272+
265273
void visitAlignmentAttr(AlignmentAttr *attr) {
266274
// Alignment must be a power of two.
267275
auto value = attr->getValue();

lib/Sema/TypeCheckDeclOverride.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1617,6 +1617,7 @@ namespace {
16171617
UNINTERESTING_ATTR(Optimize)
16181618
UNINTERESTING_ATTR(Exclusivity)
16191619
UNINTERESTING_ATTR(Extensible)
1620+
UNINTERESTING_ATTR(PreEnumExtensibility)
16201621
UNINTERESTING_ATTR(NoLocks)
16211622
UNINTERESTING_ATTR(NoAllocation)
16221623
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; // remove ExtensibleEnums feature
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+
}

0 commit comments

Comments
 (0)