Skip to content

Commit f408b2d

Browse files
authored
Merge pull request #82922 from xedin/nonexhaustive-enums-6.2
[6.2][AST/Sema] SE-0487: Implement `@nonexhaustive` attribute and new enum exhaustivity checking rule
2 parents a57432a + bdb25f4 commit f408b2d

35 files changed

+316
-208
lines changed

include/swift/AST/Attr.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,10 @@ class DeclAttribute : public AttributeBase {
244244
SWIFT_INLINE_BITFIELD(LifetimeAttr, DeclAttribute, 1,
245245
isUnderscored : 1
246246
);
247+
248+
SWIFT_INLINE_BITFIELD(NonexhaustiveAttr, DeclAttribute, NumNonexhaustiveModeBits,
249+
mode : NumNonexhaustiveModeBits
250+
);
247251
} Bits;
248252
// clang-format on
249253

@@ -3334,6 +3338,35 @@ class ABIAttr : public DeclAttribute {
33343338
}
33353339
};
33363340

3341+
/// Defines a @nonexhaustive attribute.
3342+
class NonexhaustiveAttr : public DeclAttribute {
3343+
public:
3344+
NonexhaustiveAttr(SourceLoc atLoc, SourceRange range, NonexhaustiveMode mode,
3345+
bool implicit = false)
3346+
: DeclAttribute(DeclAttrKind::Nonexhaustive, atLoc, range, implicit) {
3347+
Bits.NonexhaustiveAttr.mode = unsigned(mode);
3348+
}
3349+
3350+
NonexhaustiveAttr(NonexhaustiveMode mode)
3351+
: NonexhaustiveAttr(SourceLoc(), SourceRange(), mode) {}
3352+
3353+
NonexhaustiveMode getMode() const {
3354+
return NonexhaustiveMode(Bits.NonexhaustiveAttr.mode);
3355+
}
3356+
3357+
static bool classof(const DeclAttribute *DA) {
3358+
return DA->getKind() == DeclAttrKind::Nonexhaustive;
3359+
}
3360+
3361+
NonexhaustiveAttr *clone(ASTContext &ctx) const {
3362+
return new (ctx) NonexhaustiveAttr(AtLoc, Range, getMode(), isImplicit());
3363+
}
3364+
3365+
bool isEquivalent(const NonexhaustiveAttr *other, Decl *attachedTo) const {
3366+
return getMode() == other->getMode();
3367+
}
3368+
};
3369+
33373370
/// Attributes that may be applied to declarations.
33383371
class DeclAttributes {
33393372
/// Linked list of declaration attributes.

include/swift/AST/AttrKind.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,17 @@ enum : unsigned {
158158
InheritActorContextModifier::Last_InheritActorContextKind))
159159
};
160160

161+
enum class NonexhaustiveMode : uint8_t {
162+
Error = 0,
163+
Warning,
164+
Last_NonexhaustiveMode = Warning
165+
};
166+
167+
enum : unsigned {
168+
NumNonexhaustiveModeBits = countBitsUsed(static_cast<unsigned>(
169+
NonexhaustiveMode::Last_NonexhaustiveMode))
170+
};
171+
161172
enum class DeclAttrKind : unsigned {
162173
#define DECL_ATTR(_, CLASS, ...) CLASS,
163174
#define LAST_DECL_ATTR(CLASS) Last_DeclAttr = CLASS,

include/swift/AST/Decl.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -751,7 +751,7 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl>, public Swi
751751
HasAnyUnavailableDuringLoweringValues : 1
752752
);
753753

