Skip to content

Commit 4bb98ba

Browse files
committed
[SILGen] Add a new CaptureEmission kind specifically for emitting
captured local variables for the assign_by_wrapper setter. Since assign_by_wrapper will always be re-written to initialization if the captured local variable is uninitialized, it's unnecessary to mark the capture as an escape. This lets us support out-of-line initialization for local property wrappers.
1 parent 9e373a2 commit 4bb98ba

File tree

3 files changed

+13
-2
lines changed

3 files changed

+13
-2
lines changed

lib/SILGen/SILGenFunction.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,13 +187,18 @@ void SILGenFunction::emitCaptures(SILLocation loc,
187187
// Partial applications take ownership of the context parameters, so we'll
188188
// need to pass ownership rather than merely guaranteeing parameters.
189189
bool canGuarantee;
190+
bool captureCanEscape = true;
190191
switch (purpose) {
191192
case CaptureEmission::PartialApplication:
192193
canGuarantee = false;
193194
break;
194195
case CaptureEmission::ImmediateApplication:
195196
canGuarantee = true;
196197
break;
198+
case CaptureEmission::AssignByWrapper:
199+
canGuarantee = false;
200+
captureCanEscape = false;
201+
break;
197202
}
198203

199204
auto expansion = getTypeExpansionContext();
@@ -381,7 +386,8 @@ void SILGenFunction::emitCaptures(SILLocation loc,
381386
} else {
382387
capturedArgs.push_back(emitManagedRetain(loc, Entry.box));
383388
}
384-
escapesToMark.push_back(entryValue);
389+
if (captureCanEscape)
390+
escapesToMark.push_back(entryValue);
385391
} else {
386392
// Address only 'let' values are passed by box. This isn't great, in
387393
// that a variable captured by multiple closures will be boxed for each

lib/SILGen/SILGenFunction.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,11 @@ enum class CaptureEmission {
115115
/// Captures are being emitted for partial application to form a closure
116116
/// value.
117117
PartialApplication,
118+
/// Captures are being emitted for partial application of a local property
119+
/// wrapper setter for assign_by_wrapper. Captures are guaranteed to not
120+
/// escape, because assign_by_wrapper will not use the setter if the captured
121+
/// variable is not initialized.
122+
AssignByWrapper,
118123
};
119124

120125
/// Different ways in which an l-value can be emitted.

lib/SILGen/SILGenLValue.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1490,7 +1490,7 @@ namespace {
14901490
auto captureInfo = SGF.SGM.Types.getLoweredLocalCaptures(setter);
14911491
if (!captureInfo.getCaptures().empty()) {
14921492
SmallVector<ManagedValue, 4> captures;
1493-
SGF.emitCaptures(loc, setter, CaptureEmission::PartialApplication, captures);
1493+
SGF.emitCaptures(loc, setter, CaptureEmission::AssignByWrapper, captures);
14941494

14951495
for (auto capture : captures)
14961496
capturedArgs.push_back(capture.forward(SGF));

0 commit comments

Comments
 (0)