Skip to content

Commit 40d1adc

Browse files
authored
Merge pull request #3949 from slavapestov/fix-store-generic-member-from-extension
2 parents c1c1fe6 + 75bd889 commit 40d1adc

22 files changed

+284
-64
lines changed

include/swift/AST/Decl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1852,6 +1852,9 @@ class PatternBindingEntry {
18521852
InitCheckedAndRemoved.setInt(
18531853
InitCheckedAndRemoved.getInt() | Flags::Checked);
18541854
}
1855+
1856+
// Return the first variable initialized by this pattern.
1857+
VarDecl *getAnchoringVarDecl() const;
18551858
};
18561859

18571860
/// \brief This decl contains a pattern and optional initializer for a set

include/swift/SIL/SILDeclRef.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,10 @@ struct SILDeclRef {
117117
/// References the generator for a default argument of a function.
118118
DefaultArgGenerator,
119119

120+
/// References the initializer expression for a stored property
121+
/// of a nominal type.
122+
StoredPropertyInitializer,
123+
120124
/// References the ivar initializer for the ClassDecl in loc.
121125
///
122126
/// Only classes that are allocated using Objective-C's allocation
@@ -261,6 +265,11 @@ struct SILDeclRef {
261265
bool isDefaultArgGenerator() const {
262266
return kind == Kind::DefaultArgGenerator;
263267
}
268+
/// True if the SILDeclRef references the initializer for a stored property
269+
/// of a nominal type.
270+
bool isStoredPropertyInitializer() const {
271+
return kind == Kind::StoredPropertyInitializer;
272+
}
264273

265274
/// \brief True if the function should be treated as transparent.
266275
bool isTransparent() const;

lib/AST/Decl.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -949,6 +949,13 @@ void PatternBindingEntry::setInit(Expr *E) {
949949
}
950950
}
951951

952+
VarDecl *PatternBindingEntry::getAnchoringVarDecl() const {
953+
SmallVector<VarDecl *, 8> variables;
954+
getPattern()->collectVariables(variables);
955+
assert(variables.size() > 0);
956+
return variables[0];
957+
}
958+
952959
SourceRange PatternBindingDecl::getSourceRange() const {
953960
SourceLoc startLoc = getStartLoc();
954961

lib/IRGen/GenObjC.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,7 @@ namespace {
512512
Selector(SILDeclRef ref) {
513513
switch (ref.kind) {
514514
case SILDeclRef::Kind::DefaultArgGenerator:
515+
case SILDeclRef::Kind::StoredPropertyInitializer:
515516
case SILDeclRef::Kind::EnumElement:
516517
case SILDeclRef::Kind::GlobalAccessor:
517518
case SILDeclRef::Kind::GlobalGetter:

lib/Parse/ParseSIL.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,6 +1053,12 @@ bool SILParser::parseSILDeclRef(SILDeclRef &Result,
10531053
} else if (!ParseState && Id.str() == "ivarinitializer") {
10541054
Kind = SILDeclRef::Kind::IVarInitializer;
10551055
ParseState = 1;
1056+
} else if (!ParseState && Id.str() == "defaultarg") {
1057+
Kind = SILDeclRef::Kind::IVarInitializer;
1058+
ParseState = 1;
1059+
} else if (!ParseState && Id.str() == "propertyinit") {
1060+
Kind = SILDeclRef::Kind::StoredPropertyInitializer;
1061+
ParseState = 1;
10561062
} else if (Id.str() == "foreign") {
10571063
IsObjC = true;
10581064
break;

lib/SIL/SILDeclRef.cpp

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,11 @@ SILDeclRef::SILDeclRef(ValueDecl *vd, SILDeclRef::Kind kind,
152152
"can only create ivar initializer/destroyer SILDeclRef for class");
153153
naturalUncurryLevel = 1;
154154
} else if (auto *var = dyn_cast<VarDecl>(vd)) {
155-
assert((kind == Kind::GlobalAccessor || kind == Kind::GlobalGetter) &&
156-
"can only create GlobalAccessor or GlobalGetter SILDeclRef for var");
155+
assert((kind == Kind::GlobalAccessor ||
156+
kind == Kind::GlobalGetter ||
157+
kind == Kind::StoredPropertyInitializer) &&
158+
"can only create GlobalAccessor, GlobalGetter or "
159+
"StoredPropertyInitializer SILDeclRef for var");
157160

158161
naturalUncurryLevel = 0;
159162
assert(!var->getDeclContext()->isLocalContext() &&
@@ -316,9 +319,14 @@ SILLinkage SILDeclRef::getLinkage(ForDefinition_t forDefinition) const {
316319

317320
// Enum constructors are essentially the same as thunks, they are
318321
// emitted by need and have shared linkage.
319-
if (kind == Kind::EnumElement)
322+
if (isEnumElement())
320323
return SILLinkage::Shared;
321324

325+
// Stored property initializers have hidden linkage, since they are
326+
// not meant to be used from outside of their module.
327+
if (isStoredPropertyInitializer())
328+
return SILLinkage::Hidden;
329+
322330
// Declarations imported from Clang modules have shared linkage.
323331
const SILLinkage ClangLinkage = SILLinkage::Shared;
324332

@@ -353,6 +361,9 @@ bool SILDeclRef::isTransparent() const {
353361
if (isEnumElement())
354362
return true;
355363

364+
if (isStoredPropertyInitializer())
365+
return true;
366+
356367
if (hasAutoClosureExpr())
357368
return true;
358369

@@ -576,12 +587,18 @@ static std::string mangleConstant(SILDeclRef c, StringRef prefix) {
576587
mangler.mangleGlobalGetterEntity(c.getDecl());
577588
return mangler.finalize();
578589

579-
// entity ::= context 'e' index // default arg generator
590+
// entity ::= context 'e' index // default arg generator
580591
case SILDeclRef::Kind::DefaultArgGenerator:
581592
mangler.append(introducer);
582593
mangler.mangleDefaultArgumentEntity(cast<AbstractFunctionDecl>(c.getDecl()),
583594
c.defaultArgIndex);
584595
return mangler.finalize();
596+
597+
// entity ::= 'I' declaration 'i' // stored property initializer
598+
case SILDeclRef::Kind::StoredPropertyInitializer:
599+
mangler.append(introducer);
600+
mangler.mangleInitializerEntity(cast<VarDecl>(c.getDecl()));
601+
return mangler.finalize();
585602
}
586603

587604
llvm_unreachable("bad entity kind!");

lib/SIL/SILFunctionType.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,6 +1003,7 @@ static CanSILFunctionType getNativeSILFunctionType(SILModule &M,
10031003
case SILDeclRef::Kind::GlobalAccessor:
10041004
case SILDeclRef::Kind::GlobalGetter:
10051005
case SILDeclRef::Kind::DefaultArgGenerator:
1006+
case SILDeclRef::Kind::StoredPropertyInitializer:
10061007
case SILDeclRef::Kind::IVarInitializer:
10071008
case SILDeclRef::Kind::IVarDestroyer:
10081009
case SILDeclRef::Kind::EnumElement:
@@ -1472,6 +1473,7 @@ static SelectorFamily getSelectorFamily(SILDeclRef c) {
14721473
case SILDeclRef::Kind::GlobalGetter:
14731474
case SILDeclRef::Kind::IVarDestroyer:
14741475
case SILDeclRef::Kind::DefaultArgGenerator:
1476+
case SILDeclRef::Kind::StoredPropertyInitializer:
14751477
return SelectorFamily::None;
14761478
}
14771479
}
@@ -1653,6 +1655,7 @@ TypeConverter::getDeclRefRepresentation(SILDeclRef c) {
16531655
case SILDeclRef::Kind::GlobalAccessor:
16541656
case SILDeclRef::Kind::GlobalGetter:
16551657
case SILDeclRef::Kind::DefaultArgGenerator:
1658+
case SILDeclRef::Kind::StoredPropertyInitializer:
16561659
return SILFunctionTypeRepresentation::Thin;
16571660

16581661
case SILDeclRef::Kind::Func:
@@ -2319,6 +2322,7 @@ static AbstractFunctionDecl *getBridgedFunction(SILDeclRef declRef) {
23192322
case SILDeclRef::Kind::GlobalAccessor:
23202323
case SILDeclRef::Kind::GlobalGetter:
23212324
case SILDeclRef::Kind::DefaultArgGenerator:
2325+
case SILDeclRef::Kind::StoredPropertyInitializer:
23222326
case SILDeclRef::Kind::IVarInitializer:
23232327
case SILDeclRef::Kind::IVarDestroyer:
23242328
return nullptr;

lib/SIL/SILPrinter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,9 @@ void SILDeclRef::print(raw_ostream &OS) const {
322322
case SILDeclRef::Kind::DefaultArgGenerator:
323323
OS << "!defaultarg" << "." << defaultArgIndex;
324324
break;
325+
case SILDeclRef::Kind::StoredPropertyInitializer:
326+
OS << "!propertyinit";
327+
break;
325328
}
326329
if (uncurryLevel != 0)
327330
OS << (isDot ? '.' : '!') << uncurryLevel;

lib/SIL/TypeLowering.cpp

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1671,6 +1671,27 @@ static CanAnyFunctionType getDefaultArgGeneratorInterfaceType(
16711671
return CanFunctionType::get(TupleType::getEmpty(context), resultTy);
16721672
}
16731673

1674+
/// Get the type of a stored property initializer, () -> T.
1675+
static CanAnyFunctionType getStoredPropertyInitializerInterfaceType(
1676+
TypeConverter &TC,
1677+
VarDecl *VD,
1678+
ASTContext &context) {
1679+
auto *DC = VD->getDeclContext();
1680+
CanType resultTy =
1681+
ArchetypeBuilder::mapTypeOutOfContext(
1682+
DC, VD->getParentInitializer()->getType())
1683+
->getCanonicalType();
1684+
GenericSignature *sig = DC->getGenericSignatureOfContext();
1685+
1686+
if (sig)
1687+
return CanGenericFunctionType::get(sig->getCanonicalSignature(),
1688+
TupleType::getEmpty(context),
1689+
resultTy,
1690+
GenericFunctionType::ExtInfo());
1691+
1692+
return CanFunctionType::get(TupleType::getEmpty(context), resultTy);
1693+
}
1694+
16741695
/// Get the type of a destructor function.
16751696
static CanAnyFunctionType getDestructorInterfaceType(DestructorDecl *dd,
16761697
bool isDeallocating,
@@ -1868,8 +1889,12 @@ CanAnyFunctionType TypeConverter::makeConstantInterfaceType(SILDeclRef c) {
18681889
}
18691890
case SILDeclRef::Kind::DefaultArgGenerator:
18701891
return getDefaultArgGeneratorInterfaceType(*this,
1871-
cast<AbstractFunctionDecl>(vd),
1872-
c.defaultArgIndex, Context);
1892+
cast<AbstractFunctionDecl>(vd),
1893+
c.defaultArgIndex, Context);
1894+
case SILDeclRef::Kind::StoredPropertyInitializer:
1895+
return getStoredPropertyInitializerInterfaceType(*this,
1896+
cast<VarDecl>(vd),
1897+
Context);
18731898
case SILDeclRef::Kind::IVarInitializer:
18741899
return getIVarInitDestroyerInterfaceType(cast<ClassDecl>(vd),
18751900
c.isForeign, Context, false);
@@ -1926,6 +1951,12 @@ TypeConverter::getConstantContextGenericParams(SILDeclRef c) {
19261951
case SILDeclRef::Kind::DefaultArgGenerator:
19271952
// Use the context generic parameters of the original declaration.
19281953
return getConstantContextGenericParams(SILDeclRef(c.getDecl()));
1954+
case SILDeclRef::Kind::StoredPropertyInitializer:
1955+
// Use the context generic parameters of the containing type.
1956+
return {
1957+
c.getDecl()->getDeclContext()->getGenericParamsOfContext(),
1958+
nullptr,
1959+
};
19291960
}
19301961
}
19311962

lib/SILGen/SILGen.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -877,6 +877,21 @@ void SILGenModule::emitDefaultArgGenerator(SILDeclRef constant, Expr *arg) {
877877
});
878878
}
879879

880+
void SILGenModule::
881+
emitStoredPropertyInitialization(PatternBindingDecl *pbd, unsigned i) {
882+
const PatternBindingEntry &pbdEntry = pbd->getPatternList()[i];
883+
auto *var = pbdEntry.getAnchoringVarDecl();
884+
auto *init = pbdEntry.getInit();
885+
886+
SILDeclRef constant(var, SILDeclRef::Kind::StoredPropertyInitializer);
887+
emitOrDelayFunction(*this, constant, [this,constant,init](SILFunction *f) {
888+
preEmitFunction(constant, init, f, init);
889+
PrettyStackTraceSILFunction X("silgen emitStoredPropertyInitialization", f);
890+
SILGenFunction(*this, *f).emitGeneratorFunction(constant, init);
891+
postEmitFunction(constant, f);
892+
});
893+
}
894+
880895
SILFunction *SILGenModule::emitLazyGlobalInitializer(StringRef funcName,
881896
PatternBindingDecl *binding,
882897
unsigned pbdEntry) {

lib/SILGen/SILGen.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,10 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {
252252

253253
/// Emits the default argument generator with the given expression.
254254
void emitDefaultArgGenerator(SILDeclRef constant, Expr *arg);
255-
255+
256+
/// Emits the stored property initializer for the given pattern.
257+
void emitStoredPropertyInitialization(PatternBindingDecl *pd, unsigned i);
258+
256259
/// Emits the default argument generator for the given function.
257260
void emitDefaultArgGenerators(SILDeclRef::Loc decl,
258261
ArrayRef<ParameterList*> paramLists);

lib/SILGen/SILGenConstructor.cpp

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -253,9 +253,9 @@ void SILGenFunction::emitValueConstructor(ConstructorDecl *ctor) {
253253

254254
// If this is not a delegating constructor, emit member initializers.
255255
if (!isDelegating) {
256-
auto nominal = ctor->getDeclContext()
257-
->getAsNominalTypeOrNominalTypeExtensionContext();
258-
emitMemberInitializers(selfDecl, nominal);
256+
auto *dc = ctor->getDeclContext();
257+
auto *nominal = dc->getAsNominalTypeOrNominalTypeExtensionContext();
258+
emitMemberInitializers(dc, selfDecl, nominal);
259259
}
260260

261261
emitProfilerIncrement(ctor->getBody());
@@ -526,7 +526,8 @@ void SILGenFunction::emitClassConstructorInitializer(ConstructorDecl *ctor) {
526526
// TODO: If we could require Objective-C classes to have an attribute to get
527527
// this behavior, we could avoid runtime overhead here.
528528
VarDecl *selfDecl = ctor->getImplicitSelfDecl();
529-
auto selfClassDecl = ctor->getDeclContext()->getAsClassOrClassExtensionContext();
529+
auto *dc = ctor->getDeclContext();
530+
auto selfClassDecl = dc->getAsClassOrClassExtensionContext();
530531
bool NeedsBoxForSelf = isDelegating ||
531532
(selfClassDecl->hasSuperclass() && !ctor->hasStubImplementation());
532533
bool usesObjCAllocator = Lowering::usesObjCAllocator(selfClassDecl);
@@ -642,7 +643,7 @@ void SILGenFunction::emitClassConstructorInitializer(ConstructorDecl *ctor) {
642643
// Note that 'self' has been fully initialized at this point.
643644
} else {
644645
// Emit the member initializers.
645-
emitMemberInitializers(selfDecl, selfClassDecl);
646+
emitMemberInitializers(dc, selfDecl, selfClassDecl);
646647
}
647648

648649
emitProfilerIncrement(ctor->getBody());
@@ -841,7 +842,19 @@ static SILValue getBehaviorSetterFn(SILGenFunction &gen, VarDecl *behaviorVar) {
841842
return gen.B.createFunctionRef(behaviorVar, setFn);
842843
}
843844

844-
void SILGenFunction::emitMemberInitializers(VarDecl *selfDecl,
845+
static Type getInitializationTypeInContext(
846+
DeclContext *fromDC, DeclContext *toDC,
847+
Expr *init) {
848+
auto interfaceType =
849+
ArchetypeBuilder::mapTypeOutOfContext(fromDC, init->getType());
850+
auto resultType =
851+
ArchetypeBuilder::mapTypeIntoContext(toDC, interfaceType);
852+
853+
return resultType;
854+
}
855+
856+
void SILGenFunction::emitMemberInitializers(DeclContext *dc,
857+
VarDecl *selfDecl,
845858
NominalTypeDecl *nominal) {
846859
for (auto member : nominal->getMembers()) {
847860
// Find instance pattern binding declarations that have initializers.
@@ -854,7 +867,27 @@ void SILGenFunction::emitMemberInitializers(VarDecl *selfDecl,
854867

855868
// Cleanup after this initialization.
856869
FullExpr scope(Cleanups, entry.getPattern());
857-
emitMemberInit(*this, selfDecl, entry.getPattern(), emitRValue(init));
870+
871+
// Get the substitutions for the constructor context.
872+
ArrayRef<Substitution> subs;
873+
auto *genericParams = dc->getGenericParamsOfContext();
874+
if (genericParams)
875+
subs = genericParams->getForwardingSubstitutions(getASTContext());
876+
877+
// Get the type of the initialization result, in terms
878+
// of the constructor context's archetypes.
879+
CanType resultType = getInitializationTypeInContext(
880+
pbd->getDeclContext(), dc, init)->getCanonicalType();
881+
AbstractionPattern origResultType(resultType);
882+
883+
// FIXME: Can emitMemberInit() share code with
884+
// InitializationForPattern in SILGenDecl.cpp?
885+
RValue result = emitApplyOfStoredPropertyInitializer(
886+
init, entry, subs,
887+
resultType, origResultType,
888+
SGFContext());
889+
890+
emitMemberInit(*this, selfDecl, entry.getPattern(), std::move(result));
858891
}
859892
}
860893

@@ -913,7 +946,7 @@ void SILGenFunction::emitIVarInitializer(SILDeclRef ivarInitializer) {
913946
prepareEpilog(TupleType::getEmpty(getASTContext()), false, cleanupLoc);
914947

915948
// Emit the initializers.
916-
emitMemberInitializers(cd->getDestructor()->getImplicitSelfDecl(), cd);
949+
emitMemberInitializers(cd, selfDecl, cd);
917950

918951
// Return 'self'.
919952
B.createReturn(loc, selfArg);

lib/SILGen/SILGenExpr.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1724,6 +1724,29 @@ SILGenFunction::emitApplyOfDefaultArgGenerator(SILLocation loc,
17241724
ApplyOptions::None, None, None, C);
17251725
}
17261726

1727+
RValue SILGenFunction::emitApplyOfStoredPropertyInitializer(
1728+
SILLocation loc,
1729+
const PatternBindingEntry &entry,
1730+
ArrayRef<Substitution> subs,
1731+
CanType resultType,
1732+
AbstractionPattern origResultType,
1733+
SGFContext C) {
1734+
1735+
VarDecl *var = entry.getAnchoringVarDecl();
1736+
SILDeclRef constant(var, SILDeclRef::Kind::StoredPropertyInitializer);
1737+
auto fnRef = ManagedValue::forUnmanaged(emitGlobalFunctionRef(loc, constant));
1738+
auto fnType = fnRef.getType().castTo<SILFunctionType>();
1739+
1740+
auto substFnType = fnType->substGenericArgs(SGM.M, SGM.M.getSwiftModule(),
1741+
subs);
1742+
1743+
return emitApply(loc, fnRef, subs, {},
1744+
substFnType,
1745+
origResultType,
1746+
resultType,
1747+
ApplyOptions::None, None, None, C);
1748+
}
1749+
17271750
static void emitTupleShuffleExprInto(RValueEmitter &emitter,
17281751
TupleShuffleExpr *E,
17291752
Initialization *outerTupleInit) {

lib/SILGen/SILGenFunction.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ DeclName SILGenModule::getMagicFunctionName(SILDeclRef ref) {
120120
return getMagicFunctionName(cast<VarDecl>(ref.getDecl())->getDeclContext());
121121
case SILDeclRef::Kind::DefaultArgGenerator:
122122
return getMagicFunctionName(cast<AbstractFunctionDecl>(ref.getDecl()));
123+
case SILDeclRef::Kind::StoredPropertyInitializer:
124+
return getMagicFunctionName(cast<VarDecl>(ref.getDecl())->getDeclContext());
123125
case SILDeclRef::Kind::IVarInitializer:
124126
return getMagicFunctionName(cast<ClassDecl>(ref.getDecl()));
125127
case SILDeclRef::Kind::IVarDestroyer:

0 commit comments

Comments
 (0)