Skip to content

Commit 497034e

Browse files
committed
AST: Requestify generic signature building for @_specialized attributes.
In order to support lazy typechecking during module emission for modules containing specialized functions, the computation of generic signatures for `@_specialized` attributes must be requestified. Resolves rdar://115569606
1 parent 6170714 commit 497034e

File tree

14 files changed

+99
-21
lines changed

14 files changed

+99
-21
lines changed

include/swift/AST/Attr.h

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1427,6 +1427,7 @@ class SpecializeAttr final
14271427
private llvm::TrailingObjects<SpecializeAttr, Identifier,
14281428
AvailableAttr *, Type> {
14291429
friend class SpecializeAttrTargetDeclRequest;
1430+
friend class SerializeAttrGenericSignatureRequest;
14301431
friend TrailingObjects;
14311432

14321433
public:
@@ -1519,14 +1520,6 @@ class SpecializeAttr final
15191520

15201521
TrailingWhereClause *getTrailingWhereClause() const;
15211522

1522-
GenericSignature getSpecializedSignature() const {
1523-
return specializedSignature;
1524-
}
1525-
1526-
void setSpecializedSignature(GenericSignature newSig) {
1527-
specializedSignature = newSig;
1528-
}
1529-
15301523
bool isExported() const {
15311524
return Bits.SpecializeAttr.exported;
15321525
}
@@ -1550,6 +1543,10 @@ class SpecializeAttr final
15501543
/// \p forDecl is the value decl that the attribute belongs to.
15511544
ValueDecl *getTargetFunctionDecl(const ValueDecl *forDecl) const;
15521545

1546+
/// \p forDecl is the value decl that the attribute belongs to.
1547+
GenericSignature
1548+
getSpecializedSignature(const AbstractFunctionDecl *forDecl) const;
1549+
15531550
static bool classof(const DeclAttribute *DA) {
15541551
return DA->getKind() == DAK_Specialize;
15551552
}

include/swift/AST/TypeCheckRequests.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4399,6 +4399,28 @@ class ExpandChildTypeRefinementContextsRequest
43994399
bool isCached() const { return true; }
44004400
};
44014401

4402+
class SerializeAttrGenericSignatureRequest
4403+
: public SimpleRequest<SerializeAttrGenericSignatureRequest,
4404+
GenericSignature(const AbstractFunctionDecl *,
4405+
SpecializeAttr *),
4406+
RequestFlags::Cached> {
4407+
public:
4408+
using SimpleRequest::SimpleRequest;
4409+
4410+
private:
4411+
friend SimpleRequest;
4412+
4413+
GenericSignature evaluate(Evaluator &evaluator,
4414+
const AbstractFunctionDecl *decl,
4415+
SpecializeAttr *attr) const;
4416+
4417+
public:
4418+
// Separate caching.
4419+
bool isCached() const { return true; }
4420+
llvm::Optional<GenericSignature> getCachedResult() const;
4421+
void cacheResult(GenericSignature signature) const;
4422+
};
4423+
44024424
#define SWIFT_TYPEID_ZONE TypeChecker
44034425
#define SWIFT_TYPEID_HEADER "swift/AST/TypeCheckerTypeIDZone.def"
44044426
#include "swift/Basic/DefineTypeIDZone.h"

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,3 +500,6 @@ SWIFT_REQUEST(TypeChecker, InitAccessorReferencedVariablesRequest,
500500
SWIFT_REQUEST(TypeChecker, ExpandChildTypeRefinementContextsRequest,
501501
bool(Decl *, TypeRefinementContext *),
502502
Cached, NoLocationInfo)
503+
SWIFT_REQUEST(TypeChecker, SerializeAttrGenericSignatureRequest,
504+
bool(Decl *, SpecializeAttr *),
505+
Cached, NoLocationInfo)

lib/AST/Attr.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1198,12 +1198,13 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
11981198
}
11991199
}
12001200
SmallVector<Requirement, 4> requirementsScratch;
1201-
auto requirements = attr->getSpecializedSignature().getRequirements();
12021201
auto *FnDecl = dyn_cast_or_null<AbstractFunctionDecl>(D);
1202+
auto specializedSig = attr->getSpecializedSignature(FnDecl);
1203+
auto requirements = specializedSig.getRequirements();
12031204
if (FnDecl && FnDecl->getGenericSignature()) {
12041205
auto genericSig = FnDecl->getGenericSignature();
12051206

1206-
if (auto sig = attr->getSpecializedSignature()) {
1207+
if (auto sig = specializedSig) {
12071208
requirementsScratch = sig.requirementsNotSatisfiedBy(genericSig);
12081209
requirements = requirementsScratch;
12091210
}
@@ -2204,6 +2205,14 @@ ValueDecl * SpecializeAttr::getTargetFunctionDecl(const ValueDecl *onDecl) const
22042205
nullptr);
22052206
}
22062207

