Skip to content

Commit df7656e

Browse files
authored
Merge pull request #38323 from hborla/wrapper-generator-substitutions
[SILGen] Correct generic signature/substitutions of property wrapper generators within a closure.
2 parents a34d757 + e6fe68f commit df7656e

File tree

4 files changed

+101
-43
lines changed

4 files changed

+101
-43
lines changed

Diff for: lib/SIL/IR/TypeLowering.cpp

+32-43
Original file line numberDiff line numberDiff line change
@@ -2383,6 +2383,7 @@ static CanType removeNoEscape(CanType resultType) {
23832383

23842384
/// Get the type of a default argument generator, () -> T.
23852385
static CanAnyFunctionType getDefaultArgGeneratorInterfaceType(
2386+
TypeConverter &TC,
23862387
SILDeclRef c) {
23872388
auto *vd = c.getDecl();
23882389
auto resultTy = getParameterAt(vd,
@@ -2400,14 +2401,7 @@ static CanAnyFunctionType getDefaultArgGeneratorInterfaceType(
24002401
canResultTy = removeNoEscape(canResultTy);
24012402

24022403
// Get the generic signature from the surrounding context.
2403-
auto sig = vd->getInnermostDeclContext()->getGenericSignatureOfContext();
2404-
if (auto *afd = dyn_cast<AbstractFunctionDecl>(vd)) {
2405-
auto *param = getParameterAt(afd, c.defaultArgIndex);
2406-
if (param->hasDefaultExpr()) {
2407-
auto captureInfo = param->getDefaultArgumentCaptureInfo();
2408-
sig = getEffectiveGenericSignature(afd, captureInfo);
2409-
}
2410-
}
2404+
auto sig = TC.getConstantGenericSignature(c);
24112405

24122406
// FIXME: Verify ExtInfo state is correct, not working by accident.
24132407
CanAnyFunctionType::ExtInfo info;
@@ -2447,38 +2441,20 @@ static CanAnyFunctionType getStoredPropertyInitializerInterfaceType(
24472441
/// (property-type) -> backing-type.
24482442
static CanAnyFunctionType getPropertyWrapperBackingInitializerInterfaceType(
24492443
TypeConverter &TC,
2450-
VarDecl *VD) {
2451-
CanType resultType =
2452-
VD->getPropertyWrapperBackingPropertyType()->getCanonicalType();
2453-
2454-
auto *DC = VD->getInnermostDeclContext();
2455-
CanType inputType =
2456-
VD->getPropertyWrapperInitValueInterfaceType()->getCanonicalType();
2457-
2458-
auto sig = DC->getGenericSignatureOfContext();
2459-
2460-
AnyFunctionType::Param param(
2461-
inputType, Identifier(),
2462-
ParameterTypeFlags().withValueOwnership(ValueOwnership::Owned));
2463-
// FIXME: Verify ExtInfo state is correct, not working by accident.
2464-
CanAnyFunctionType::ExtInfo info;
2465-
return CanAnyFunctionType::get(getCanonicalSignatureOrNull(sig), {param},
2466-
resultType, info);
2467-
}
2468-
2469-
static CanAnyFunctionType getPropertyWrapperInitFromProjectedValueInterfaceType(TypeConverter &TC,
2470-
VarDecl *VD) {
2444+
SILDeclRef c) {
2445+
auto *VD = cast<VarDecl>(c.getDecl());
24712446
CanType resultType =
24722447
VD->getPropertyWrapperBackingPropertyType()->getCanonicalType();
24732448

2474-
Type interfaceType = VD->getPropertyWrapperProjectionVar()->getInterfaceType();
2475-
if (interfaceType->hasArchetype())
2476-
interfaceType = interfaceType->mapTypeOutOfContext();
2477-
2478-
CanType inputType = interfaceType->getCanonicalType();
2449+
CanType inputType;
2450+
if (c.kind == SILDeclRef::Kind::PropertyWrapperBackingInitializer) {
2451+
inputType = VD->getPropertyWrapperInitValueInterfaceType()->getCanonicalType();
2452+
} else {
2453+
Type interfaceType = VD->getPropertyWrapperProjectionVar()->getInterfaceType();
2454+
inputType = interfaceType->getCanonicalType();
2455+
}
24792456

2480-
auto *DC = VD->getInnermostDeclContext();
2481-
auto sig = DC->getGenericSignatureOfContext();
2457+
GenericSignature sig = TC.getConstantGenericSignature(c);
24822458

24832459
AnyFunctionType::Param param(
24842460
inputType, Identifier(),
@@ -2678,15 +2654,12 @@ CanAnyFunctionType TypeConverter::makeConstantInterfaceType(SILDeclRef c) {
26782654
return getGlobalAccessorType(var->getInterfaceType()->getCanonicalType());
26792655
}
26802656
case SILDeclRef::Kind::DefaultArgGenerator:
2681-
return getDefaultArgGeneratorInterfaceType(c);
2657+
return getDefaultArgGeneratorInterfaceType(*this, c);
26822658
case SILDeclRef::Kind::StoredPropertyInitializer:
26832659
return getStoredPropertyInitializerInterfaceType(cast<VarDecl>(vd));
26842660
case SILDeclRef::Kind::PropertyWrapperBackingInitializer:
2685-
return getPropertyWrapperBackingInitializerInterfaceType(*this,
2686-
cast<VarDecl>(vd));
26872661
case SILDeclRef::Kind::PropertyWrapperInitFromProjectedValue:
2688-
return getPropertyWrapperInitFromProjectedValueInterfaceType(*this,
2689-
cast<VarDecl>(vd));
2662+
return getPropertyWrapperBackingInitializerInterfaceType(*this, c);
26902663
case SILDeclRef::Kind::IVarInitializer:
26912664
return getIVarInitDestroyerInterfaceType(cast<ClassDecl>(vd),
26922665
c.isForeign, false);
@@ -2724,11 +2697,27 @@ TypeConverter::getConstantGenericSignature(SILDeclRef c) {
27242697
return getEffectiveGenericSignature(
27252698
vd->getInnermostDeclContext(), captureInfo);
27262699
}
2700+
case SILDeclRef::Kind::PropertyWrapperBackingInitializer:
2701+
case SILDeclRef::Kind::PropertyWrapperInitFromProjectedValue: {
2702+
// FIXME: It might be better to compute lowered local captures of
2703+
// the property wrapper generator directly and collapse this into the
2704+
// above case. For now, take the generic signature of the enclosing
2705+
// context.
2706+
auto *dc = vd->getDeclContext();
2707+
if (dc->isLocalContext()) {
2708+
SILDeclRef enclosingDecl;
2709+
if (auto *closure = dyn_cast<AbstractClosureExpr>(dc)) {
2710+
enclosingDecl = SILDeclRef(closure);
2711+
} else {
2712+
enclosingDecl = SILDeclRef(cast<AbstractFunctionDecl>(dc));
2713+
}
2714+
return getConstantGenericSignature(enclosingDecl);
2715+
}
2716+
return dc->getGenericSignatureOfContext();
2717+
}
27272718
case SILDeclRef::Kind::EnumElement:
27282719
case SILDeclRef::Kind::GlobalAccessor:
27292720
case SILDeclRef::Kind::StoredPropertyInitializer:
2730-
case SILDeclRef::Kind::PropertyWrapperBackingInitializer:
2731-
case SILDeclRef::Kind::PropertyWrapperInitFromProjectedValue:
27322721
return vd->getDeclContext()->getGenericSignatureOfContext();
27332722
case SILDeclRef::Kind::EntryPoint:
27342723
llvm_unreachable("Doesn't have generic signature");

Diff for: lib/SILGen/SILGenExpr.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -5251,9 +5251,15 @@ RValue RValueEmitter::visitAppliedPropertyWrapperExpr(
52515251
break;
52525252
}
52535253

5254+
// The property wrapper generator function needs the same substitutions as the
5255+
// enclosing function or closure. If the parameter is declared in a function, take
5256+
// the substitutions from the concrete callee. Otherwise, forward the archetypes
5257+
// from the closure.
52545258
SubstitutionMap subs;
52555259
if (param->getDeclContext()->getAsDecl()) {
52565260
subs = E->getCallee().getSubstitutions();
5261+
} else {
5262+
subs = SGF.getForwardingSubstitutionMap();
52575263
}
52585264

52595265
return SGF.emitApplyOfPropertyWrapperBackingInitializer(

Diff for: test/SILGen/default_arguments_local.swift

+13
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,16 @@ class ArtClass<T> {
7070

7171
inner()
7272
}
73+
74+
// CHECK-LABEL: sil hidden [ossa] @$s23default_arguments_local5outeryyxlF : $@convention(thin) <T> (@in_guaranteed T) -> ()
75+
func outer<T>(_: T) {
76+
// CHECK-LABEL: sil private [ossa] @$s23default_arguments_local5outeryyxlF5innerL_yylF : $@convention(thin) <T> () -> ()
77+
func inner() { print(T.self) }
78+
79+
// default argument 0 of hasDefault #1 <A>(x:) in outer<A>(_:)
80+
// CHECK-LABEL: sil private [ossa] @$s23default_arguments_local5outeryyxlF10hasDefaultL_1xySi_tlFfA_ : $@convention(thin) <T> () -> Int
81+
82+
// CHECK-LABEL: sil private [ossa] @$s23default_arguments_local5outeryyxlF10hasDefaultL_1xySi_tlF : $@convention(thin) <T> (Int) -> ()
83+
func hasDefault(x: Int = { inner(); return 3 }()) {}
84+
hasDefault()
85+
}

Diff for: test/SILGen/property_wrapper_parameter.swift

+50
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,56 @@ func testImplicitPropertyWrapper(projection: ProjectionWrapper<Int>) {
208208
// CHECK: sil private [ossa] @$s26property_wrapper_parameter27testImplicitPropertyWrapper10projectionyAA010ProjectionG0VySiG_tFSi_AFtAFcfu0_Si_AFtAFcfU0_5valueL_Sivg : $@convention(thin) (ProjectionWrapper<Int>) -> Int
209209
}
210210

211+
protocol P {}
212+
213+
// CHECK-LABEL: sil hidden [ossa] @$s26property_wrapper_parameter14genericContextyyxAA1PRzlF : $@convention(thin) <T where T : P> (@in_guaranteed T) -> ()
214+
func genericContext<T>(_: T) where T: P {
215+
let _: (ProjectionWrapper<Int>) -> Void = { $value in }
216+
217+
// implicit closure #1 in genericContext<A>(_:)
218+
// CHECK-LABEL: sil private [ossa] @$s26property_wrapper_parameter14genericContextyyxAA1PRzlFyAA17ProjectionWrapperVySiGcfu_ : $@convention(thin) (ProjectionWrapper<Int>) -> ()
219+
220+
// This property wrapper generator function should _not_ have a generic signature,
221+
// because the closure doesn't have one.
222+
223+
// property wrapper init from projected value of $value #1 in closure #1 in implicit closure #1 in genericContext<A>(_:)
224+
// CHECK-LABEL: sil private [ossa] @$s26property_wrapper_parameter14genericContextyyxAA1PRzlFyAA17ProjectionWrapperVySiGcfu_yAFcfU_6$valueL_AFvpfW : $@convention(thin) (ProjectionWrapper<Int>) -> ProjectionWrapper<Int>
225+
226+
let _: (ProjectionWrapper<Int>) -> T = { $value in
227+
fatalError()
228+
}
229+
230+
// implicit closure #2 in genericContext<A>(_:)
231+
// CHECK-LABEL: sil private [ossa] @$s26property_wrapper_parameter14genericContextyyxAA1PRzlFxAA17ProjectionWrapperVySiGcfu0_ : $@convention(thin) <T where T : P> (ProjectionWrapper<Int>) -> @out T
232+
233+
// This property wrapper generator function _should_ have a generic signature, because
234+
// the closure does have one.
235+
236+
// property wrapper init from projected value of $value #1 in closure #2 in implicit closure #2 in genericContext<A>(_:)
237+
// CHECK-LABEL: sil private [ossa] @$s26property_wrapper_parameter14genericContextyyxAA1PRzlFxAA17ProjectionWrapperVySiGcfu0_xAFcfU0_6$valueL_AFvpfW : $@convention(thin) <T where T : P> (ProjectionWrapper<Int>) -> ProjectionWrapper<Int>
238+
239+
// CHECK-LABEL: sil private [ossa] @$s26property_wrapper_parameter14genericContextyyxAA1PRzlF5innerL_1ayAA7WrapperVySiG_tAaCRzlF : $@convention(thin) (Wrapper<Int>) -> ()
240+
func inner(@Wrapper a: Int) {}
241+
242+
// property wrapper backing initializer of a #1 in inner #1 <A>(a:) in genericContext<A>(_:)
243+
// CHECK-LABEL: sil private [ossa] @$s26property_wrapper_parameter14genericContextyyxAA1PRzlF5innerL_1ayAA7WrapperVySiG_tAaCRzlFAEL_SivpfP : $@convention(thin) (Int) -> Wrapper<Int>
244+
245+
inner(a: 1)
246+
247+
// CHECK-LABEL: sil private [ossa] @$s26property_wrapper_parameter14genericContextyyxAA1PRzlF5innerL0_yyAaCRzlF : $@convention(thin) <T where T : P> () -> ()
248+
func inner() { _ = T.self }
249+
250+
// CHECK-LABEL: sil private [ossa] @$s26property_wrapper_parameter14genericContextyyxAA1PRzlF5innerL1_1byAA7WrapperVySiG_tAaCRzlF : $@convention(thin) <T where T : P> (Wrapper<Int>) -> ()
251+
func inner(@Wrapper b: Int) {
252+
inner()
253+
}
254+
255+
// property wrapper backing initializer of b #1 in inner #3 <A>(b:) in genericContext<A>(_:)
256+
// CHECK-LABEL: sil private [ossa] @$s26property_wrapper_parameter14genericContextyyxAA1PRzlF5innerL1_1byAA7WrapperVySiG_tAaCRzlFAEL_SivpfP : $@convention(thin) <T where T : P> (Int) -> Wrapper<Int>
257+
258+
inner(b: 1)
259+
}
260+
211261
@propertyWrapper
212262
public struct PublicWrapper<T> {
213263
public var wrappedValue: T

0 commit comments

Comments
 (0)