Skip to content

Commit 6f7d20b

Browse files
committed
Synthesize default values for memberwise init
Introduce stored property default argument kind Fix indent Assign nil to optionals with no initializers Don't emit generator for stored property default arg Fix problem with rebase Indentation Serialize stored property default arg text Fix some tests Add missing constructor in test Print stored property's initializer expression cleanups preserve switch complete_constructor formatting fix conflict
1 parent c69b7f4 commit 6f7d20b

17 files changed

+167
-28
lines changed

include/swift/AST/Decl.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4855,7 +4855,7 @@ class ParamDecl : public VarDecl {
48554855
SourceLoc SpecifierLoc;
48564856

48574857
struct StoredDefaultArgument {
4858-
Expr *DefaultArg = nullptr;
4858+
PointerUnion<Expr *, VarDecl *> DefaultArg;
48594859
Initializer *InitContext = nullptr;
48604860
StringRef StringRepresentation;
48614861
};
@@ -4912,12 +4912,20 @@ class ParamDecl : public VarDecl {
49124912

49134913
Expr *getDefaultValue() const {
49144914
if (auto stored = DefaultValueAndFlags.getPointer())
4915-
return stored->DefaultArg;
4915+
return stored->DefaultArg.dyn_cast<Expr *>();
4916+
return nullptr;
4917+
}
4918+
4919+
VarDecl *getStoredProperty() const {
4920+
if (auto stored = DefaultValueAndFlags.getPointer())
4921+
return stored->DefaultArg.dyn_cast<VarDecl *>();
49164922
return nullptr;
49174923
}
49184924

49194925
void setDefaultValue(Expr *E);
49204926

4927+
void setStoredProperty(VarDecl *var);
4928+
49214929
Initializer *getDefaultArgumentInitContext() const {
49224930
if (auto stored = DefaultValueAndFlags.getPointer())
49234931
return stored->InitContext;

include/swift/AST/DefaultArgumentKind.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ enum class DefaultArgumentKind : uint8_t {
5252
EmptyArray,
5353
/// An empty dictionary literal.
5454
EmptyDictionary,
55+
/// A reference to the stored property. This is a special default argument
56+
/// kind for the synthesized memberwise constructor to emit a call to the
57+
// property's initializer.
58+
StoredProperty,
5559
};
5660
enum { NumDefaultArgumentKindBits = 4 };
5761

include/swift/Serialization/ModuleFormat.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,7 @@ enum class DefaultArgumentKind : uint8_t {
379379
NilLiteral,
380380
EmptyArray,
381381
EmptyDictionary,
382+
StoredProperty,
382383
};
383384
using DefaultArgumentField = BCFixed<4>;
384385

lib/AST/ASTDumper.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@ static StringRef getDefaultArgumentKindString(DefaultArgumentKind value) {
305305
case DefaultArgumentKind::EmptyArray: return "[]";
306306
case DefaultArgumentKind::EmptyDictionary: return "[:]";
307307
case DefaultArgumentKind::Normal: return "normal";
308+
case DefaultArgumentKind::StoredProperty: return "stored property";
308309
}
309310

310311
llvm_unreachable("Unhandled DefaultArgumentKind in switch.");

lib/AST/Decl.cpp

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5173,6 +5173,17 @@ void ParamDecl::setDefaultValue(Expr *E) {
51735173
DefaultValueAndFlags.getPointer()->DefaultArg = E;
51745174
}
51755175

5176+
void ParamDecl::setStoredProperty(VarDecl *var) {
5177+
if (!DefaultValueAndFlags.getPointer()) {
5178+
if (!var) return;
5179+
5180+
DefaultValueAndFlags.setPointer(
5181+
getASTContext().Allocate<StoredDefaultArgument>());
5182+
}
5183+
5184+
DefaultValueAndFlags.getPointer()->DefaultArg = var;
5185+
}
5186+
51765187
void ParamDecl::setDefaultArgumentInitContext(Initializer *initContext) {
51775188
assert(DefaultValueAndFlags.getPointer());
51785189
DefaultValueAndFlags.getPointer()->InitContext = initContext;
@@ -5201,6 +5212,17 @@ ParamDecl::getDefaultValueStringRepresentation(
52015212
return extractInlinableText(getASTContext().SourceMgr, getDefaultValue(),
52025213
scratch);
52035214
}
5215+
case DefaultArgumentKind::StoredProperty: {
5216+
assert(DefaultValueAndFlags.getPointer() &&
5217+
"default value not provided yet");
5218+
auto existing = DefaultValueAndFlags.getPointer()->StringRepresentation;
5219+
if (!existing.empty())
5220+
return existing;
5221+
auto var = getStoredProperty();
5222+
return extractInlinableText(getASTContext().SourceMgr,
5223+
var->getParentInitializer(),
5224+
scratch);
5225+
}
52045226
case DefaultArgumentKind::Inherited:
52055227
// FIXME: This needs /some/ kind of textual representation, but this isn't
52065228
// a great one.
@@ -5219,7 +5241,8 @@ ParamDecl::getDefaultValueStringRepresentation(
52195241

52205242
void
52215243
ParamDecl::setDefaultValueStringRepresentation(StringRef stringRepresentation) {
5222-
assert(getDefaultArgumentKind() == DefaultArgumentKind::Normal);
5244+
assert(getDefaultArgumentKind() == DefaultArgumentKind::Normal ||
5245+
getDefaultArgumentKind() == DefaultArgumentKind::StoredProperty);
52235246
assert(!stringRepresentation.empty());
52245247

52255248
if (!DefaultValueAndFlags.getPointer()) {
@@ -5238,7 +5261,7 @@ void DefaultArgumentInitializer::changeFunction(
52385261
}
52395262

52405263
auto param = paramList->get(getIndex());
5241-
if (param->getDefaultValue())
5264+
if (param->isDefaultArgument())
52425265
param->setDefaultArgumentInitContext(this);
52435266
}
52445267

lib/IDE/CodeCompletion.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2034,6 +2034,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
20342034
for (auto param : *func->getParameters()) {
20352035
switch (param->getDefaultArgumentKind()) {
20362036
case DefaultArgumentKind::Normal:
2037+
case DefaultArgumentKind::StoredProperty:
20372038
case DefaultArgumentKind::Inherited: // FIXME: include this?
20382039
return true;
20392040
default:
@@ -2061,6 +2062,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
20612062
return false;
20622063

20632064
case DefaultArgumentKind::Normal:
2065+
case DefaultArgumentKind::StoredProperty:
20642066
case DefaultArgumentKind::Inherited:
20652067
case DefaultArgumentKind::NilLiteral:
20662068
case DefaultArgumentKind::EmptyArray:

lib/SILGen/SILGen.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,6 +1082,7 @@ void SILGenModule::emitDefaultArgGenerator(SILDeclRef constant, Expr *arg,
10821082
case DefaultArgumentKind::NilLiteral:
10831083
case DefaultArgumentKind::EmptyArray:
10841084
case DefaultArgumentKind::EmptyDictionary:
1085+
case DefaultArgumentKind::StoredProperty:
10851086
return;
10861087
}
10871088

lib/SILGen/SILGenApply.cpp

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "swift/AST/ASTContext.h"
2626
#include "swift/AST/DiagnosticsSIL.h"
2727
#include "swift/AST/ForeignErrorConvention.h"
28+
#include "swift/AST/GenericEnvironment.h"
2829
#include "swift/AST/GenericSignature.h"
2930
#include "swift/AST/ParameterList.h"
3031
#include "swift/AST/Module.h"
@@ -3340,12 +3341,58 @@ void DelayedArgument::emitDefaultArgument(SILGenFunction &SGF,
33403341
const DefaultArgumentStorage &info,
33413342
SmallVectorImpl<ManagedValue> &args,
33423343
size_t &argIndex) {
3343-
auto value = SGF.emitApplyOfDefaultArgGenerator(info.loc,
3344-
info.defaultArgsOwner,
3345-
info.destIndex,
3346-
info.resultType,
3347-
info.origResultType);
3348-
3344+
RValue value;
3345+
bool isStoredPropertyDefaultArg = false;
3346+
3347+
// Check if this is a synthesized memberwise constructor for stored property
3348+
// default values
3349+
if (auto ctor = dyn_cast<ConstructorDecl>(info.defaultArgsOwner.getDecl())) {
3350+
if (ctor->isMemberwiseInitializer() && ctor->isImplicit()) {
3351+
auto param = ctor->getParameters()->get(info.destIndex);
3352+
3353+
if (auto var = param->getStoredProperty()) {
3354+
// This is a stored property default arg. Do not emit a call to the
3355+
// default arg generator, but rather the variable initializer expression
3356+
isStoredPropertyDefaultArg = true;
3357+
3358+
auto pbd = var->getParentPatternBinding();
3359+
auto entry = pbd->getPatternEntryForVarDecl(var);
3360+
3361+
SubstitutionMap subs;
3362+
auto *genericEnv = ctor->getGenericEnvironmentOfContext();
3363+
auto typeGenericSig =
3364+
var->getDeclContext()->getGenericSignatureOfContext();
3365+
3366+
if (genericEnv && typeGenericSig) {
3367+
subs = SubstitutionMap::get(
3368+
typeGenericSig,
3369+
[&](SubstitutableType *type) {
3370+
if (auto gp = type->getAs<GenericTypeParamType>()) {
3371+
return genericEnv->mapTypeIntoContext(gp);
3372+
}
3373+
3374+
return Type(type);
3375+
},
3376+
MakeAbstractConformanceForGenericType());
3377+
}
3378+
3379+
value = SGF.emitApplyOfStoredPropertyInitializer(info.loc,
3380+
entry, subs,
3381+
info.resultType,
3382+
info.origResultType,
3383+
SGFContext());
3384+
}
3385+
}
3386+
}
3387+
3388+
if (!isStoredPropertyDefaultArg) {
3389+
value = SGF.emitApplyOfDefaultArgGenerator(info.loc,
3390+
info.defaultArgsOwner,
3391+
info.destIndex,
3392+
info.resultType,
3393+
info.origResultType);
3394+
}
3395+
33493396
SmallVector<ManagedValue, 4> loweredArgs;
33503397
SmallVector<DelayedArgument, 4> delayedArgs;
33513398
Optional<ForeignErrorConvention> errorConvention = None;

lib/Sema/CSApply.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4896,6 +4896,7 @@ getCallerDefaultArg(ConstraintSystem &cs, DeclContext *dc,
48964896
case DefaultArgumentKind::None:
48974897
llvm_unreachable("No default argument here?");
48984898

4899+
case DefaultArgumentKind::StoredProperty:
48994900
case DefaultArgumentKind::Normal:
49004901
return {nullptr, param->getDefaultArgumentKind()};
49014902

lib/Sema/CodeSynthesis.cpp

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1655,12 +1655,13 @@ ConstructorDecl *swift::createImplicitConstructor(TypeChecker &tc,
16551655
ImplicitConstructorKind ICK) {
16561656
assert(!decl->hasClangNode());
16571657

1658-
ASTContext &context = tc.Context;
1658+
ASTContext &C = tc.Context;
16591659
SourceLoc Loc = decl->getLoc();
16601660
auto accessLevel = AccessLevel::Internal;
16611661

16621662
// Determine the parameter type of the implicit constructor.
16631663
SmallVector<ParamDecl*, 8> params;
1664+
SmallVector<DefaultArgumentInitializer *, 8> defaultInits;
16641665
if (ICK == ImplicitConstructorKind::Memberwise) {
16651666
assert(isa<StructDecl>(decl) && "Only struct have memberwise constructor");
16661667

@@ -1693,28 +1694,64 @@ ConstructorDecl *swift::createImplicitConstructor(TypeChecker &tc,
16931694
// If var is a lazy property, its value is provided for the underlying
16941695
// storage. We thus take an optional of the properties type. We only
16951696
// need to do this because the implicit constructor is added before all
1696-
// the properties are type checked. Perhaps init() synth should be moved
1697+
// the properties are type checked. Perhaps init() synth should be moved
16971698
// later.
16981699
if (var->getAttrs().hasAttribute<LazyAttr>())
16991700
varInterfaceType = OptionalType::get(varInterfaceType);
17001701

17011702
// Create the parameter.
1702-
auto *arg = new (context)
1703+
auto *arg = new (C)
17031704
ParamDecl(VarDecl::Specifier::Default, SourceLoc(), Loc,
17041705
var->getName(), Loc, var->getName(), decl);
17051706
arg->setInterfaceType(varInterfaceType);
17061707
arg->setImplicit();
17071708

1709+
// If this is a var that has a default value, lets assign a default value
1710+
// to the parameter with the same expression.
1711+
if (!var->isLet()) {
1712+
if (auto init = var->getParentInitializer()) {
1713+
// Give this some bogus context right now, we'll fix it after making
1714+
// the constructor.
1715+
auto *initDC = new (C) DefaultArgumentInitializer(
1716+
arg->getDeclContext(), params.size());
1717+
1718+
defaultInits.push_back(initDC);
1719+
1720+
// Set the default value to the variable. When we emit this in silgen
1721+
// we're going to call the variable's initializer expression.
1722+
arg->setStoredProperty(var);
1723+
arg->setDefaultArgumentKind(DefaultArgumentKind::StoredProperty);
1724+
}
1725+
}
1726+
1727+
// Now that we have default values for this synthesized constructor,
1728+
// if the property is an optional and does not have an initializer,
1729+
// and is not a let property because it can never be reassigned,
1730+
// assign nil as the default value.
1731+
if (var->getType()->getOptionalObjectType() &&
1732+
var->getParentPatternBinding()->isDefaultInitializable() &&
1733+
!var->isLet() &&
1734+
!var->getParentInitializer()) {
1735+
auto *initDC = new (C) DefaultArgumentInitializer(
1736+
arg->getDeclContext(), params.size());
1737+
1738+
defaultInits.push_back(initDC);
1739+
1740+
auto nil = new (C) NilLiteralExpr(SourceLoc(), /*implicit*/ true);
1741+
arg->setDefaultValue(nil);
1742+
arg->setDefaultArgumentKind(DefaultArgumentKind::NilLiteral);
1743+
}
1744+
17081745
params.push_back(arg);
17091746
}
17101747
}
17111748

1712-
auto paramList = ParameterList::create(context, params);
1749+
auto paramList = ParameterList::create(C, params);
17131750

17141751
// Create the constructor.
1715-
DeclName name(context, DeclBaseName::createConstructor(), paramList);
1752+
DeclName name(C, DeclBaseName::createConstructor(), paramList);
17161753
auto *ctor =
1717-
new (context) ConstructorDecl(name, Loc,
1754+
new (C) ConstructorDecl(name, Loc,
17181755
OTK_None, /*FailabilityLoc=*/SourceLoc(),
17191756
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
17201757
paramList, /*GenericParams=*/nullptr, decl);
@@ -1723,6 +1760,11 @@ ConstructorDecl *swift::createImplicitConstructor(TypeChecker &tc,
17231760
ctor->setImplicit();
17241761
ctor->setAccess(accessLevel);
17251762

1763+
// Fix default argument init contexts now that we have a constructor
1764+
for (auto initDC : defaultInits) {
1765+
initDC->changeFunction(ctor, paramList);
1766+
}
1767+
17261768
if (ICK == ImplicitConstructorKind::Memberwise)
17271769
ctor->setIsMemberwiseInitializer();
17281770

@@ -1731,7 +1773,7 @@ ConstructorDecl *swift::createImplicitConstructor(TypeChecker &tc,
17311773
// 'override' attribute.
17321774
if (auto classDecl = dyn_cast<ClassDecl>(decl)) {
17331775
if (classDecl->getSuperclass())
1734-
ctor->getAttrs().add(new (tc.Context) OverrideAttr(/*IsImplicit=*/true));
1776+
ctor->getAttrs().add(new (C) OverrideAttr(/*IsImplicit=*/true));
17351777
}
17361778

17371779
return ctor;

0 commit comments

Comments
 (0)