[SILGen] InitAccessors: Start emitting init property initialization expressions

Similar to regular stored properties emit initialization expressions
for properties with init accessors at constructor's prolog.
This commit is contained in:
Pavel Yaskevich
2023-07-12 17:51:48 -07:00
parent 1f87ee8ca3
commit aa52e42b3e
4 changed files with 268 additions and 3 deletions

View File

@@ -1459,6 +1459,49 @@ emitAndStoreInitialValueInto(SILGenFunction &SGF,
std::move(result).forwardInto(SGF, loc, init);
}
void SILGenFunction::emitMemberInitializationViaInitAccessor(
DeclContext *dc, VarDecl *selfDecl, PatternBindingDecl *member,
SubstitutionMap subs) {
auto *var = member->getSingleVar();
assert(var->hasInitAccessor());
auto init = member->getExecutableInit(0);
if (!init)
return;
auto *varPattern = member->getPattern(0);
// Cleanup after this initialization.
FullExpr scope(Cleanups, varPattern);
auto resultType =
getInitializationTypeInContext(member->getDeclContext(), dc, varPattern);
RValue initResult = emitApplyOfStoredPropertyInitializer(
init, var, subs, resultType.second, resultType.first, SGFContext());
SILLocation loc(init);
loc.markAutoGenerated();
auto selfValue = emitSelfForMemberInit(*this, varPattern, selfDecl);
ManagedValue selfRef = selfValue;
if (selfValue.isLValue()) {
auto accessToSelf =
B.createBeginAccess(loc, selfValue.getValue(), SILAccessKind::Modify,
SILAccessEnforcement::Unknown,
/*noNestedConflict=*/false,
/*fromBuiltin=*/false);
selfRef = ManagedValue::forUnmanaged(accessToSelf);
}
emitAssignOrInit(loc, selfRef, var,
std::move(initResult).getAsSingleValue(*this, loc), subs);
if (selfValue.isLValue())
B.createEndAccess(loc, selfRef.getValue(), /*aborted=*/false);
}
void SILGenFunction::emitMemberInitializers(DeclContext *dc,
VarDecl *selfDecl,
NominalTypeDecl *nominal) {
@@ -1469,11 +1512,12 @@ void SILGenFunction::emitMemberInitializers(DeclContext *dc,
if (auto pbd = dyn_cast<PatternBindingDecl>(member)) {
if (pbd->isStatic()) continue;
// Skip properties with init accessors, they could only be used
// explicitly and in memberwise initializers.
// Emit default initialization for an init accessor property.
if (auto *var = pbd->getSingleVar()) {
if (var->hasInitAccessor())
if (var->hasInitAccessor()) {
emitMemberInitializationViaInitAccessor(dc, selfDecl, pbd, subs);
continue;
}
}
for (auto i : range(pbd->getNumPatternEntries())) {