Skip to content

Commit 8c96a8d

Browse files
committed
[rbi] When finding closure uses in an immediately invoked closure, distinguish in between captures and parameters.
Otherwise, when one diagnoses code like the following: ``` Task { { use($0) }(x) } ``` One gets that $0 was captured instead of x. Unfortunately, since function parameters do not have locations associated with them, we do not mark x itself... instead, we mark the closure... which is unfortunate.
1 parent 39e63b4 commit 8c96a8d

File tree

2 files changed

+15
-7
lines changed

2 files changed

+15
-7
lines changed

lib/SILOptimizer/Mandatory/SendNonSendable.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -294,14 +294,16 @@ findClosureUse(Operand *initialOperand) {
294294
// immediately invoked. In such a case, we can emit a better diagnostic in
295295
// the called closure.
296296
if (auto fas = FullApplySite::isa(op->getUser())) {
297-
if (auto *f = fas.getCalleeFunction();
298-
f && f->getDeclRef().getClosureExpr()) {
299-
auto *fArg = f->getArgument(fas.getCalleeArgIndex(*op));
300-
for (auto *use : fArg->getUses()) {
301-
if (visitedOperand.insert(use).second)
302-
worklist.emplace_back(use, fArg);
297+
if (auto *f = fas.getCalleeFunction()) {
298+
auto *fArg = cast<SILFunctionArgument>(
299+
f->getArgument(fas.getCalleeArgIndex(*op)));
300+
if (fArg->isClosureCapture()) {
301+
for (auto *use : fArg->getUses()) {
302+
if (visitedOperand.insert(use).second)
303+
worklist.emplace_back(use, fArg);
304+
}
305+
continue;
303306
}
304-
continue;
305307
}
306308
}
307309

test/Concurrency/transfernonsendable_sending_params.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,12 @@ func taskIsolatedCaptureInSendingClosureLiteral(_ x: NonSendableKlass) {
524524
}()
525525
}
526526

527+
Task { // expected-warning {{passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure}}
528+
{ // expected-note {{closure captures 'x' which is accessible to code in the current task}}
529+
print($0)
530+
}(x)
531+
}
532+
527533
takeClosure { // expected-warning {{passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure}}
528534
print(x) // expected-note {{closure captures 'x' which is accessible to code in the current task}}
529535
}

0 commit comments

Comments
 (0)