From 44342284fbf3b99e8fbdfa954c8e192c413c750e Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Tue, 26 Mar 2024 16:59:38 -0700 Subject: [PATCH 01/10] Serialization: Remove serialization support for @_allowFeatureSuppression. It isn't used since the attribute doesn't get serialized. --- lib/Serialization/Deserialization.cpp | 16 ---------------- lib/Serialization/ModuleFormat.h | 8 ++------ lib/Serialization/Serialization.cpp | 15 +-------------- 3 files changed, 3 insertions(+), 36 deletions(-) diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index 48c52407d1e24..7eba797841b18 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -6034,22 +6034,6 @@ llvm::Error DeclDeserializer::deserializeDeclCommon() { break; } - case decls_block::AllowFeatureSuppression_DECL_ATTR: { - bool isImplicit; - ArrayRef featureIds; - serialization::decls_block::AllowFeatureSuppressionDeclAttrLayout - ::readRecord(scratch, isImplicit, featureIds); - - SmallVector features; - for (auto id : featureIds) - features.push_back(MF.getIdentifier(id)); - - Attr = AllowFeatureSuppressionAttr::create(ctx, SourceLoc(), - SourceRange(), isImplicit, - features); - break; - } - case decls_block::UnavailableFromAsync_DECL_ATTR: { bool isImplicit; serialization::decls_block::UnavailableFromAsyncDeclAttrLayout:: diff --git a/lib/Serialization/ModuleFormat.h b/lib/Serialization/ModuleFormat.h index a0a5466e9f386..d2222d97d328f 100644 --- a/lib/Serialization/ModuleFormat.h +++ b/lib/Serialization/ModuleFormat.h @@ -2138,12 +2138,6 @@ namespace decls_block { BCArray // name components >; - using AllowFeatureSuppressionDeclAttrLayout = BCRecordLayout< - AllowFeatureSuppression_DECL_ATTR, - BCFixed<1>, // implicit flag - BCArray // feature names - >; - using SPIAccessControlDeclAttrLayout = BCRecordLayout< SPIAccessControl_DECL_ATTR, BCArray // SPI names @@ -2254,6 +2248,8 @@ namespace decls_block { using ClangImporterSynthesizedTypeDeclAttrLayout = BCRecordLayout; using PrivateImportDeclAttrLayout = BCRecordLayout; + using AllowFeatureSuppressionDeclAttrLayout = + BCRecordLayout; using ProjectedValuePropertyDeclAttrLayout = BCRecordLayout< ProjectedValueProperty_DECL_ATTR, BCFixed<1>, // isImplicit diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index d808630c6588d..43d8c4b7ab937 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -2717,6 +2717,7 @@ class Serializer::DeclSerializer : public DeclVisitor { case DeclAttrKind::RestatedObjCConformance: case DeclAttrKind::ClangImporterSynthesizedType: case DeclAttrKind::PrivateImport: + case DeclAttrKind::AllowFeatureSuppression: llvm_unreachable("cannot serialize attribute"); #define SIMPLE_DECL_ATTR(_, CLASS, ...) \ @@ -2769,20 +2770,6 @@ class Serializer::DeclSerializer : public DeclVisitor { return; } - case DeclAttrKind::AllowFeatureSuppression: { - auto *theAttr = cast(DA); - auto abbrCode = - S.DeclTypeAbbrCodes[AllowFeatureSuppressionDeclAttrLayout::Code]; - - SmallVector ids; - for (auto id : theAttr->getSuppressedFeatures()) - ids.push_back(S.addUniquedStringRef(id.str())); - - AllowFeatureSuppressionDeclAttrLayout::emitRecord( - S.Out, S.ScratchRecord, abbrCode, theAttr->isImplicit(), ids); - return; - } - case DeclAttrKind::SPIAccessControl: { auto theAttr = cast(DA); auto abbrCode = S.DeclTypeAbbrCodes[SPIAccessControlDeclAttrLayout::Code]; From 3703131146e75712bc2cf34354375be124357f18 Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Tue, 26 Mar 2024 17:00:31 -0700 Subject: [PATCH 02/10] AST: Introduce `@_disallowFeatureSuppression` attribute. This attribute is the inverse of the existing `@_allowFeatureSuppression` attribute. Part of rdar://125138945 --- include/swift/AST/ASTBridging.h | 3 +- include/swift/AST/Attr.h | 15 ++++--- include/swift/AST/DeclAttr.def | 1 + include/swift/Basic/Features.def | 5 +++ include/swift/Parse/Parser.h | 3 +- lib/AST/ASTBridging.cpp | 6 ++- lib/AST/Attr.cpp | 41 +++++++++++-------- lib/AST/FeatureSet.cpp | 27 +++++++++--- lib/ASTGen/Sources/ASTGen/DeclAttrs.swift | 13 +++++- lib/Parse/ParseDecl.cpp | 15 ++++--- .../retroactive-conformances.swift | 13 +++++- 11 files changed, 102 insertions(+), 40 deletions(-) diff --git a/include/swift/AST/ASTBridging.h b/include/swift/AST/ASTBridging.h index b93a2d6286fcd..e40baa6752302 100644 --- a/include/swift/AST/ASTBridging.h +++ b/include/swift/AST/ASTBridging.h @@ -483,12 +483,13 @@ BridgedAlignmentAttr_createParsed(BridgedASTContext cContext, BridgedSourceLoc cAtLoc, BridgedSourceRange cRange, size_t cValue); -SWIFT_NAME("BridgedAllowFeatureSuppressionAttr.createParsed(_:atLoc:range:features:)") +SWIFT_NAME("BridgedAllowFeatureSuppressionAttr.createParsed(_:atLoc:range:inverted:features:)") BridgedAllowFeatureSuppressionAttr BridgedAllowFeatureSuppressionAttr_createParsed( BridgedASTContext cContext, BridgedSourceLoc cAtLoc, BridgedSourceRange cRange, + bool inverted, BridgedArrayRef cFeatures); SWIFT_NAME("BridgedCDeclAttr.createParsed(_:atLoc:range:name:)") diff --git a/include/swift/AST/Attr.h b/include/swift/AST/Attr.h index 68f32b4126718..e52d98ca28f6c 100644 --- a/include/swift/AST/Attr.h +++ b/include/swift/AST/Attr.h @@ -192,9 +192,11 @@ class DeclAttribute : public AttributeBase { isUnsafe : 1 ); - SWIFT_INLINE_BITFIELD_FULL(AllowFeatureSuppressionAttr, DeclAttribute, 32, + SWIFT_INLINE_BITFIELD_FULL(AllowFeatureSuppressionAttr, DeclAttribute, 1+31, : NumPadBits, - NumFeatures : 32 + Inverted : 1, + + NumFeatures : 31 ); } Bits; // clang-format on @@ -2628,14 +2630,17 @@ class AllowFeatureSuppressionAttr final private llvm::TrailingObjects { friend TrailingObjects; - /// Create an implicit @objc attribute with the given (optional) name. - AllowFeatureSuppressionAttr(SourceLoc atLoc, SourceRange range, - bool implicit, ArrayRef features); + AllowFeatureSuppressionAttr(SourceLoc atLoc, SourceRange range, bool implicit, + bool inverted, ArrayRef features); + public: static AllowFeatureSuppressionAttr *create(ASTContext &ctx, SourceLoc atLoc, SourceRange range, bool implicit, + bool inverted, ArrayRef features); + bool getInverted() const { return Bits.AllowFeatureSuppressionAttr.Inverted; } + ArrayRef getSuppressedFeatures() const { return {getTrailingObjects(), Bits.AllowFeatureSuppressionAttr.NumFeatures}; diff --git a/include/swift/AST/DeclAttr.def b/include/swift/AST/DeclAttr.def index 76bd21c67a57d..a9ce626e33085 100644 --- a/include/swift/AST/DeclAttr.def +++ b/include/swift/AST/DeclAttr.def @@ -489,6 +489,7 @@ SIMPLE_DECL_ATTR(_noObjCBridging, NoObjCBridging, DECL_ATTR(_allowFeatureSuppression, AllowFeatureSuppression, OnAnyDecl | UserInaccessible | NotSerialized | ABIStableToAdd | APIStableToAdd | ABIStableToRemove | APIStableToRemove, 157) +DECL_ATTR_ALIAS(_disallowFeatureSuppression, AllowFeatureSuppression) SIMPLE_DECL_ATTR(_preInverseGenerics, PreInverseGenerics, OnAbstractFunction | OnSubscript | OnVar | OnExtension | UserInaccessible | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove, 158) diff --git a/include/swift/Basic/Features.def b/include/swift/Basic/Features.def index 0390e8bd8af51..0a73ec3ccd0e0 100644 --- a/include/swift/Basic/Features.def +++ b/include/swift/Basic/Features.def @@ -34,6 +34,11 @@ // imply the existence of earlier features. (This only needs to apply to // suppressible features.) // +// Sometimes, certain declarations will conflict with existing declarations +// when printed with a suppressible feature disabled. The attribute +// @_disallowFeatureSuppression can be used to suppress feature suppression on +// a particular declaration. +// // If suppressing a feature in general is problematic, but it's okay to // suppress it for specific declarations, the feature can be made // conditionally suppressible. Declarations opt in to suppression with diff --git a/include/swift/Parse/Parser.h b/include/swift/Parse/Parser.h index 9be736a9e6163..e175590799331 100644 --- a/include/swift/Parse/Parser.h +++ b/include/swift/Parse/Parser.h @@ -1157,7 +1157,8 @@ class Parser { std::optional &Visibility); ParserResult - parseAllowFeatureSuppressionAttribute(SourceLoc atLoc, SourceLoc loc); + parseAllowFeatureSuppressionAttribute(bool inverted, SourceLoc atLoc, + SourceLoc loc); /// Parse the @attached or @freestanding attribute that specifies a macro /// role. diff --git a/lib/AST/ASTBridging.cpp b/lib/AST/ASTBridging.cpp index 49f7335d10f8a..eb7d7b70bd4bd 100644 --- a/lib/AST/ASTBridging.cpp +++ b/lib/AST/ASTBridging.cpp @@ -433,12 +433,14 @@ BridgedAllowFeatureSuppressionAttr BridgedAllowFeatureSuppressionAttr_createParsed(BridgedASTContext cContext, BridgedSourceLoc cAtLoc, BridgedSourceRange cRange, + bool inverted, BridgedArrayRef cFeatures) { SmallVector features; for (auto elem : cFeatures.unbridged()) features.push_back(elem.unbridged()); - return AllowFeatureSuppressionAttr::create(cContext.unbridged(), - cAtLoc.unbridged(), cRange.unbridged(), /*implicit*/ false, features); + return AllowFeatureSuppressionAttr::create( + cContext.unbridged(), cAtLoc.unbridged(), cRange.unbridged(), + /*implicit*/ false, inverted, features); } BridgedCDeclAttr BridgedCDeclAttr_createParsed(BridgedASTContext cContext, diff --git a/lib/AST/Attr.cpp b/lib/AST/Attr.cpp index e065f09cd3b84..bbef3e151d52b 100644 --- a/lib/AST/Attr.cpp +++ b/lib/AST/Attr.cpp @@ -1275,14 +1275,17 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options, Printer << "(" << cast(this)->getValue() << ")"; break; - case DeclAttrKind::AllowFeatureSuppression: - Printer.printAttrName("@_allowFeatureSuppression"); + case DeclAttrKind::AllowFeatureSuppression: { + auto Attr = cast(this); + Printer.printAttrName(Attr->getInverted() ? "@_disallowFeatureSuppression" + : "@_allowFeatureSuppression"); Printer << "("; - interleave(cast(this)->getSuppressedFeatures(), - [&](Identifier ident) { Printer << ident; }, - [&] { Printer << ", "; }); + interleave( + Attr->getSuppressedFeatures(), + [&](Identifier ident) { Printer << ident; }, [&] { Printer << ", "; }); Printer << ")"; break; + } case DeclAttrKind::SILGenName: Printer.printAttrName("@_silgen_name"); @@ -1947,7 +1950,11 @@ StringRef DeclAttribute::getAttrName() const { case DeclAttrKind::Extern: return "_extern"; case DeclAttrKind::AllowFeatureSuppression: - return "_allowFeatureSuppression"; + if (cast(this)->getInverted()) { + return "_disallowFeatureSuppression"; + } else { + return "_allowFeatureSuppression"; + } } llvm_unreachable("bad DeclAttrKind"); } @@ -2932,24 +2939,24 @@ StorageRestrictionsAttr::getAccessesProperties(AccessorDecl *attachedTo) const { {}); } -AllowFeatureSuppressionAttr::AllowFeatureSuppressionAttr(SourceLoc atLoc, - SourceRange range, - bool implicit, - ArrayRef features) - : DeclAttribute(DeclAttrKind::AllowFeatureSuppression, - atLoc, range, implicit) { +AllowFeatureSuppressionAttr::AllowFeatureSuppressionAttr( + SourceLoc atLoc, SourceRange range, bool implicit, bool inverted, + ArrayRef features) + : DeclAttribute(DeclAttrKind::AllowFeatureSuppression, atLoc, range, + implicit) { + Bits.AllowFeatureSuppressionAttr.Inverted = inverted; Bits.AllowFeatureSuppressionAttr.NumFeatures = features.size(); std::uninitialized_copy(features.begin(), features.end(), getTrailingObjects()); } -AllowFeatureSuppressionAttr * -AllowFeatureSuppressionAttr::create(ASTContext &ctx, SourceLoc atLoc, - SourceRange range, bool implicit, - ArrayRef features) { +AllowFeatureSuppressionAttr *AllowFeatureSuppressionAttr::create( + ASTContext &ctx, SourceLoc atLoc, SourceRange range, bool implicit, + bool inverted, ArrayRef features) { unsigned size = totalSizeToAlloc(features.size()); auto *mem = ctx.Allocate(size, alignof(AllowFeatureSuppressionAttr)); - return new (mem) AllowFeatureSuppressionAttr(atLoc, range, implicit, features); + return new (mem) + AllowFeatureSuppressionAttr(atLoc, range, implicit, inverted, features); } void swift::simple_display(llvm::raw_ostream &out, const DeclAttribute *attr) { diff --git a/lib/AST/FeatureSet.cpp b/lib/AST/FeatureSet.cpp index db646bb8ef1d4..a2323743c8f04 100644 --- a/lib/AST/FeatureSet.cpp +++ b/lib/AST/FeatureSet.cpp @@ -691,9 +691,14 @@ void FeatureSet::collectSuppressibleFeature(Feature feature, operation == Insert); } -static bool shouldSuppressFeature(StringRef featureName, Decl *decl) { +static bool hasFeatureSuppressionAttribute(Decl *decl, StringRef featureName, + bool inverted) { auto attr = decl->getAttrs().getAttribute(); - if (!attr) return false; + if (!attr) + return false; + + if (attr->getInverted() != inverted) + return false; for (auto suppressedFeature : attr->getSuppressedFeatures()) { if (suppressedFeature.is(featureName)) @@ -703,6 +708,14 @@ static bool shouldSuppressFeature(StringRef featureName, Decl *decl) { return false; } +static bool disallowFeatureSuppression(StringRef featureName, Decl *decl) { + return hasFeatureSuppressionAttribute(decl, featureName, true); +} + +static bool allowFeatureSuppression(StringRef featureName, Decl *decl) { + return hasFeatureSuppressionAttribute(decl, featureName, false); +} + /// Go through all the features used by the given declaration and /// either add or remove them to this set. void FeatureSet::collectFeaturesUsed(Decl *decl, InsertOrRemove operation) { @@ -712,11 +725,15 @@ void FeatureSet::collectFeaturesUsed(Decl *decl, InsertOrRemove operation) { if (usesFeature##FeatureName(decl)) \ collectRequiredFeature(Feature::FeatureName, operation); #define SUPPRESSIBLE_LANGUAGE_FEATURE(FeatureName, SENumber, Description) \ - if (usesFeature##FeatureName(decl)) \ - collectSuppressibleFeature(Feature::FeatureName, operation); + if (usesFeature##FeatureName(decl)) { \ + if (disallowFeatureSuppression(#FeatureName, decl)) \ + collectRequiredFeature(Feature::FeatureName, operation); \ + else \ + collectSuppressibleFeature(Feature::FeatureName, operation); \ + } #define CONDITIONALLY_SUPPRESSIBLE_LANGUAGE_FEATURE(FeatureName, SENumber, Description) \ if (usesFeature##FeatureName(decl)) { \ - if (shouldSuppressFeature(#FeatureName, decl)) \ + if (allowFeatureSuppression(#FeatureName, decl)) \ collectSuppressibleFeature(Feature::FeatureName, operation); \ else \ collectRequiredFeature(Feature::FeatureName, operation); \ diff --git a/lib/ASTGen/Sources/ASTGen/DeclAttrs.swift b/lib/ASTGen/Sources/ASTGen/DeclAttrs.swift index e3628632db18f..ede0dca465169 100644 --- a/lib/ASTGen/Sources/ASTGen/DeclAttrs.swift +++ b/lib/ASTGen/Sources/ASTGen/DeclAttrs.swift @@ -345,6 +345,16 @@ extension ASTGenVisitor { return nil } + let inverted: Bool + switch node.attributeName { + case "_allowFeatureSuppression": + inverted = false + case "_disallowFeatureSuppression": + inverted = true + default: + return nil + } + let features = args.compactMap(in: self) { arg -> BridgedIdentifier? in guard arg.label == nil, let declNameExpr = arg.expression.as(DeclReferenceExprSyntax.self), @@ -361,6 +371,7 @@ extension ASTGenVisitor { self.ctx, atLoc: self.generateSourceLoc(node.atSign), range: self.generateSourceRange(node), + inverted: inverted, features: features) } @@ -388,7 +399,7 @@ extension ASTGenVisitor { func generateAvailableAttr(attribute node: AttributeSyntax) -> [BridgedAvailableAttr] { guard - // `@_OriginallyDefinedIn` has special argument list syntax. + // `@available` has special argument list syntax. let args = node.arguments?.as(AvailabilityArgumentListSyntax.self) else { // TODO: Diagnose. diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 6554ead73a090..f5b53d77288d0 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -2461,8 +2461,10 @@ Parser::parseDocumentationAttribute(SourceLoc atLoc, SourceLoc loc) { } ParserResult -Parser::parseAllowFeatureSuppressionAttribute(SourceLoc atLoc, SourceLoc loc) { - StringRef attrName = "_allowFeatureSuppression"; +Parser::parseAllowFeatureSuppressionAttribute(bool inverted, SourceLoc atLoc, + SourceLoc loc) { + StringRef attrName = + inverted ? "_disallowFeatureSuppression" : "_allowFeatureSuppression"; SmallVector features; SourceRange parensRange; @@ -2479,9 +2481,9 @@ Parser::parseAllowFeatureSuppressionAttribute(SourceLoc atLoc, SourceLoc loc) { return status; auto range = SourceRange(loc, parensRange.End); - return makeParserResult( - AllowFeatureSuppressionAttr::create(Context, loc, range, /*implicit*/ false, - features)); + return makeParserResult(AllowFeatureSuppressionAttr::create( + Context, loc, range, /*implicit*/ false, /*inverted*/ inverted, + features)); } static std::optional @@ -3900,7 +3902,8 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes, break; } case DeclAttrKind::AllowFeatureSuppression: { - auto Attr = parseAllowFeatureSuppressionAttribute(AtLoc, Loc); + auto inverted = (AttrName == "_disallowFeatureSuppression"); + auto Attr = parseAllowFeatureSuppressionAttribute(inverted, AtLoc, Loc); Status |= Attr; if (Attr.isNonNull()) Attributes.add(Attr.get()); diff --git a/test/ModuleInterface/retroactive-conformances.swift b/test/ModuleInterface/retroactive-conformances.swift index 015670b66e009..ee803f20a4ff7 100644 --- a/test/ModuleInterface/retroactive-conformances.swift +++ b/test/ModuleInterface/retroactive-conformances.swift @@ -1,5 +1,5 @@ -// RUN: %target-swift-emit-module-interface(%t.swiftinterface) %s -// RUN: %target-swift-typecheck-module-from-interface(%t.swiftinterface) +// RUN: %target-swift-emit-module-interface(%t.swiftinterface) %s -module-name Test +// RUN: %target-swift-typecheck-module-from-interface(%t.swiftinterface) -module-name Test // RUN: %FileCheck %s < %t.swiftinterface // CHECK: #if compiler(>=5.3) && $RetroactiveAttribute @@ -20,3 +20,12 @@ extension Int: @retroactive Identifiable { public var id: Int { self } } + +// CHECK: #if compiler(>=5.3) && $RetroactiveAttribute +// CHECK: extension Swift.String : @retroactive Swift.Identifiable { +// CHECK-NOT: #else +// CHECK: #endif +@_disallowFeatureSuppression(RetroactiveAttribute) +extension String: @retroactive Identifiable { + public var id: String { self } +} From 7d0dcf26b8276b7cdf0573213547bc0c0cf3b8d1 Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Tue, 26 Mar 2024 22:31:56 -0700 Subject: [PATCH 03/10] Runtime: Fix a -Wlogical-op-parentheses warning. Introduced by https://github.com/apple/swift/pull/72591. --- include/swift/Runtime/TracingCommon.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/swift/Runtime/TracingCommon.h b/include/swift/Runtime/TracingCommon.h index a0c89b22adddd..ccfb51b0f3038 100644 --- a/include/swift/Runtime/TracingCommon.h +++ b/include/swift/Runtime/TracingCommon.h @@ -33,8 +33,8 @@ static inline bool shouldEnableTracing() { return false; if (__progname && (strcmp(__progname, "logd") == 0 || strcmp(__progname, "diagnosticd") == 0 || - strcmp(__progname, "notifyd") == 0) || - strcmp(__progname, "xpcproxy") == 0) + strcmp(__progname, "notifyd") == 0 || + strcmp(__progname, "xpcproxy") == 0)) return false; return true; } From 26569e0b1deabd19ecf29304db91f01211721896 Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Tue, 26 Mar 2024 16:37:23 -0700 Subject: [PATCH 04/10] stdlib: Make typed throws ABI placeholders properly `@usableFromInline`. Functions that are used in public `@inlinable` function bodies can't be marked `@_spi` nor can they be made obsolete. Also, they must retain `rethrows` so that use of these entry points from other `rethrows` functions is accepted. Builds on https://github.com/apple/swift/pull/72365. Once we no longer have to support pre-`$TypedThrows` compilers, all of this can be reverted. Part of rdar://125138945 --- stdlib/public/core/FloatingPointParsing.swift.gyb | 4 ++-- stdlib/public/core/LifetimeManager.swift | 15 +++++++++------ stdlib/public/core/Random.swift | 2 +- stdlib/public/core/Runtime.swift | 2 +- stdlib/public/core/SmallString.swift | 2 +- stdlib/public/core/UnicodeScalar.swift | 2 +- .../public/core/UnsafeRawBufferPointer.swift.gyb | 15 +++++++++------ stdlib/public/core/UnsafeRawPointer.swift | 2 +- stdlib/public/core/VarArgs.swift | 2 +- .../stability-stdlib-abi-without-asserts.test | 15 +++++++++++---- 10 files changed, 37 insertions(+), 24 deletions(-) diff --git a/stdlib/public/core/FloatingPointParsing.swift.gyb b/stdlib/public/core/FloatingPointParsing.swift.gyb index aa050010e1894..6c22432147cbe 100644 --- a/stdlib/public/core/FloatingPointParsing.swift.gyb +++ b/stdlib/public/core/FloatingPointParsing.swift.gyb @@ -169,7 +169,7 @@ extension ${Self}: LosslessStringConvertible { self.init(Substring(text)) } else { self = 0.0 -#if hasFeature(TypedThrows) +#if $TypedThrows let success = _withUnprotectedUnsafeMutablePointer(to: &self) { p -> Bool in text.withCString { chars -> Bool in switch chars[0] { @@ -216,7 +216,7 @@ extension ${Self}: LosslessStringConvertible { @available(SwiftStdlib 5.3, *) public init?(_ text: Substring) { self = 0.0 -#if hasFeature(TypedThrows) +#if $TypedThrows let success = _withUnprotectedUnsafeMutablePointer(to: &self) { p -> Bool in text.withCString { chars -> Bool in switch chars[0] { diff --git a/stdlib/public/core/LifetimeManager.swift b/stdlib/public/core/LifetimeManager.swift index 2d8110b8df80c..f324622b68d9c 100644 --- a/stdlib/public/core/LifetimeManager.swift +++ b/stdlib/public/core/LifetimeManager.swift @@ -87,13 +87,14 @@ public func withUnsafeMutablePointer< try body(UnsafeMutablePointer(Builtin.addressof(&value))) } -@_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 1) +// FIXME(TypedThrows): Uncomment @_spi and revert rethrows +//@_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 1) @_silgen_name("$ss24withUnsafeMutablePointer2to_q_xz_q_SpyxGKXEtKr0_lF") @usableFromInline internal func __abi_se0413_withUnsafeMutablePointer( to value: inout T, _ body: (UnsafeMutablePointer) throws -> Result -) throws -> Result { +) rethrows -> Result { return try body(UnsafeMutablePointer(Builtin.addressof(&value))) } @@ -147,13 +148,14 @@ public func withUnsafePointer( /// ABI: Historical withUnsafePointer(to:_:) rethrows, expressed as "throws", /// which is ABI-compatible with "rethrows". -@_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 1) +// FIXME(TypedThrows): Uncomment @_spi and revert rethrows +//@_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 1) @_silgen_name("$ss17withUnsafePointer2to_q_x_q_SPyxGKXEtKr0_lF") @usableFromInline internal func __abi_withUnsafePointer( to value: T, _ body: (UnsafePointer) throws -> Result -) throws -> Result +) rethrows -> Result { return try body(UnsafePointer(Builtin.addressOfBorrow(value))) } @@ -192,13 +194,14 @@ public func withUnsafePointer( /// ABI: Historical withUnsafePointer(to:_:) rethrows, /// expressed as "throws", which is ABI-compatible with "rethrows". -@_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 1) +// FIXME(TypedThrows): Uncomment @_spi and revert rethrows +//@_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 1) @_silgen_name("$ss17withUnsafePointer2to_q_xz_q_SPyxGKXEtKr0_lF") @usableFromInline internal func __abi_se0413_withUnsafePointer( to value: inout T, _ body: (UnsafePointer) throws -> Result -) throws -> Result { +) rethrows -> Result { return try body(UnsafePointer(Builtin.addressof(&value))) } diff --git a/stdlib/public/core/Random.swift b/stdlib/public/core/Random.swift index 566979863430d..068d33e35c3ff 100644 --- a/stdlib/public/core/Random.swift +++ b/stdlib/public/core/Random.swift @@ -158,7 +158,7 @@ public struct SystemRandomNumberGenerator: RandomNumberGenerator, Sendable { @inlinable public mutating func next() -> UInt64 { var random: UInt64 = 0 -#if hasFeature(TypedThrows) +#if $TypedThrows _withUnprotectedUnsafeMutablePointer(to: &random) { swift_stdlib_random($0, MemoryLayout.size) } diff --git a/stdlib/public/core/Runtime.swift b/stdlib/public/core/Runtime.swift index f0af0c01dec4b..8ea0cd1025b6b 100644 --- a/stdlib/public/core/Runtime.swift +++ b/stdlib/public/core/Runtime.swift @@ -139,7 +139,7 @@ func _stdlib_atomicInitializeARCRef( let desiredPtr = unmanaged.toOpaque() let rawTarget = UnsafeMutableRawPointer(target).assumingMemoryBound( to: Optional.self) -#if hasFeature(TypedThrows) +#if $TypedThrows let wonRace = withUnsafeMutablePointer(to: &expected) { _stdlib_atomicCompareExchangeStrongPtr( object: rawTarget, expected: $0, desired: desiredPtr diff --git a/stdlib/public/core/SmallString.swift b/stdlib/public/core/SmallString.swift index f68e787bc6517..3bf5cab591b31 100644 --- a/stdlib/public/core/SmallString.swift +++ b/stdlib/public/core/SmallString.swift @@ -223,7 +223,7 @@ extension _SmallString { ) rethrows -> Result { let count = self.count var raw = self.zeroTerminatedRawCodeUnits -#if hasFeature(TypedThrows) +#if $TypedThrows return try Swift._withUnprotectedUnsafeBytes(of: &raw) { let rawPtr = $0.baseAddress._unsafelyUnwrappedUnchecked // Rebind the underlying (UInt64, UInt64) tuple to UInt8 for the diff --git a/stdlib/public/core/UnicodeScalar.swift b/stdlib/public/core/UnicodeScalar.swift index 55eb69391006c..0f182c8a706f3 100644 --- a/stdlib/public/core/UnicodeScalar.swift +++ b/stdlib/public/core/UnicodeScalar.swift @@ -535,7 +535,7 @@ extension Unicode.Scalar { // The first code unit is in the least significant byte of codeUnits. codeUnits = codeUnits.littleEndian -#if hasFeature(TypedThrows) +#if $TypedThrows return try Swift._withUnprotectedUnsafePointer(to: &codeUnits) { return try $0.withMemoryRebound(to: UInt8.self, capacity: 4) { return try body(UnsafeBufferPointer(start: $0, count: utf8Count)) diff --git a/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb b/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb index 275e20774053e..886f7845736a8 100644 --- a/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb +++ b/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb @@ -1230,13 +1230,14 @@ public func withUnsafeMutableBytes( /// ABI: Historical withUnsafeMutableBytes(of:_:) rethrows, /// expressed as "throws", which is ABI-compatible with "rethrows". -@_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 1) +// FIXME(TypedThrows): Uncomment @_spi and revert rethrows +//@_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 1) @_silgen_name("$ss22withUnsafeMutableBytes2of_q_xz_q_SwKXEtKr0_lF") @usableFromInline func __abi_se0413_withUnsafeMutableBytes( of value: inout T, _ body: (UnsafeMutableRawBufferPointer) throws -> Result -) throws -> Result { +) rethrows -> Result { return try withUnsafeMutablePointer(to: &value) { return try body(UnsafeMutableRawBufferPointer( start: $0, count: MemoryLayout.size)) @@ -1297,13 +1298,14 @@ public func withUnsafeBytes( /// ABI: Historical withUnsafeBytes(of:_:) rethrows, /// expressed as "throws", which is ABI-compatible with "rethrows". -@_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 1) +// FIXME(TypedThrows): Uncomment @_spi and revert rethrows +//@_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 1) @_silgen_name("$ss15withUnsafeBytes2of_q_xz_q_SWKXEtKr0_lF") @usableFromInline func __abi_se0413_withUnsafeBytes( of value: inout T, _ body: (UnsafeRawBufferPointer) throws -> Result -) throws -> Result { +) rethrows -> Result { return try withUnsafePointer(to: &value) { try body(UnsafeRawBufferPointer(start: $0, count: MemoryLayout.size)) } @@ -1361,13 +1363,14 @@ public func withUnsafeBytes< /// ABI: Historical withUnsafeBytes(of:_:) rethrows, /// expressed as "throws", which is ABI-compatible with "rethrows". -@_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 1) +// FIXME(TypedThrows): Uncomment @_spi and revert rethrows +//@_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 1) @_silgen_name("$ss15withUnsafeBytes2of_q_x_q_SWKXEtKr0_lF") @usableFromInline func __abi_se0413_withUnsafeBytes( of value: T, _ body: (UnsafeRawBufferPointer) throws -> Result -) throws -> Result { +) rethrows -> Result { let addr = UnsafeRawPointer(Builtin.addressOfBorrow(value)) let buffer = UnsafeRawBufferPointer(start: addr, count: MemoryLayout.size) return try body(buffer) diff --git a/stdlib/public/core/UnsafeRawPointer.swift b/stdlib/public/core/UnsafeRawPointer.swift index d681fa9ed6fdb..54044898ee2d6 100644 --- a/stdlib/public/core/UnsafeRawPointer.swift +++ b/stdlib/public/core/UnsafeRawPointer.swift @@ -1501,7 +1501,7 @@ extension UnsafeMutableRawPointer { "storeBytes to misaligned raw pointer") var temp = value -#if hasFeature(TypedThrows) +#if $TypedThrows withUnsafeMutablePointer(to: &temp) { source in let rawSrc = UnsafeMutableRawPointer(source)._rawValue // FIXME: to be replaced by _memcpy when conversions are implemented. diff --git a/stdlib/public/core/VarArgs.swift b/stdlib/public/core/VarArgs.swift index 92ebf6a412363..7dc05b341aa0c 100644 --- a/stdlib/public/core/VarArgs.swift +++ b/stdlib/public/core/VarArgs.swift @@ -215,7 +215,7 @@ public func _encodeBitsAsWords(_ x: T) -> [Int] { _internalInvariant(!result.isEmpty) var tmp = x // FIXME: use UnsafeMutablePointer.assign(from:) instead of memcpy. -#if hasFeature(TypedThrows) +#if $TypedThrows _withUnprotectedUnsafeMutablePointer(to: &tmp) { _memcpy(dest: UnsafeMutablePointer(result._baseAddressIfContiguous!), src: $0, diff --git a/test/api-digester/stability-stdlib-abi-without-asserts.test b/test/api-digester/stability-stdlib-abi-without-asserts.test index 5747cf2e7ae31..af2e9a2db5f09 100644 --- a/test/api-digester/stability-stdlib-abi-without-asserts.test +++ b/test/api-digester/stability-stdlib-abi-without-asserts.test @@ -712,10 +712,17 @@ Func withExtendedLifetime(_:_:) has generic signature change from to Func withExtendedLifetime(_:_:) has mangled name changing from 'Swift.withExtendedLifetime(A, () throws -> B) throws -> B' to 'Swift.withExtendedLifetime(A, () throws -> B) throws -> B' Func withExtendedLifetime(_:_:) has parameter 0 changing from Default to Shared Func withExtendedLifetime(_:_:) is now with @_preInverseGenerics -Func withUnsafeBytes(of:_:) has been removed -Func withUnsafeMutableBytes(of:_:) has been removed -Func withUnsafeMutablePointer(to:_:) has been removed -Func withUnsafePointer(to:_:) has been removed +Func withUnsafeBytes(of:_:) has been renamed to Func __abi_se0413_withUnsafeBytes(of:_:) +Func withUnsafeBytes(of:_:) has mangled name changing from 'Swift.withUnsafeBytes(of: A, _: (Swift.UnsafeRawBufferPointer) throws -> B) throws -> B' to 'Swift.__abi_se0413_withUnsafeBytes(of: A, _: (Swift.UnsafeRawBufferPointer) throws -> B) throws -> B' +Func withUnsafeBytes(of:_:) has mangled name changing from 'Swift.withUnsafeBytes(of: inout A, _: (Swift.UnsafeRawBufferPointer) throws -> B) throws -> B' to 'Swift.__abi_se0413_withUnsafeBytes(of: inout A, _: (Swift.UnsafeRawBufferPointer) throws -> B) throws -> B' +Func withUnsafeMutableBytes(of:_:) has been renamed to Func __abi_se0413_withUnsafeMutableBytes(of:_:) +Func withUnsafeMutableBytes(of:_:) has mangled name changing from 'Swift.withUnsafeMutableBytes(of: inout A, _: (Swift.UnsafeMutableRawBufferPointer) throws -> B) throws -> B' to 'Swift.__abi_se0413_withUnsafeMutableBytes(of: inout A, _: (Swift.UnsafeMutableRawBufferPointer) throws -> B) throws -> B' +Func withUnsafeMutablePointer(to:_:) has been renamed to Func __abi_se0413_withUnsafeMutablePointer(to:_:) +Func withUnsafeMutablePointer(to:_:) has mangled name changing from 'Swift.withUnsafeMutablePointer(to: inout A, _: (Swift.UnsafeMutablePointer) throws -> B) throws -> B' to 'Swift.__abi_se0413_withUnsafeMutablePointer(to: inout A, _: (Swift.UnsafeMutablePointer) throws -> B) throws -> B' +Func withUnsafePointer(to:_:) has been renamed to Func __abi_se0413_withUnsafePointer(to:_:) +Func withUnsafePointer(to:_:) has been renamed to Func __abi_withUnsafePointer(to:_:) +Func withUnsafePointer(to:_:) has mangled name changing from 'Swift.withUnsafePointer(to: A, _: (Swift.UnsafePointer) throws -> B) throws -> B' to 'Swift.__abi_withUnsafePointer(to: A, _: (Swift.UnsafePointer) throws -> B) throws -> B' +Func withUnsafePointer(to:_:) has mangled name changing from 'Swift.withUnsafePointer(to: inout A, _: (Swift.UnsafePointer) throws -> B) throws -> B' to 'Swift.__abi_se0413_withUnsafePointer(to: inout A, _: (Swift.UnsafePointer) throws -> B) throws -> B' Protocol _Pointer has generic signature change from to Struct ManagedBufferPointer has generic signature change from to Struct UnsafeBufferPointer has generic signature change from to From abc42e86b28d6c0d88eac6f66945c89695d2c673 Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Wed, 27 Mar 2024 18:03:37 -0700 Subject: [PATCH 05/10] Concurrency: Declare explicit Failure typealiases on AsyncSequence iterators. Associated type inference ought to take care of providing the `Failure` typealias for these `AsyncIteratorProtocol` types. However, the inferred typealias is printed with `@_implements` in the `.swiftinterface`, guarded with the `$AssociatedTypeImplements` language feature guard, which means older compilers cannot see the typealias and therefore think the conformance is incomplete. To make sure the `_Concurrency` module's interface is backward compatible, we must manually define these typealiases temporarily. Part of rdar://125138945 --- stdlib/public/Concurrency/AsyncCompactMapSequence.swift | 4 ++++ stdlib/public/Concurrency/AsyncDropFirstSequence.swift | 4 ++++ stdlib/public/Concurrency/AsyncDropWhileSequence.swift | 4 ++++ stdlib/public/Concurrency/AsyncFilterSequence.swift | 4 ++++ stdlib/public/Concurrency/AsyncFlatMapSequence.swift | 4 ++++ stdlib/public/Concurrency/AsyncMapSequence.swift | 4 ++++ stdlib/public/Concurrency/AsyncPrefixSequence.swift | 4 ++++ stdlib/public/Concurrency/AsyncPrefixWhileSequence.swift | 4 ++++ 8 files changed, 32 insertions(+) diff --git a/stdlib/public/Concurrency/AsyncCompactMapSequence.swift b/stdlib/public/Concurrency/AsyncCompactMapSequence.swift index 38eb415657ed0..aa1d5dc2376d0 100644 --- a/stdlib/public/Concurrency/AsyncCompactMapSequence.swift +++ b/stdlib/public/Concurrency/AsyncCompactMapSequence.swift @@ -94,6 +94,10 @@ extension AsyncCompactMapSequence: AsyncSequence { public struct Iterator: AsyncIteratorProtocol { public typealias Element = ElementOfResult + // FIXME: Remove when $AssociatedTypeImplements is no longer needed + @available(SwiftStdlib 6.0, *) + public typealias Failure = Base.Failure + @usableFromInline var baseIterator: Base.AsyncIterator diff --git a/stdlib/public/Concurrency/AsyncDropFirstSequence.swift b/stdlib/public/Concurrency/AsyncDropFirstSequence.swift index bbad49caa493d..b10d401b4c605 100644 --- a/stdlib/public/Concurrency/AsyncDropFirstSequence.swift +++ b/stdlib/public/Concurrency/AsyncDropFirstSequence.swift @@ -81,6 +81,10 @@ extension AsyncDropFirstSequence: AsyncSequence { /// The iterator that produces elements of the drop-first sequence. public struct Iterator: AsyncIteratorProtocol { + // FIXME: Remove when $AssociatedTypeImplements is no longer needed + @available(SwiftStdlib 6.0, *) + public typealias Failure = Base.Failure + @usableFromInline var baseIterator: Base.AsyncIterator diff --git a/stdlib/public/Concurrency/AsyncDropWhileSequence.swift b/stdlib/public/Concurrency/AsyncDropWhileSequence.swift index 69e08dba93af5..8aa67f0a94f2b 100644 --- a/stdlib/public/Concurrency/AsyncDropWhileSequence.swift +++ b/stdlib/public/Concurrency/AsyncDropWhileSequence.swift @@ -90,6 +90,10 @@ extension AsyncDropWhileSequence: AsyncSequence { /// The iterator that produces elements of the drop-while sequence. public struct Iterator: AsyncIteratorProtocol { + // FIXME: Remove when $AssociatedTypeImplements is no longer needed + @available(SwiftStdlib 6.0, *) + public typealias Failure = Base.Failure + @usableFromInline var baseIterator: Base.AsyncIterator diff --git a/stdlib/public/Concurrency/AsyncFilterSequence.swift b/stdlib/public/Concurrency/AsyncFilterSequence.swift index d9e3d54c2856e..88435e9c1228a 100644 --- a/stdlib/public/Concurrency/AsyncFilterSequence.swift +++ b/stdlib/public/Concurrency/AsyncFilterSequence.swift @@ -80,6 +80,10 @@ extension AsyncFilterSequence: AsyncSequence { /// The iterator that produces elements of the filter sequence. public struct Iterator: AsyncIteratorProtocol { + // FIXME: Remove when $AssociatedTypeImplements is no longer needed + @available(SwiftStdlib 6.0, *) + public typealias Failure = Base.Failure + @usableFromInline var baseIterator: Base.AsyncIterator diff --git a/stdlib/public/Concurrency/AsyncFlatMapSequence.swift b/stdlib/public/Concurrency/AsyncFlatMapSequence.swift index 988061f94fdc4..7a9adf0100432 100644 --- a/stdlib/public/Concurrency/AsyncFlatMapSequence.swift +++ b/stdlib/public/Concurrency/AsyncFlatMapSequence.swift @@ -197,6 +197,10 @@ extension AsyncFlatMapSequence: AsyncSequence { /// The iterator that produces elements of the flat map sequence. public struct Iterator: AsyncIteratorProtocol { + // FIXME: Remove when $AssociatedTypeImplements is no longer needed + @available(SwiftStdlib 6.0, *) + public typealias Failure = Base.Failure + @usableFromInline var baseIterator: Base.AsyncIterator diff --git a/stdlib/public/Concurrency/AsyncMapSequence.swift b/stdlib/public/Concurrency/AsyncMapSequence.swift index 30b0f092021b4..d6fac62d8335e 100644 --- a/stdlib/public/Concurrency/AsyncMapSequence.swift +++ b/stdlib/public/Concurrency/AsyncMapSequence.swift @@ -90,6 +90,10 @@ extension AsyncMapSequence: AsyncSequence { /// The iterator that produces elements of the map sequence. public struct Iterator: AsyncIteratorProtocol { + // FIXME: Remove when $AssociatedTypeImplements is no longer needed + @available(SwiftStdlib 6.0, *) + public typealias Failure = Base.Failure + @usableFromInline var baseIterator: Base.AsyncIterator diff --git a/stdlib/public/Concurrency/AsyncPrefixSequence.swift b/stdlib/public/Concurrency/AsyncPrefixSequence.swift index 4a0957bfd7571..f6da15c7bdff0 100644 --- a/stdlib/public/Concurrency/AsyncPrefixSequence.swift +++ b/stdlib/public/Concurrency/AsyncPrefixSequence.swift @@ -81,6 +81,10 @@ extension AsyncPrefixSequence: AsyncSequence { /// The iterator that produces elements of the prefix sequence. public struct Iterator: AsyncIteratorProtocol { + // FIXME: Remove when $AssociatedTypeImplements is no longer needed + @available(SwiftStdlib 6.0, *) + public typealias Failure = Base.Failure + @usableFromInline var baseIterator: Base.AsyncIterator diff --git a/stdlib/public/Concurrency/AsyncPrefixWhileSequence.swift b/stdlib/public/Concurrency/AsyncPrefixWhileSequence.swift index 69c20b89fbc5e..773eb0e43357b 100644 --- a/stdlib/public/Concurrency/AsyncPrefixWhileSequence.swift +++ b/stdlib/public/Concurrency/AsyncPrefixWhileSequence.swift @@ -85,6 +85,10 @@ extension AsyncPrefixWhileSequence: AsyncSequence { /// The iterator that produces elements of the prefix-while sequence. public struct Iterator: AsyncIteratorProtocol { + // FIXME: Remove when $AssociatedTypeImplements is no longer needed + @available(SwiftStdlib 6.0, *) + public typealias Failure = Base.Failure + @usableFromInline var predicateHasFailed = false From 9c3768734a5082ecdcd8979944132974cfc7bda5 Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Tue, 26 Mar 2024 18:31:03 -0700 Subject: [PATCH 06/10] Frontend: Introduce an alias for the NoncopyableGenerics experimental feature. The `.swiftinterface` of the standard library must remain compatible with some older compilers. Unfortunately, some of those older compilers do not allow the experimental feature `NoncopyableGenerics` to be enabled in production. To allow the stdlib to build with non-copyable generics enabled and still have the older compilers consume its interface, we have to use a new experimental feature identifier that they do not know about. Partially resolves rdar://125138945 --- include/swift/Basic/Features.def | 3 +++ lib/AST/FeatureSet.cpp | 2 ++ lib/Frontend/CompilerInvocation.cpp | 3 +++ stdlib/cmake/modules/SwiftSource.cmake | 2 +- 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/include/swift/Basic/Features.def b/include/swift/Basic/Features.def index 0a73ec3ccd0e0..9aa6eef7db2a0 100644 --- a/include/swift/Basic/Features.def +++ b/include/swift/Basic/Features.def @@ -319,6 +319,9 @@ EXPERIMENTAL_FEATURE(Embedded, true) /// Enables noncopyable generics SUPPRESSIBLE_EXPERIMENTAL_FEATURE(NoncopyableGenerics, true) +// Alias for NoncopyableGenerics +EXPERIMENTAL_FEATURE(NoncopyableGenerics2, true) + /// Allow destructuring stored `let` bindings in structs. EXPERIMENTAL_FEATURE(StructLetDestructuring, true) diff --git a/lib/AST/FeatureSet.cpp b/lib/AST/FeatureSet.cpp index a2323743c8f04..82a6a622c0824 100644 --- a/lib/AST/FeatureSet.cpp +++ b/lib/AST/FeatureSet.cpp @@ -568,6 +568,8 @@ static bool usesFeatureNoncopyableGenerics(Decl *decl) { return !inverseReqs.empty(); } +UNINTERESTING_FEATURE(NoncopyableGenerics2) + static bool usesFeatureStructLetDestructuring(Decl *decl) { auto sd = dyn_cast(decl); if (!sd) diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 96ac571cbc01d..dc67c07788e0e 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -883,6 +883,9 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args, #else Opts.enableFeature(*feature); #endif + + if (*feature == Feature::NoncopyableGenerics2) + Opts.enableFeature(Feature::NoncopyableGenerics); } // Hack: In order to support using availability macros in SPM packages, we diff --git a/stdlib/cmake/modules/SwiftSource.cmake b/stdlib/cmake/modules/SwiftSource.cmake index 850db6e0dc158..758356df73b58 100644 --- a/stdlib/cmake/modules/SwiftSource.cmake +++ b/stdlib/cmake/modules/SwiftSource.cmake @@ -612,7 +612,7 @@ function(_compile_swift_files list(APPEND swift_flags "-experimental-hermetic-seal-at-link") endif() - list(APPEND swift_flags "-enable-experimental-feature" "NoncopyableGenerics") + list(APPEND swift_flags "-enable-experimental-feature" "NoncopyableGenerics2") if(SWIFT_ENABLE_EXPERIMENTAL_NONESCAPABLE_TYPES) list(APPEND swift_flags "-enable-experimental-feature" "NonescapableTypes") From 747fda0a807620da032a58144197c73c5bf2ed07 Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Tue, 26 Mar 2024 18:34:32 -0700 Subject: [PATCH 07/10] AST: Adjust declaration printing when NoncopyableGenerics2 is suppressed. When printing declarations with `NoncopyableGenerics2` suppressed we must avoid printing the `@_preInverseGenerics` attribute and any `borrowing` or `consuming` parameter ownership modifiers. --- include/swift/AST/PrintOptions.h | 3 +++ lib/AST/ASTPrinter.cpp | 22 ++++++++++++++++--- lib/AST/FeatureSet.cpp | 3 +++ .../Inputs/NoncopyableGenerics_Misc.swift | 3 +++ .../noncopyable_generics.swift | 10 +++++++++ 5 files changed, 38 insertions(+), 3 deletions(-) diff --git a/include/swift/AST/PrintOptions.h b/include/swift/AST/PrintOptions.h index 1aa3b63c3f13e..e7b8e00c590cd 100644 --- a/include/swift/AST/PrintOptions.h +++ b/include/swift/AST/PrintOptions.h @@ -385,6 +385,9 @@ struct PrintOptions { /// Suppress Noncopyable generics. bool SuppressNoncopyableGenerics = false; + /// Suppress printing of `borrowing` and `consuming`. + bool SuppressNoncopyableOwnershipModifiers = false; + /// List of attribute kinds that should not be printed. std::vector ExcludeAttrList = { DeclAttrKind::Transparent, DeclAttrKind::Effects, diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index 2f7bcced0653f..a019afcd48e94 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -1154,7 +1154,16 @@ class PrintAST : public ASTVisitor { Printer.callPrintDeclPre(D, Options.BracketOptions); if (Options.PrintCompatibilityFeatureChecks) { - printWithCompatibilityFeatureChecks(Printer, Options, D, [&]{ + printWithCompatibilityFeatureChecks(Printer, Options, D, [&] { + // If we are in a scope where non-copyable generics are being suppressed + // and we are also printing a decl that has @_preInverseGenerics, make + // sure we also suppress printing ownership modifiers that were added + // to satisfy the requirements of non-copyability. + llvm::SaveAndRestore scope( + Options.SuppressNoncopyableOwnershipModifiers, + Options.SuppressNoncopyableGenerics && + D->getAttrs().hasAttribute()); + ASTVisitor::visit(D); }); } else { @@ -3139,9 +3148,12 @@ static void suppressingFeatureAssociatedTypeImplements(PrintOptions &options, static void suppressingFeatureNoncopyableGenerics( PrintOptions &options, llvm::function_ref action) { + unsigned originalExcludeAttrCount = options.ExcludeAttrList.size(); + options.ExcludeAttrList.push_back(DeclAttrKind::PreInverseGenerics); llvm::SaveAndRestore scope( options.SuppressNoncopyableGenerics, true); action(); + options.ExcludeAttrList.resize(originalExcludeAttrCount); } /// Suppress the printing of a particular feature. @@ -3696,10 +3708,14 @@ static void printParameterFlags(ASTPrinter &printer, printer.printKeyword("inout", options, " "); break; case ParamSpecifier::Borrowing: - printer.printKeyword("borrowing", options, " "); + if (!options.SuppressNoncopyableOwnershipModifiers) { + printer.printKeyword("borrowing", options, " "); + } break; case ParamSpecifier::Consuming: - printer.printKeyword("consuming", options, " "); + if (!options.SuppressNoncopyableOwnershipModifiers) { + printer.printKeyword("consuming", options, " "); + } break; case ParamSpecifier::LegacyShared: printer.printKeyword("__shared", options, " "); diff --git a/lib/AST/FeatureSet.cpp b/lib/AST/FeatureSet.cpp index 82a6a622c0824..da44f6b39ba79 100644 --- a/lib/AST/FeatureSet.cpp +++ b/lib/AST/FeatureSet.cpp @@ -506,6 +506,9 @@ static bool usesFeatureRawLayout(Decl *decl) { UNINTERESTING_FEATURE(Embedded) static bool usesFeatureNoncopyableGenerics(Decl *decl) { + if (decl->getAttrs().hasAttribute()) + return true; + if (auto *valueDecl = dyn_cast(decl)) { if (isa(decl)) { auto *nominalDecl = cast(valueDecl); diff --git a/test/ModuleInterface/Inputs/NoncopyableGenerics_Misc.swift b/test/ModuleInterface/Inputs/NoncopyableGenerics_Misc.swift index dcf0ead91cbe0..67d00773c44dc 100644 --- a/test/ModuleInterface/Inputs/NoncopyableGenerics_Misc.swift +++ b/test/ModuleInterface/Inputs/NoncopyableGenerics_Misc.swift @@ -106,3 +106,6 @@ extension Outer.InnerStruct { @_preInverseGenerics public func old_swap(_ a: inout T, _ b: inout T) {} + +@_preInverseGenerics +public func borrowsNoncopyable(_ t: borrowing T) {} diff --git a/test/ModuleInterface/noncopyable_generics.swift b/test/ModuleInterface/noncopyable_generics.swift index bec9e54784685..35fbe3b88e7b2 100644 --- a/test/ModuleInterface/noncopyable_generics.swift +++ b/test/ModuleInterface/noncopyable_generics.swift @@ -144,8 +144,18 @@ import NoncopyableGenerics_Misc // CHECK-MISC: #if compiler(>=5.3) && $NoncopyableGenerics // CHECK-MISC-NEXT: @_preInverseGenerics public func old_swap(_ a: inout T, _ b: inout T) where T : ~Copyable +// CHECK-MISC-NEXT: #else +// CHECK-MISC-NOT: @_preInverseGenerics +// CHECK-MISC-NEXT: public func old_swap(_ a: inout T, _ b: inout T) // CHECK-MISC: #endif +// CHECK-MISC: #if compiler(>=5.3) && $NoncopyableGenerics +// CHECK-MISC-NEXT: @_preInverseGenerics public func borrowsNoncopyable(_ t: borrowing T) where T : ~Copyable +// CHECK-MISC-NEXT: #else +// CHECK-MISC-NOT: @_preInverseGenerics +// CHECK-MISC-NEXT: public func borrowsNoncopyable(_ t: T) +// CHECK-MISC-NEXT: #endif + import Swiftskell // CHECK: #if compiler(>=5.3) && $NoncopyableGenerics From dc998bb4fb02541d5ee06ba99a9eaf7e2cce9391 Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Tue, 26 Mar 2024 18:34:45 -0700 Subject: [PATCH 08/10] stdlib: Adopt `@_disallowFeatureSuppression(NoncopyableGenerics)`. This prevents some re-declaration errors when building the standard library from its `.swiftinterface` with older compilers. --- stdlib/public/core/Optional.swift | 13 +++++-------- stdlib/public/core/Result.swift | 7 +++---- stdlib/public/core/UnsafeBufferPointer.swift.gyb | 1 + stdlib/public/core/UnsafePointer.swift | 4 ++++ .../Inputs/NoncopyableGenerics_Misc.swift | 3 +++ test/ModuleInterface/noncopyable_generics.swift | 5 +++++ 6 files changed, 21 insertions(+), 12 deletions(-) diff --git a/stdlib/public/core/Optional.swift b/stdlib/public/core/Optional.swift index 0aaf886f68d4e..9be0b7f073281 100644 --- a/stdlib/public/core/Optional.swift +++ b/stdlib/public/core/Optional.swift @@ -213,20 +213,22 @@ extension Optional where Wrapped: ~Copyable { } } -#if hasFeature(BorrowingSwitch) // FIXME(NCG): Make this public. @_alwaysEmitIntoClient public borrowing func _borrowingMap( _ transform: (borrowing Wrapped) throws(E) -> U ) throws(E) -> U? { + #if $NoncopyableGenerics switch self { case .some(_borrowing y): return .some(try transform(y)) case .none: return .none } + #else + fatalError("unsupported compiler") + #endif } -#endif } extension Optional { @@ -263,6 +265,7 @@ extension Optional { } } +@_disallowFeatureSuppression(NoncopyableGenerics) extension Optional where Wrapped: ~Copyable { // FIXME(NCG): Make this public. @_alwaysEmitIntoClient @@ -277,7 +280,6 @@ extension Optional where Wrapped: ~Copyable { } } -#if hasFeature(BorrowingSwitch) // FIXME(NCG): Make this public. @_alwaysEmitIntoClient public func _borrowingFlatMap( @@ -290,7 +292,6 @@ extension Optional where Wrapped: ~Copyable { return .none } } -#endif } extension Optional { @@ -546,7 +547,6 @@ public struct _OptionalNilComparisonType: ExpressibleByNilLiteral { } } -#if hasFeature(BorrowingSwitch) extension Optional where Wrapped: ~Copyable { /// Returns a Boolean value indicating whether an argument matches `nil`. /// @@ -735,9 +735,6 @@ extension Optional where Wrapped: ~Copyable { } } } -#else -#error("FIXME(NCG): Fill this out.") -#endif /// Performs a nil-coalescing operation, returning the wrapped value of an /// `Optional` instance or a default value. diff --git a/stdlib/public/core/Result.swift b/stdlib/public/core/Result.swift index fc356bf90e356..52c086db7f6bd 100644 --- a/stdlib/public/core/Result.swift +++ b/stdlib/public/core/Result.swift @@ -61,6 +61,7 @@ extension Result { } } +@_disallowFeatureSuppression(NoncopyableGenerics) extension Result where Success: ~Copyable { // FIXME(NCG): Make this public. @_alwaysEmitIntoClient @@ -75,7 +76,6 @@ extension Result where Success: ~Copyable { } } -#if $BorrowingSwitch // FIXME(NCG): Make this public. @_alwaysEmitIntoClient public borrowing func _borrowingMap( @@ -88,7 +88,6 @@ extension Result where Success: ~Copyable { return .failure(failure) } } -#endif } extension Result where Success: ~Copyable { @@ -131,6 +130,7 @@ extension Result where Success: ~Copyable { } } +@_disallowFeatureSuppression(NoncopyableGenerics) extension Result { @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 1) @usableFromInline @@ -186,6 +186,7 @@ extension Result { } } +@_disallowFeatureSuppression(NoncopyableGenerics) extension Result where Success: ~Copyable { // FIXME(NCG): Make this public. @_alwaysEmitIntoClient @@ -200,7 +201,6 @@ extension Result where Success: ~Copyable { } } -#if $BorrowingSwitch // FIXME(NCG): Make this public. @_alwaysEmitIntoClient public borrowing func _borrowingFlatMap( @@ -213,7 +213,6 @@ extension Result where Success: ~Copyable { return .failure(failure) } } -#endif } extension Result { diff --git a/stdlib/public/core/UnsafeBufferPointer.swift.gyb b/stdlib/public/core/UnsafeBufferPointer.swift.gyb index f5328873bd371..c390c7267da89 100644 --- a/stdlib/public/core/UnsafeBufferPointer.swift.gyb +++ b/stdlib/public/core/UnsafeBufferPointer.swift.gyb @@ -456,6 +456,7 @@ extension Unsafe${Mutable}BufferPointer where Element: ~Copyable { } +@_disallowFeatureSuppression(NoncopyableGenerics) extension Unsafe${Mutable}BufferPointer { /// Accesses the element at the specified position. /// diff --git a/stdlib/public/core/UnsafePointer.swift b/stdlib/public/core/UnsafePointer.swift index d5522e07e6b65..01f354ca3f814 100644 --- a/stdlib/public/core/UnsafePointer.swift +++ b/stdlib/public/core/UnsafePointer.swift @@ -286,6 +286,7 @@ extension UnsafePointer where Pointee: ~Copyable { } } +@_disallowFeatureSuppression(NoncopyableGenerics) extension UnsafePointer { // This preserves the ABI of the original (pre-6.0) `pointee` property that // used to export a getter. The current one above would export a read @@ -315,6 +316,7 @@ extension UnsafePointer where Pointee: ~Copyable { } } +@_disallowFeatureSuppression(NoncopyableGenerics) extension UnsafePointer { // This preserves the ABI of the original (pre-6.0) subscript that used to // export a getter. The current one above would export a read accessor, if it @@ -843,6 +845,7 @@ extension UnsafeMutablePointer where Pointee: ~Copyable { } } +@_disallowFeatureSuppression(NoncopyableGenerics) extension UnsafeMutablePointer { // This preserves the ABI of the original (pre-6.0) `pointee` property that // used to export a getter. The current one above would export a read @@ -1300,6 +1303,7 @@ extension UnsafeMutablePointer where Pointee: ~Copyable { } } +@_disallowFeatureSuppression(NoncopyableGenerics) extension UnsafeMutablePointer { // This preserves the ABI of the original (pre-6.0) subscript that used to // export a getter. The current one above would export a read accessor, if it diff --git a/test/ModuleInterface/Inputs/NoncopyableGenerics_Misc.swift b/test/ModuleInterface/Inputs/NoncopyableGenerics_Misc.swift index 67d00773c44dc..1eb4b198f41f3 100644 --- a/test/ModuleInterface/Inputs/NoncopyableGenerics_Misc.swift +++ b/test/ModuleInterface/Inputs/NoncopyableGenerics_Misc.swift @@ -109,3 +109,6 @@ public func old_swap(_ a: inout T, _ b: inout T) {} @_preInverseGenerics public func borrowsNoncopyable(_ t: borrowing T) {} + +@_disallowFeatureSuppression(NoncopyableGenerics) +public func suppressesNoncopyableGenerics(_ t: borrowing T) {} diff --git a/test/ModuleInterface/noncopyable_generics.swift b/test/ModuleInterface/noncopyable_generics.swift index 35fbe3b88e7b2..80084577f3f7b 100644 --- a/test/ModuleInterface/noncopyable_generics.swift +++ b/test/ModuleInterface/noncopyable_generics.swift @@ -156,6 +156,11 @@ import NoncopyableGenerics_Misc // CHECK-MISC-NEXT: public func borrowsNoncopyable(_ t: T) // CHECK-MISC-NEXT: #endif +// CHECK-MISC: #if compiler(>=5.3) && $NoncopyableGenerics +// CHECK-MISC-NEXT: public func suppressesNoncopyableGenerics(_ t: borrowing T) where T : ~Copyable +// CHECK-MISC-NEXT: #endif + + import Swiftskell // CHECK: #if compiler(>=5.3) && $NoncopyableGenerics From 3607096b3ac97268858bfa896c58074f470866d3 Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Tue, 26 Mar 2024 22:12:22 -0700 Subject: [PATCH 09/10] tests: Un-XFAIL some CxxInterop tests that pass now. --- .../bridge-cxx-struct-back-to-cxx-execution.cpp | 3 --- test/Interop/SwiftToCxx/stdlib/swift-stdlib-in-cxx.swift | 3 --- 2 files changed, 6 deletions(-) diff --git a/test/Interop/CxxToSwiftToCxx/bridge-cxx-struct-back-to-cxx-execution.cpp b/test/Interop/CxxToSwiftToCxx/bridge-cxx-struct-back-to-cxx-execution.cpp index a2468d5433f40..778228ec9a983 100644 --- a/test/Interop/CxxToSwiftToCxx/bridge-cxx-struct-back-to-cxx-execution.cpp +++ b/test/Interop/CxxToSwiftToCxx/bridge-cxx-struct-back-to-cxx-execution.cpp @@ -13,9 +13,6 @@ // REQUIRES: executable_test -// FIXME(NCG): This test requires NoncopyableGenerics to be a "suppressible" compiler feature. -// XFAIL: !noncopyable_generics - //--- header.h #include diff --git a/test/Interop/SwiftToCxx/stdlib/swift-stdlib-in-cxx.swift b/test/Interop/SwiftToCxx/stdlib/swift-stdlib-in-cxx.swift index f024d78864db8..b282ad0dad9f0 100644 --- a/test/Interop/SwiftToCxx/stdlib/swift-stdlib-in-cxx.swift +++ b/test/Interop/SwiftToCxx/stdlib/swift-stdlib-in-cxx.swift @@ -5,9 +5,6 @@ // RUN: %check-interop-cxx-header-in-clang(%t/Swift.h -DSWIFT_CXX_INTEROP_HIDE_STL_OVERLAY -Wno-unused-private-field -Wno-unused-function -Wc++98-compat-extra-semi) // RUN: %check-interop-cxx-header-in-clang(%t/Swift.h -DSWIFT_CXX_INTEROP_HIDE_STL_OVERLAY -Wno-unused-private-field -Wno-unused-function -Wc++98-compat-extra-semi -DDEBUG=1) -// FIXME(NCG): This test requires NoncopyableGenerics to be a "suppressible" compiler feature. -// XFAIL: !noncopyable_generics - // CHECK: namespace swift SWIFT_PRIVATE_ATTR SWIFT_SYMBOL_MODULE("swift") { // CHECK: template From aa43d6059d22ce943693fdbcf0cbdbb182e6eba5 Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Wed, 27 Mar 2024 20:43:07 -0700 Subject: [PATCH 10/10] Frontend: Introduce an alias for the IsolatedAny experimental feature. To preserve compatibility with older compilers that do not allow `IsolatedAny` to be enabled in production compilers, use an alias experimental feature when building the stdlib (`IsolatedAny2`). Also, add `@_allowFeatureSuppression(IsolatedAny)` in a couple spots it was forgotten. Partially resolves rdar://125138945 --- include/swift/Basic/Features.def | 3 +++ lib/AST/FeatureSet.cpp | 2 ++ lib/Frontend/CompilerInvocation.cpp | 3 +++ stdlib/public/Concurrency/CMakeLists.txt | 2 +- stdlib/public/Concurrency/TaskGroup.swift | 2 ++ test/ModuleInterface/isolated_any_suppression.swift | 1 + 6 files changed, 12 insertions(+), 1 deletion(-) diff --git a/include/swift/Basic/Features.def b/include/swift/Basic/Features.def index 9aa6eef7db2a0..602b622fc5c3e 100644 --- a/include/swift/Basic/Features.def +++ b/include/swift/Basic/Features.def @@ -361,6 +361,9 @@ EXPERIMENTAL_FEATURE(ClosureIsolation, true) // Enable isolated(any) attribute on function types. CONDITIONALLY_SUPPRESSIBLE_EXPERIMENTAL_FEATURE(IsolatedAny, true) +// Alias for IsolatedAny +EXPERIMENTAL_FEATURE(IsolatedAny2, true) + #undef EXPERIMENTAL_FEATURE_EXCLUDED_FROM_MODULE_INTERFACE #undef EXPERIMENTAL_FEATURE #undef UPCOMING_FEATURE diff --git a/lib/AST/FeatureSet.cpp b/lib/AST/FeatureSet.cpp index da44f6b39ba79..e9d527b7e7793 100644 --- a/lib/AST/FeatureSet.cpp +++ b/lib/AST/FeatureSet.cpp @@ -681,6 +681,8 @@ static bool usesFeatureIsolatedAny(Decl *decl) { }); } +UNINTERESTING_FEATURE(IsolatedAny2) + // ---------------------------------------------------------------------------- // MARK: - FeatureSet // ---------------------------------------------------------------------------- diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index dc67c07788e0e..440bddb645af5 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -886,6 +886,9 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args, if (*feature == Feature::NoncopyableGenerics2) Opts.enableFeature(Feature::NoncopyableGenerics); + + if (*feature == Feature::IsolatedAny2) + Opts.enableFeature(Feature::IsolatedAny); } // Hack: In order to support using availability macros in SPM packages, we diff --git a/stdlib/public/Concurrency/CMakeLists.txt b/stdlib/public/Concurrency/CMakeLists.txt index 9c38a4fd6c8f7..7a597d0f5bac2 100644 --- a/stdlib/public/Concurrency/CMakeLists.txt +++ b/stdlib/public/Concurrency/CMakeLists.txt @@ -62,7 +62,7 @@ endif() list(APPEND SWIFT_RUNTIME_CONCURRENCY_SWIFT_FLAGS "-enable-experimental-feature" - "IsolatedAny" + "IsolatedAny2" ) list(APPEND SWIFT_RUNTIME_CONCURRENCY_C_FLAGS diff --git a/stdlib/public/Concurrency/TaskGroup.swift b/stdlib/public/Concurrency/TaskGroup.swift index 590d664a42d4a..c06a2966cf3eb 100644 --- a/stdlib/public/Concurrency/TaskGroup.swift +++ b/stdlib/public/Concurrency/TaskGroup.swift @@ -782,6 +782,7 @@ public struct ThrowingTaskGroup { /// to set the child task's priority to the priority of the group. /// - operation: The operation to execute as part of the task group. @_alwaysEmitIntoClient + @_allowFeatureSuppression(IsolatedAny) public mutating func addTask( priority: TaskPriority? = nil, operation: __owned @Sendable @escaping @isolated(any) () async throws -> ChildTaskResult @@ -823,6 +824,7 @@ public struct ThrowingTaskGroup { /// - Returns: `true` if the child task was added to the group; /// otherwise `false`. @_alwaysEmitIntoClient + @_allowFeatureSuppression(IsolatedAny) public mutating func addTaskUnlessCancelled( priority: TaskPriority? = nil, operation: __owned @Sendable @escaping @isolated(any) () async throws -> ChildTaskResult diff --git a/test/ModuleInterface/isolated_any_suppression.swift b/test/ModuleInterface/isolated_any_suppression.swift index 7d8c74f5884d3..b6a4378546ce6 100644 --- a/test/ModuleInterface/isolated_any_suppression.swift +++ b/test/ModuleInterface/isolated_any_suppression.swift @@ -1,6 +1,7 @@ // RUN: %empty-directory(%t) // RUN: %target-swift-frontend -swift-version 5 -enable-library-evolution -module-name isolated_any -emit-module -o %t/isolated_any.swiftmodule -emit-module-interface-path - -enable-experimental-feature IsolatedAny %s | %FileCheck %s +// RUN: %target-swift-frontend -swift-version 5 -enable-library-evolution -module-name isolated_any -emit-module -o %t/isolated_any.swiftmodule -emit-module-interface-path - -enable-experimental-feature IsolatedAny2 %s | %FileCheck %s // CHECK: #if compiler(>=5.3) && $IsolatedAny // CHECK-NEXT: {{^}}public func test1(fn: @isolated(any) @Sendable () -> ())