Skip to content

Commit b7537cf

Browse files
authored
Merge pull request #28434 from CodaFi/rialto-repls
[NFC] Refactor @_dynamicReplacement Checking
2 parents 83c1e7b + 72e80c2 commit b7537cf

21 files changed

+199
-181
lines changed

include/swift/AST/Attr.h

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class FuncDecl;
5252
class ClassDecl;
5353
class GenericFunctionType;
5454
class LazyConformanceLoader;
55+
class LazyMemberLoader;
5556
class PatternBindingInitializer;
5657
class TrailingWhereClause;
5758

@@ -1010,18 +1011,31 @@ class DynamicReplacementAttr final
10101011
: public DeclAttribute,
10111012
private llvm::TrailingObjects<DynamicReplacementAttr, SourceLoc> {
10121013
friend TrailingObjects;
1014+
friend class DynamicallyReplacedDeclRequest;
10131015

10141016
DeclName ReplacedFunctionName;
1015-
AbstractFunctionDecl *ReplacedFunction;
1017+
LazyMemberLoader *Resolver = nullptr;
1018+
uint64_t ResolverContextData;
10161019

10171020
/// Create an @_dynamicReplacement(for:) attribute written in the source.
10181021
DynamicReplacementAttr(SourceLoc atLoc, SourceRange baseRange,
10191022
DeclName replacedFunctionName, SourceRange parenRange);
10201023

1021-
explicit DynamicReplacementAttr(DeclName name)
1024+
DynamicReplacementAttr(DeclName name, AbstractFunctionDecl *f)
10221025
: DeclAttribute(DAK_DynamicReplacement, SourceLoc(), SourceRange(),
10231026
/*Implicit=*/false),
1024-
ReplacedFunctionName(name), ReplacedFunction(nullptr) {
1027+
ReplacedFunctionName(name),
1028+
Resolver(nullptr), ResolverContextData(0) {
1029+
Bits.DynamicReplacementAttr.HasTrailingLocationInfo = false;
1030+
}
1031+
1032+
DynamicReplacementAttr(DeclName name,
1033+
LazyMemberLoader *Resolver = nullptr,
1034+
uint64_t Data = 0)
1035+
: DeclAttribute(DAK_DynamicReplacement, SourceLoc(), SourceRange(),
1036+
/*Implicit=*/false),
1037+
ReplacedFunctionName(name),
1038+
Resolver(Resolver), ResolverContextData(Data) {
10251039
Bits.DynamicReplacementAttr.HasTrailingLocationInfo = false;
10261040
}
10271041

@@ -1045,25 +1059,18 @@ class DynamicReplacementAttr final
10451059
SourceLoc LParenLoc, DeclName replacedFunction, SourceLoc RParenLoc);
10461060

10471061
static DynamicReplacementAttr *create(ASTContext &ctx,
1048-
DeclName replacedFunction);
1062+
DeclName replacedFunction,
1063+
AbstractFunctionDecl *replacedFuncDecl);
10491064

10501065
static DynamicReplacementAttr *create(ASTContext &ctx,
10511066
DeclName replacedFunction,
1052-
AbstractFunctionDecl *replacedFuncDecl);
1067+
LazyMemberLoader *Resolver,
1068+
uint64_t Data);
10531069

10541070
DeclName getReplacedFunctionName() const {
10551071
return ReplacedFunctionName;
10561072
}
10571073

1058-
AbstractFunctionDecl *getReplacedFunction() const {
1059-
return ReplacedFunction;
1060-
}
1061-
1062-
void setReplacedFunction(AbstractFunctionDecl *f) {
1063-
assert(ReplacedFunction == nullptr);
1064-
ReplacedFunction = f;
1065-
}
1066-
10671074
/// Retrieve the location of the opening parentheses, if there is one.
10681075
SourceLoc getLParenLoc() const;
10691076

include/swift/AST/Decl.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2389,6 +2389,7 @@ class ValueDecl : public Decl {
23892389
unsigned isIUO : 1;
23902390
} LazySemanticInfo = { };
23912391

2392+
friend class DynamicallyReplacedDeclRequest;
23922393
friend class OverriddenDeclsRequest;
23932394
friend class IsObjCRequest;
23942395
friend class IsFinalRequest;
@@ -2749,6 +2750,11 @@ class ValueDecl : public Decl {
27492750
/// Retrieve the @functionBuilder type attached to this declaration,
27502751
/// if there is one.
27512752
Type getFunctionBuilderType() const;
2753+
2754+
/// If this value or its backing storage is annotated
2755+
/// @_dynamicReplacement(for: ...), compute the original declaration
2756+
/// that this declaration dynamically replaces.
2757+
ValueDecl *getDynamicallyReplacedDecl() const;
27522758
};
27532759

