Skip to content

Commit 7a37830

Browse files
authored
Merge pull request #26461 from slavapestov/lazy-accessor-synthesis-part-1
Lazy accessor synthesis for storage in secondary files
2 parents 1a92886 + 24b20a3 commit 7a37830

39 files changed

+307
-362
lines changed

include/swift/AST/Decl.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4592,6 +4592,23 @@ class AbstractStorageDecl : public ValueDecl {
45924592
/// with caution.
45934593
AccessorDecl *getSynthesizedAccessor(AccessorKind kind) const;
45944594

4595+
/// Return an accessor part of the set of opaque accessors dictated by the
4596+
/// requirements of the ABI.
4597+
///
4598+
/// This will synthesize the accessor if one is required but not specified
4599+
/// in source; for example, most of the time a mutable property is required
4600+
/// to have a 'modify' accessor, but if the property was only written with
4601+
/// 'get' and 'set' accessors, 'modify' will be synthesized to call 'get'
4602+
/// followed by 'set'.
4603+
///
4604+
/// If the accessor is not needed for ABI reasons, this returns nullptr.
4605+
/// To ensure an accessor is always returned, use getSynthesizedAccessor().
4606+
AccessorDecl *getOpaqueAccessor(AccessorKind kind) const;
4607+
4608+
/// Return an accessor that was written in source. Returns null if the
4609+
/// accessor was not explicitly defined by the user.
4610+
AccessorDecl *getParsedAccessor(AccessorKind kind) const;
4611+
45954612
/// Visit all the opaque accessors that this storage is expected to have.
45964613
void visitExpectedOpaqueAccessors(
45974614
llvm::function_ref<void (AccessorKind)>) const;

lib/AST/ASTPrinter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1804,7 +1804,7 @@ void PrintAST::printAccessors(const AbstractStorageDecl *ASD) {
18041804
if ((PrintAbstract || isGetSetImpl()) &&
18051805
!Options.PrintGetSetOnRWProperties &&
18061806
!Options.FunctionDefinitions &&
1807-
!ASD->getAccessor(AccessorKind::Get)->isMutating() &&
1807+
!ASD->isGetterMutating() &&
18081808
!ASD->getAccessor(AccessorKind::Set)->isExplicitNonMutating()) {
18091809
return;
18101810
}

lib/AST/ASTVerifier.cpp

Lines changed: 23 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1876,7 +1876,7 @@ class Verifier : public ASTWalker {
18761876
if (auto *baseIOT = E->getBase()->getType()->getAs<InOutType>()) {
18771877
if (!baseIOT->getObjectType()->is<ArchetypeType>()) {
18781878
auto *VD = dyn_cast<VarDecl>(E->getMember().getDecl());
1879-
if (!VD || VD->getAllAccessors().empty()) {
1879+
if (!VD || !VD->requiresOpaqueAccessors()) {
18801880
Out << "member_ref_expr on value of inout type\n";
18811881
E->dump(Out);
18821882
Out << "\n";
@@ -2446,6 +2446,9 @@ class Verifier : public ASTWalker {
24462446
}
24472447

24482448
void verifyChecked(VarDecl *var) {
2449+
if (!var->hasInterfaceType())
2450+
return;
2451+
24492452
PrettyStackTraceDecl debugStack("verifying VarDecl", var);
24502453

24512454
// Variables must have materializable type.
@@ -2472,27 +2475,21 @@ class Verifier : public ASTWalker {
24722475
}
24732476

24742477
Type typeForAccessors = var->getValueInterfaceType();
2475-
if (!var->getDeclContext()->contextHasLazyGenericEnvironment()) {
2476-
typeForAccessors =
2477-
var->getDeclContext()->mapTypeIntoContext(typeForAccessors);
2478-
if (const FuncDecl *getter = var->getAccessor(AccessorKind::Get)) {
2479-
if (getter->getParameters()->size() != 0) {
2480-
Out << "property getter has parameters\n";
2478+
if (const FuncDecl *getter = var->getAccessor(AccessorKind::Get)) {
2479+
if (getter->getParameters()->size() != 0) {
2480+
Out << "property getter has parameters\n";
2481+
abort();
2482+
}
2483+
if (getter->hasInterfaceType()) {
2484+
Type getterResultType = getter->getResultInterfaceType();
2485+
if (!getterResultType->isEqual(typeForAccessors)) {
2486+
Out << "property and getter have mismatched types: '";
2487+
typeForAccessors.print(Out);
2488+
Out << "' vs. '";
2489+
getterResultType.print(Out);
2490+
Out << "'\n";
24812491
abort();
24822492
}
2483-
if (getter->hasInterfaceType()) {
2484-
Type getterResultType = getter->getResultInterfaceType();
2485-
getterResultType =
2486-
var->getDeclContext()->mapTypeIntoContext(getterResultType);
2487-
if (!getterResultType->isEqual(typeForAccessors)) {
2488-
Out << "property and getter have mismatched types: '";
2489-
typeForAccessors.print(Out);
2490-
Out << "' vs. '";
2491-
getterResultType.print(Out);
2492-
Out << "'\n";
2493-
abort();
2494-
}
2495-
}
24962493
}
24972494
}
24982495

@@ -2512,15 +2509,12 @@ class Verifier : public ASTWalker {
25122509
}
25132510
const ParamDecl *param = setter->getParameters()->get(0);
25142511
Type paramType = param->getInterfaceType();
2515-
if (!var->getDeclContext()->contextHasLazyGenericEnvironment()) {
2516-
paramType = var->getDeclContext()->mapTypeIntoContext(paramType);
2517-
if (!paramType->isEqual(typeForAccessors)) {
2518-
Out << "property and setter param have mismatched types:\n";
2519-
typeForAccessors.dump(Out, 2);
2520-
Out << "vs.\n";
2521-
paramType.dump(Out, 2);
2522-
abort();
2523-
}
2512+
if (!paramType->isEqual(typeForAccessors)) {
2513+
Out << "property and setter param have mismatched types:\n";
2514+
typeForAccessors.dump(Out, 2);
2515+
Out << "vs.\n";
2516+
paramType.dump(Out, 2);
2517+
abort();
25242518
}
25252519
}
25262520
}

lib/AST/AccessRequests.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,7 @@ static bool isStoredWithPrivateSetter(VarDecl *VD) {
161161
return false;
162162

163163
if (VD->isLet() ||
164-
(VD->getAccessor(AccessorKind::Set) &&
165-
!VD->getAccessor(AccessorKind::Set)->isImplicit()))
164+
VD->getParsedAccessor(AccessorKind::Set))
166165
return false;
167166

168167
return true;

lib/AST/Decl.cpp

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1970,6 +1970,28 @@ AccessorDecl *AbstractStorageDecl::getSynthesizedAccessor(AccessorKind kind) con
19701970
nullptr);
19711971
}
19721972

1973+
AccessorDecl *AbstractStorageDecl::getOpaqueAccessor(AccessorKind kind) const {
1974+
auto *accessor = getAccessor(kind);
1975+
if (accessor && !accessor->isImplicit())
1976+
return accessor;
1977+
1978+
if (!requiresOpaqueAccessors())
1979+
return nullptr;
1980+
1981+
if (!requiresOpaqueAccessor(kind))
1982+
return nullptr;
1983+
1984+
return getSynthesizedAccessor(kind);
1985+
}
1986+
1987+
AccessorDecl *AbstractStorageDecl::getParsedAccessor(AccessorKind kind) const {
1988+
auto *accessor = getAccessor(kind);
1989+
if (accessor && !accessor->isImplicit())
1990+
return accessor;
1991+
1992+
return nullptr;
1993+
}
1994+
19731995
void AbstractStorageDecl::visitExpectedOpaqueAccessors(
19741996
llvm::function_ref<void (AccessorKind)> visit) const {
19751997
if (!requiresOpaqueAccessors())
@@ -1993,8 +2015,9 @@ void AbstractStorageDecl::visitExpectedOpaqueAccessors(
19932015
void AbstractStorageDecl::visitOpaqueAccessors(
19942016
llvm::function_ref<void (AccessorDecl*)> visit) const {
19952017
visitExpectedOpaqueAccessors([&](AccessorKind kind) {
1996-
auto accessor = getAccessor(kind);
1997-
assert(accessor && "didn't have expected opaque accessor");
2018+
auto accessor = getSynthesizedAccessor(kind);
2019+
assert(!accessor->hasForcedStaticDispatch() &&
2020+
"opaque accessor with forced static dispatch?");
19982021
visit(accessor);
19992022
});
20002023
}
@@ -4029,7 +4052,7 @@ ClassDecl::findOverridingDecl(const AbstractFunctionDecl *Method) const {
40294052
auto *Storage = Accessor->getStorage();
40304053
if (auto *Derived = ::findOverridingDecl(this, Storage)) {
40314054
auto *DerivedStorage = cast<AbstractStorageDecl>(Derived);
4032-
return DerivedStorage->getAccessor(Accessor->getAccessorKind());
4055+
return DerivedStorage->getOpaqueAccessor(Accessor->getAccessorKind());
40334056
}
40344057

40354058
return nullptr;
@@ -4651,9 +4674,9 @@ bool AbstractStorageDecl::hasPrivateAccessor() const {
46514674
}
46524675

46534676
bool AbstractStorageDecl::hasDidSetOrWillSetDynamicReplacement() const {
4654-
if (auto *func = getAccessor(AccessorKind::DidSet))
4677+
if (auto *func = getParsedAccessor(AccessorKind::DidSet))
46554678
return func->getAttrs().hasAttribute<DynamicReplacementAttr>();
4656-
if (auto *func = getAccessor(AccessorKind::WillSet))
4679+
if (auto *func = getParsedAccessor(AccessorKind::WillSet))
46574680
return func->getAttrs().hasAttribute<DynamicReplacementAttr>();
46584681
return false;
46594682
}
@@ -4855,7 +4878,7 @@ getNameFromObjcAttribute(const ObjCAttr *attr, DeclName preferredName) {
48554878
ObjCSelector
48564879
AbstractStorageDecl::getObjCGetterSelector(Identifier preferredName) const {
48574880
// If the getter has an @objc attribute with a name, use that.
4858-
if (auto getter = getAccessor(AccessorKind::Get)) {
4881+
if (auto getter = getParsedAccessor(AccessorKind::Get)) {
48594882
if (auto name = getNameFromObjcAttribute(getter->getAttrs().
48604883
getAttribute<ObjCAttr>(), preferredName))
48614884
return *name;
@@ -4885,7 +4908,7 @@ AbstractStorageDecl::getObjCGetterSelector(Identifier preferredName) const {
48854908
ObjCSelector
48864909
AbstractStorageDecl::getObjCSetterSelector(Identifier preferredName) const {
48874910
// If the setter has an @objc attribute with a name, use that.
4888-
auto setter = getAccessor(AccessorKind::Set);
4911+
auto setter = getParsedAccessor(AccessorKind::Set);
48894912
auto objcAttr = setter ? setter->getAttrs().getAttribute<ObjCAttr>()
48904913
: nullptr;
48914914
if (auto name = getNameFromObjcAttribute(objcAttr, DeclName(preferredName))) {

lib/AST/SwiftNameTranslation.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ getObjCNameForSwiftDecl(const ValueDecl *VD, DeclName PreferredName){
114114
return {BaseName, ObjCSelector()};
115115
return {VAD->getObjCPropertyName(), ObjCSelector()};
116116
} else if (auto *SD = dyn_cast<SubscriptDecl>(VD)) {
117-
return getObjCNameForSwiftDecl(SD->getAccessor(AccessorKind::Get),
117+
return getObjCNameForSwiftDecl(SD->getParsedAccessor(AccessorKind::Get),
118118
PreferredName);
119119
} else if (auto *EL = dyn_cast<EnumElementDecl>(VD)) {
120120
SmallString<64> Buffer;

lib/AST/Type.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2556,7 +2556,7 @@ bool ReplaceOpaqueTypesWithUnderlyingTypes::shouldPerformSubstitution(
25562556
return true;
25572557
}
25582558
} else if (auto *asd = dyn_cast<AbstractStorageDecl>(namingDecl)) {
2559-
auto *getter = asd->getAccessor(AccessorKind::Get);
2559+
auto *getter = asd->getOpaqueAccessor(AccessorKind::Get);
25602560
if (getter &&
25612561
getter->getResilienceExpansion() == ResilienceExpansion::Minimal) {
25622562
return true;

lib/ClangImporter/ImportDecl.cpp

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3628,13 +3628,13 @@ namespace {
36283628
case ImportedAccessorKind::PropertyGetter: {
36293629
auto property = getImplicitProperty(importedName, decl);
36303630
if (!property) return nullptr;
3631-
return property->getAccessor(AccessorKind::Get);
3631+
return property->getParsedAccessor(AccessorKind::Get);
36323632
}
36333633

36343634
case ImportedAccessorKind::PropertySetter:
36353635
auto property = getImplicitProperty(importedName, decl);
36363636
if (!property) return nullptr;
3637-
return property->getAccessor(AccessorKind::Set);
3637+
return property->getParsedAccessor(AccessorKind::Set);
36383638
}
36393639

36403640
return importFunctionDecl(decl, importedName, correctSwiftName, None);
@@ -5010,8 +5010,8 @@ namespace {
50105010
// Only record overrides of class members.
50115011
if (overridden) {
50125012
result->setOverriddenDecl(overridden);
5013-
getter->setOverriddenDecl(overridden->getAccessor(AccessorKind::Get));
5014-
if (auto parentSetter = overridden->getAccessor(AccessorKind::Set))
5013+
getter->setOverriddenDecl(overridden->getParsedAccessor(AccessorKind::Get));
5014+
if (auto parentSetter = overridden->getParsedAccessor(AccessorKind::Set))
50155015
if (setter)
50165016
setter->setOverriddenDecl(parentSetter);
50175017
}
@@ -6516,10 +6516,10 @@ void SwiftDeclConverter::recordObjCOverride(SubscriptDecl *subscript) {
65166516

65176517
// The index types match. This is an override, so mark it as such.
65186518
subscript->setOverriddenDecl(parentSub);
6519-
auto getterThunk = subscript->getAccessor(AccessorKind::Get);
6520-
getterThunk->setOverriddenDecl(parentSub->getAccessor(AccessorKind::Get));
6521-
if (auto parentSetter = parentSub->getAccessor(AccessorKind::Set)) {
6522-
if (auto setterThunk = subscript->getAccessor(AccessorKind::Set))
6519+
auto getterThunk = subscript->getParsedAccessor(AccessorKind::Get);
6520+
getterThunk->setOverriddenDecl(parentSub->getParsedAccessor(AccessorKind::Get));
6521+
if (auto parentSetter = parentSub->getParsedAccessor(AccessorKind::Set)) {
6522+
if (auto setterThunk = subscript->getParsedAccessor(AccessorKind::Set))
65236523
setterThunk->setOverriddenDecl(parentSetter);
65246524
}
65256525

@@ -8397,10 +8397,8 @@ ClangImporter::Implementation::createConstant(Identifier name, DeclContext *dc,
83978397
func->computeType();
83988398
func->setAccess(getOverridableAccessLevel(dc));
83998399
func->setValidationToChecked();
8400-
func->setImplicit();
84018400
func->setIsObjC(false);
84028401
func->setIsDynamic(false);
8403-
func->setIsTransparent(false);
84048402

84058403
func->setBodySynthesizer(synthesizeConstantGetterBody,
84068404
ConstantGetterBodyContextData(valueExpr, convertKind)

lib/IDE/Formatting.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -268,9 +268,8 @@ class FormatContext {
268268
// return 0; <- No indentation added because of the getter.
269269
// }
270270
if (auto VD = dyn_cast_or_null<VarDecl>(Cursor->getAsDecl())) {
271-
if (auto Getter = VD->getAccessor(AccessorKind::Get)) {
272-
if (!Getter->isImplicit() &&
273-
Getter->getAccessorKeywordLoc().isInvalid()) {
271+
if (auto Getter = VD->getParsedAccessor(AccessorKind::Get)) {
272+
if (Getter->getAccessorKeywordLoc().isInvalid()) {
274273
LineAndColumn = ParentLineAndColumn;
275274
continue;
276275
}

lib/IRGen/GenClass.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1793,7 +1793,7 @@ namespace {
17931793
}
17941794

17951795
// Don't emit descriptors for properties without accessors.
1796-
auto getter = var->getAccessor(AccessorKind::Get);
1796+
auto getter = var->getOpaqueAccessor(AccessorKind::Get);
17971797
if (!getter)
17981798
return;
17991799

@@ -1804,7 +1804,7 @@ namespace {
18041804
auto &methods = getMethodList(var);
18051805
methods.push_back(getter);
18061806

1807-
if (auto setter = var->getAccessor(AccessorKind::Set))
1807+
if (auto setter = var->getOpaqueAccessor(AccessorKind::Set))
18081808
methods.push_back(setter);
18091809
}
18101810
}
@@ -2030,13 +2030,13 @@ namespace {
20302030
void visitSubscriptDecl(SubscriptDecl *subscript) {
20312031
if (!requiresObjCSubscriptDescriptor(IGM, subscript)) return;
20322032

2033-
auto getter = subscript->getAccessor(AccessorKind::Get);
2033+
auto getter = subscript->getOpaqueAccessor(AccessorKind::Get);
20342034
if (!getter) return;
20352035

20362036
auto &methods = getMethodList(subscript);
20372037
methods.push_back(getter);
20382038

2039-
if (auto setter = subscript->getAccessor(AccessorKind::Set))
2039+
if (auto setter = subscript->getOpaqueAccessor(AccessorKind::Set))
20402040
methods.push_back(setter);
20412041
}
20422042
};

lib/IRGen/GenObjC.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -923,7 +923,7 @@ static llvm::Constant *getObjCGetterPointer(IRGenModule &IGM,
923923
if (isa<ProtocolDecl>(property->getDeclContext()))
924924
return llvm::ConstantPointerNull::get(IGM.Int8PtrTy);
925925

926-
SILDeclRef getter = SILDeclRef(property->getAccessor(AccessorKind::Get),
926+
SILDeclRef getter = SILDeclRef(property->getOpaqueAccessor(AccessorKind::Get),
927927
SILDeclRef::Kind::Func)
928928
.asForeign();
929929

@@ -944,7 +944,7 @@ static llvm::Constant *getObjCSetterPointer(IRGenModule &IGM,
944944
assert(property->isSettable(property->getDeclContext()) &&
945945
"property is not settable?!");
946946

947-
SILDeclRef setter = SILDeclRef(property->getAccessor(AccessorKind::Set),
947+
SILDeclRef setter = SILDeclRef(property->getOpaqueAccessor(AccessorKind::Set),
948948
SILDeclRef::Kind::Func)
949949
.asForeign();
950950
return findSwiftAsObjCThunk(IGM, setter, silFn);
@@ -1013,8 +1013,7 @@ static CanSILFunctionType getObjCMethodType(IRGenModule &IGM,
10131013
static clang::CanQualType getObjCPropertyType(IRGenModule &IGM,
10141014
VarDecl *property) {
10151015
// Use the lowered return type of the foreign getter.
1016-
auto getter = property->getAccessor(AccessorKind::Get);
1017-
assert(getter);
1016+
auto getter = property->getOpaqueAccessor(AccessorKind::Get);
10181017
CanSILFunctionType methodTy = getObjCMethodType(IGM, getter);
10191018
return IGM.getClangType(
10201019
methodTy->getFormalCSemanticResult().getASTType());
@@ -1173,7 +1172,7 @@ SILFunction *irgen::emitObjCGetterDescriptorParts(IRGenModule &IGM,
11731172
Selector getterSel(subscript, Selector::ForGetter);
11741173
selectorRef = IGM.getAddrOfObjCMethodName(getterSel.str());
11751174
auto methodTy = getObjCMethodType(IGM,
1176-
subscript->getAccessor(AccessorKind::Get));
1175+
subscript->getOpaqueAccessor(AccessorKind::Get));
11771176
atEncoding = getObjCEncodingForMethodType(IGM, methodTy, /*extended*/false);
11781177
SILFunction *silFn = nullptr;
11791178
impl = getObjCGetterPointer(IGM, subscript, silFn);
@@ -1250,7 +1249,7 @@ SILFunction *irgen::emitObjCSetterDescriptorParts(IRGenModule &IGM,
12501249
Selector setterSel(subscript, Selector::ForSetter);
12511250
selectorRef = IGM.getAddrOfObjCMethodName(setterSel.str());
12521251
auto methodTy = getObjCMethodType(IGM,
1253-
subscript->getAccessor(AccessorKind::Set));
1252+
subscript->getOpaqueAccessor(AccessorKind::Set));
12541253
atEncoding = getObjCEncodingForMethodType(IGM, methodTy, /*extended*/false);
12551254
SILFunction *silFn = nullptr;
12561255
impl = getObjCSetterPointer(IGM, subscript, silFn);
@@ -1401,7 +1400,7 @@ bool irgen::requiresObjCPropertyDescriptor(IRGenModule &IGM,
14011400
// Don't generate a descriptor for a property without any accessors.
14021401
// This is only possible in SIL files because Sema will normally
14031402
// implicitly synthesize accessors for @objc properties.
1404-
return property->isObjC() && property->getAccessor(AccessorKind::Get);
1403+
return property->isObjC() && property->requiresOpaqueAccessors();
14051404
}
14061405

14071406
bool irgen::requiresObjCSubscriptDescriptor(IRGenModule &IGM,

lib/IRGen/Linking.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,7 @@ SILLinkage LinkEntity::getLinkage(ForDefinition_t forDefinition) const {
567567
// property itself (for instance, with a private/internal property whose
568568
// accessor is @inlinable or @usableFromInline)
569569
auto getterDecl = cast<AbstractStorageDecl>(getDecl())
570-
->getAccessor(AccessorKind::Get);
570+
->getOpaqueAccessor(AccessorKind::Get);
571571
return getSILLinkage(getDeclLinkage(getterDecl), forDefinition);
572572
}
573573

0 commit comments

Comments
 (0)