mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
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
This commit is contained in:
@@ -244,6 +244,10 @@ protected:
|
||||
SWIFT_INLINE_BITFIELD(LifetimeAttr, DeclAttribute, 1,
|
||||
isUnderscored : 1
|
||||
);
|
||||
|
||||
SWIFT_INLINE_BITFIELD(NonexhaustiveAttr, DeclAttribute, NumNonexhaustiveModeBits,
|
||||
mode : NumNonexhaustiveModeBits
|
||||
);
|
||||
} Bits;
|
||||
// clang-format on
|
||||
|
||||
@@ -3334,6 +3338,35 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/// Defines a @nonexhaustive attribute.
|
||||
class NonexhaustiveAttr : public DeclAttribute {
|
||||
public:
|
||||
NonexhaustiveAttr(SourceLoc atLoc, SourceRange range, NonexhaustiveMode mode,
|
||||
bool implicit = false)
|
||||
: DeclAttribute(DeclAttrKind::Nonexhaustive, atLoc, range, implicit) {
|
||||
Bits.NonexhaustiveAttr.mode = unsigned(mode);
|
||||
}
|
||||
|
||||
NonexhaustiveAttr(NonexhaustiveMode mode)
|
||||
: NonexhaustiveAttr(SourceLoc(), SourceRange(), mode) {}
|
||||
|
||||
NonexhaustiveMode getMode() const {
|
||||
return NonexhaustiveMode(Bits.NonexhaustiveAttr.mode);
|
||||
}
|
||||
|
||||
static bool classof(const DeclAttribute *DA) {
|
||||
return DA->getKind() == DeclAttrKind::Nonexhaustive;
|
||||
}
|
||||
|
||||
NonexhaustiveAttr *clone(ASTContext &ctx) const {
|
||||
return new (ctx) NonexhaustiveAttr(AtLoc, Range, getMode(), isImplicit());
|
||||
}
|
||||
|
||||
bool isEquivalent(const NonexhaustiveAttr *other, Decl *attachedTo) const {
|
||||
return getMode() == other->getMode();
|
||||
}
|
||||
};
|
||||
|
||||
/// Attributes that may be applied to declarations.
|
||||
class DeclAttributes {
|
||||
/// Linked list of declaration attributes.
|
||||
|
||||
@@ -158,6 +158,17 @@ enum : unsigned {
|
||||
InheritActorContextModifier::Last_InheritActorContextKind))
|
||||
};
|
||||
|
||||
enum class NonexhaustiveMode : uint8_t {
|
||||
Error = 0,
|
||||
Warning,
|
||||
Last_NonexhaustiveMode = Warning
|
||||
};
|
||||
|
||||
enum : unsigned {
|
||||
NumNonexhaustiveModeBits = countBitsUsed(static_cast<unsigned>(
|
||||
NonexhaustiveMode::Last_NonexhaustiveMode))
|
||||
};
|
||||
|
||||
enum class DeclAttrKind : unsigned {
|
||||
#define DECL_ATTR(_, CLASS, ...) CLASS,
|
||||
#define LAST_DECL_ATTR(CLASS) Last_DeclAttr = CLASS,
|
||||
|
||||
@@ -751,7 +751,7 @@ protected:
|
||||
HasAnyUnavailableDuringLoweringValues : 1
|
||||
);
|
||||
|
||||
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,
|
||||
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,
|
||||
/// If the module is compiled as static library.
|
||||
StaticLibrary : 1,
|
||||
|
||||
@@ -820,10 +820,7 @@ protected:
|
||||
SerializePackageEnabled : 1,
|
||||
|
||||
/// Whether this module has enabled strict memory safety checking.
|
||||
StrictMemorySafety : 1,
|
||||
|
||||
/// Whether this module has enabled `ExtensibleEnums` feature.
|
||||
ExtensibleEnums : 1
|
||||
StrictMemorySafety : 1
|
||||
);
|
||||
|
||||
SWIFT_INLINE_BITFIELD(PrecedenceGroupDecl, Decl, 1+2,
|
||||
|
||||
@@ -876,11 +876,19 @@ SIMPLE_DECL_ATTR(constInitialized, ConstInitialized,
|
||||
168)
|
||||
DECL_ATTR_FEATURE_REQUIREMENT(ConstInitialized, CompileTimeValues)
|
||||
|
||||
DECL_ATTR(nonexhaustive, Nonexhaustive,
|
||||
OnEnum,
|
||||
ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove | ForbiddenInABIAttr,
|
||||
169)
|
||||
DECL_ATTR_FEATURE_REQUIREMENT(Nonexhaustive, NonexhaustiveAttribute)
|
||||
|
||||
SIMPLE_DECL_ATTR(concurrent, Concurrent,
|
||||
OnFunc | OnConstructor | OnSubscript | OnVar,
|
||||
ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove | UnconstrainedInABIAttr,
|
||||
170)
|
||||
|
||||
// Unused '171': Used to be `@preEnumExtensibility`
|
||||
|
||||
LAST_DECL_ATTR(Concurrent)
|
||||
|
||||
#undef DECL_ATTR_ALIAS
|
||||
|
||||
@@ -8714,6 +8714,19 @@ GROUPED_WARNING(
|
||||
"behavior",
|
||||
(StringRef))
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// MARK: @nonexhaustive and @preEnumExtensibility Attributes
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
ERROR(nonexhaustive_attr_on_frozen_type,none,
|
||||
"cannot use '@nonexhaustive' together with '@frozen'", ())
|
||||
|
||||
ERROR(nonexhaustive_attr_on_internal_type,none,
|
||||
"'@nonexhaustive' attribute can only be applied to public or package "
|
||||
"declarations, but %0 is "
|
||||
"%select{private|fileprivate|internal|%error|%error|%error}1",
|
||||
(DeclName, AccessLevel))
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// MARK: `using` declaration
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -169,6 +169,7 @@ IDENTIFIER(value)
|
||||
IDENTIFIER_WITH_NAME(value_, "_value")
|
||||
IDENTIFIER(Void)
|
||||
IDENTIFIER(WinSDK)
|
||||
IDENTIFIER(warn)
|
||||
IDENTIFIER(with)
|
||||
IDENTIFIER(withArguments)
|
||||
IDENTIFIER(withKeywordArguments)
|
||||
|
||||
@@ -835,14 +835,6 @@ public:
|
||||
Bits.ModuleDecl.ObjCNameLookupCachePopulated = value;
|
||||
}
|
||||
|
||||
bool supportsExtensibleEnums() const {
|
||||
return Bits.ModuleDecl.ExtensibleEnums;
|
||||
}
|
||||
|
||||
void setSupportsExtensibleEnums(bool value = true) {
|
||||
Bits.ModuleDecl.ExtensibleEnums = value;
|
||||
}
|
||||
|
||||
/// For the main module, retrieves the list of primary source files being
|
||||
/// compiled, that is, the files we're generating code for.
|
||||
ArrayRef<SourceFile *> getPrimarySourceFiles() const;
|
||||
|
||||
@@ -268,6 +268,7 @@ LANGUAGE_FEATURE(BuiltinSelect, 0, "Builtin.select")
|
||||
LANGUAGE_FEATURE(AlwaysInheritActorContext, 472, "@_inheritActorContext(always)")
|
||||
LANGUAGE_FEATURE(NonescapableAccessorOnTrivial, 0, "Support UnsafeMutablePointer.mutableSpan")
|
||||
LANGUAGE_FEATURE(InlineArrayTypeSugar, 483, "Type sugar for InlineArray")
|
||||
SUPPRESSIBLE_LANGUAGE_FEATURE(NonexhaustiveAttribute, 487, "Nonexhaustive Enums")
|
||||
|
||||
// Swift 6
|
||||
UPCOMING_FEATURE(ConciseMagicFile, 274, 6)
|
||||
@@ -505,11 +506,6 @@ SUPPRESSIBLE_EXPERIMENTAL_FEATURE(AddressableTypes, true)
|
||||
/// Allow custom availability domains to be defined and referenced.
|
||||
EXPERIMENTAL_FEATURE(CustomAvailability, true)
|
||||
|
||||
/// Allow public enumerations to be extensible by default
|
||||
/// regardless of whether the module they are declared in
|
||||
/// is resilient or not.
|
||||
EXPERIMENTAL_FEATURE(ExtensibleEnums, true)
|
||||
|
||||
/// Syntax sugar features for concurrency.
|
||||
EXPERIMENTAL_FEATURE(ConcurrencySyntaxSugar, true)
|
||||
|
||||
|
||||
@@ -40,7 +40,8 @@ enum class ParameterizedDeclAttributeKind {
|
||||
FreestandingMacro,
|
||||
AttachedMacro,
|
||||
StorageRestrictions,
|
||||
InheritActorContext
|
||||
InheritActorContext,
|
||||
Nonexhaustive,
|
||||
};
|
||||
|
||||
/// A bit of a hack. When completing inside the '@storageRestrictions'
|
||||
|
||||
@@ -150,7 +150,6 @@ class ExtendedValidationInfo {
|
||||
unsigned AllowNonResilientAccess: 1;
|
||||
unsigned SerializePackageEnabled: 1;
|
||||
unsigned StrictMemorySafety: 1;
|
||||
unsigned SupportsExtensibleEnums : 1;
|
||||
} Bits;
|
||||
|
||||
public:
|
||||
@@ -272,11 +271,6 @@ public:
|
||||
version, SourceLoc(), /*Diags=*/nullptr))
|
||||
SwiftInterfaceCompilerVersion = genericVersion.value();
|
||||
}
|
||||
|
||||
bool supportsExtensibleEnums() const { return Bits.SupportsExtensibleEnums; }
|
||||
void setSupportsExtensibleEnums(bool val) {
|
||||
Bits.SupportsExtensibleEnums = val;
|
||||
}
|
||||
};
|
||||
|
||||
struct SearchPath {
|
||||
|
||||
Reference in New Issue
Block a user