Skip to content

Commit a0ae93d

Browse files
committed
[AST/Sema] Add @extensible attribute on enum declarations
This attribute controls whether cross-module access to the declaration needs `@unknown default:` because it's allowed to gain new cases even if the module is non-resilient.
1 parent 4d28cc6 commit a0ae93d

File tree

14 files changed

+99
-23
lines changed

14 files changed

+99
-23
lines changed

include/swift/AST/DeclAttr.def

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -879,7 +879,12 @@ SIMPLE_DECL_ATTR(constInitialized, ConstInitialized,
879879
168)
880880
DECL_ATTR_FEATURE_REQUIREMENT(ConstInitialized, CompileTimeValues)
881881

882-
LAST_DECL_ATTR(ConstInitialized)
882+
SIMPLE_DECL_ATTR(extensible, Extensible,
883+
OnEnum,
884+
ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove | ForbiddenInABIAttr,
885+
169)
886+
887+
LAST_DECL_ATTR(Extensible)
883888

884889
#undef DECL_ATTR_ALIAS
885890
#undef CONTEXTUAL_DECL_ATTR_ALIAS

include/swift/AST/DiagnosticsSema.def

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8572,6 +8572,19 @@ GROUPED_WARNING(
85728572
"behavior",
85738573
(StringRef, DeclAttribute))
85748574

8575+
//===----------------------------------------------------------------------===//
8576+
// MARK: @extensible Attribute
8577+
//===----------------------------------------------------------------------===//
8578+
8579+
ERROR(extensible_attr_on_frozen_type,none,
8580+
"cannot use '@extensible' together with '@frozen'", ())
8581+
8582+
ERROR(extensible_attr_on_internal_type,none,
8583+
"'@extensible' attribute can only be applied to public or package "
8584+
"declarations, but %0 is "
8585+
"%select{private|fileprivate|internal|%error|%error|%error}1",
8586+
(DeclName, AccessLevel))
8587+
85758588
//===----------------------------------------------------------------------===//
85768589
// MARK: SwiftSettings
85778590
//===----------------------------------------------------------------------===//

lib/AST/ASTDumper.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4925,6 +4925,7 @@ class PrintAttribute : public AttributeVisitor<PrintAttribute, void, Label>,
49254925
TRIVIAL_ATTR_PRINTER(Used, used)
49264926
TRIVIAL_ATTR_PRINTER(WarnUnqualifiedAccess, warn_unqualified_access)
49274927
TRIVIAL_ATTR_PRINTER(WeakLinked, weak_linked)
4928+
TRIVIAL_ATTR_PRINTER(Extensible, extensible)
49284929

49294930
#undef TRIVIAL_ATTR_PRINTER
49304931

lib/AST/ASTPrinter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,7 @@ PrintOptions PrintOptions::printSwiftInterfaceFile(ModuleDecl *ModuleToPrint,
402402
DeclAttrKind::RestatedObjCConformance,
403403
DeclAttrKind::NonSendable,
404404
DeclAttrKind::AllowFeatureSuppression,
405+
DeclAttrKind::Extensible,
405406
};
406407

407408
return result;

lib/AST/Decl.cpp

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6854,14 +6854,11 @@ bool EnumDecl::treatAsExhaustiveForDiags(const DeclContext *useDC) const {
68546854
if (enumModule->inSamePackage(useDC->getParentModule()))
68556855
return true;
68566856

6857-
// If the module where enum is declared supports extensible enumerations
6858-
// and this enum is not explicitly marked as "@frozen", cross-module
6859-
// access cannot be exhaustive and requires `@unknown default:`.
6860-
if (enumModule->supportsExtensibleEnums() &&
6861-
!getAttrs().hasAttribute<FrozenAttr>()) {
6862-
if (useDC != enumModule->getDeclContext())
6863-
return false;
6864-
}
6857+
// When the enum is marked as `@extensible` cross-module access
6858+
// cannot be exhaustive and requires `@unknown default:`.
6859+
if (getAttrs().hasAttribute<ExtensibleAttr>() &&
6860+
enumModule != useDC->getParentModule())
6861+
return false;
68656862
}
68666863

68676864
return isFormallyExhaustive(useDC);

lib/ASTGen/Sources/ASTGen/DeclAttrs.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ extension ASTGenVisitor {
228228
.dynamicCallable,
229229
.eagerMove,
230230
.exported,
231+
.extensible,
231232
.discardableResult,
232233
.disfavoredOverload,
233234
.dynamicMemberLookup,

lib/Sema/TypeCheckAttr.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,21 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
241241
}
242242
}
243243

244+
void visitExtensibleAttr(ExtensibleAttr *attr) {
245+
auto *E = cast<EnumDecl>(D);
246+
247+
if (D->getAttrs().hasAttribute<FrozenAttr>()) {
248+
diagnoseAndRemoveAttr(attr, diag::extensible_attr_on_frozen_type);
249+
return;
250+
}
251+
252+
if (E->getFormalAccess() < AccessLevel::Package) {
253+
diagnoseAndRemoveAttr(attr, diag::extensible_attr_on_internal_type,
254+
E->getName(), E->getFormalAccess());
255+
return;
256+
}
257+
}
258+
244259
void visitAlignmentAttr(AlignmentAttr *attr) {
245260
// Alignment must be a power of two.
246261
auto value = attr->getValue();

lib/Sema/TypeCheckDeclOverride.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1615,6 +1615,7 @@ namespace {
16151615
UNINTERESTING_ATTR(Isolated)
16161616
UNINTERESTING_ATTR(Optimize)
16171617
UNINTERESTING_ATTR(Exclusivity)
1618+
UNINTERESTING_ATTR(Extensible)
16181619
UNINTERESTING_ATTR(NoLocks)
16191620
UNINTERESTING_ATTR(NoAllocation)
16201621
UNINTERESTING_ATTR(NoRuntime)

lib/Sema/TypeCheckSwitchStmt.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1159,10 +1159,7 @@ namespace {
11591159
auto *enumModule = theEnum->getParentModule();
11601160
shouldIncludeFutureVersionComment =
11611161
enumModule->isSystemModule() ||
1162-
enumModule->supportsExtensibleEnums();
1163-
// Since the module enabled `ExtensibleEnums` feature they
1164-
// opted-in all of their clients into exhaustivity errors.
1165-
shouldDowngradeToWarning = !enumModule->supportsExtensibleEnums();
1162+
theEnum->getAttrs().hasAttribute<ExtensibleAttr>();
11661163
}
11671164
DE.diagnose(startLoc, diag::non_exhaustive_switch_unknown_only,
11681165
subjectType, shouldIncludeFutureVersionComment)

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 = 933; // isConstantValue
61+
const uint16_t SWIFTMODULE_VERSION_MINOR = 934; // @extensible attribute
6262

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

0 commit comments

Comments
 (0)