Skip to content

Commit 2b41bee

Browse files
Merge pull request #39966 from aschwaighofer/feature_specialize_with_availability
Define a feature for _specialize with availability
2 parents 1069225 + 0bb2944 commit 2b41bee

File tree

9 files changed

+59
-9
lines changed

9 files changed

+59
-9
lines changed

include/swift/AST/ASTPrinter.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,9 @@ void getInheritedForPrinting(
386386
StringRef getAccessorKindString(AccessorKind value);
387387

388388
bool printCompatibilityFeatureChecksPre(ASTPrinter &printer, Decl *decl);
389-
void printCompatibilityFeatureChecksPost(ASTPrinter &printer);
389+
void printCompatibilityFeatureChecksPost(
390+
ASTPrinter &printer,
391+
llvm::function_ref<void()> printElse = []() -> void {});
390392

391393
} // namespace swift
392394

include/swift/AST/Attr.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1369,7 +1369,7 @@ class SpecializeAttr final
13691369
numSPIGroups };
13701370
}
13711371

1372-
ArrayRef<AvailableAttr *> getAvailabeAttrs() const {
1372+
ArrayRef<AvailableAttr *> getAvailableAttrs() const {
13731373
return {this->template getTrailingObjects<AvailableAttr *>(),
13741374
numAvailableAttrs};
13751375
}

include/swift/AST/PrintOptions.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,10 @@ struct PrintOptions {
477477
/// compilers that might parse the result.
478478
bool PrintCompatibilityFeatureChecks = false;
479479

480+
/// Whether to print @_specialize attributes that have an availability
481+
/// parameter.
482+
bool PrintSpecializeAttributeWithAvailability = true;
483+
480484
/// \see ShouldQualifyNestedDeclarations
481485
enum class QualifyNestedDeclarations {
482486
Never,

include/swift/Basic/Features.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,5 +56,6 @@ LANGUAGE_FEATURE(BuiltinBuildMainExecutor, 0, "MainActor executor building built
5656
LANGUAGE_FEATURE(BuiltinCreateAsyncTaskInGroup, 0, "MainActor executor building builtin", true)
5757
LANGUAGE_FEATURE(BuiltinMove, 0, "Builtin.move()", true)
5858
LANGUAGE_FEATURE(BuiltinCopy, 0, "Builtin.copy()", true)
59+
LANGUAGE_FEATURE(SpecializeAttributeWithAvailability, 0, "@_specialize attribute with availability", true)
5960

6061
#undef LANGUAGE_FEATURE

lib/AST/ASTPrinter.cpp

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,7 @@ static bool willUseTypeReprPrinting(TypeLoc tyLoc,
534534
(tyLoc.getType().isNull() && tyLoc.getTypeRepr()));
535535
}
536536

537+
static std::vector<Feature> getUniqueFeaturesUsed(Decl *decl);
537538
namespace {
538539
/// AST pretty-printer.
539540
class PrintAST : public ASTVisitor<PrintAST> {
@@ -1003,7 +1004,22 @@ class PrintAST : public ASTVisitor<PrintAST> {
10031004
ASTVisitor::visit(D);
10041005

10051006
if (haveFeatureChecks) {
1006-
printCompatibilityFeatureChecksPost(Printer);
1007+
1008+
printCompatibilityFeatureChecksPost(Printer, [&]() -> void {
1009+
auto features = getUniqueFeaturesUsed(D);
1010+
assert(!features.empty());
1011+
if (std::find_if(features.begin(), features.end(),
1012+
[](Feature feature) -> bool {
1013+
return getFeatureName(feature).equals(
1014+
"SpecializeAttributeWithAvailability");
1015+
}) != features.end()) {
1016+
Printer << "#else\n";
1017+
Options.PrintSpecializeAttributeWithAvailability = false;
1018+
ASTVisitor::visit(D);
1019+
Options.PrintSpecializeAttributeWithAvailability = true;
1020+
Printer.printNewline();
1021+
}
1022+
});
10071023
}
10081024

10091025
if (Synthesize) {
@@ -2818,6 +2834,16 @@ static bool usesFeatureBuiltinMove(Decl *decl) {
28182834

28192835
static bool usesFeatureBuiltinCopy(Decl *decl) { return false; }
28202836

2837+
static bool usesFeatureSpecializeAttributeWithAvailability(Decl *decl) {
2838+
if (auto func = dyn_cast<AbstractFunctionDecl>(decl)) {
2839+
for (auto specialize : func->getAttrs().getAttributes<SpecializeAttr>()) {
2840+
if (!specialize->getAvailableAttrs().empty())
2841+
return true;
2842+
}
2843+
}
2844+
return false;
2845+
}
2846+
28212847
static bool usesFeatureInheritActorContext(Decl *decl) {
28222848
if (auto func = dyn_cast<AbstractFunctionDecl>(decl)) {
28232849
for (auto param : *func->getParameters()) {
@@ -2926,12 +2952,13 @@ bool swift::printCompatibilityFeatureChecksPre(
29262952
return true;
29272953
}
29282954

2929-
void swift::printCompatibilityFeatureChecksPost(ASTPrinter &printer) {
2955+
void swift::printCompatibilityFeatureChecksPost(
2956+
ASTPrinter &printer, llvm::function_ref<void()> printElse) {
29302957
printer.printNewline();
2958+
printElse();
29312959
printer << "#endif\n";
29322960
}
29332961

2934-
29352962
void PrintAST::visitExtensionDecl(ExtensionDecl *decl) {
29362963
if (Options.TransformContext &&
29372964
Options.TransformContext->isPrintingSynthesizedExtension()) {

lib/AST/Attr.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -982,6 +982,12 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
982982
if (!Options.PrintSPIs && !attr->getSPIGroups().empty())
983983
return false;
984984

985+
// Don't print the _specialize attribute if we are asked to skip the ones
986+
// with availability parameters.
987+
if (!Options.PrintSpecializeAttributeWithAvailability &&
988+
!attr->getAvailableAttrs().empty())
989+
return false;
990+
985991
Printer << "@" << getAttrName() << "(";
986992
auto exported = attr->isExported() ? "true" : "false";
987993
auto kind = attr->isPartialSpecialization() ? "partial" : "full";
@@ -993,7 +999,7 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
993999
Printer << "kind: " << kind << ", ";
9941000
if (target)
9951001
Printer << "target: " << target << ", ";
996-
auto availAttrs = attr->getAvailabeAttrs();
1002+
auto availAttrs = attr->getAvailableAttrs();
9971003
if (!availAttrs.empty()) {
9981004
Printer << "availability: ";
9991005
auto numAttrs = availAttrs.size();

lib/AST/Availability.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ AvailabilityInference::annotatedAvailableRangeForAttr(const SpecializeAttr* attr
182182

183183
const AvailableAttr *bestAvailAttr = nullptr;
184184

185-
for (auto *availAttr : attr->getAvailabeAttrs()) {
185+
for (auto *availAttr : attr->getAvailableAttrs()) {
186186
if (availAttr == nullptr || !availAttr->Introduced.hasValue() ||
187187
!availAttr->isActivePlatform(ctx) ||
188188
availAttr->isLanguageVersionSpecific() ||

lib/Serialization/Serialization.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2611,14 +2611,14 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
26112611
auto numSPIGroups = attr->getSPIGroups().size();
26122612
assert(pieces.size() == numArgs + numSPIGroups ||
26132613
pieces.size() == (numArgs - 1 + numSPIGroups));
2614-
auto numAvailabilityAttrs = attr->getAvailabeAttrs().size();
2614+
auto numAvailabilityAttrs = attr->getAvailableAttrs().size();
26152615
SpecializeDeclAttrLayout::emitRecord(
26162616
S.Out, S.ScratchRecord, abbrCode, (unsigned)attr->isExported(),
26172617
(unsigned)attr->getSpecializationKind(),
26182618
S.addGenericSignatureRef(attr->getSpecializedSignature()),
26192619
S.addDeclRef(targetFunDecl), numArgs, numSPIGroups,
26202620
numAvailabilityAttrs, pieces);
2621-
for (auto availAttr : attr->getAvailabeAttrs()) {
2621+
for (auto availAttr : attr->getAvailableAttrs()) {
26222622
writeDeclAttribute(D, availAttr);
26232623
}
26242624
return;

test/ModuleInterface/features.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,16 @@
99
// the uses of those features are guarded by appropriate #if's that allow older
1010
// compilers to skip over the uses of newer features.
1111

12+
// CHECK: #if compiler(>=5.3) && $SpecializeAttributeWithAvailability
13+
// CHECK: @_specialize(exported: true, kind: full, availability: macOS, introduced: 12; where T == Swift.Int)
14+
// CHECK: public func specializeWithAvailability<T>(_ t: T)
15+
// CHECK: #else
16+
// CHECK: public func specializeWithAvailability<T>(_ t: T)
17+
// CHECK: #endif
18+
@_specialize(exported: true, availability: macOS 12, *; where T == Int)
19+
public func specializeWithAvailability<T>(_ t: T) {
20+
}
21+
1222
// CHECK: #if compiler(>=5.3) && $Actors
1323
// CHECK-NEXT: public actor MyActor
1424
// CHECK: @_semantics("defaultActor") nonisolated final public var unownedExecutor: _Concurrency.UnownedSerialExecutor {

0 commit comments

Comments
 (0)