Skip to content

Commit 16a4e6a

Browse files
authored
Merge pull request #23752 from Azoy/se-0242-5.1
[5.1] Synthesize default values for the memberwise initializer
2 parents d703f54 + f4fd12c commit 16a4e6a

26 files changed

+503
-65
lines changed

include/swift/AST/Decl.h

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

49194919
struct StoredDefaultArgument {
4920-
Expr *DefaultArg = nullptr;
4920+
PointerUnion<Expr *, VarDecl *> DefaultArg;
49214921
Initializer *InitContext = nullptr;
49224922
StringRef StringRepresentation;
49234923
};
@@ -4974,12 +4974,20 @@ class ParamDecl : public VarDecl {
49744974

49754975
Expr *getDefaultValue() const {
49764976
if (auto stored = DefaultValueAndFlags.getPointer())
4977-
return stored->DefaultArg;
4977+
return stored->DefaultArg.dyn_cast<Expr *>();
4978+
return nullptr;
4979+
}
4980+
4981+
VarDecl *getStoredProperty() const {
4982+
if (auto stored = DefaultValueAndFlags.getPointer())
4983+
return stored->DefaultArg.dyn_cast<VarDecl *>();
49784984
return nullptr;
49794985
}
49804986

49814987
void setDefaultValue(Expr *E);
49824988

4989+
void setStoredProperty(VarDecl *var);
4990+
49834991
Initializer *getDefaultArgumentInitContext() const {
49844992
if (auto stored = DefaultValueAndFlags.getPointer())
49854993
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: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5252
/// describe what change you made. The content of this comment isn't important;
5353
/// it just ensures a conflict if two people change the module format.
5454
/// Don't worry about adhering to the 80-column limit for this line.
55-
const uint16_t SWIFTMODULE_VERSION_MINOR = 478; // Last change: import control
55+
const uint16_t SWIFTMODULE_VERSION_MINOR = 479; // stored property default arg
5656

5757
using DeclIDField = BCFixed<31>;
5858

@@ -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
@@ -5262,6 +5262,17 @@ void ParamDecl::setDefaultValue(Expr *E) {
52625262
DefaultValueAndFlags.getPointer()->DefaultArg = E;
52635263
}
52645264

5265+
void ParamDecl::setStoredProperty(VarDecl *var) {
5266+
if (!DefaultValueAndFlags.getPointer()) {
5267+
if (!var) return;
5268+
5269+
DefaultValueAndFlags.setPointer(
5270+
getASTContext().Allocate<StoredDefaultArgument>());
5271+
}
5272+
5273+
DefaultValueAndFlags.getPointer()->DefaultArg = var;
5274+
}
5275+
52655276
void ParamDecl::setDefaultArgumentInitContext(Initializer *initContext) {
52665277
assert(DefaultValueAndFlags.getPointer());
52675278
DefaultValueAndFlags.getPointer()->InitContext = initContext;
@@ -5290,6 +5301,17 @@ ParamDecl::getDefaultValueStringRepresentation(
52905301
return extractInlinableText(getASTContext().SourceMgr, getDefaultValue(),
52915302
scratch);
52925303
}
5304+
case DefaultArgumentKind::StoredProperty: {
5305+
assert(DefaultValueAndFlags.getPointer() &&
5306+
"default value not provided yet");
5307+
auto existing = DefaultValueAndFlags.getPointer()->StringRepresentation;
5308+
if (!existing.empty())
5309+
return existing;
5310+
auto var = getStoredProperty();
5311+
return extractInlinableText(getASTContext().SourceMgr,
5312+
var->getParentInitializer(),
5313+
scratch);
5314+
}
52935315
case DefaultArgumentKind::Inherited:
52945316
// FIXME: This needs /some/ kind of textual representation, but this isn't
52955317
// a great one.
@@ -5308,7 +5330,8 @@ ParamDecl::getDefaultValueStringRepresentation(
53085330

53095331
void
53105332
ParamDecl::setDefaultValueStringRepresentation(StringRef stringRepresentation) {
5311-
assert(getDefaultArgumentKind() == DefaultArgumentKind::Normal);
5333+
assert(getDefaultArgumentKind() == DefaultArgumentKind::Normal ||
5334+
getDefaultArgumentKind() == DefaultArgumentKind::StoredProperty);
53125335
assert(!stringRepresentation.empty());
53135336

53145337
if (!DefaultValueAndFlags.getPointer()) {
@@ -5327,7 +5350,7 @@ void DefaultArgumentInitializer::changeFunction(
53275350
}
53285351

53295352
auto param = paramList->get(getIndex());
5330-
if (param->getDefaultValue())
5353+
if (param->getDefaultValue() || param->getStoredProperty())
53315354
param->setDefaultArgumentInitContext(this);
53325355
}
53335356

lib/IDE/CodeCompletion.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2069,6 +2069,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
20692069
for (auto param : *func->getParameters()) {
20702070
switch (param->getDefaultArgumentKind()) {
20712071
case DefaultArgumentKind::Normal:
2072+
case DefaultArgumentKind::StoredProperty:
20722073
case DefaultArgumentKind::Inherited: // FIXME: include this?
20732074
return true;
20742075
default:
@@ -2096,6 +2097,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
20962097
return false;
20972098

20982099
case DefaultArgumentKind::Normal:
2100+
case DefaultArgumentKind::StoredProperty:
20992101
case DefaultArgumentKind::Inherited:
21002102
case DefaultArgumentKind::NilLiteral:
21012103
case DefaultArgumentKind::EmptyArray:

lib/SILGen/SILGen.cpp

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1060,19 +1060,41 @@ void SILGenModule::emitDestructor(ClassDecl *cd, DestructorDecl *dd) {
10601060
}
10611061
}
10621062

1063-
void SILGenModule::emitDefaultArgGenerator(SILDeclRef constant, Expr *arg,
1064-
DefaultArgumentKind kind,
1065-
DeclContext *initDC) {
1066-
switch (kind) {
1063+
void SILGenModule::emitDefaultArgGenerator(SILDeclRef constant,
1064+
ParamDecl *param) {
1065+
auto initDC = param->getDefaultArgumentInitContext();
1066+
1067+
switch (param->getDefaultArgumentKind()) {
10671068
case DefaultArgumentKind::None:
10681069
llvm_unreachable("No default argument here?");
10691070

1070-
case DefaultArgumentKind::Normal:
1071-
break;
1071+
case DefaultArgumentKind::Normal: {
1072+
auto arg = param->getDefaultValue();
1073+
emitOrDelayFunction(*this, constant,
1074+
[this,constant,arg,initDC](SILFunction *f) {
1075+
preEmitFunction(constant, arg, f, arg);
1076+
PrettyStackTraceSILFunction X("silgen emitDefaultArgGenerator ", f);
1077+
SILGenFunction SGF(*this, *f, initDC);
1078+
SGF.emitGeneratorFunction(constant, arg);
1079+
postEmitFunction(constant, f);
1080+
});
1081+
return;
1082+
}
10721083

1073-
case DefaultArgumentKind::Inherited:
1084+
case DefaultArgumentKind::StoredProperty: {
1085+
auto arg = param->getStoredProperty();
1086+
emitOrDelayFunction(*this, constant,
1087+
[this,constant,arg,initDC](SILFunction *f) {
1088+
preEmitFunction(constant, arg, f, arg);
1089+
PrettyStackTraceSILFunction X("silgen emitDefaultArgGenerator ", f);
1090+
SILGenFunction SGF(*this, *f, initDC);
1091+
SGF.emitGeneratorFunction(constant, arg);
1092+
postEmitFunction(constant, f);
1093+
});
10741094
return;
1095+
}
10751096

1097+
case DefaultArgumentKind::Inherited:
10761098
case DefaultArgumentKind::Column:
10771099
case DefaultArgumentKind::File:
10781100
case DefaultArgumentKind::Line:
@@ -1083,15 +1105,6 @@ void SILGenModule::emitDefaultArgGenerator(SILDeclRef constant, Expr *arg,
10831105
case DefaultArgumentKind::EmptyDictionary:
10841106
return;
10851107
}
1086-
1087-
emitOrDelayFunction(*this, constant,
1088-
[this,constant,arg,initDC](SILFunction *f) {
1089-
preEmitFunction(constant, arg, f, arg);
1090-
PrettyStackTraceSILFunction X("silgen emitDefaultArgGenerator ", f);
1091-
SILGenFunction SGF(*this, *f, initDC);
1092-
SGF.emitGeneratorFunction(constant, arg);
1093-
postEmitFunction(constant, f);
1094-
});
10951108
}
10961109

10971110
void SILGenModule::
@@ -1160,10 +1173,9 @@ void SILGenModule::emitDefaultArgGenerators(SILDeclRef::Loc decl,
11601173
ParameterList *paramList) {
11611174
unsigned index = 0;
11621175
for (auto param : *paramList) {
1163-
if (auto defaultArg = param->getDefaultValue())
1176+
if (param->isDefaultArgument())
11641177
emitDefaultArgGenerator(SILDeclRef::getDefaultArgGenerator(decl, index),
1165-
defaultArg, param->getDefaultArgumentKind(),
1166-
param->getDefaultArgumentInitContext());
1178+
param);
11671179
++index;
11681180
}
11691181
}

lib/SILGen/SILGen.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -240,8 +240,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {
240240
void emitEnumConstructor(EnumElementDecl *decl);
241241

242242
/// Emits the default argument generator with the given expression.
243-
void emitDefaultArgGenerator(SILDeclRef constant, Expr *arg,
244-
DefaultArgumentKind kind, DeclContext *DC);
243+
void emitDefaultArgGenerator(SILDeclRef constant, ParamDecl *param);
245244

246245
/// Emits the stored property initializer for the given pattern.
247246
void emitStoredPropertyInitialization(PatternBindingDecl *pd, unsigned i);

lib/SILGen/SILGenApply.cpp

Lines changed: 2 additions & 1 deletion
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"
@@ -3345,7 +3346,7 @@ void DelayedArgument::emitDefaultArgument(SILGenFunction &SGF,
33453346
info.destIndex,
33463347
info.resultType,
33473348
info.origResultType);
3348-
3349+
33493350
SmallVector<ManagedValue, 4> loweredArgs;
33503351
SmallVector<DelayedArgument, 4> delayedArgs;
33513352
Optional<ForeignErrorConvention> errorConvention = None;

lib/SILGen/SILGenFunction.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,56 @@ void SILGenFunction::emitGeneratorFunction(SILDeclRef function, Expr *value) {
638638
emitEpilog(Loc);
639639
}
640640

641+
void SILGenFunction::emitGeneratorFunction(SILDeclRef function, VarDecl *var) {
642+
MagicFunctionName = SILGenModule::getMagicFunctionName(function);
643+
644+
RegularLocation loc(var);
645+
loc.markAutoGenerated();
646+
647+
auto decl = function.getAbstractFunctionDecl();
648+
auto *dc = decl->getInnermostDeclContext();
649+
auto interfaceType = var->getValueInterfaceType();
650+
emitProlog(/*paramList*/ nullptr, /*selfParam*/ nullptr, interfaceType, dc,
651+
false);
652+
prepareEpilog(var->getType(), false, CleanupLocation::get(loc));
653+
654+
auto pbd = var->getParentPatternBinding();
655+
auto entry = pbd->getPatternEntryForVarDecl(var);
656+
auto subs = getForwardingSubstitutionMap();
657+
auto resultType = decl->mapTypeIntoContext(interfaceType)->getCanonicalType();
658+
auto origResultType = AbstractionPattern(resultType);
659+
660+
SmallVector<SILValue, 4> directResults;
661+
662+
if (F.getConventions().hasIndirectSILResults()) {
663+
Scope scope(Cleanups, CleanupLocation(var));
664+
665+
SmallVector<CleanupHandle, 4> cleanups;
666+
auto init = prepareIndirectResultInit(resultType, directResults, cleanups);
667+
668+
emitApplyOfStoredPropertyInitializer(loc, entry, subs, resultType,
669+
origResultType,
670+
SGFContext(init.get()));
671+
672+
for (auto cleanup : cleanups) {
673+
Cleanups.forwardCleanup(cleanup);
674+
}
675+
} else {
676+
Scope scope(Cleanups, CleanupLocation(var));
677+
678+
// If we have no indirect results, just return the result.
679+
auto result = emitApplyOfStoredPropertyInitializer(loc, entry, subs,
680+
resultType,
681+
origResultType,
682+
SGFContext())
683+
.ensurePlusOne(*this, loc);
684+
std::move(result).forwardAll(*this, directResults);
685+
}
686+
687+
Cleanups.emitBranchAndCleanups(ReturnDest, loc, directResults);
688+
emitEpilog(loc);
689+
}
690+
641691
static SILLocation getLocation(ASTNode Node) {
642692
if (auto *E = Node.dyn_cast<Expr *>())
643693
return E;

lib/SILGen/SILGenFunction.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,11 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
554554
// be in a different scope.
555555
}
556556

557+
std::unique_ptr<Initialization>
558+
prepareIndirectResultInit(CanType formalResultType,
559+
SmallVectorImpl<SILValue> &directResultsBuffer,
560+
SmallVectorImpl<CleanupHandle> &cleanups);
561+
557562
//===--------------------------------------------------------------------===//
558563
// Entry points for codegen
559564
//===--------------------------------------------------------------------===//
@@ -624,6 +629,10 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
624629
/// Generate a nullary function that returns the given value.
625630
void emitGeneratorFunction(SILDeclRef function, Expr *value);
626631

632+
/// Generate a nullary function that returns the value of the given variable's
633+
/// expression initializer.
634+
void emitGeneratorFunction(SILDeclRef function, VarDecl *var);
635+
627636
/// Generate an ObjC-compatible destructor (-dealloc).
628637
void emitObjCDestructor(SILDeclRef dtor);
629638

lib/SILGen/SILGenStmt.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -425,22 +425,22 @@ prepareIndirectResultInit(SILGenFunction &SGF, CanType resultType,
425425
/// components of the result
426426
/// \param cleanups - will be filled (after initialization completes)
427427
/// with all the active cleanups managing the result values
428-
static std::unique_ptr<Initialization>
429-
prepareIndirectResultInit(SILGenFunction &SGF, CanType formalResultType,
430-
SmallVectorImpl<SILValue> &directResultsBuffer,
431-
SmallVectorImpl<CleanupHandle> &cleanups) {
432-
auto fnConv = SGF.F.getConventions();
428+
std::unique_ptr<Initialization>
429+
SILGenFunction::prepareIndirectResultInit(CanType formalResultType,
430+
SmallVectorImpl<SILValue> &directResultsBuffer,
431+
SmallVectorImpl<CleanupHandle> &cleanups) {
432+
auto fnConv = F.getConventions();
433433

434434
// Make space in the direct-results array for all the entries we need.
435435
directResultsBuffer.append(fnConv.getNumDirectSILResults(), SILValue());
436436

437437
ArrayRef<SILResultInfo> allResults = fnConv.funcTy->getResults();
438438
MutableArrayRef<SILValue> directResults = directResultsBuffer;
439-
ArrayRef<SILArgument*> indirectResultAddrs = SGF.F.getIndirectResults();
439+
ArrayRef<SILArgument*> indirectResultAddrs = F.getIndirectResults();
440440

441-
auto init = prepareIndirectResultInit(SGF, formalResultType, allResults,
442-
directResults, indirectResultAddrs,
443-
cleanups);
441+
auto init = ::prepareIndirectResultInit(*this, formalResultType, allResults,
442+
directResults, indirectResultAddrs,
443+
cleanups);
444444

445445
assert(allResults.empty());
446446
assert(directResults.empty());
@@ -460,7 +460,7 @@ void SILGenFunction::emitReturnExpr(SILLocation branchLoc,
460460
// Build an initialization which recursively destructures the tuple.
461461
SmallVector<CleanupHandle, 4> resultCleanups;
462462
InitializationPtr resultInit =
463-
prepareIndirectResultInit(*this, ret->getType()->getCanonicalType(),
463+
prepareIndirectResultInit(ret->getType()->getCanonicalType(),
464464
directResults, resultCleanups);
465465

466466
// Emit the result expression into the initialization.

lib/Sema/CSApply.cpp

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

4845+
case DefaultArgumentKind::StoredProperty:
48454846
case DefaultArgumentKind::Normal:
48464847
return {nullptr, param->getDefaultArgumentKind()};
48474848

0 commit comments

Comments
 (0)