Skip to content

Commit 441f809

Browse files
authored
Merge pull request #18357 from jckarter/keypath-writeback-nesting
SILGen: Fix ordering of key path application writebacks with other lvalue components.
2 parents a14889c + 76534e1 commit 441f809

File tree

2 files changed

+73
-0
lines changed

2 files changed

+73
-0
lines changed

lib/SILGen/SILGenLValue.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1982,6 +1982,38 @@ namespace {
19821982
// Mark the projected address's dependence on the owner.
19831983
projectedAddr = SGF.B.createMarkDependence(loc, projectedAddr,
19841984
projectedOwner.getValue());
1985+
1986+
// Push a cleanup to destroy the owner object. We don't want to leave
1987+
// it to release whenever because the key path implementation hangs
1988+
// the writeback operations specific to the traversal onto the destruction
1989+
// of the owner.
1990+
struct DestroyOwnerPseudoComponent : WritebackPseudoComponent {
1991+
ManagedValue owner;
1992+
1993+
DestroyOwnerPseudoComponent(const LValueTypeData &typeData,
1994+
ManagedValue owner)
1995+
: WritebackPseudoComponent(typeData), owner(owner)
1996+
{}
1997+
1998+
void writeback(SILGenFunction &SGF, SILLocation loc,
1999+
ManagedValue base,
2000+
MaterializedLValue materialized,
2001+
bool isFinal) override {
2002+
SGF.Cleanups.popAndEmitCleanup(owner.getCleanup(),
2003+
CleanupLocation::get(loc),
2004+
NotForUnwind);
2005+
}
2006+
2007+
void dump(raw_ostream &OS, unsigned indent) const override {
2008+
OS << "DestroyOwnerPseudoComponent";
2009+
}
2010+
};
2011+
2012+
std::unique_ptr<LogicalPathComponent> component(
2013+
new DestroyOwnerPseudoComponent(getTypeData(), projectedOwner));
2014+
2015+
pushWriteback(SGF, loc, std::move(component), base, MaterializedLValue());
2016+
19852017
return ManagedValue::forLValue(projectedAddr);
19862018
}
19872019

test/SILGen/keypath_application.swift

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,44 @@ func partial<A>(valueA: A,
122122
_ = valueB[keyPath: pkpB]
123123
}
124124

125+
extension Int {
126+
var b: Int { get { return 0 } set { } }
127+
var u: Int { get { return 0 } set { } }
128+
var tt: Int { get { return 0 } set { } }
129+
}
130+
131+
// CHECK-LABEL: sil hidden @{{.*}}writebackNesting
132+
func writebackNesting(x: inout Int,
133+
y: WritableKeyPath<Int, Int>,
134+
z: WritableKeyPath<Int, Int>,
135+
w: Int) -> Int {
136+
// -- get 'b'
137+
// CHECK: function_ref @$SSi19keypath_applicationE1bSivg
138+
// -- apply keypath y
139+
// CHECK: [[PROJECT_FN:%.*]] = function_ref @{{.*}}_projectKeyPathWritable
140+
// CHECK: [[PROJECT_RET:%.*]] = apply [[PROJECT_FN]]
141+
// CHECK: [[PROJECT_RET_BORROW:%.*]] = begin_borrow [[PROJECT_RET]]
142+
// CHECK: [[PROJECT_RET_BORROW_OWNER:%.*]] = tuple_extract [[PROJECT_RET_BORROW]] {{.*}}, 1
143+
// CHECK: [[OWNER_Y:%.*]] = copy_value [[PROJECT_RET_BORROW_OWNER]]
144+
// -- get 'u'
145+
// CHECK: function_ref @$SSi19keypath_applicationE1uSivg
146+
// -- apply keypath z
147+
// CHECK: [[PROJECT_FN:%.*]] = function_ref @{{.*}}_projectKeyPathWritable
148+
// CHECK: [[PROJECT_RET:%.*]] = apply [[PROJECT_FN]]
149+
// CHECK: [[PROJECT_RET_BORROW:%.*]] = begin_borrow [[PROJECT_RET]]
150+
// CHECK: [[PROJECT_RET_BORROW_OWNER:%.*]] = tuple_extract [[PROJECT_RET_BORROW]] {{.*}}, 1
151+
// CHECK: [[OWNER_Z:%.*]] = copy_value [[PROJECT_RET_BORROW_OWNER]]
152+
153+
// -- set 'tt'
154+
// CHECK: function_ref @$SSi19keypath_applicationE2ttSivs
155+
// -- destroy owner for keypath projection z
156+
// CHECK: destroy_value [[OWNER_Z]]
157+
// -- set 'u'
158+
// CHECK: function_ref @$SSi19keypath_applicationE1uSivs
159+
// -- destroy owner for keypath projection y
160+
// CHECK: destroy_value [[OWNER_Y]]
161+
// -- set 'b'
162+
// CHECK: function_ref @$SSi19keypath_applicationE1bSivs
163+
164+
x.b[keyPath: y].u[keyPath: z].tt = w
165+
}

0 commit comments

Comments
 (0)