Skip to content

Commit 478a195

Browse files
authored
Merge pull request #15393 from aschwaighofer/silgen_fix_withoutActuallyEscaping_of_blocks
2 parents 3cbabfd + eac5f83 commit 478a195

File tree

2 files changed

+48
-0
lines changed

2 files changed

+48
-0
lines changed

lib/SILGen/SILGenExpr.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5480,6 +5480,28 @@ RValue RValueEmitter::visitMakeTemporarilyEscapableExpr(
54805480
visit(E->getNonescapingClosureValue()).getAsSingleValue(SGF, E);
54815481

54825482
auto escapingFnTy = SGF.getLoweredType(E->getOpaqueValue()->getType());
5483+
auto silFnTy = escapingFnTy.castTo<SILFunctionType>();
5484+
5485+
// Handle @convention(block). No withoutActuallyEscaping verification yet.
5486+
if (silFnTy->getExtInfo().getRepresentation() !=
5487+
SILFunctionTypeRepresentation::Thick) {
5488+
RValue rvalue;
5489+
auto escapingClosure =
5490+
SGF.emitManagedRValueWithCleanup(SGF.B.createConvertFunction(
5491+
E, functionValue.ensurePlusOne(SGF, E).forward(SGF), escapingFnTy));
5492+
// Bind the opaque value to the escaping function.
5493+
SILGenFunction::OpaqueValueState opaqueValue{
5494+
escapingClosure,
5495+
/*consumable*/ true,
5496+
/*hasBeenConsumed*/ false,
5497+
};
5498+
SILGenFunction::OpaqueValueRAII pushOpaqueValue(SGF, E->getOpaqueValue(),
5499+
opaqueValue);
5500+
5501+
// Emit the guarded expression.
5502+
rvalue = visit(E->getSubExpr(), C);
5503+
return rvalue;
5504+
}
54835505

54845506
// Convert it to an escaping function value.
54855507
auto escapingClosure =
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// RUN: %target-swift-frontend -module-name without_actually_escaping -emit-silgen -enable-sil-ownership %s | %FileCheck %s
2+
3+
// REQUIRES: objc_interop
4+
5+
import Foundation
6+
7+
typealias Callback = @convention(block) () -> Void
8+
9+
// CHECK-LABEL: sil {{.*}} @$S25without_actually_escaping9testBlock5blockyyyXB_tF
10+
// CHECK: bb0([[ARG:%.*]] : @guaranteed $@convention(block) @noescape () -> ()):
11+
// CHECK: [[C1:%.*]] = copy_block [[ARG]]
12+
// CHECK: [[B1:%.*]] = begin_borrow [[C1]]
13+
// CHECK: [[C2:%.*]] = copy_value [[B1]]
14+
// CHECK: [[CVT:%.*]] = convert_function [[C2]] : $@convention(block) @noescape () -> () to $@convention(block) () -> ()
15+
// CHECK: [[B2:%.*]] = begin_borrow [[CVT]]
16+
// CHECK: [[FN:%.*]] = function_ref @$S25without_actually_escaping9testBlock5blockyyyXB_tFyyyXBXEfU_
17+
// CHECK: apply [[FN]]([[B2]])
18+
// CHECK: end_borrow [[B2]] from [[CVT]]
19+
// CHECK: destroy_value [[CVT]]
20+
// CHECK: end_borrow [[B1]] from [[C1]]
21+
// CHECK: destroy_value [[C1]]
22+
// CHECK: return
23+
24+
func testBlock(block: Callback) {
25+
withoutActuallyEscaping(block) { $0() }
26+
}

0 commit comments

Comments
 (0)