Skip to content

Commit e3403b5

Browse files
authored
Merge pull request #30063 from slavapestov/property-wrapper-backing-init-constrained-extension-5.2
SILGen: Fix substitution map when calling property wrapper backing initializer [5.2]
2 parents bccd0b6 + 46de701 commit e3403b5

File tree

4 files changed

+74
-43
lines changed

4 files changed

+74
-43
lines changed

lib/SILGen/SILGenApply.cpp

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5062,25 +5062,11 @@ RValue SILGenFunction::emitApplyMethod(SILLocation loc, ConcreteDeclRef declRef,
50625062
RValue SILGenFunction::emitApplyOfPropertyWrapperBackingInitializer(
50635063
SILLocation loc,
50645064
VarDecl *var,
5065+
SubstitutionMap subs,
50655066
RValue &&originalValue,
50665067
SGFContext C) {
50675068
SILDeclRef constant(var, SILDeclRef::Kind::PropertyWrapperBackingInitializer);
50685069

5069-
SubstitutionMap subs;
5070-
auto varDC = var->getInnermostDeclContext();
5071-
if (auto genericSig = varDC->getGenericSignatureOfContext()) {
5072-
subs = SubstitutionMap::get(
5073-
genericSig,
5074-
[&](SubstitutableType *type) {
5075-
if (auto gp = type->getAs<GenericTypeParamType>()) {
5076-
return F.mapTypeIntoContext(gp);
5077-
}
5078-
5079-
return Type(type);
5080-
},
5081-
LookUpConformanceInModule(varDC->getParentModule()));
5082-
}
5083-
50845070
FormalEvaluationScope writebackScope(*this);
50855071

50865072
auto callee = Callee::forDirect(*this, constant, subs, loc);

lib/SILGen/SILGenConstructor.cpp

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ static RValue maybeEmitPropertyWrapperInitFromValue(
107107
SILGenFunction &SGF,
108108
SILLocation loc,
109109
VarDecl *field,
110+
SubstitutionMap subs,
110111
RValue &&arg) {
111112
auto originalProperty = field->getOriginalWrappedProperty();
112113
if (!originalProperty ||
@@ -118,7 +119,33 @@ static RValue maybeEmitPropertyWrapperInitFromValue(
118119
return std::move(arg);
119120

120121
return SGF.emitApplyOfPropertyWrapperBackingInitializer(loc, originalProperty,
121-
std::move(arg));
122+
subs, std::move(arg));
123+
}
124+
125+
static SubstitutionMap getSubstitutionsForPropertyInitializer(
126+
DeclContext *dc,
127+
NominalTypeDecl *nominal) {
128+
// We want a substitution list written in terms of the generic
129+
// signature of the type, with replacement archetypes from the
130+
// constructor's context (which might be in an extension of
131+
// the type, which adds additional generic requirements).
132+
if (auto *genericEnv = dc->getGenericEnvironmentOfContext()) {
133+
// Generate a set of substitutions for the initialization function,
134+
// whose generic signature is that of the type context, and whose
135+
// replacement types are the archetypes of the initializer itself.
136+
return SubstitutionMap::get(
137+
nominal->getGenericSignatureOfContext(),
138+
[&](SubstitutableType *type) {
139+
if (auto gp = type->getAs<GenericTypeParamType>()) {
140+
return genericEnv->mapTypeIntoContext(gp);
141+
}
142+
143+
return Type(type);
144+
},
145+
LookUpConformanceInModule(dc->getParentModule()));
146+
}
147+
148+
return SubstitutionMap();
122149
}
123150

124151
static void emitImplicitValueConstructor(SILGenFunction &SGF,
@@ -161,6 +188,8 @@ static void emitImplicitValueConstructor(SILGenFunction &SGF,
161188
auto *decl = selfTy.getStructOrBoundGenericStruct();
162189
assert(decl && "not a struct?!");
163190

191+
auto subs = getSubstitutionsForPropertyInitializer(decl, decl);
192+
164193
// If we have an indirect return slot, initialize it in-place.
165194
if (resultSlot) {
166195
auto elti = elements.begin(), eltEnd = elements.end();
@@ -178,7 +207,8 @@ static void emitImplicitValueConstructor(SILGenFunction &SGF,
178207
"number of args does not match number of fields");
179208
(void)eltEnd;
180209
FullExpr scope(SGF.Cleanups, field->getParentPatternBinding());
181-
maybeEmitPropertyWrapperInitFromValue(SGF, Loc, field, std::move(*elti))
210+
maybeEmitPropertyWrapperInitFromValue(SGF, Loc, field, subs,
211+
std::move(*elti))
182212
.forwardInto(SGF, Loc, init.get());
183213
++elti;
184214
} else {
@@ -213,7 +243,7 @@ static void emitImplicitValueConstructor(SILGenFunction &SGF,
213243
assert(elti != eltEnd && "number of args does not match number of fields");
214244
(void)eltEnd;
215245
v = maybeEmitPropertyWrapperInitFromValue(
216-
SGF, Loc, field, std::move(*elti))
246+
SGF, Loc, field, subs, std::move(*elti))
217247
.forwardAsSingleStorageValue(SGF, fieldTy, Loc);
218248
++elti;
219249
} else {
@@ -912,6 +942,8 @@ static Type getInitializationTypeInContext(
912942
void SILGenFunction::emitMemberInitializers(DeclContext *dc,
913943
VarDecl *selfDecl,
914944
NominalTypeDecl *nominal) {
945+
auto subs = getSubstitutionsForPropertyInitializer(dc, nominal);
946+
915947
for (auto member : nominal->getMembers()) {
916948
// Find instance pattern binding declarations that have initializers.
917949
if (auto pbd = dyn_cast<PatternBindingDecl>(member)) {
@@ -925,30 +957,6 @@ void SILGenFunction::emitMemberInitializers(DeclContext *dc,
925957
// Cleanup after this initialization.
926958
FullExpr scope(Cleanups, varPattern);
927959

928-
// We want a substitution list written in terms of the generic
929-
// signature of the type, with replacement archetypes from the
930-
// constructor's context (which might be in an extension of
931-
// the type, which adds additional generic requirements).
932-
SubstitutionMap subs;
933-
auto *genericEnv = dc->getGenericEnvironmentOfContext();
934-
auto typeGenericSig = nominal->getGenericSignatureOfContext();
935-
936-
if (genericEnv && typeGenericSig) {
937-
// Generate a set of substitutions for the initialization function,
938-
// whose generic signature is that of the type context, and whose
939-
// replacement types are the archetypes of the initializer itself.
940-
subs = SubstitutionMap::get(
941-
typeGenericSig,
942-
[&](SubstitutableType *type) {
943-
if (auto gp = type->getAs<GenericTypeParamType>()) {
944-
return genericEnv->mapTypeIntoContext(gp);
945-
}
946-
947-
return Type(type);
948-
},
949-
LookUpConformanceInModule(dc->getParentModule()));
950-
}
951-
952960
// Get the type of the initialization result, in terms
953961
// of the constructor context's archetypes.
954962
CanType resultType = getInitializationTypeInContext(
@@ -970,7 +978,7 @@ void SILGenFunction::emitMemberInitializers(DeclContext *dc,
970978
if (originalVar &&
971979
originalVar->isPropertyMemberwiseInitializedWithWrappedType()) {
972980
result = maybeEmitPropertyWrapperInitFromValue(
973-
*this, init, singleVar, std::move(result));
981+
*this, init, singleVar, subs, std::move(result));
974982
}
975983
}
976984

lib/SILGen/SILGenFunction.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1499,6 +1499,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
14991499
RValue emitApplyOfPropertyWrapperBackingInitializer(
15001500
SILLocation loc,
15011501
VarDecl *var,
1502+
SubstitutionMap subs,
15021503
RValue &&originalValue,
15031504
SGFContext C = SGFContext());
15041505

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// RUN: %target-swift-emit-silgen -primary-file %s | %FileCheck %s
2+
3+
@propertyWrapper
4+
public struct Horse<Value> {
5+
private var stored: Value
6+
7+
public var wrappedValue: Value {
8+
get { stored }
9+
set { stored = newValue }
10+
}
11+
12+
public init(wrappedValue initialValue: Value) {
13+
stored = initialValue
14+
}
15+
16+
public var projectedValue: Self {
17+
mutating get { self }
18+
set { self = newValue }
19+
}
20+
}
21+
22+
public protocol Fuzzball {}
23+
24+
public struct Cat : Fuzzball {}
25+
26+
public struct Dog<Pet : Fuzzball> {
27+
@Horse public var foo: Int = 17
28+
}
29+
30+
extension Dog where Pet == Cat {
31+
public init() {}
32+
}
33+
34+
// CHECK-LABEL: sil [ossa] @$s39property_wrappers_constrained_extension3DogVA2A3CatVRszrlEACyAEGycfC : $@convention(method) (@thin Dog<Cat>.Type) -> Dog<Cat> {
35+
// CHECK: [[FN:%.*]] = function_ref @$s39property_wrappers_constrained_extension3DogV4_foo33_{{.*}}LLAA5HorseVySiGvpfi : $@convention(thin) <τ_0_0 where τ_0_0 : Fuzzball> () -> Int
36+
// CHECK: apply [[FN]]<Cat>() : $@convention(thin) <τ_0_0 where τ_0_0 : Fuzzball> () -> Int

0 commit comments

Comments
 (0)