Skip to content

Commit c2cd64d

Browse files
committed
SILGen: Account for abstraction differences when assigning in key path setters
1 parent 70a1f9f commit c2cd64d

File tree

2 files changed

+37
-0
lines changed

2 files changed

+37
-0
lines changed

lib/SILGen/SILGenExpr.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3239,6 +3239,15 @@ static SILFunction *getOrCreateKeyPathSetter(SILGenModule &SGM,
32393239
std::move(subscriptIndices),
32403240
/*index for diags*/ nullptr);
32413241

3242+
// If the assigned value will need to be reabstracted, add a reabstraction
3243+
// component.
3244+
const auto loweredSubstType = subSGF.getLoweredType(lv.getSubstFormalType());
3245+
if (lv.getTypeOfRValue() != loweredSubstType.getObjectType()) {
3246+
// Logical components always re-abstract back to the substituted type.
3247+
assert(lv.isLastComponentPhysical());
3248+
lv.addOrigToSubstComponent(loweredSubstType);
3249+
}
3250+
32423251
subSGF.emitAssignToLValue(loc,
32433252
RValue(subSGF, loc, propertyType, valueSubst),
32443253
std::move(lv));
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// RUN: %target-swift-emit-silgen %s | %FileCheck %s
2+
3+
// https://github.com/apple/swift/issues/63682
4+
// Test that we adjust to abstraction differences when assigning in generated
5+
// key path accessors.
6+
7+
struct Foo<A> {
8+
var closure: () -> A?
9+
}
10+
11+
// CHECK-LABEL: sil hidden [ossa] @{{.+}}physicalFunctionValue
12+
func physicalFunctionValue() {
13+
// CHECK: keypath $WritableKeyPath<Foo<Bool>, () -> Optional<Bool>>, (root $Foo<Bool>; settable_property $() -> Optional<Bool>, id ##Foo.closure, getter @$[[GETTER:[_a-zA-Z0-9]+]] {{.+}}, setter @$[[SETTER:[_a-zA-Z0-9]+]]
14+
let _ = \Foo<Bool>.closure
15+
} // CHECK: // end sil function '{{.+}}physicalFunctionValue
16+
17+
// CHECK: sil shared [thunk] [ossa] @$[[GETTER]] : $@convention(thin) (@in_guaranteed Foo<Bool>) -> @out @callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for <Optional<Bool>> {
18+
// CHECK: bb0([[OUT_FN:%[0-9]+]] {{.+}}):
19+
// CHECK: [[SRC_REABSTR:%[0-9]+]] = convert_function %{{[0-9]+}} : $@callee_guaranteed () -> @out Optional<Bool> to $@callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for <Optional<Bool>>
20+
// CHECK-NEXT: store [[SRC_REABSTR]] to [init] [[OUT_FN]] : $*@callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for <Optional<Bool>>
21+
// CHECK: } // end sil function '$[[GETTER]]'
22+
23+
// CHECK: sil shared [thunk] [ossa] @$[[SETTER]] : $@convention(thin) (@in_guaranteed @callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for <Optional<Bool>>, @inout Foo<Bool>) -> () {
24+
// CHECK: bb0({{.+}}, [[FOO:%[0-9]+]] : $*Foo<Bool>):
25+
// CHECK: [[SRC_REABSTR:%[0-9]+]] = convert_function %{{[0-9]+}} : $@callee_guaranteed () -> @out Optional<Bool> to $@callee_guaranteed @substituted <τ_0_0> () -> @out Optional<τ_0_0> for <Bool>
26+
// CHECK-NEXT: [[DEST:%[0-9]+]] = struct_element_addr [[FOO]] : $*Foo<Bool>, #Foo.closure
27+
// CHECK-NEXT: assign [[SRC_REABSTR]] to [[DEST]] : $*@callee_guaranteed @substituted <τ_0_0> () -> @out Optional<τ_0_0> for <Bool>
28+
// CHECK: } // end sil function '$[[SETTER]]'

0 commit comments

Comments
 (0)