2208+
GenericSignature SpecializeAttr::getSpecializedSignature(
2209+
const AbstractFunctionDecl *onDecl) const {
2210+
return evaluateOrDefault(onDecl->getASTContext().evaluator,
2211+
SerializeAttrGenericSignatureRequest{
2212+
onDecl, const_cast<SpecializeAttr *>(this)},
2213+
nullptr);
2214+
}
2215+
22072216
SPIAccessControlAttr::SPIAccessControlAttr(SourceLoc atLoc, SourceRange range,
22082217
ArrayRef<Identifier> spiGroups)
22092218
: DeclAttribute(DAK_SPIAccessControl, atLoc, range,

lib/SIL/IR/SILFunctionBuilder.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ void SILFunctionBuilder::addFunctionAttributes(
7272
: SILSpecializeAttr::SpecializationKind::Partial;
7373
assert(!constant.isNull());
7474
SILFunction *targetFunction = nullptr;
75-
auto *attributedFuncDecl = constant.getDecl();
75+
auto *attributedFuncDecl = constant.getAbstractFunctionDecl();
7676
auto *targetFunctionDecl = SA->getTargetFunctionDecl(attributedFuncDecl);
7777
// Filter out _spi.
7878
auto spiGroups = SA->getSPIGroups();
@@ -91,16 +91,17 @@ void SILFunctionBuilder::addFunctionAttributes(
9191
auto availability =
9292
AvailabilityInference::annotatedAvailableRangeForAttr(SA,
9393
M.getSwiftModule()->getASTContext());
94+
auto specializedSignature = SA->getSpecializedSignature(attributedFuncDecl);
9495
if (targetFunctionDecl) {
9596
SILDeclRef declRef(targetFunctionDecl, constant.kind, false);
9697
targetFunction = getOrCreateDeclaration(targetFunctionDecl, declRef);
9798
F->addSpecializeAttr(SILSpecializeAttr::create(
98-
M, SA->getSpecializedSignature(), SA->getTypeErasedParams(),
99+
M, specializedSignature, SA->getTypeErasedParams(),
99100
SA->isExported(), kind, targetFunction, spiGroupIdent,
100101
attributedFuncDecl->getModuleContext(), availability));
101102
} else {
102103
F->addSpecializeAttr(SILSpecializeAttr::create(
103-
M, SA->getSpecializedSignature(), SA->getTypeErasedParams(),
104+
M, specializedSignature, SA->getTypeErasedParams(),
104105
SA->isExported(), kind, nullptr, spiGroupIdent,
105106
attributedFuncDecl->getModuleContext(), availability));
106107
}

lib/SIL/IR/SILSymbolVisitor.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -442,8 +442,9 @@ class SILSymbolVisitorImpl : public ASTVisitor<SILSymbolVisitorImpl> {
442442
if (!attr->isExported())
443443
continue;
444444

445-
auto erasedSignature = attr->getSpecializedSignature().typeErased(
446-
attr->getTypeErasedParams());
445+
auto specializedSignature = attr->getSpecializedSignature(AFD);
446+
auto erasedSignature =
447+
specializedSignature.typeErased(attr->getTypeErasedParams());
447448

448449
if (auto *targetFun = attr->getTargetFunctionDecl(AFD)) {
449450
addFunction(SILDeclRef(targetFun, erasedSignature),

lib/SILOptimizer/Transforms/GenericSpecializer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ static void transferSpecializeAttributeTargets(SILModule &M,
6868
SA, M.getSwiftModule()->getASTContext());
6969

7070
targetSILFunction->addSpecializeAttr(SILSpecializeAttr::create(
71-
M, SA->getSpecializedSignature(), SA->getTypeErasedParams(),
71+
M, SA->getSpecializedSignature(vd), SA->getTypeErasedParams(),
7272
SA->isExported(), kind, nullptr,
7373
spiGroupIdent, vd->getModuleContext(), availability));
7474
}

lib/Sema/TypeCheckAttr.cpp

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2834,10 +2834,25 @@ void AttributeChecker::visitSpecializeAttr(SpecializeAttr *attr) {
28342834
return;
28352835
}
28362836

2837+
(void)attr->getSpecializedSignature(FD);
2838+
}
2839+
2840+
GenericSignature
2841+
SerializeAttrGenericSignatureRequest::evaluate(Evaluator &evaluator,
2842+
const AbstractFunctionDecl *FD,
2843+
SpecializeAttr *attr) const {
2844+
if (attr->specializedSignature)
2845+
return attr->specializedSignature;
2846+
2847+
auto &Ctx = FD->getASTContext();
2848+
auto genericSig = FD->getGenericSignature();
2849+
if (!genericSig)
2850+
return nullptr;
2851+
28372852
InferredGenericSignatureRequest request{
28382853
genericSig.getPointer(),
28392854
/*genericParams=*/nullptr,
2840-
WhereClauseOwner(FD, attr),
2855+
WhereClauseOwner(const_cast<AbstractFunctionDecl *>(FD), attr),
28412856
/*addedRequirements=*/{},
28422857
/*inferenceSources=*/{},
28432858
/*allowConcreteGenericParams=*/true};
@@ -2865,10 +2880,26 @@ void AttributeChecker::visitSpecializeAttr(SpecializeAttr *attr) {
28652880
attr->setTypeErasedParams(typeErasedParams);
28662881
}
28672882

2868-
attr->setSpecializedSignature(specializedSig);
2869-
28702883
// Check the target function if there is one.
28712884
attr->getTargetFunctionDecl(FD);
2885+
2886+
return specializedSig;
2887+
}
2888+
2889+
llvm::Optional<GenericSignature>
2890+
SerializeAttrGenericSignatureRequest::getCachedResult() const {
2891+
const auto &storage = getStorage();
2892+
SpecializeAttr *attr = std::get<1>(storage);
2893+
if (auto signature = attr->specializedSignature)
2894+
return signature;
2895+
return llvm::None;
2896+
}
2897+
2898+
void SerializeAttrGenericSignatureRequest::cacheResult(
2899+
GenericSignature signature) const {
2900+
const auto &storage = getStorage();
2901+
SpecializeAttr *attr = std::get<1>(storage);
2902+
attr->specializedSignature = signature;
28722903
}
28732904

28742905
void AttributeChecker::visitFixedLayoutAttr(FixedLayoutAttr *attr) {

lib/Serialization/Serialization.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2883,7 +2883,8 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
28832883
auto abbrCode = S.DeclTypeAbbrCodes[SpecializeDeclAttrLayout::Code];
28842884
auto attr = cast<SpecializeAttr>(DA);
28852885
auto targetFun = attr->getTargetFunctionName();
2886-
auto *targetFunDecl = attr->getTargetFunctionDecl(cast<ValueDecl>(D));
2886+
auto *afd = cast<AbstractFunctionDecl>(D);
2887+
auto *targetFunDecl = attr->getTargetFunctionDecl(afd);
28872888

28882889
SmallVector<IdentifierID, 4> pieces;
28892890

@@ -2917,7 +2918,7 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
29172918
SpecializeDeclAttrLayout::emitRecord(
29182919
S.Out, S.ScratchRecord, abbrCode, (unsigned)attr->isExported(),
29192920
(unsigned)attr->getSpecializationKind(),
2920-
S.addGenericSignatureRef(attr->getSpecializedSignature()),
2921+
S.addGenericSignatureRef(attr->getSpecializedSignature(afd)),
29212922
S.addDeclRef(targetFunDecl), numArgs, numSPIGroups,
29222923
numAvailabilityAttrs, numTypeErasedParams,
29232924
pieces);

test/Inputs/lazy_typecheck.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ public func constrainedGenericPublicFunction<T>(_ t: T) where T: PublicProto {
3333
doesNotExist() // expected-error {{cannot find 'doesNotExist' in scope}}
3434
}
3535

36+
@_specialize(exported: true, where T == PublicProto)
37+
public func publicSpecializedFunc<T>(_ t: T) -> T {
38+
return doesNotExist() // expected-error {{cannot find 'doesNotExist' in scope}}
39+
}
40+
3641
@available(SwiftStdlib 5.1, *)
3742
public func publicFuncWithOpaqueReturnType() -> some PublicProto { // expected-note {{opaque return type declared here}}
3843
return 1 // expected-error {{return type of global function 'publicFuncWithOpaqueReturnType()' requires that 'Int' conform to 'PublicProto'}}

test/Inputs/lazy_typecheck_client.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ func testGlobalFunctions() {
1414
_ = packageFunc()
1515
#endif
1616
constrainedGenericPublicFunction(ConformsToPublicProto())
17+
_ = publicSpecializedFunc(4)
18+
_ = publicSpecializedFunc(ConformsToPublicProto())
1719
if #available(SwiftStdlib 5.1, *) {
1820
_ = publicFuncWithOpaqueReturnType()
1921
_ = publicAEICFuncWithOpaqueReturnType()

test/ModuleInterface/lazy-typecheck.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
// CHECK-NEXT: return 1
1515
// CHECK-NEXT: }
1616
// CHECK: public func constrainedGenericPublicFunction<T>(_ t: T) where T : lazy_typecheck.PublicProto
17+
// CHECK: @_specialize(exported: true, kind: full, where T == any lazy_typecheck.PublicProto)
18+
// CHECK-NEXT: public func publicSpecializedFunc<T>(_ t: T) -> T
1719
// CHECK: @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
1820
// CHECK-NEXT: public func publicFuncWithOpaqueReturnType() -> some lazy_typecheck.PublicProto
1921

test/Serialization/serialize-external-decls-only-lazy-typecheck.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,6 @@
33
// RUN: %target-swift-frontend -swift-version 5 %S/../Inputs/lazy_typecheck.swift -module-name lazy_typecheck -emit-module -emit-module-path %t/lazy_typecheck.swiftmodule -enable-library-evolution -parse-as-library -package-name Package -DFLAG -experimental-lazy-typecheck -experimental-skip-all-function-bodies -experimental-serialize-external-decls-only
44

55
// RUN: %target-swift-frontend -package-name Package -typecheck -verify %S/../Inputs/lazy_typecheck_client.swift -DFLAG -I %t
6+
7+
// FIXME: Re-run the test with -experimental-skip-non-inlinable-function-bodies
8+

test/TBD/lazy-typecheck.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ exports:
123123
'_$s14lazy_typecheck19PublicGenericStructVyxGAA05EmptyC5ProtoA2A08InternalE13ForConstraintVRszlWP',
124124
'_$s14lazy_typecheck19PublicRethrowsProtoMp', '_$s14lazy_typecheck19PublicRethrowsProtoP3reqSiyKFTj',
125125
'_$s14lazy_typecheck19PublicRethrowsProtoP3reqSiyKFTq', '_$s14lazy_typecheck19PublicRethrowsProtoTL',
126+
'_$s14lazy_typecheck21publicSpecializedFuncyxxlF', '_$s14lazy_typecheck21publicSpecializedFuncyxxlFAA11PublicProto_p_Ts5',
126127
'_$s14lazy_typecheck24publicFuncWithDefaultArgyS2iF', '_$s14lazy_typecheck27publicGlobalVarInferredTypeSSvM',
127128
'_$s14lazy_typecheck27publicGlobalVarInferredTypeSSvg', '_$s14lazy_typecheck27publicGlobalVarInferredTypeSSvs',
128129
'_$s14lazy_typecheck30publicFuncWithOpaqueReturnTypeQryF',

0 commit comments

Comments
 (0)