Skip to content

Commit 28a39d6

Browse files
committed
[AST] NFC: Add a way to request initialized/accesses properties from init accessor
1 parent 94522ff commit 28a39d6

File tree

9 files changed

+80
-105
lines changed

9 files changed

+80
-105
lines changed

include/swift/AST/Decl.h

+7
Original file line numberDiff line numberDiff line change
@@ -7650,6 +7650,13 @@ class AccessorDecl final : public FuncDecl {
76507650
/// for anything other than a getter or setter.
76517651
void printUserFacingName(llvm::raw_ostream &out) const;
76527652

7653+
/// If this is an init accessor, retrieve a list of instance properties
7654+
/// initialized by it.
7655+
ArrayRef<VarDecl *> getInitializedProperties() const;
7656+
/// If this is an init accessor, retrieve a list of instance properties
7657+
/// accessed by it.
7658+
ArrayRef<VarDecl *> getAccessedProperties() const;
7659+
76537660
static bool classof(const Decl *D) {
76547661
return D->getKind() == DeclKind::Accessor;
76557662
}

lib/AST/Decl.cpp

+21-16
Original file line numberDiff line numberDiff line change
@@ -4948,11 +4948,8 @@ void NominalTypeDecl::collectPropertiesInitializableByInitAccessors(
49484948
std::multimap<VarDecl *, VarDecl *> &result) const {
49494949
for (auto *property : getInitAccessorProperties()) {
49504950
auto *initAccessor = property->getAccessor(AccessorKind::Init);
4951-
if (auto *initAttr =
4952-
initAccessor->getAttrs().getAttribute<InitializesAttr>()) {
4953-
for (auto *subsumed : initAttr->getPropertyDecls(initAccessor))
4954-
result.insert({subsumed, property});
4955-
}
4951+
for (auto *subsumed : initAccessor->getInitializedProperties())
4952+
result.insert({subsumed, property});
49564953
}
49574954
}
49584955

@@ -6868,21 +6865,15 @@ bool VarDecl::isSettable(const DeclContext *UseDC,
68686865
// designated initializer(s) or by init accessors.
68696866
if (isInstanceMember()) {
68706867
// Init accessors allow assignments to `let` properties if a
6871-
// property is part of `initializes(...)` list.
6868+
// property is part of `initializes` list.
68726869
if (auto *accessor =
68736870
dyn_cast<AccessorDecl>(const_cast<DeclContext *>(UseDC))) {
6874-
// Check whether this property is part of `initializes(...)` list,
6871+
// Check whether this property is part of `initializes` list,
68756872
// and allow assignment/mutation if so. DI would be responsible
68766873
// for checking for re-assignment.
6877-
if (auto *initAttr =
6878-
accessor->getAttrs().getAttribute<InitializesAttr>()) {
6879-
return llvm::is_contained(initAttr->getPropertyDecls(accessor),
6880-
const_cast<VarDecl *>(this));
6881-
}
6882-
6883-
// If there is no `initializes` attribute, no referenced properties
6884-
// can be assignment to or mutated.
6885-
return false;
6874+
return accessor->isInitAccessor() &&
6875+
llvm::is_contained(accessor->getInitializedProperties(),
6876+
const_cast<VarDecl *>(this));
68866877
}
68876878

68886879
auto *CD = dyn_cast<ConstructorDecl>(UseDC);
@@ -9548,6 +9539,20 @@ void AccessorDecl::printUserFacingName(raw_ostream &out) const {
95489539
out << ")";
95499540
}
95509541

9542+
ArrayRef<VarDecl *> AccessorDecl::getInitializedProperties() const {
9543+
assert(isInitAccessor());
9544+
if (auto *initAttr = getAttrs().getAttribute<InitializesAttr>())
9545+
return initAttr->getPropertyDecls(const_cast<AccessorDecl *>(this));
9546+
return {};
9547+
}
9548+
9549+
ArrayRef<VarDecl *> AccessorDecl::getAccessedProperties() const {
9550+
assert(isInitAccessor());
9551+
if (auto *accessAttr = getAttrs().getAttribute<AccessesAttr>())
9552+
return accessAttr->getPropertyDecls(const_cast<AccessorDecl *>(this));
9553+
return {};
9554+
}
9555+
95519556
StaticSpellingKind FuncDecl::getCorrectStaticSpelling() const {
95529557
assert(getDeclContext()->isTypeContext());
95539558
if (!isStatic())

lib/SIL/IR/SILFunctionType.cpp

+11-15
Original file line numberDiff line numberDiff line change
@@ -2373,26 +2373,22 @@ static CanSILFunctionType getSILFunctionTypeForInitAccessor(
23732373
// Drop `self` parameter.
23742374
inputs.pop_back();
23752375

2376-
// `accesses(...)` appear as `inout` parameters because they could be
2376+
// accessed properties appear as `inout` parameters because they could be
23772377
// read from and modified.
2378-
if (auto *attr = accessor->getAttrs().getAttribute<AccessesAttr>()) {
2379-
for (auto *property : attr->getPropertyDecls(accessor)) {
2380-
inputs.push_back(
2381-
SILParameterInfo(property->getInterfaceType()->getCanonicalType(),
2382-
ParameterConvention::Indirect_Inout));
2383-
}
2378+
for (auto *property : accessor->getAccessedProperties()) {
2379+
inputs.push_back(
2380+
SILParameterInfo(property->getInterfaceType()->getCanonicalType(),
2381+
ParameterConvention::Indirect_Inout));
23842382
}
23852383

23862384
SmallVector<SILResultInfo, 8> results;
23872385

2388-
// `initializes(...)` appear as `@out` result because they are initialized
2389-
// by the accessor.
2390-
if (auto *attr = accessor->getAttrs().getAttribute<InitializesAttr>()) {
2391-
for (auto *property : attr->getPropertyDecls(accessor)) {
2392-
results.push_back(
2393-
SILResultInfo(property->getInterfaceType()->getCanonicalType(),
2394-
ResultConvention::Indirect));
2395-
}
2386+
// initialized properties appear as `@out` results because they are
2387+
// initialized by the accessor.
2388+
for (auto *property : accessor->getInitializedProperties()) {
2389+
results.push_back(
2390+
SILResultInfo(property->getInterfaceType()->getCanonicalType(),
2391+
ResultConvention::Indirect));
23962392
}
23972393

23982394
auto calleeConvention = ParameterConvention::Direct_Unowned;

lib/SIL/IR/SILInstructions.cpp

+5-13
Original file line numberDiff line numberDiff line change
@@ -1311,26 +1311,18 @@ AccessorDecl *AssignOrInitInst::getReferencedInitAccessor() const {
13111311
}
13121312

13131313
unsigned AssignOrInitInst::getNumInitializedProperties() const {
1314-
if (auto *accessor = getReferencedInitAccessor()) {
1315-
auto *initAttr = accessor->getAttrs().getAttribute<InitializesAttr>();
1316-
return initAttr ? initAttr->getNumProperties() : 0;
1317-
}
1318-
return 0;
1314+
return getInitializedProperties().size();
13191315
}
13201316

13211317
ArrayRef<VarDecl *> AssignOrInitInst::getInitializedProperties() const {
1322-
if (auto *accessor = getReferencedInitAccessor()) {
1323-
if (auto *initAttr = accessor->getAttrs().getAttribute<InitializesAttr>())
1324-
return initAttr->getPropertyDecls(accessor);
1325-
}
1318+
if (auto *accessor = getReferencedInitAccessor())
1319+
return accessor->getInitializedProperties();
13261320
return {};
13271321
}
13281322

13291323
ArrayRef<VarDecl *> AssignOrInitInst::getAccessedProperties() const {
1330-
if (auto *accessor = getReferencedInitAccessor()) {
1331-
if (auto *accessAttr = accessor->getAttrs().getAttribute<AccessesAttr>())
1332-
return accessAttr->getPropertyDecls(accessor);
1333-
}
1324+
if (auto *accessor = getReferencedInitAccessor())
1325+
return accessor->getAccessedProperties();
13341326
return {};
13351327
}
13361328

lib/SILGen/SILGenConstructor.cpp

+18-28
Original file line numberDiff line numberDiff line change
@@ -284,21 +284,17 @@ emitApplyOfInitAccessor(SILGenFunction &SGF, SILLocation loc,
284284
};
285285

286286
// First, let's emit all of the indirect results.
287-
if (auto *initAttr = accessor->getAttrs().getAttribute<InitializesAttr>()) {
288-
for (auto *property : initAttr->getPropertyDecls(accessor)) {
289-
arguments.push_back(emitFieldReference(property, /*forInit=*/true));
290-
}
287+
for (auto *property : accessor->getInitializedProperties()) {
288+
arguments.push_back(emitFieldReference(property, /*forInit=*/true));
291289
}
292290

293291
// `initialValue`
294292
std::move(initialValue).forwardAll(SGF, arguments);
295293

296-
// And finally, all of the properties in `accesses(...)` list which are
294+
// And finally, all of the properties in `accesses` list which are
297295
// `inout` arguments.
298-
if (auto *accessAttr = accessor->getAttrs().getAttribute<AccessesAttr>()) {
299-
for (auto *property : accessAttr->getPropertyDecls(accessor)) {
300-
arguments.push_back(emitFieldReference(property));
301-
}
296+
for (auto *property : accessor->getAccessedProperties()) {
297+
arguments.push_back(emitFieldReference(property));
302298
}
303299

304300
SubstitutionMap subs;
@@ -1603,39 +1599,33 @@ void SILGenFunction::emitInitAccessor(AccessorDecl *accessor) {
16031599
InitAccessorArgumentMappings[property] = arg;
16041600
};
16051601

1606-
// First, emit results, this is our "initializes(...)" properties and
1602+
// First, emit results, this is our "initializes" properties and
16071603
// require DI to check that each property is fully initialized.
1608-
if (auto *initAttr = accessor->getAttrs().getAttribute<InitializesAttr>()) {
1609-
auto initializedProperties = initAttr->getPropertyDecls(accessor);
1610-
for (unsigned i = 0, n = initializedProperties.size(); i != n; ++i) {
1611-
auto *property = initializedProperties[i];
1612-
auto propertyTy =
1613-
getSILTypeInContext(accessorTy->getResults()[i], accessorTy);
1614-
createArgument(property, propertyTy, /*markUninitialized=*/true);
1615-
}
1604+
auto initializedProperties = accessor->getInitializedProperties();
1605+
for (unsigned i = 0, n = initializedProperties.size(); i != n; ++i) {
1606+
auto *property = initializedProperties[i];
1607+
auto propertyTy =
1608+
getSILTypeInContext(accessorTy->getResults()[i], accessorTy);
1609+
createArgument(property, propertyTy, /*markUninitialized=*/true);
16161610
}
16171611

16181612
// Collect all of the parameters that represent properties listed by
16191613
// "accesses" attribute. They have to be emitted in order of arguments which
16201614
// means after the "newValue" which is emitted by \c emitBasicProlog.
1621-
llvm::Optional<ArrayRef<VarDecl *>> accessedProperties;
1622-
{
1623-
if (auto *accessAttr = accessor->getAttrs().getAttribute<AccessesAttr>())
1624-
accessedProperties = accessAttr->getPropertyDecls(accessor);
1625-
}
1615+
auto accessedProperties = accessor->getAccessedProperties();
16261616

16271617
// Emit `newValue` argument.
16281618
emitBasicProlog(accessor->getParameters(), /*selfParam=*/nullptr,
16291619
TupleType::getEmpty(F.getASTContext()), accessor,
16301620
/*throws=*/false, /*throwsLoc=*/SourceLoc(),
16311621
/*ignored parameters*/
1632-
accessedProperties ? accessedProperties->size() : 0);
1622+
accessedProperties.size());
16331623

1634-
// Emit arguments for all `accesses(...)` properties.
1635-
if (accessedProperties) {
1636-
auto propertyIter = accessedProperties->begin();
1624+
// Emit arguments for all `accesses` properties.
1625+
if (!accessedProperties.empty()) {
1626+
auto propertyIter = accessedProperties.begin();
16371627
auto propertyArgs = accessorTy->getParameters().slice(
1638-
accessorTy->getNumParameters() - accessedProperties->size());
1628+
accessorTy->getNumParameters() - accessedProperties.size());
16391629

16401630
for (const auto &argument : propertyArgs) {
16411631
createArgument(*propertyIter, getSILTypeInContext(argument, accessorTy));

lib/SILOptimizer/Mandatory/RawSILInstLowering.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ lowerAssignOrInitInstruction(SILBuilderWithScope &b,
314314

315315
SmallVector<SILValue> arguments;
316316

317-
// First, emit all of the properties listed in `initializes(...)`. They
317+
// First, emit all of the properties listed in `initializes`. They
318318
// are passed as indirect results.
319319
{
320320
auto toInitialize = inst->getInitializedProperties();
@@ -330,7 +330,7 @@ lowerAssignOrInitInstruction(SILBuilderWithScope &b,
330330
emitInitAccessorInitialValueArgument(arguments, src, convention, b,
331331
forCleanup);
332332

333-
// And finally, emit all of the `accesses(...)` properties.
333+
// And finally, emit all of the `accesses` properties.
334334
for (auto *property : inst->getAccessedProperties())
335335
arguments.push_back(emitFieldReference(property));
336336

lib/Sema/CSSimplify.cpp

+9-15
Original file line numberDiff line numberDiff line change
@@ -9652,21 +9652,15 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName,
96529652
// If name doesn't appear in either `initializes` or `accesses`
96539653
// then it's invalid instance member.
96549654

9655-
if (auto *initializesAttr =
9656-
accessor->getAttrs().getAttribute<InitializesAttr>()) {
9657-
isValidReference |= llvm::any_of(
9658-
initializesAttr->getProperties(), [&](Identifier name) {
9659-
return DeclNameRef(name) == memberName;
9660-
});
9661-
}
9662-
9663-
if (auto *accessesAttr =
9664-
accessor->getAttrs().getAttribute<AccessesAttr>()) {
9665-
isValidReference |= llvm::any_of(
9666-
accessesAttr->getProperties(), [&](Identifier name) {
9667-
return DeclNameRef(name) == memberName;
9668-
});
9669-
}
9655+
isValidReference |= llvm::any_of(
9656+
accessor->getInitializedProperties(), [&](VarDecl *prop) {
9657+
return prop->createNameRef() == memberName;
9658+
});
9659+
9660+
isValidReference |= llvm::any_of(
9661+
accessor->getAccessedProperties(), [&](VarDecl *prop) {
9662+
return prop->createNameRef() == memberName;
9663+
});
96709664

96719665
if (!isValidReference) {
96729666
result.addUnviable(

lib/Sema/CodeSynthesis.cpp

+5-13
Original file line numberDiff line numberDiff line change
@@ -1304,22 +1304,14 @@ HasMemberwiseInitRequest::evaluate(Evaluator &evaluator,
13041304
if (auto *initAccessor = var->getAccessor(AccessorKind::Init)) {
13051305
// Make sure that all properties accessed by init accessor
13061306
// are previously initialized.
1307-
if (auto accessAttr =
1308-
initAccessor->getAttrs().getAttribute<AccessesAttr>()) {
1309-
for (auto *property : accessAttr->getPropertyDecls(initAccessor)) {
1310-
if (!initializedProperties.count(property))
1311-
invalidOrderings.push_back(
1312-
{var, property->getName()});
1313-
}
1307+
for (auto *property : initAccessor->getAccessedProperties()) {
1308+
if (!initializedProperties.count(property))
1309+
invalidOrderings.push_back({var, property->getName()});
13141310
}
13151311

13161312
// Record all of the properties initialized by calling init accessor.
1317-
if (auto initAttr =
1318-
initAccessor->getAttrs().getAttribute<InitializesAttr>()) {
1319-
auto properties = initAttr->getPropertyDecls(initAccessor);
1320-
initializedProperties.insert(properties.begin(), properties.end());
1321-
}
1322-
1313+
auto properties = initAccessor->getInitializedProperties();
1314+
initializedProperties.insert(properties.begin(), properties.end());
13231315
continue;
13241316
}
13251317

lib/Sema/TypeCheckStorage.cpp

+2-3
Original file line numberDiff line numberDiff line change
@@ -368,9 +368,8 @@ MemberwiseInitPropertiesRequest::evaluate(Evaluator &evaluator,
368368
// that the accessor initializes. Mark those stored properties as being subsumed; we'll
369369
// get back to them later.
370370
if (auto initAccessor = var->getAccessor(AccessorKind::Init)) {
371-
if (auto initAttr = initAccessor->getAttrs().getAttribute<InitializesAttr>()) {
372-
for (auto subsumed : initAttr->getPropertyDecls(initAccessor))
373-
subsumedViaInitAccessor.insert(subsumed);
371+
for (auto subsumed : initAccessor->getInitializedProperties()) {
372+
subsumedViaInitAccessor.insert(subsumed);
374373
}
375374
}
376375
};

0 commit comments

Comments
 (0)