Skip to content

AST: Requestify generic signature building for @_specialized attributes #68555

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 5 additions & 8 deletions include/swift/AST/Attr.h
Original file line number Diff line number Diff line change
Expand Up @@ -1427,6 +1427,7 @@ class SpecializeAttr final
private llvm::TrailingObjects<SpecializeAttr, Identifier,
AvailableAttr *, Type> {
friend class SpecializeAttrTargetDeclRequest;
friend class SerializeAttrGenericSignatureRequest;
friend TrailingObjects;

public:
Expand Down Expand Up @@ -1519,14 +1520,6 @@ class SpecializeAttr final

TrailingWhereClause *getTrailingWhereClause() const;

GenericSignature getSpecializedSignature() const {
return specializedSignature;
}

void setSpecializedSignature(GenericSignature newSig) {
specializedSignature = newSig;
}

bool isExported() const {
return Bits.SpecializeAttr.exported;
}
Expand All @@ -1550,6 +1543,10 @@ class SpecializeAttr final
/// \p forDecl is the value decl that the attribute belongs to.
ValueDecl *getTargetFunctionDecl(const ValueDecl *forDecl) const;

/// \p forDecl is the value decl that the attribute belongs to.
GenericSignature
getSpecializedSignature(const AbstractFunctionDecl *forDecl) const;

static bool classof(const DeclAttribute *DA) {
return DA->getKind() == DAK_Specialize;
}
Expand Down
22 changes: 22 additions & 0 deletions include/swift/AST/TypeCheckRequests.h
Original file line number Diff line number Diff line change
Expand Up @@ -4399,6 +4399,28 @@ class ExpandChildTypeRefinementContextsRequest
bool isCached() const { return true; }
};

class SerializeAttrGenericSignatureRequest
: public SimpleRequest<SerializeAttrGenericSignatureRequest,
GenericSignature(const AbstractFunctionDecl *,
SpecializeAttr *),
RequestFlags::Cached> {
public:
using SimpleRequest::SimpleRequest;

private:
friend SimpleRequest;

GenericSignature evaluate(Evaluator &evaluator,
const AbstractFunctionDecl *decl,
SpecializeAttr *attr) const;

public:
// Separate caching.
bool isCached() const { return true; }
llvm::Optional<GenericSignature> getCachedResult() const;
void cacheResult(GenericSignature signature) const;
};

#define SWIFT_TYPEID_ZONE TypeChecker
#define SWIFT_TYPEID_HEADER "swift/AST/TypeCheckerTypeIDZone.def"
#include "swift/Basic/DefineTypeIDZone.h"
Expand Down
3 changes: 3 additions & 0 deletions include/swift/AST/TypeCheckerTypeIDZone.def
Original file line number Diff line number Diff line change
Expand Up @@ -500,3 +500,6 @@ SWIFT_REQUEST(TypeChecker, InitAccessorReferencedVariablesRequest,
SWIFT_REQUEST(TypeChecker, ExpandChildTypeRefinementContextsRequest,
bool(Decl *, TypeRefinementContext *),
Cached, NoLocationInfo)
SWIFT_REQUEST(TypeChecker, SerializeAttrGenericSignatureRequest,
bool(Decl *, SpecializeAttr *),
Cached, NoLocationInfo)
13 changes: 11 additions & 2 deletions lib/AST/Attr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1198,12 +1198,13 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
}
}
SmallVector<Requirement, 4> requirementsScratch;
auto requirements = attr->getSpecializedSignature().getRequirements();
auto *FnDecl = dyn_cast_or_null<AbstractFunctionDecl>(D);
auto specializedSig = attr->getSpecializedSignature(FnDecl);
auto requirements = specializedSig.getRequirements();
if (FnDecl && FnDecl->getGenericSignature()) {
auto genericSig = FnDecl->getGenericSignature();

if (auto sig = attr->getSpecializedSignature()) {
if (auto sig = specializedSig) {
requirementsScratch = sig.requirementsNotSatisfiedBy(genericSig);
requirements = requirementsScratch;
}
Expand Down Expand Up @@ -2204,6 +2205,14 @@ ValueDecl * SpecializeAttr::getTargetFunctionDecl(const ValueDecl *onDecl) const
nullptr);
}

GenericSignature SpecializeAttr::getSpecializedSignature(
const AbstractFunctionDecl *onDecl) const {
return evaluateOrDefault(onDecl->getASTContext().evaluator,
SerializeAttrGenericSignatureRequest{
onDecl, const_cast<SpecializeAttr *>(this)},
nullptr);
}

