Skip to content

Commit 1a169b9

Browse files
committed
Centralize the definition of isMemberwiseInitialized()
This utility was defined in Sema, used in Sema and Index, declared in two headers, and semi- copy-pasted into SILGen. Pull it into VarDecl::isMemberwiseInitialized() and use it consistently.
1 parent 209e7fc commit 1a169b9

File tree

8 files changed

+43
-39
lines changed

8 files changed

+43
-39
lines changed

include/swift/AST/Decl.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5142,7 +5142,11 @@ class VarDecl : public AbstractStorageDecl {
51425142

51435143
/// Returns true if the name is the self identifier and is implicit.
51445144
bool isSelfParameter() const;
5145-
5145+
5146+
/// Determine whether this property will be part of the implicit memberwise
5147+
/// initializer.
5148+
bool isMemberwiseInitialized() const;
5149+
51465150
// Implement isa/cast/dyncast/etc.
51475151
static bool classof(const Decl *D) {
51485152
return D->getKind() == DeclKind::Var || D->getKind() == DeclKind::Param;

include/swift/Sema/IDETypeChecking.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -239,10 +239,6 @@ namespace swift {
239239
/// \param DC The DeclContext from which the subscript is being referenced.
240240
Optional<Type> getRootTypeOfKeypathDynamicMember(SubscriptDecl *subscript,
241241
const DeclContext *DC);
242-
243-
/// Determine whether the given property is part of the memberwise initializer
244-
/// for a struct.
245-
bool isMemberwiseInitialized(VarDecl *var);
246242
}
247243

248244
#endif

lib/AST/Decl.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5254,6 +5254,30 @@ bool VarDecl::isSelfParameter() const {
52545254
return false;
52555255
}
52565256

5257+
bool VarDecl::isMemberwiseInitialized() const {
5258+
if (!getDeclContext()->isTypeContext())
5259+
return false;
5260+
5261+
// Implicit, computed, and static properties are not initialized.
5262+
// The exception is lazy properties, which due to batch mode we may or
5263+
// may not have yet finalized, so they may currently be "stored" or
5264+
// "computed" in the current AST state.
5265+
if (isImplicit() || isStatic())
5266+
return false;
5267+
5268+
if (!hasStorage() && !getAttrs().hasAttribute<LazyAttr>() &&
5269+
!getAttachedPropertyDelegate())
5270+
return false;
5271+
5272+
// Initialized 'let' properties have storage, but don't get an argument
5273+
// to the memberwise initializer since they already have an initial
5274+
// value that cannot be overridden.
5275+
if (isLet() && isParentInitialized())
5276+
return false;
5277+
5278+
return true;
5279+
}
5280+
52575281
void VarDecl::setSpecifier(Specifier specifier) {
52585282
Bits.VarDecl.Specifier = static_cast<unsigned>(specifier);
52595283
setSupportsMutationIfStillStored(

lib/Index/Index.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
364364
if (auto Original = Prop->getOriginalDelegatedProperty())
365365
Prop = Original;
366366

367-
if (!isMemberwiseInitialized(Prop))
367+
if (!Prop->isMemberwiseInitialized())
368368
continue;
369369

370370
if (CurLabel == LabelLocs.size())

lib/SILGen/SILGenConstructor.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -217,14 +217,8 @@ static void emitImplicitValueConstructor(SILGenFunction &SGF,
217217
auto fieldTy = selfTy.getFieldType(field, SGF.SGM.M);
218218
SILValue v;
219219

220-
// An initialized 'let' property has a single value specified by the
221-
// initializer - it doesn't come from an argument.
222-
if (!field->isStatic() && field->isLet() && field->getParentInitializer()) {
223-
// Cleanup after this initialization.
224-
FullExpr scope(SGF.Cleanups, field->getParentPatternBinding());
225-
v = SGF.emitRValue(field->getParentInitializer())
226-
.forwardAsSingleStorageValue(SGF, fieldTy, Loc);
227-
} else {
220+
// If it's memberwise initialized, do so now.
221+
if (field->isMemberwiseInitialized()) {
228222
FullExpr scope(SGF.Cleanups, field->getParentPatternBinding());
229223
assert(elti != eltEnd && "number of args does not match number of fields");
230224
(void)eltEnd;
@@ -237,6 +231,14 @@ static void emitImplicitValueConstructor(SILGenFunction &SGF,
237231
v = std::move(*elti).forwardAsSingleStorageValue(SGF, fieldTy, Loc);
238232
}
239233
++elti;
234+
} else {
235+
// Otherwise, use its initializer.
236+
assert(field->isParentInitialized());
237+
238+
// Cleanup after this initialization.
239+
FullExpr scope(SGF.Cleanups, field->getParentPatternBinding());
240+
v = SGF.emitRValue(field->getParentInitializer())
241+
.forwardAsSingleStorageValue(SGF, fieldTy, Loc);
240242
}
241243

242244
eltValues.push_back(v);

lib/Sema/CodeSynthesis.cpp

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2050,26 +2050,6 @@ static void maybeAddMemberwiseDefaultArg(ParamDecl *arg, VarDecl *var,
20502050
arg->setDefaultArgumentKind(DefaultArgumentKind::StoredProperty);
20512051
}
20522052

2053-
bool swift::isMemberwiseInitialized(VarDecl *var) {
2054-
// Implicit, computed, and static properties are not initialized.
2055-
// The exception is lazy properties, which due to batch mode we may or
2056-
// may not have yet finalized, so they may currently be "stored" or
2057-
// "computed" in the current AST state.
2058-
if (var->isImplicit() || var->isStatic())
2059-
return false;
2060-
2061-
if (!var->hasStorage() && !var->getAttrs().hasAttribute<LazyAttr>() &&
2062-
!var->getAttachedPropertyDelegate())
2063-
return false;
2064-
2065-
// Initialized 'let' properties have storage, but don't get an argument
2066-
// to the memberwise initializer since they already have an initial
2067-
// value that cannot be overridden.
2068-
if (var->isLet() && var->isParentInitialized())
2069-
return false;
2070-
2071-
return true;
2072-
}
20732053
/// Create an implicit struct or class constructor.
20742054
///
20752055
/// \param decl The struct or class for which a constructor will be created.
@@ -2097,7 +2077,7 @@ ConstructorDecl *swift::createImplicitConstructor(TypeChecker &tc,
20972077
if (!var)
20982078
continue;
20992079

2100-
if (!isMemberwiseInitialized(var))
2080+
if (!var->isMemberwiseInitialized())
21012081
continue;
21022082

21032083
accessLevel = std::min(accessLevel, var->getFormalAccess());

lib/Sema/CodeSynthesis.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,6 @@ enum class ImplicitConstructorKind {
6969
Memberwise
7070
};
7171

72-
bool isMemberwiseInitialized(VarDecl *var);
73-
7472
/// Create an implicit struct or class constructor.
7573
///
7674
/// \param decl The struct or class for which a constructor will be created.

lib/Sema/TypeCheckDecl.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5230,7 +5230,7 @@ void TypeChecker::addImplicitConstructors(NominalTypeDecl *decl) {
52305230
if (isa<StructDecl>(decl)) {
52315231
for (auto member : decl->getMembers()) {
52325232
if (auto var = dyn_cast<VarDecl>(member)) {
5233-
if (!isMemberwiseInitialized(var))
5233+
if (!var->isMemberwiseInitialized())
52345234
continue;
52355235

52365236
validateDecl(var);
@@ -5303,7 +5303,7 @@ void TypeChecker::addImplicitConstructors(NominalTypeDecl *decl) {
53035303
if (backingStorageVars.count(var) > 0)
53045304
continue;
53055305

5306-
if (isMemberwiseInitialized(var)) {
5306+
if (var->isMemberwiseInitialized()) {
53075307
// Initialized 'let' properties have storage, but don't get an argument
53085308
// to the memberwise initializer since they already have an initial
53095309
// value that cannot be overridden.

0 commit comments

Comments
 (0)