27542760
/// This is a common base class for declarations which declare a type.
@@ -4768,8 +4774,6 @@ class AbstractStorageDecl : public ValueDecl {
47684774

47694775
bool hasAnyNativeDynamicAccessors() const;
47704776

4771-
bool hasAnyDynamicReplacementAccessors() const;
4772-
47734777
// Implement isa/cast/dyncast/etc.
47744778
static bool classof(const Decl *D) {
47754779
return D->getKind() >= DeclKind::First_AbstractStorageDecl &&

include/swift/AST/LazyResolver.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,11 @@ class alignas(void*) LazyMemberLoader {
103103
virtual void
104104
loadRequirementSignature(const ProtocolDecl *proto, uint64_t contextData,
105105
SmallVectorImpl<Requirement> &requirements) = 0;
106+
107+
/// Returns the replaced decl for a given @_dynamicReplacement(for:) attribute.
108+
virtual ValueDecl *
109+
loadDynamicallyReplacedFunctionDecl(const DynamicReplacementAttr *DRA,
110+
uint64_t contextData) = 0;
106111
};
107112

108113
/// A class that can lazily load conformances from a serialized format.

include/swift/AST/TypeCheckRequests.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1930,6 +1930,24 @@ class IsCallableNominalTypeRequest
19301930
bool isCached() const { return true; }
19311931
};
19321932

1933+
class DynamicallyReplacedDeclRequest
1934+
: public SimpleRequest<DynamicallyReplacedDeclRequest,
1935+
ValueDecl *(ValueDecl *), CacheKind::Cached> {
1936+
public:
1937+
using SimpleRequest::SimpleRequest;
1938+
1939+
private:
1940+
friend SimpleRequest;
1941+
1942+
// Evaluation.
1943+
llvm::Expected<ValueDecl *> evaluate(Evaluator &evaluator,
1944+
ValueDecl *VD) const;
1945+
1946+
public:
1947+
// Caching.
1948+
bool isCached() const { return true; }
1949+
};
1950+
19331951
// Allow AnyValue to compare two Type values, even though Type doesn't
19341952
// support ==.
19351953
template<>

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ SWIFT_REQUEST(TypeChecker, DefaultDefinitionTypeRequest,
4343
SWIFT_REQUEST(TypeChecker, DefaultTypeRequest,
4444
Type(KnownProtocolKind, const DeclContext *), SeparatelyCached,
4545
NoLocationInfo)
46+
SWIFT_REQUEST(TypeChecker, DynamicallyReplacedDeclRequest,
47+
ValueDecl *(ValueDecl *),
48+
Cached, NoLocationInfo)
4649
SWIFT_REQUEST(TypeChecker, EmittedMembersRequest, DeclRange(ClassDecl *),
4750
SeparatelyCached, NoLocationInfo)
4851
SWIFT_REQUEST(TypeChecker, EnumRawValuesRequest,

lib/AST/Attr.cpp

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@
2222
#include "swift/AST/GenericEnvironment.h"
2323
#include "swift/AST/IndexSubset.h"
2424
#include "swift/AST/Module.h"
25+
#include "swift/AST/ParameterList.h"
2526
#include "swift/AST/TypeRepr.h"
2627
#include "swift/AST/Types.h"
27-
#include "swift/AST/ParameterList.h"
2828
#include "swift/Basic/Defer.h"
2929
#include "llvm/ADT/SmallString.h"
30-
#include "llvm/Support/raw_ostream.h"
31-
#include "llvm/Support/ErrorHandling.h"
3230
#include "llvm/ADT/StringSwitch.h"
31+
#include "llvm/Support/ErrorHandling.h"
32+
#include "llvm/Support/raw_ostream.h"
3333
using namespace swift;
3434

3535
#define DECL_ATTR(_, Id, ...) \
@@ -1148,7 +1148,7 @@ DynamicReplacementAttr::DynamicReplacementAttr(SourceLoc atLoc,
11481148
SourceRange parenRange)
11491149
: DeclAttribute(DAK_DynamicReplacement, atLoc, baseRange,
11501150
/*Implicit=*/false),
1151-
ReplacedFunctionName(name), ReplacedFunction(nullptr) {
1151+
ReplacedFunctionName(name) {
11521152
Bits.DynamicReplacementAttr.HasTrailingLocationInfo = true;
11531153
getTrailingLocations()[0] = parenRange.Start;
11541154
getTrailingLocations()[1] = parenRange.End;
@@ -1165,17 +1165,16 @@ DynamicReplacementAttr::create(ASTContext &Ctx, SourceLoc AtLoc,
11651165
SourceRange(LParenLoc, RParenLoc));
11661166
}
11671167

1168-
DynamicReplacementAttr *DynamicReplacementAttr::create(ASTContext &Ctx,
1169-
DeclName name) {
1170-
return new (Ctx) DynamicReplacementAttr(name);
1168+
DynamicReplacementAttr *
1169+
DynamicReplacementAttr::create(ASTContext &Ctx, DeclName name,
1170+
AbstractFunctionDecl *f) {
1171+
return new (Ctx) DynamicReplacementAttr(name, f);
11711172
}
11721173

11731174
DynamicReplacementAttr *
11741175
DynamicReplacementAttr::create(ASTContext &Ctx, DeclName name,
1175-
AbstractFunctionDecl *f) {
1176-
auto res = new (Ctx) DynamicReplacementAttr(name);
1177-
res->setReplacedFunction(f);
1178-
return res;
1176+
LazyMemberLoader *Resolver, uint64_t Data) {
1177+
return new (Ctx) DynamicReplacementAttr(name, Resolver, Data);
11791178
}
11801179

11811180
SourceLoc DynamicReplacementAttr::getLParenLoc() const {

lib/AST/Decl.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2833,6 +2833,13 @@ void ValueDecl::setIsDynamic(bool value) {
28332833
LazySemanticInfo.isDynamic = value;
28342834
}
28352835

2836+
ValueDecl *ValueDecl::getDynamicallyReplacedDecl() const {
2837+
return evaluateOrDefault(getASTContext().evaluator,
2838+
DynamicallyReplacedDeclRequest{
2839+
const_cast<ValueDecl *>(this)},
2840+
nullptr);
2841+
}
2842+
28362843
bool ValueDecl::canBeAccessedByDynamicLookup() const {
28372844
if (!hasName())
28382845
return false;
@@ -4958,9 +4965,9 @@ bool AbstractStorageDecl::hasPrivateAccessor() const {
49584965

49594966
bool AbstractStorageDecl::hasDidSetOrWillSetDynamicReplacement() const {
49604967
if (auto *func = getParsedAccessor(AccessorKind::DidSet))
4961-
return func->getAttrs().hasAttribute<DynamicReplacementAttr>();
4968+
return (bool)func->getDynamicallyReplacedDecl();
49624969
if (auto *func = getParsedAccessor(AccessorKind::WillSet))
4963-
return func->getAttrs().hasAttribute<DynamicReplacementAttr>();
4970+
return (bool)func->getDynamicallyReplacedDecl();
49644971
return false;
49654972
}
49664973

@@ -4972,13 +4979,6 @@ bool AbstractStorageDecl::hasAnyNativeDynamicAccessors() const {
49724979
return false;
49734980
}
49744981

4975-
bool AbstractStorageDecl::hasAnyDynamicReplacementAccessors() const {
4976-
for (auto accessor : getAllAccessors()) {
4977-
if (accessor->getAttrs().hasAttribute<DynamicReplacementAttr>())
4978-
return true;
4979-
}
4980-
return false;
4981-
}
49824982
void AbstractStorageDecl::setAccessors(SourceLoc lbraceLoc,
49834983
ArrayRef<AccessorDecl *> accessors,
49844984
SourceLoc rbraceLoc) {

lib/ClangImporter/ImporterImpl.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1230,6 +1230,12 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
12301230
llvm_unreachable("unimplemented for ClangImporter");
12311231
}
12321232

1233+
ValueDecl *
1234+
loadDynamicallyReplacedFunctionDecl(const DynamicReplacementAttr *DRA,
1235+
uint64_t contextData) override {
1236+
llvm_unreachable("unimplemented for ClangImporter");
1237+
}
1238+
12331239
void loadRequirementSignature(const ProtocolDecl *decl, uint64_t contextData,
12341240
SmallVectorImpl<Requirement> &reqs) override {
12351241
llvm_unreachable("unimplemented for ClangImporter");

lib/IRGen/GenArchetype.cpp

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -452,21 +452,18 @@ withOpaqueTypeGenericArgs(IRGenFunction &IGF,
452452

453453
bool shouldUseOpaqueTypeDescriptorAccessor(OpaqueTypeDecl *opaque) {
454454
auto *namingDecl = opaque->getNamingDecl();
455-
auto *abstractStorage = dyn_cast<AbstractStorageDecl>(namingDecl);
456455

457456
// Don't emit accessors for abstract storage that is not dynamic or a dynamic
458457
// replacement.
459-
if (abstractStorage) {
458+
if (auto *abstractStorage = dyn_cast<AbstractStorageDecl>(namingDecl)) {
460459
return abstractStorage->hasAnyNativeDynamicAccessors() ||
461-
abstractStorage->hasAnyDynamicReplacementAccessors();
460+
abstractStorage->getDynamicallyReplacedDecl();
462461
}
463462

464463
// Don't emit accessors for functions that are not dynamic or dynamic
465464
// replacements.
466-
return opaque->getNamingDecl()->isNativeDynamic() ||
467-
opaque->getNamingDecl()
468-
->getAttrs()
469-
.hasAttribute<DynamicReplacementAttr>();
465+
return namingDecl->isNativeDynamic() ||
466+
(bool)namingDecl->getDynamicallyReplacedDecl();
470467
}
471468

472469
static llvm::Value *

lib/IRGen/GenDecl.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2371,24 +2371,20 @@ void IRGenModule::emitOpaqueTypeDescriptorAccessor(OpaqueTypeDecl *opaque) {
23712371
auto *abstractStorage = dyn_cast<AbstractStorageDecl>(namingDecl);
23722372

23732373
bool isNativeDynamic = false;
2374-
bool isDynamicReplacement = false;
2374+
const bool isDynamicReplacement = namingDecl->getDynamicallyReplacedDecl();
23752375

23762376
// Don't emit accessors for abstract storage that is not dynamic or a dynamic
23772377
// replacement.
23782378
if (abstractStorage) {
23792379
isNativeDynamic = abstractStorage->hasAnyNativeDynamicAccessors();
2380-
isDynamicReplacement = abstractStorage->hasAnyDynamicReplacementAccessors();
23812380
if (!isNativeDynamic && !isDynamicReplacement)
23822381
return;
23832382
}
23842383

23852384
// Don't emit accessors for functions that are not dynamic or dynamic
23862385
// replacements.
23872386
if (!abstractStorage) {
2388-
isNativeDynamic = opaque->getNamingDecl()->isNativeDynamic();
2389-
isDynamicReplacement = opaque->getNamingDecl()
2390-
->getAttrs()
2391-
.hasAttribute<DynamicReplacementAttr>();
2387+
isNativeDynamic = namingDecl->isNativeDynamic();
23922388
if (!isNativeDynamic && !isDynamicReplacement)
23932389
return;
23942390
}

lib/SIL/SILFunctionBuilder.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,13 @@ void SILFunctionBuilder::addFunctionAttributes(SILFunction *F,
7676
SILFunctionTypeRepresentation::ObjCMethod)
7777
return;
7878

79-
auto *replacedFuncAttr = Attrs.getAttribute<DynamicReplacementAttr>();
80-
if (!replacedFuncAttr)
79+
// Only assign replacements when the thing being replaced is function-like and
80+
// explicitly declared.
81+
auto *origDecl = decl->getDynamicallyReplacedDecl();
82+
auto *replacedDecl = dyn_cast_or_null<AbstractFunctionDecl>(origDecl);
83+
if (!replacedDecl)
8184
return;
8285

83-
auto *replacedDecl = replacedFuncAttr->getReplacedFunction();
84-
assert(replacedDecl);
85-
8686
if (decl->isObjC()) {
8787
F->setObjCReplacement(replacedDecl);
8888
return;

lib/SILGen/SILGenApply.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -789,8 +789,7 @@ bool isCallToReplacedInDynamicReplacement(SILGenFunction &SGF,
789789
bool &isObjCReplacementSelfCall) {
790790
if (auto *func =
791791
dyn_cast_or_null<AbstractFunctionDecl>(SGF.FunctionDC->getAsDecl())) {
792-
auto *repl = func->getAttrs().getAttribute<DynamicReplacementAttr>();
793-
if (repl && repl->getReplacedFunction() == afd) {
792+
if (func->getDynamicallyReplacedDecl() == afd) {
794793
isObjCReplacementSelfCall = afd->isObjC();
795794
return true;
796795
}

0 commit comments

Comments
 (0)