SPIAccessControlAttr::SPIAccessControlAttr(SourceLoc atLoc, SourceRange range,
ArrayRef<Identifier> spiGroups)
: DeclAttribute(DAK_SPIAccessControl, atLoc, range,
Expand Down
7 changes: 4 additions & 3 deletions lib/SIL/IR/SILFunctionBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ void SILFunctionBuilder::addFunctionAttributes(
: SILSpecializeAttr::SpecializationKind::Partial;
assert(!constant.isNull());
SILFunction *targetFunction = nullptr;
auto *attributedFuncDecl = constant.getDecl();
auto *attributedFuncDecl = constant.getAbstractFunctionDecl();
auto *targetFunctionDecl = SA->getTargetFunctionDecl(attributedFuncDecl);
// Filter out _spi.
auto spiGroups = SA->getSPIGroups();
Expand All @@ -91,16 +91,17 @@ void SILFunctionBuilder::addFunctionAttributes(
auto availability =
AvailabilityInference::annotatedAvailableRangeForAttr(SA,
M.getSwiftModule()->getASTContext());
auto specializedSignature = SA->getSpecializedSignature(attributedFuncDecl);
if (targetFunctionDecl) {
SILDeclRef declRef(targetFunctionDecl, constant.kind, false);
targetFunction = getOrCreateDeclaration(targetFunctionDecl, declRef);
F->addSpecializeAttr(SILSpecializeAttr::create(
M, SA->getSpecializedSignature(), SA->getTypeErasedParams(),
M, specializedSignature, SA->getTypeErasedParams(),
SA->isExported(), kind, targetFunction, spiGroupIdent,
attributedFuncDecl->getModuleContext(), availability));
} else {
F->addSpecializeAttr(SILSpecializeAttr::create(
M, SA->getSpecializedSignature(), SA->getTypeErasedParams(),
M, specializedSignature, SA->getTypeErasedParams(),
SA->isExported(), kind, nullptr, spiGroupIdent,
attributedFuncDecl->getModuleContext(), availability));
}
Expand Down
5 changes: 3 additions & 2 deletions lib/SIL/IR/SILSymbolVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -442,8 +442,9 @@ class SILSymbolVisitorImpl : public ASTVisitor<SILSymbolVisitorImpl> {
if (!attr->isExported())
continue;

auto erasedSignature = attr->getSpecializedSignature().typeErased(
attr->getTypeErasedParams());
auto specializedSignature = attr->getSpecializedSignature(AFD);
auto erasedSignature =
specializedSignature.typeErased(attr->getTypeErasedParams());

if (auto *targetFun = attr->getTargetFunctionDecl(AFD)) {
addFunction(SILDeclRef(targetFun, erasedSignature),
Expand Down
2 changes: 1 addition & 1 deletion lib/SILOptimizer/Transforms/GenericSpecializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ static void transferSpecializeAttributeTargets(SILModule &M,
SA, M.getSwiftModule()->getASTContext());

targetSILFunction->addSpecializeAttr(SILSpecializeAttr::create(
M, SA->getSpecializedSignature(), SA->getTypeErasedParams(),
M, SA->getSpecializedSignature(vd), SA->getTypeErasedParams(),
SA->isExported(), kind, nullptr,
spiGroupIdent, vd->getModuleContext(), availability));
}
Expand Down
37 changes: 34 additions & 3 deletions lib/Sema/TypeCheckAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2834,10 +2834,25 @@ void AttributeChecker::visitSpecializeAttr(SpecializeAttr *attr) {
return;
}

(void)attr->getSpecializedSignature(FD);
}

GenericSignature
SerializeAttrGenericSignatureRequest::evaluate(Evaluator &evaluator,
const AbstractFunctionDecl *FD,
SpecializeAttr *attr) const {
if (attr->specializedSignature)
return attr->specializedSignature;

auto &Ctx = FD->getASTContext();
auto genericSig = FD->getGenericSignature();
if (!genericSig)
return nullptr;

InferredGenericSignatureRequest request{
genericSig.getPointer(),
/*genericParams=*/nullptr,
WhereClauseOwner(FD, attr),
WhereClauseOwner(const_cast<AbstractFunctionDecl *>(FD), attr),
/*addedRequirements=*/{},
/*inferenceSources=*/{},
/*allowConcreteGenericParams=*/true};
Expand Down Expand Up @@ -2865,10 +2880,26 @@ void AttributeChecker::visitSpecializeAttr(SpecializeAttr *attr) {
attr->setTypeErasedParams(typeErasedParams);
}

attr->setSpecializedSignature(specializedSig);

// Check the target function if there is one.
attr->getTargetFunctionDecl(FD);

return specializedSig;
}

llvm::Optional<GenericSignature>
SerializeAttrGenericSignatureRequest::getCachedResult() const {
const auto &storage = getStorage();
SpecializeAttr *attr = std::get<1>(storage);
if (auto signature = attr->specializedSignature)
return signature;
return llvm::None;
}

void SerializeAttrGenericSignatureRequest::cacheResult(
GenericSignature signature) const {
const auto &storage = getStorage();
SpecializeAttr *attr = std::get<1>(storage);
attr->specializedSignature = signature;
}

void AttributeChecker::visitFixedLayoutAttr(FixedLayoutAttr *attr) {
Expand Down
5 changes: 3 additions & 2 deletions lib/Serialization/Serialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2883,7 +2883,8 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
auto abbrCode = S.DeclTypeAbbrCodes[SpecializeDeclAttrLayout::Code];
auto attr = cast<SpecializeAttr>(DA);
auto targetFun = attr->getTargetFunctionName();
auto *targetFunDecl = attr->getTargetFunctionDecl(cast<ValueDecl>(D));
auto *afd = cast<AbstractFunctionDecl>(D);
auto *targetFunDecl = attr->getTargetFunctionDecl(afd);

SmallVector<IdentifierID, 4> pieces;

Expand Down Expand Up @@ -2917,7 +2918,7 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
SpecializeDeclAttrLayout::emitRecord(
S.Out, S.ScratchRecord, abbrCode, (unsigned)attr->isExported(),
(unsigned)attr->getSpecializationKind(),
S.addGenericSignatureRef(attr->getSpecializedSignature()),
S.addGenericSignatureRef(attr->getSpecializedSignature(afd)),
S.addDeclRef(targetFunDecl), numArgs, numSPIGroups,
numAvailabilityAttrs, numTypeErasedParams,
pieces);
Expand Down
5 changes: 5 additions & 0 deletions test/Inputs/lazy_typecheck.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ public func constrainedGenericPublicFunction<T>(_ t: T) where T: PublicProto {
doesNotExist() // expected-error {{cannot find 'doesNotExist' in scope}}
}

@_specialize(exported: true, where T == PublicProto)
public func publicSpecializedFunc<T>(_ t: T) -> T {
return doesNotExist() // expected-error {{cannot find 'doesNotExist' in scope}}
}

@available(SwiftStdlib 5.1, *)
public func publicFuncWithOpaqueReturnType() -> some PublicProto { // expected-note {{opaque return type declared here}}
return 1 // expected-error {{return type of global function 'publicFuncWithOpaqueReturnType()' requires that 'Int' conform to 'PublicProto'}}
Expand Down
2 changes: 2 additions & 0 deletions test/Inputs/lazy_typecheck_client.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ func testGlobalFunctions() {
_ = packageFunc()
#endif
constrainedGenericPublicFunction(ConformsToPublicProto())
_ = publicSpecializedFunc(4)
_ = publicSpecializedFunc(ConformsToPublicProto())
if #available(SwiftStdlib 5.1, *) {
_ = publicFuncWithOpaqueReturnType()
_ = publicAEICFuncWithOpaqueReturnType()
Expand Down
2 changes: 2 additions & 0 deletions test/ModuleInterface/lazy-typecheck.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
// CHECK-NEXT: return 1
// CHECK-NEXT: }
// CHECK: public func constrainedGenericPublicFunction<T>(_ t: T) where T : lazy_typecheck.PublicProto
// CHECK: @_specialize(exported: true, kind: full, where T == any lazy_typecheck.PublicProto)
// CHECK-NEXT: public func publicSpecializedFunc<T>(_ t: T) -> T
// CHECK: @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
// CHECK-NEXT: public func publicFuncWithOpaqueReturnType() -> some lazy_typecheck.PublicProto

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@
// 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

// RUN: %target-swift-frontend -package-name Package -typecheck -verify %S/../Inputs/lazy_typecheck_client.swift -DFLAG -I %t

// FIXME: Re-run the test with -experimental-skip-non-inlinable-function-bodies

1 change: 1 addition & 0 deletions test/TBD/lazy-typecheck.swift
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ exports:
'_$s14lazy_typecheck19PublicGenericStructVyxGAA05EmptyC5ProtoA2A08InternalE13ForConstraintVRszlWP',
'_$s14lazy_typecheck19PublicRethrowsProtoMp', '_$s14lazy_typecheck19PublicRethrowsProtoP3reqSiyKFTj',
'_$s14lazy_typecheck19PublicRethrowsProtoP3reqSiyKFTq', '_$s14lazy_typecheck19PublicRethrowsProtoTL',
'_$s14lazy_typecheck21publicSpecializedFuncyxxlF', '_$s14lazy_typecheck21publicSpecializedFuncyxxlFAA11PublicProto_p_Ts5',
'_$s14lazy_typecheck24publicFuncWithDefaultArgyS2iF', '_$s14lazy_typecheck27publicGlobalVarInferredTypeSSvM',
'_$s14lazy_typecheck27publicGlobalVarInferredTypeSSvg', '_$s14lazy_typecheck27publicGlobalVarInferredTypeSSvs',
'_$s14lazy_typecheck30publicFuncWithOpaqueReturnTypeQryF',
Expand Down