Skip to content

Commit 33c7ddd

Browse files
committed
[move-only] Do not box captures if the capturing closure is no escape.
Thanks to JoeG for seeing this quickly and preventing me from having to track this down!
1 parent 1bd89b6 commit 33c7ddd

File tree

2 files changed

+11
-9
lines changed

2 files changed

+11
-9
lines changed

lib/SIL/IR/TypeLowering.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,10 +116,11 @@ CaptureKind TypeConverter::getDeclCaptureKind(CapturedValue capture,
116116
var->getType(), TypeExpansionContext::noOpaqueTypeArchetypesSubstitution(
117117
expansion.getResilienceExpansion()));
118118

119-
// If this is a noncopyable 'let' constant that is not a shared paramdecl,
120-
// then we know it is boxed and want to pass it in its boxed form so we can
121-
// obey Swift's capture reference semantics.
122-
if (!var->supportsMutation() && lowering.getLoweredType().isPureMoveOnly()) {
119+
// If this is a noncopyable 'let' constant that is not a shared paramdecl or
120+
// used by a noescape capture, then we know it is boxed and want to pass it in
121+
// its boxed form so we can obey Swift's capture reference semantics.
122+
if (!var->supportsMutation() && lowering.getLoweredType().isPureMoveOnly() &&
123+
!capture.isNoEscape()) {
123124
auto *param = dyn_cast<ParamDecl>(var);
124125
if (!param || param->getValueOwnership() != ValueOwnership::Shared) {
125126
return CaptureKind::ImmutableBox;

test/SILOptimizer/moveonly_nonescaping_closures.swift

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,21 +46,22 @@ func a(x: __shared M) {
4646
borrow(x)
4747
}
4848

49-
func b(x: __owned M) {
49+
func b(x: __owned M) { // expected-error {{'x' used after consume}}
5050
clodger({ borrow(x) }, consume: x)
51-
// expected-error @-1 {{'x' was consumed but it is illegal to consume a noncopyable immutable capture of an escaping closure. One can only read from it}}
51+
// expected-note @-1:25 {{non-consuming use here}}
52+
// expected-note @-2:37 {{consuming use here}}
5253
}
5354

5455
func c(x: __owned M) {
5556
clodger({ borrow(x) })
5657
borrow(x)
5758
consume(x)
58-
// expected-error @-1 {{'x' was consumed but it is illegal to consume a noncopyable immutable capture of an escaping closure. One can only read from it}}
5959
}
6060

61-
func d(x: __owned M) {
61+
func d(x: __owned M) { // expected-error {{'x' consumed in closure. This is illegal since if the closure is invoked more than once the binding will be uninitialized on later invocations}}
6262
clodger({ consume(x) })
63-
// expected-error @-1 {{'x' was consumed but it is illegal to consume a noncopyable immutable capture of an escaping closure. One can only read from it}}
63+
// expected-error @-1 {{copy of noncopyable typed value. This is a compiler bug. Please file a bug with a small example of the bug}}
64+
// expected-note @-2 {{consuming use here}}
6465
}
6566

6667
func e(x: inout M) {

0 commit comments

Comments
 (0)