diff --git a/include/swift/AST/Attr.h b/include/swift/AST/Attr.h index 7a1e809f293fe..d6aa76eba9c81 100644 --- a/include/swift/AST/Attr.h +++ b/include/swift/AST/Attr.h @@ -136,6 +136,11 @@ enum : unsigned { InheritActorContextModifier::Last_InheritActorContextKind)) }; +enum : unsigned { + NumNonexhaustiveModeBits = countBitsUsed( + static_cast(NonexhaustiveMode::Last_NonexhaustiveMode)) +}; + enum : unsigned { NumDeclAttrKindBits = countBitsUsed(NumDeclAttrKinds - 1) }; enum : unsigned { NumTypeAttrKindBits = countBitsUsed(NumTypeAttrKinds - 1) }; @@ -277,6 +282,10 @@ class DeclAttribute : public AttributeBase { SWIFT_INLINE_BITFIELD(LifetimeAttr, DeclAttribute, 1, isUnderscored : 1 ); + + SWIFT_INLINE_BITFIELD(NonexhaustiveAttr, DeclAttribute, NumNonexhaustiveModeBits, + mode : NumNonexhaustiveModeBits + ); } Bits; // clang-format on @@ -3500,6 +3509,36 @@ class ABIAttr : public DeclAttribute { } }; +/// 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(); + } +}; + + /// The kind of unary operator, if any. enum class UnaryOperatorKind : uint8_t { None, Prefix, Postfix }; diff --git a/include/swift/AST/AttrKind.h b/include/swift/AST/AttrKind.h index f18642887279c..aa9196aea1cf8 100644 --- a/include/swift/AST/AttrKind.h +++ b/include/swift/AST/AttrKind.h @@ -135,6 +135,12 @@ enum class ENUM_EXTENSIBILITY_ATTR(closed) Last_InheritActorContextKind = Always }; +enum class ENUM_EXTENSIBILITY_ATTR(closed) NonexhaustiveMode : uint8_t { + Error SWIFT_NAME("error") = 0, + Warning SWIFT_NAME("warning") = 1, + Last_NonexhaustiveMode = Warning +}; + enum class ENUM_EXTENSIBILITY_ATTR(closed) DeclAttrKind : unsigned { #define DECL_ATTR(_, CLASS, ...) CLASS, #define LAST_DECL_ATTR(CLASS) Last_DeclAttr = CLASS, diff --git a/include/swift/AST/DeclAttr.def b/include/swift/AST/DeclAttr.def index a7d827a837b8c..51ed6e7808f39 100644 --- a/include/swift/AST/DeclAttr.def +++ b/include/swift/AST/DeclAttr.def @@ -877,22 +877,18 @@ SIMPLE_DECL_ATTR(constInitialized, ConstInitialized, 168) DECL_ATTR_FEATURE_REQUIREMENT(ConstInitialized, CompileTimeValues) -SIMPLE_DECL_ATTR(extensible, Extensible, +DECL_ATTR(nonexhaustive, Nonexhaustive, OnEnum, ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove | ForbiddenInABIAttr, 169) -DECL_ATTR_FEATURE_REQUIREMENT(Extensible, ExtensibleAttribute) +DECL_ATTR_FEATURE_REQUIREMENT(Nonexhaustive, NonexhaustiveAttribute) SIMPLE_DECL_ATTR(concurrent, Concurrent, OnFunc | OnConstructor | OnSubscript | OnVar, ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove | UnconstrainedInABIAttr, 170) -SIMPLE_DECL_ATTR(preEnumExtensibility, PreEnumExtensibility, - OnEnum, - ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIBreakingToRemove | UnconstrainedInABIAttr, - 171) -DECL_ATTR_FEATURE_REQUIREMENT(PreEnumExtensibility, ExtensibleAttribute) +// Unused '171': Used to be `@preEnumExtensibility` DECL_ATTR(specialized, Specialized, OnConstructor | OnFunc | OnAccessor, diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 4b1f41ca64aab..e968c6cd4aece 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -8799,21 +8799,18 @@ GROUPED_WARNING( (StringRef)) //===----------------------------------------------------------------------===// -// MARK: @extensible and @preEnumExtensibility Attributes +// MARK: @nonexhaustive and @preEnumExtensibility Attributes //===----------------------------------------------------------------------===// -ERROR(extensible_attr_on_frozen_type,none, - "cannot use '@extensible' together with '@frozen'", ()) +ERROR(nonexhaustive_attr_on_frozen_type,none, + "cannot use '@nonexhaustive' together with '@frozen'", ()) -ERROR(extensible_attr_on_internal_type,none, - "'@extensible' attribute can only be applied to public or package " +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)) -ERROR(pre_enum_extensibility_without_extensible,none, - "%0 can only be used together with '@extensible' attribute", (DeclAttribute)) - //===----------------------------------------------------------------------===// // MARK: `using` declaration //===----------------------------------------------------------------------===// diff --git a/include/swift/AST/KnownIdentifiers.def b/include/swift/AST/KnownIdentifiers.def index 8be2729b9376a..a9728b0ea31fb 100644 --- a/include/swift/AST/KnownIdentifiers.def +++ b/include/swift/AST/KnownIdentifiers.def @@ -169,6 +169,7 @@ IDENTIFIER(value) IDENTIFIER_WITH_NAME(value_, "_value") IDENTIFIER(Void) IDENTIFIER(WinSDK) +IDENTIFIER(warn) IDENTIFIER(with) IDENTIFIER(withArguments) IDENTIFIER(withKeywordArguments) diff --git a/include/swift/Basic/Features.def b/include/swift/Basic/Features.def index d2b5b5266a34b..f7f70e8eecc74 100644 --- a/include/swift/Basic/Features.def +++ b/include/swift/Basic/Features.def @@ -519,8 +519,8 @@ EXPERIMENTAL_FEATURE(AllowRuntimeSymbolDeclarations, true) /// Allow use of `@cdecl` EXPERIMENTAL_FEATURE(CDecl, false) -/// Allow use of `@extensible` on public enums -SUPPRESSIBLE_EXPERIMENTAL_FEATURE(ExtensibleAttribute, false) +/// Allow use of `@nonexhaustive` on public enums +SUPPRESSIBLE_EXPERIMENTAL_FEATURE(NonexhaustiveAttribute, false) /// Allow use of `Module::name` syntax EXPERIMENTAL_FEATURE(ModuleSelector, false) diff --git a/include/swift/Parse/IDEInspectionCallbacks.h b/include/swift/Parse/IDEInspectionCallbacks.h index 45c2634cbdd8e..7147a5f945c5d 100644 --- a/include/swift/Parse/IDEInspectionCallbacks.h +++ b/include/swift/Parse/IDEInspectionCallbacks.h @@ -40,7 +40,8 @@ enum class ParameterizedDeclAttributeKind { FreestandingMacro, AttachedMacro, StorageRestrictions, - InheritActorContext + InheritActorContext, + Nonexhaustive, }; /// A bit of a hack. When completing inside the '@storageRestrictions' diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index d36bfdf9b1aa0..a320104d9fc09 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -5047,9 +5047,8 @@ class PrintAttribute : public AttributeVisitor, TRIVIAL_ATTR_PRINTER(Used, used) TRIVIAL_ATTR_PRINTER(WarnUnqualifiedAccess, warn_unqualified_access) TRIVIAL_ATTR_PRINTER(WeakLinked, weak_linked) - TRIVIAL_ATTR_PRINTER(Extensible, extensible) + TRIVIAL_ATTR_PRINTER(Nonexhaustive, nonexhaustive) TRIVIAL_ATTR_PRINTER(Concurrent, concurrent) - TRIVIAL_ATTR_PRINTER(PreEnumExtensibility, preEnumExtensibility) #undef TRIVIAL_ATTR_PRINTER diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index 81ae267421721..bcbac3a89b5a4 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -3325,10 +3325,9 @@ suppressingFeatureAddressableTypes(PrintOptions &options, } static void -suppressingFeatureExtensibleAttribute(PrintOptions &options, - llvm::function_ref action) { - ExcludeAttrRAII scope1(options.ExcludeAttrList, DeclAttrKind::Extensible); - ExcludeAttrRAII scope2(options.ExcludeAttrList, DeclAttrKind::PreEnumExtensibility); +suppressingFeatureNonexhaustiveAttribute(PrintOptions &options, + llvm::function_ref action) { + ExcludeAttrRAII scope(options.ExcludeAttrList, DeclAttrKind::Nonexhaustive); action(); } diff --git a/lib/AST/Attr.cpp b/lib/AST/Attr.cpp index 744b7c3b65a8e..e08808d49d603 100644 --- a/lib/AST/Attr.cpp +++ b/lib/AST/Attr.cpp @@ -1732,6 +1732,19 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options, break; } + case DeclAttrKind::Nonexhaustive: { + auto *attr = cast(this); + Printer << "@nonexhaustive"; + switch (attr->getMode()) { + case NonexhaustiveMode::Error: + break; + case NonexhaustiveMode::Warning: + Printer << "(warn)"; + break; + } + break; + } + #define SIMPLE_DECL_ATTR(X, CLASS, ...) case DeclAttrKind::CLASS: #include "swift/AST/DeclAttr.def" llvm_unreachable("handled above"); @@ -1967,6 +1980,8 @@ StringRef DeclAttribute::getAttrName() const { } case DeclAttrKind::Lifetime: return cast(this)->isUnderscored() ? "_lifetime" : "lifetime"; + case DeclAttrKind::Nonexhaustive: + return "nonexhaustive"; } llvm_unreachable("bad DeclAttrKind"); } diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 2ba6baf3a7461..6a67aae895d0d 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -7035,9 +7035,9 @@ bool EnumDecl::treatAsExhaustiveForDiags(const DeclContext *useDC) const { if (enumModule->inSamePackage(useDC->getParentModule())) return true; - // When the enum is marked as `@extensible` cross-module access + // When the enum is marked as `@nonexhaustive` cross-module access // cannot be exhaustive and requires `@unknown default:`. - if (getAttrs().hasAttribute() && + if (getAttrs().hasAttribute() && enumModule != useDC->getParentModule()) return false; } diff --git a/lib/AST/FeatureSet.cpp b/lib/AST/FeatureSet.cpp index 9c0b7ac8200e5..4c603336de472 100644 --- a/lib/AST/FeatureSet.cpp +++ b/lib/AST/FeatureSet.cpp @@ -667,8 +667,8 @@ static bool usesFeatureAsyncExecutionBehaviorAttributes(Decl *decl) { return false; } -static bool usesFeatureExtensibleAttribute(Decl *decl) { - return decl->getAttrs().hasAttribute(); +static bool usesFeatureNonexhaustiveAttribute(Decl *decl) { + return decl->getAttrs().hasAttribute(); } static bool usesFeatureAlwaysInheritActorContext(Decl *decl) { diff --git a/lib/ASTGen/Sources/ASTGen/DeclAttrs.swift b/lib/ASTGen/Sources/ASTGen/DeclAttrs.swift index 962ffe5b6487b..4ff2f698add29 100644 --- a/lib/ASTGen/Sources/ASTGen/DeclAttrs.swift +++ b/lib/ASTGen/Sources/ASTGen/DeclAttrs.swift @@ -239,8 +239,7 @@ extension ASTGenVisitor { .DynamicCallable, .EagerMove, .Exported, - .Extensible, - .PreEnumExtensibility, + .Nonexhaustive, .DiscardableResult, .DisfavoredOverload, .DynamicMemberLookup, diff --git a/lib/IDE/CompletionLookup.cpp b/lib/IDE/CompletionLookup.cpp index 21c4de6ac465d..ed8d108fa72db 100644 --- a/lib/IDE/CompletionLookup.cpp +++ b/lib/IDE/CompletionLookup.cpp @@ -3278,6 +3278,11 @@ void CompletionLookup::getAttributeDeclParamCompletions( getStoredPropertyCompletions(NT); } } + break; + } + case ParameterizedDeclAttributeKind::Nonexhaustive: { + addDeclAttrParamKeyword("warn", /*Parameters=*/{}, "", false); + break; } } } diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index fcb11e0e89d29..78de6ddde3484 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -4033,6 +4033,21 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes, Attributes.add(Attr.get()); break; } + + case DeclAttrKind::Nonexhaustive: { + auto mode = parseSingleAttrOption( + *this, Loc, AttrRange, AttrName, DK, + {{Context.Id_warn, NonexhaustiveMode::Warning}}, + NonexhaustiveMode::Error, + ParameterizedDeclAttributeKind::Nonexhaustive); + if (!mode) + return makeParserSuccess(); + + if (!DiscardAttribute) + Attributes.add(new (Context) NonexhaustiveAttr(AtLoc, AttrRange, *mode)); + + break; + } } if (DuplicateAttribute) { diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index 72823e718a73b..b933b22380765 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -233,29 +233,21 @@ class AttributeChecker : public AttributeVisitor { } } - void visitExtensibleAttr(ExtensibleAttr *attr) { + void visitNonexhaustiveAttr(NonexhaustiveAttr *attr) { auto *E = cast(D); if (D->getAttrs().hasAttribute()) { - diagnoseAndRemoveAttr(attr, diag::extensible_attr_on_frozen_type); + diagnoseAndRemoveAttr(attr, diag::nonexhaustive_attr_on_frozen_type); return; } if (E->getFormalAccess() < AccessLevel::Package) { - diagnoseAndRemoveAttr(attr, diag::extensible_attr_on_internal_type, + diagnoseAndRemoveAttr(attr, diag::nonexhaustive_attr_on_internal_type, E->getName(), E->getFormalAccess()); return; } } - void visitPreEnumExtensibilityAttr(PreEnumExtensibilityAttr *attr) { - if (!D->getAttrs().hasAttribute()) { - diagnoseAndRemoveAttr( - attr, diag::pre_enum_extensibility_without_extensible, attr); - return; - } - } - void visitConcurrentAttr(ConcurrentAttr *attr) { checkExecutionBehaviorAttribute(attr); diff --git a/lib/Sema/TypeCheckDeclOverride.cpp b/lib/Sema/TypeCheckDeclOverride.cpp index c2b9d89d69df1..dc0a7a10f3d01 100644 --- a/lib/Sema/TypeCheckDeclOverride.cpp +++ b/lib/Sema/TypeCheckDeclOverride.cpp @@ -1614,8 +1614,7 @@ namespace { UNINTERESTING_ATTR(Isolated) UNINTERESTING_ATTR(Optimize) UNINTERESTING_ATTR(Exclusivity) - UNINTERESTING_ATTR(Extensible) - UNINTERESTING_ATTR(PreEnumExtensibility) + UNINTERESTING_ATTR(Nonexhaustive) UNINTERESTING_ATTR(NoLocks) UNINTERESTING_ATTR(NoAllocation) UNINTERESTING_ATTR(NoRuntime) diff --git a/lib/Sema/TypeCheckSwitchStmt.cpp b/lib/Sema/TypeCheckSwitchStmt.cpp index e537bad054781..2dcc2b59297df 100644 --- a/lib/Sema/TypeCheckSwitchStmt.cpp +++ b/lib/Sema/TypeCheckSwitchStmt.cpp @@ -1160,21 +1160,27 @@ namespace { auto *enumModule = theEnum->getParentModule(); shouldIncludeFutureVersionComment = enumModule->isSystemModule() || - theEnum->getAttrs().hasAttribute(); + theEnum->getAttrs().hasAttribute(); } auto diag = DE.diagnose(startLoc, diag::non_exhaustive_switch_unknown_only, subjectType, shouldIncludeFutureVersionComment); - // Presence of `@preEnumExtensibility` pushed the warning farther - // into the future. - if (theEnum && - theEnum->getAttrs().hasAttribute()) { - diag.warnUntilFutureSwiftVersion(); - } else { - diag.warnUntilSwiftVersion(6); - } + auto shouldWarnUntilVersion = [&theEnum]() -> unsigned { + if (theEnum) { + // Presence of `@nonexhaustive(warn)` pushes the warning farther, + // into the future. + if (auto *nonexhaustive = + theEnum->getAttrs().getAttribute()) { + if (nonexhaustive->getMode() == NonexhaustiveMode::Warning) + return swift::version::Version::getFutureMajorLanguageVersion(); + } + } + return 6; + }; + + diag.warnUntilSwiftVersion(shouldWarnUntilVersion()); mainDiagType = std::nullopt; } diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index 7a1d9a5bb074e..ba5279eeac455 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -6676,6 +6676,14 @@ llvm::Error DeclDeserializer::deserializeDeclCommon() { break; } + case decls_block::Nonexhaustive_DECL_ATTR: { + unsigned mode; + serialization::decls_block::NonexhaustiveDeclAttrLayout::readRecord( + scratch, mode); + Attr = new (ctx) NonexhaustiveAttr((NonexhaustiveMode)mode); + break; + } + #define SIMPLE_DECL_ATTR(NAME, CLASS, ...) \ case decls_block::CLASS##_DECL_ATTR: { \ bool isImplicit; \ diff --git a/lib/Serialization/ModuleFormat.h b/lib/Serialization/ModuleFormat.h index 52a69ffa34f92..3837f86d19767 100644 --- a/lib/Serialization/ModuleFormat.h +++ b/lib/Serialization/ModuleFormat.h @@ -2591,6 +2591,11 @@ namespace decls_block { BCArray> // concatenated param indices >; + using NonexhaustiveDeclAttrLayout = BCRecordLayout< + Nonexhaustive_DECL_ATTR, + BCFixed<2> // mode + >; + // clang-format on #undef SYNTAX_SUGAR_TYPE_LAYOUT diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index 59fd3dfef2851..8519a2eb40143 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -3548,6 +3548,13 @@ class Serializer::DeclSerializer : public DeclVisitor { case DeclAttrKind::Lifetime: { return; } + case DeclAttrKind::Nonexhaustive: { + auto *theAttr = cast(DA); + auto abbrCode = S.DeclTypeAbbrCodes[NonexhaustiveDeclAttrLayout::Code]; + NonexhaustiveDeclAttrLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode, + (unsigned)theAttr->getMode()); + return; + } } } diff --git a/test/IDE/complete_nonexhaustive.swift b/test/IDE/complete_nonexhaustive.swift new file mode 100644 index 0000000000000..003bce451db02 --- /dev/null +++ b/test/IDE/complete_nonexhaustive.swift @@ -0,0 +1,9 @@ +// RUN: %batch-code-completion -enable-experimental-feature NonexhaustiveAttribute + +// REQUIRES: swift_feature_NonexhaustiveAttribute + +// NONEXHAUSTIVE-DAG: Keyword/None: warn; name=warn + +@nonexhaustive(#^NONEXHAUSTIVE^#) +public enum E { +} diff --git a/test/ModuleInterface/extensible_attr.swift b/test/ModuleInterface/nonexhaustive_attr.swift similarity index 52% rename from test/ModuleInterface/extensible_attr.swift rename to test/ModuleInterface/nonexhaustive_attr.swift index 0137ebb2c8a38..c4151e36d5177 100644 --- a/test/ModuleInterface/extensible_attr.swift +++ b/test/ModuleInterface/nonexhaustive_attr.swift @@ -1,29 +1,28 @@ // RUN: %empty-directory(%t) -// RUN: %target-swift-emit-module-interface(%t/Library.swiftinterface) %s -enable-experimental-feature ExtensibleAttribute -module-name Library -// RUN: %target-swift-typecheck-module-from-interface(%t/Library.swiftinterface) -enable-experimental-feature ExtensibleAttribute -module-name Library +// RUN: %target-swift-emit-module-interface(%t/Library.swiftinterface) %s -enable-experimental-feature NonexhaustiveAttribute -module-name Library +// RUN: %target-swift-typecheck-module-from-interface(%t/Library.swiftinterface) -enable-experimental-feature NonexhaustiveAttribute -module-name Library // RUN: %target-swift-typecheck-module-from-interface(%t/Library.swiftinterface) -module-name Library // RUN: %FileCheck %s < %t/Library.swiftinterface -// REQUIRES: swift_feature_ExtensibleAttribute +// REQUIRES: swift_feature_NonexhaustiveAttribute -// CHECK: #if compiler(>=5.3) && $ExtensibleAttribute -// CHECK-NEXT: @extensible public enum E { +// CHECK: #if compiler(>=5.3) && $NonexhaustiveAttribute +// CHECK-NEXT: @nonexhaustive public enum E { // CHECK-NEXT: } // CHECK-NEXT: #else // CHECK-NEXT: public enum E { // CHECK-NEXT: } // CHECK-NEXT: #endif -@extensible +@nonexhaustive public enum E { } -// CHECK: #if compiler(>=5.3) && $ExtensibleAttribute -// CHECK-NEXT: @preEnumExtensibility @extensible public enum F { +// CHECK: #if compiler(>=5.3) && $NonexhaustiveAttribute +// CHECK-NEXT: @nonexhaustive(warn) public enum F { // CHECK: #else // CHECK-NEXT: public enum F { // CHECK: #endif -@preEnumExtensibility -@extensible +@nonexhaustive(warn) public enum F { case a } diff --git a/test/ModuleInterface/extensible_enums.swift b/test/ModuleInterface/nonexhaustive_enums.swift similarity index 92% rename from test/ModuleInterface/extensible_enums.swift rename to test/ModuleInterface/nonexhaustive_enums.swift index 81dc581b84892..7f28cd5202187 100644 --- a/test/ModuleInterface/extensible_enums.swift +++ b/test/ModuleInterface/nonexhaustive_enums.swift @@ -6,9 +6,9 @@ // RUN: %target-swift-frontend -emit-module %t/src/Lib.swift \ // RUN: -module-name Lib \ // RUN: -emit-module-path %t/Lib.swiftmodule \ -// RUN: -enable-experimental-feature ExtensibleAttribute +// RUN: -enable-experimental-feature NonexhaustiveAttribute -// Check that the errors are produced when using enums from module with `ExtensibleEnums` feature enabled. +// Check that the errors are produced when using enums from module with `NonexhaustiveEnums` feature enabled. // RUN: %target-swift-frontend -typecheck %t/src/TestChecking.swift \ // RUN: -swift-version 5 -module-name Client -I %t \ // RUN: -verify @@ -20,7 +20,7 @@ // RUN: -module-name Lib \ // RUN: -package-name Test \ // RUN: -emit-module-path %t/Lib.swiftmodule \ -// RUN: -enable-experimental-feature ExtensibleAttribute +// RUN: -enable-experimental-feature NonexhaustiveAttribute // Different module but the same package @@ -34,17 +34,16 @@ // RUN: -swift-version 6 -module-name Client -I %t \ // RUN: -verify -// REQUIRES: swift_feature_ExtensibleAttribute +// REQUIRES: swift_feature_NonexhaustiveAttribute //--- Lib.swift -@extensible +@nonexhaustive public enum E { case a } -@preEnumExtensibility -@extensible +@nonexhaustive(warn) public enum PE { case a } @@ -70,7 +69,7 @@ func test_same_module(e: E, f: F) { import Lib func test(e: E, pe: PE, f: F) { - // `E` is marked as `@extensible` which means it gets new semantics + // `E` is marked as `@nonexhaustive` which means it gets new semantics switch e { // expected-warning@-1 {{switch covers known cases, but 'E' may have additional unknown values, possibly added in future versions; this is an error in the Swift 6 language mode}} diff --git a/test/attr/attr_extensible.swift b/test/attr/attr_extensible.swift deleted file mode 100644 index 7f7c3faf264ff..0000000000000 --- a/test/attr/attr_extensible.swift +++ /dev/null @@ -1,49 +0,0 @@ -// RUN: %target-typecheck-verify-swift -enable-experimental-feature ExtensibleAttribute - -// REQUIRES: swift_feature_ExtensibleAttribute - -@extensible -public enum E1 { // Ok -} - -@extensible // expected-error {{'@extensible' attribute can only be applied to public or package declarations, but 'E2' is fileprivate}} -fileprivate enum E2 {} - -@extensible // expected-error {{cannot use '@extensible' together with '@frozen'}} -@frozen -public enum E3 { -} - -@extensible // expected-error {{'@extensible' attribute can only be applied to public or package declarations, but 'E4' is internal}} -@usableFromInline -enum E4 {} - -@extensible // expected-error {{@extensible may only be used on 'enum' declarations}} -struct Test { - @extensible // expected-error {{@extensible may only be used on 'enum' declarations}} - var v: Int { - @extensible // expected-error {{@extensible may only be used on 'enum' declarations}} - get { 0 } - } - - @extensible // expected-error {{@extensible may only be used on 'enum' declarations}} - var v2: String = "" - - @extensible // expected-error {{@extensible may only be used on 'enum' declarations}} - func test() {} - - @extensible // expected-error {{@extensible may only be used on 'enum' declarations}} - subscript(a: Int) -> Bool { - get { false } - set { } - } -} - -@preEnumExtensibility -@extensible -public enum PE { -} - -@preEnumExtensibility // expected-error {{@preEnumExtensibility can only be used together with '@extensible' attribute}} -public enum WrongPreE { -} diff --git a/test/attr/attr_nonexhaustive.swift b/test/attr/attr_nonexhaustive.swift new file mode 100644 index 0000000000000..48dfa19270efc --- /dev/null +++ b/test/attr/attr_nonexhaustive.swift @@ -0,0 +1,49 @@ +// RUN: %target-typecheck-verify-swift -enable-experimental-feature NonexhaustiveAttribute + +// REQUIRES: swift_feature_NonexhaustiveAttribute + +@nonexhaustive +public enum E1 { // Ok +} + +@nonexhaustive // expected-error {{'@nonexhaustive' attribute can only be applied to public or package declarations, but 'E2' is fileprivate}} +fileprivate enum E2 {} + +@nonexhaustive // expected-error {{cannot use '@nonexhaustive' together with '@frozen'}} +@frozen +public enum E3 { +} + +@nonexhaustive // expected-error {{'@nonexhaustive' attribute can only be applied to public or package declarations, but 'E4' is internal}} +@usableFromInline +enum E4 {} + +@nonexhaustive // expected-error {{@nonexhaustive may only be used on 'enum' declarations}} +struct Test { + @nonexhaustive // expected-error {{@nonexhaustive may only be used on 'enum' declarations}} + var v: Int { + @nonexhaustive // expected-error {{@nonexhaustive may only be used on 'enum' declarations}} + get { 0 } + } + + @nonexhaustive // expected-error {{@nonexhaustive may only be used on 'enum' declarations}} + var v2: String = "" + + @nonexhaustive // expected-error {{@nonexhaustive may only be used on 'enum' declarations}} + func test() {} + + @nonexhaustive // expected-error {{@nonexhaustive may only be used on 'enum' declarations}} + subscript(a: Int) -> Bool { + get { false } + set { } + } +} + +@nonexhaustive(warn) +public enum PE { +} + +@nonexhaustive // expected-note {{attribute already specified here}} +@nonexhaustive(warn) // expected-error {{duplicate attribute}} +public enum WrongPreE { +} diff --git a/test/attr/feature_requirement.swift b/test/attr/feature_requirement.swift index eb127063d5a00..b69c42026340f 100644 --- a/test/attr/feature_requirement.swift +++ b/test/attr/feature_requirement.swift @@ -1,17 +1,17 @@ // RUN: %target-typecheck-verify-swift -parse-as-library -disable-experimental-parser-round-trip -verify-additional-prefix disabled- -// RUN: %target-typecheck-verify-swift -parse-as-library -verify-additional-prefix enabled- -enable-experimental-feature ExtensibleAttribute +// RUN: %target-typecheck-verify-swift -parse-as-library -verify-additional-prefix enabled- -enable-experimental-feature NonexhaustiveAttribute // REQUIRES: asserts // This test checks whether DECL_ATTR_FEATURE_REQUIREMENT is being applied correctly. // It is expected to need occasional edits as experimental features are stabilized. -@extensible -public enum E {} // expected-disabled-error@-1 {{'extensible' attribute is only valid when experimental feature ExtensibleAttribute is enabled}} +@nonexhaustive +public enum E {} // expected-disabled-error@-1 {{'nonexhaustive' attribute is only valid when experimental feature NonexhaustiveAttribute is enabled}} -#if hasAttribute(extensible) - #error("does have @extensible") // expected-enabled-error {{does have @extensible}} +#if hasAttribute(nonexhaustive) + #error("does have @nonexhaustive") // expected-enabled-error {{does have @nonexhaustive}} #else - #error("doesn't have @extensible") // expected-disabled-error {{doesn't have @extensible}} + #error("doesn't have @nonexhaustive") // expected-disabled-error {{doesn't have @nonexhaustive}} #endif