Skip to content

Commit b5e5254

Browse files
committed
[SILGen] For property wrapper generators, don't use the generic signature of
the enclosing context if the property wrapper is declared in a closure that does not capture any generic parameters. In this case, the enclosing closure won't have a generic signature, nor any substitutions to forward when calling the property wrapper generator, which previously caused an assertion failure when emitting the call because there were no substitutions to use.
1 parent 6c108c2 commit b5e5254

File tree

3 files changed

+39
-1
lines changed

3 files changed

+39
-1
lines changed

lib/SIL/IR/TypeLowering.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2461,7 +2461,10 @@ static CanAnyFunctionType getPropertyWrapperBackingInitializerInterfaceType(
24612461
inputType = interfaceType->getCanonicalType();
24622462
}
24632463

2464-
auto sig = DC->getGenericSignatureOfContext();
2464+
GenericSignature sig;
2465+
auto *closure = dyn_cast<AbstractClosureExpr>(DC);
2466+
if (!closure || closure->getCaptureInfo().hasGenericParamCaptures())
2467+
sig = DC->getGenericSignatureOfContext();
24652468

24662469
AnyFunctionType::Param param(
24672470
inputType, Identifier(),

lib/SILGen/SILGenExpr.cpp

Lines changed: 6 additions & 0 deletions
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(

test/SILGen/property_wrapper_parameter.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,35 @@ 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+
211240
@propertyWrapper
212241
public struct PublicWrapper<T> {
213242
public var wrappedValue: T

0 commit comments

Comments
 (0)