Skip to content

Commit 4e36fc0

Browse files
committed
Replace semantic usages of DynamicReplacementAttr with the request
Complete the refactoring by splitting the semantic callers for the original decl of a dynamically replaced declaration. There's also a change to the way this attribute is validated and placed. The old model visited the attribute on any functions and variable declarations it encountered in the primary. Once there, it would strip the attribute off of variables and attach the corresponding attribute to each parsed accessor, then perform some additional ObjC-related validation. The new approach instead leaves the attribute alone. The request exists specifically to perform the lookups and type matching required to find replaced decls, and the attribute visitor no longer needs to worry about revisiting decls it has just grafted attributes onto. This also means that a bunch of parts of IRGen and SILGen that needed to fan out to the accessors to ask for the @_dynamicReplacement attribute to undo the work the type checker had done can just look at the storage itself. Further, syntactic requests for the attribute will now consistently succeed, where before they would fail dependending on whether or not the type checker had run - which was generally not an issue by the time we hit SIL.
1 parent 8201b5c commit 4e36fc0

File tree

10 files changed

+25
-45
lines changed

10 files changed

+25
-45
lines changed

include/swift/AST/Decl.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4774,8 +4774,6 @@ class AbstractStorageDecl : public ValueDecl {
47744774

47754775
bool hasAnyNativeDynamicAccessors() const;
47764776

4777-
bool hasAnyDynamicReplacementAccessors() const;
4778-
47794777
// Implement isa/cast/dyncast/etc.
47804778
static bool classof(const Decl *D) {
47814779
return D->getKind() >= DeclKind::First_AbstractStorageDecl &&

lib/AST/Decl.cpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4979,13 +4979,6 @@ bool AbstractStorageDecl::hasAnyNativeDynamicAccessors() const {
49794979
return false;
49804980
}
49814981

4982-
bool AbstractStorageDecl::hasAnyDynamicReplacementAccessors() const {
4983-
for (auto accessor : getAllAccessors()) {
4984-
if (accessor->getAttrs().hasAttribute<DynamicReplacementAttr>())
4985-
return true;
4986-
}
4987-
return false;
4988-
}
49894982
void AbstractStorageDecl::setAccessors(SourceLoc lbraceLoc,
49904983
ArrayRef<AccessorDecl *> accessors,
49914984
SourceLoc rbraceLoc) {

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: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2369,26 +2369,22 @@ static void emitDynamicallyReplaceableThunk(IRGenModule &IGM,
23692369
void IRGenModule::emitOpaqueTypeDescriptorAccessor(OpaqueTypeDecl *opaque) {
23702370
auto *namingDecl = opaque->getNamingDecl();
23712371
auto *abstractStorage = dyn_cast<AbstractStorageDecl>(namingDecl);
2372-
2372+
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
}

lib/Sema/TypeCheckDeclObjC.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,11 +1045,10 @@ Optional<ObjCReason> shouldMarkAsObjC(const ValueDecl *VD, bool allowImplicit) {
10451045
if (isa<AbstractFunctionDecl>(VD) || isa<AbstractStorageDecl>(VD))
10461046
if (auto *replacementAttr =
10471047
VD->getAttrs().getAttribute<DynamicReplacementAttr>()) {
1048-
if (auto *replaced = replacementAttr->getReplacedFunction()) {
1048+
if (auto *replaced = VD->getDynamicallyReplacedDecl()) {
10491049
if (replaced->isObjC())
10501050
return ObjCReason(ObjCReason::ImplicitlyObjC);
1051-
} else if (auto *replaced =
1052-
TypeChecker::findReplacedDynamicFunction(VD)) {
1051+
} else if (auto *replaced = VD->getDynamicallyReplacedDecl()) {
10531052
if (replaced->isObjC())
10541053
return ObjCReason(ObjCReason::ImplicitlyObjC);
10551054
}

lib/Serialization/Deserialization.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4114,9 +4114,6 @@ llvm::Error DeclDeserializer::deserializeDeclAttributes() {
41144114
serialization::decls_block::DynamicReplacementDeclAttrLayout::
41154115
readRecord(scratch, isImplicit, replacedFunID, numArgs, rawPieceIDs);
41164116

4117-
auto replacedFunDecl = MF.getDeclChecked(replacedFunID);
4118-
if (!replacedFunDecl)
4119-
return replacedFunDecl.takeError();
41204117
auto baseName = MF.getDeclBaseName(rawPieceIDs[0]);
41214118
SmallVector<Identifier, 4> pieces;
41224119
for (auto pieceID : rawPieceIDs.slice(1))
@@ -4125,8 +4122,8 @@ llvm::Error DeclDeserializer::deserializeDeclAttributes() {
41254122
assert(numArgs != 0);
41264123
assert(!isImplicit && "Need to update for implicit");
41274124
Attr = DynamicReplacementAttr::create(
4128-
ctx, DeclName(ctx, baseName, ArrayRef<Identifier>(pieces)),
4129-
cast<AbstractFunctionDecl>(*replacedFunDecl));
4125+
ctx, DeclName(ctx, baseName, ArrayRef<Identifier>(pieces)), &MF,
4126+
replacedFunID);
41304127
break;
41314128
}
41324129

lib/Serialization/Serialization.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2069,7 +2069,7 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
20692069
didVerifyAttrs = true;
20702070
}
20712071

2072-
void writeDeclAttribute(const DeclAttribute *DA) {
2072+
void writeDeclAttribute(const Decl *D, const DeclAttribute *DA) {
20732073
using namespace decls_block;
20742074

20752075
// Completely ignore attributes that aren't serialized.
@@ -2261,10 +2261,11 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
22612261
pieces.push_back(S.addDeclBaseNameRef(replacedFun.getBaseName()));
22622262
for (auto argName : replacedFun.getArgumentNames())
22632263
pieces.push_back(S.addDeclBaseNameRef(argName));
2264-
assert(theAttr->getReplacedFunction());
2264+
auto *afd = cast<ValueDecl>(D)->getDynamicallyReplacedDecl();
2265+
assert(afd && "Missing replaced decl!");
22652266
DynamicReplacementDeclAttrLayout::emitRecord(
22662267
S.Out, S.ScratchRecord, abbrCode, false, /*implicit flag*/
2267-
S.addDeclRef(theAttr->getReplacedFunction()), pieces.size(), pieces);
2268+
S.addDeclRef(afd), pieces.size(), pieces);
22682269
return;
22692270
}
22702271

@@ -2673,7 +2674,7 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
26732674
void visit(const Decl *D) {
26742675
// Emit attributes (if any).
26752676
for (auto Attr : D->getAttrs())
2676-
writeDeclAttribute(Attr);
2677+
writeDeclAttribute(D, Attr);
26772678

26782679
if (auto *value = dyn_cast<ValueDecl>(D))
26792680
writeDiscriminatorsIfNeeded(value);

lib/TBDGen/TBDGen.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ void TBDGenVisitor::visitAbstractFunctionDecl(AbstractFunctionDecl *AFD) {
226226
addSymbol(
227227
LinkEntity::forDynamicallyReplaceableFunctionKey(AFD, useAllocator));
228228
}
229-
if (AFD->getAttrs().hasAttribute<DynamicReplacementAttr>()) {
229+
if (AFD->getDynamicallyReplacedDecl()) {
230230
bool useAllocator = shouldUseAllocatorMangling(AFD);
231231
addSymbol(LinkEntity::forDynamicallyReplaceableFunctionVariable(
232232
AFD, useAllocator));
@@ -254,7 +254,7 @@ void TBDGenVisitor::visitFuncDecl(FuncDecl *FD) {
254254
addSymbol(LinkEntity::forOpaqueTypeDescriptorAccessorKey(opaqueResult));
255255
addSymbol(LinkEntity::forOpaqueTypeDescriptorAccessorVar(opaqueResult));
256256
}
257-
if (FD->getAttrs().hasAttribute<DynamicReplacementAttr>()) {
257+
if (FD->getDynamicallyReplacedDecl()) {
258258
addSymbol(LinkEntity::forOpaqueTypeDescriptorAccessor(opaqueResult));
259259
addSymbol(LinkEntity::forOpaqueTypeDescriptorAccessorVar(opaqueResult));
260260
}
@@ -282,7 +282,7 @@ void TBDGenVisitor::visitAbstractStorageDecl(AbstractStorageDecl *ASD) {
282282
addSymbol(LinkEntity::forOpaqueTypeDescriptorAccessorKey(opaqueResult));
283283
addSymbol(LinkEntity::forOpaqueTypeDescriptorAccessorVar(opaqueResult));
284284
}
285-
if (ASD->hasAnyDynamicReplacementAccessors()) {
285+
if (ASD->getDynamicallyReplacedDecl()) {
286286
addSymbol(LinkEntity::forOpaqueTypeDescriptorAccessor(opaqueResult));
287287
addSymbol(LinkEntity::forOpaqueTypeDescriptorAccessorVar(opaqueResult));
288288
}

0 commit comments

Comments
 (0)