754-
SWIFT_INLINE_BITFIELD(ModuleDecl, TypeDecl, 1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+8,
754+
SWIFT_INLINE_BITFIELD(ModuleDecl, TypeDecl, 1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+8,
755755
/// If the module is compiled as static library.
756756
StaticLibrary : 1,
757757

@@ -820,10 +820,7 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl>, public Swi
820820
SerializePackageEnabled : 1,
821821

822822
/// Whether this module has enabled strict memory safety checking.
823-
StrictMemorySafety : 1,
824-
825-
/// Whether this module has enabled `ExtensibleEnums` feature.
826-
ExtensibleEnums : 1
823+
StrictMemorySafety : 1
827824
);
828825

829826
SWIFT_INLINE_BITFIELD(PrecedenceGroupDecl, Decl, 1+2,

include/swift/AST/DeclAttr.def

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

879+
DECL_ATTR(nonexhaustive, Nonexhaustive,
880+
OnEnum,
881+
ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove | ForbiddenInABIAttr,
882+
169)
883+
DECL_ATTR_FEATURE_REQUIREMENT(Nonexhaustive, NonexhaustiveAttribute)
884+
879885
SIMPLE_DECL_ATTR(concurrent, Concurrent,
880886
OnFunc | OnConstructor | OnSubscript | OnVar,
881887
ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove | UnconstrainedInABIAttr,
882888
170)
883889

890+
// Unused '171': Used to be `@preEnumExtensibility`
891+
884892
LAST_DECL_ATTR(Concurrent)
885893

886894
#undef DECL_ATTR_ALIAS

include/swift/AST/DiagnosticsSema.def

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8714,6 +8714,19 @@ GROUPED_WARNING(
87148714
"behavior",
87158715
(StringRef))
87168716

8717+
//===----------------------------------------------------------------------===//
8718+
// MARK: @nonexhaustive and @preEnumExtensibility Attributes
8719+
//===----------------------------------------------------------------------===//
8720+
8721+
ERROR(nonexhaustive_attr_on_frozen_type,none,
8722+
"cannot use '@nonexhaustive' together with '@frozen'", ())
8723+
8724+
ERROR(nonexhaustive_attr_on_internal_type,none,
8725+
"'@nonexhaustive' attribute can only be applied to public or package "
8726+
"declarations, but %0 is "
8727+
"%select{private|fileprivate|internal|%error|%error|%error}1",
8728+
(DeclName, AccessLevel))
8729+
87178730
//===----------------------------------------------------------------------===//
87188731
// MARK: `using` declaration
87198732
//===----------------------------------------------------------------------===//

include/swift/AST/KnownIdentifiers.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ IDENTIFIER(value)
169169
IDENTIFIER_WITH_NAME(value_, "_value")
170170
IDENTIFIER(Void)
171171
IDENTIFIER(WinSDK)
172+
IDENTIFIER(warn)
172173
IDENTIFIER(with)
173174
IDENTIFIER(withArguments)
174175
IDENTIFIER(withKeywordArguments)

include/swift/AST/Module.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -835,14 +835,6 @@ class ModuleDecl
835835
Bits.ModuleDecl.ObjCNameLookupCachePopulated = value;
836836
}
837837

838-
bool supportsExtensibleEnums() const {
839-
return Bits.ModuleDecl.ExtensibleEnums;
840-
}
841-
842-
void setSupportsExtensibleEnums(bool value = true) {
843-
Bits.ModuleDecl.ExtensibleEnums = value;
844-
}
845-
846838
/// For the main module, retrieves the list of primary source files being
847839
/// compiled, that is, the files we're generating code for.
848840
ArrayRef<SourceFile *> getPrimarySourceFiles() const;

include/swift/Basic/Features.def

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@ LANGUAGE_FEATURE(BuiltinSelect, 0, "Builtin.select")
268268
LANGUAGE_FEATURE(AlwaysInheritActorContext, 472, "@_inheritActorContext(always)")
269269
LANGUAGE_FEATURE(NonescapableAccessorOnTrivial, 0, "Support UnsafeMutablePointer.mutableSpan")
270270
LANGUAGE_FEATURE(InlineArrayTypeSugar, 483, "Type sugar for InlineArray")
271+
SUPPRESSIBLE_LANGUAGE_FEATURE(NonexhaustiveAttribute, 487, "Nonexhaustive Enums")
271272

272273
// Swift 6
273274
UPCOMING_FEATURE(ConciseMagicFile, 274, 6)
@@ -505,11 +506,6 @@ SUPPRESSIBLE_EXPERIMENTAL_FEATURE(AddressableTypes, true)
505506
/// Allow custom availability domains to be defined and referenced.
506507
EXPERIMENTAL_FEATURE(CustomAvailability, true)
507508

508-
/// Allow public enumerations to be extensible by default
509-
/// regardless of whether the module they are declared in
510-
/// is resilient or not.
511-
EXPERIMENTAL_FEATURE(ExtensibleEnums, true)
512-
513509
/// Syntax sugar features for concurrency.
514510
EXPERIMENTAL_FEATURE(ConcurrencySyntaxSugar, true)
515511

include/swift/Parse/IDEInspectionCallbacks.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ enum class ParameterizedDeclAttributeKind {
4040
FreestandingMacro,
4141
AttachedMacro,
4242
StorageRestrictions,
43-
InheritActorContext
43+
InheritActorContext,
44+
Nonexhaustive,
4445
};
4546

4647
/// A bit of a hack. When completing inside the '@storageRestrictions'

include/swift/Serialization/Validation.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,6 @@ class ExtendedValidationInfo {
150150
unsigned AllowNonResilientAccess: 1;
151151
unsigned SerializePackageEnabled: 1;
152152
unsigned StrictMemorySafety: 1;
153-
unsigned SupportsExtensibleEnums : 1;
154153
} Bits;
155154

156155
public:
@@ -272,11 +271,6 @@ class ExtendedValidationInfo {
272271
version, SourceLoc(), /*Diags=*/nullptr))
273272
SwiftInterfaceCompilerVersion = genericVersion.value();
274273
}
275-
276-
bool supportsExtensibleEnums() const { return Bits.SupportsExtensibleEnums; }
277-
void setSupportsExtensibleEnums(bool val) {
278-
Bits.SupportsExtensibleEnums = val;
279-
}
280274
};
281275

282276
struct SearchPath {

0 commit comments

Comments
 (0)