Skip to content

Commit bcf38a1

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. (cherry picked from commit a0ae93d)
1 parent 49dbb15 commit bcf38a1

File tree

14 files changed

+98
-22
lines changed

14 files changed

+98
-22
lines changed

include/swift/AST/DeclAttr.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -876,6 +876,11 @@ SIMPLE_DECL_ATTR(constInitialized, ConstInitialized,
876876
168)
877877
DECL_ATTR_FEATURE_REQUIREMENT(ConstInitialized, CompileTimeValues)
878878

879+
SIMPLE_DECL_ATTR(extensible, Extensible,
880+
OnEnum,
881+
ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove | ForbiddenInABIAttr,
882+
169)
883+
879884
SIMPLE_DECL_ATTR(concurrent, Concurrent,
880885
OnFunc | OnConstructor | OnSubscript | OnVar,
881886
ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove | UnconstrainedInABIAttr,

include/swift/AST/DiagnosticsSema.def

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8711,6 +8711,19 @@ GROUPED_WARNING(
87118711
"behavior",
87128712
(StringRef))
87138713

8714+
//===----------------------------------------------------------------------===//
8715+
// MARK: @extensible Attribute
8716+
//===----------------------------------------------------------------------===//
8717+
8718+
ERROR(extensible_attr_on_frozen_type,none,
8719+
"cannot use '@extensible' together with '@frozen'", ())
8720+
8721+
ERROR(extensible_attr_on_internal_type,none,
8722+
"'@extensible' attribute can only be applied to public or package "
8723+
"declarations, but %0 is "
8724+
"%select{private|fileprivate|internal|%error|%error|%error}1",
8725+
(DeclName, AccessLevel))
8726+
87148727
//===----------------------------------------------------------------------===//
87158728
// MARK: `using` declaration
87168729
//===----------------------------------------------------------------------===//

lib/AST/ASTDumper.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5064,6 +5064,7 @@ class PrintAttribute : public AttributeVisitor<PrintAttribute, void, Label>,
50645064
TRIVIAL_ATTR_PRINTER(Used, used)
50655065
TRIVIAL_ATTR_PRINTER(WarnUnqualifiedAccess, warn_unqualified_access)
50665066
TRIVIAL_ATTR_PRINTER(WeakLinked, weak_linked)
5067+
TRIVIAL_ATTR_PRINTER(Extensible, extensible)
50675068
TRIVIAL_ATTR_PRINTER(Concurrent, concurrent)
50685069

50695070
#undef TRIVIAL_ATTR_PRINTER

lib/AST/ASTPrinter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,7 @@ PrintOptions PrintOptions::printSwiftInterfaceFile(ModuleDecl *ModuleToPrint,
407407
DeclAttrKind::RestatedObjCConformance,
408408
DeclAttrKind::NonSendable,
409409
DeclAttrKind::AllowFeatureSuppression,
410+
DeclAttrKind::Extensible,
410411
};
411412

412413
return result;

lib/AST/Decl.cpp

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

7030-
// If the module where enum is declared supports extensible enumerations
7031-
// and this enum is not explicitly marked as "@frozen", cross-module
7032-
// access cannot be exhaustive and requires `@unknown default:`.
7033-
if (enumModule->supportsExtensibleEnums() &&
7034-
!getAttrs().hasAttribute<FrozenAttr>()) {
7035-
if (useDC != enumModule->getDeclContext())
7036-
return false;
7037-
}
7030+
// When the enum is marked as `@extensible` cross-module access
7031+
// cannot be exhaustive and requires `@unknown default:`.
7032+
if (getAttrs().hasAttribute<ExtensibleAttr>() &&
7033+
enumModule != useDC->getParentModule())
7034+
return false;
70387035
}
70397036

70407037
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
@@ -247,6 +247,21 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
247247
}
248248
}
249249

250+
void visitExtensibleAttr(ExtensibleAttr *attr) {
251+
auto *E = cast<EnumDecl>(D);
252+
253+
if (D->getAttrs().hasAttribute<FrozenAttr>()) {
254+
diagnoseAndRemoveAttr(attr, diag::extensible_attr_on_frozen_type);
255+
return;
256+
}
257+
258+
if (E->getFormalAccess() < AccessLevel::Package) {
259+
diagnoseAndRemoveAttr(attr, diag::extensible_attr_on_internal_type,
260+
E->getName(), E->getFormalAccess());
261+
return;
262+
}
263+
}
264+
250265
void visitAlignmentAttr(AlignmentAttr *attr) {
251266
// Alignment must be a power of two.
252267
auto value = attr->getValue();

lib/Sema/TypeCheckDeclOverride.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1616,6 +1616,7 @@ namespace {
16161616
UNINTERESTING_ATTR(Isolated)
16171617
UNINTERESTING_ATTR(Optimize)
16181618
UNINTERESTING_ATTR(Exclusivity)
1619+
UNINTERESTING_ATTR(Extensible)
16191620
UNINTERESTING_ATTR(NoLocks)
16201621
UNINTERESTING_ATTR(NoAllocation)
16211622
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 = 944; // nonisolated(nonsending) isolation was moved
61+
const uint16_t SWIFTMODULE_VERSION_MINOR = 945; // @extensible attribute
6262

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

0 commit comments

Comments
 (0)