Skip to content

Commit 2f52b65

Browse files
committed
[Concurrency] Apply nonisolated(unsafe) to iterator variables for
async for-in loops. Async iterators are not `Sendable`; they're only meant to be used from the isolation domain that creates them. But the `next()` method runs on the generic executor, so calling it from an actor-isolated context passes non-`Sendable` state across the isolation boundary. `next()` should inherit the isolation of the caller, but for now, use the opt out. (cherry picked from commit 0c6c369)
1 parent 4f70eb2 commit 2f52b65

File tree

2 files changed

+17
-0
lines changed

2 files changed

+17
-0
lines changed

lib/Sema/CSGen.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4413,6 +4413,19 @@ generateForEachStmtConstraints(ConstraintSystem &cs,
44134413
sequenceExpr->getStartLoc(), ctx.getIdentifier(name), dc);
44144414
makeIteratorVar->setImplicit();
44154415

4416+
// FIXME: Apply `nonisolated(unsafe)` to async iterators.
4417+
//
4418+
// Async iterators are not `Sendable`; they're only meant to be used from
4419+
// the isolation domain that creates them. But the `next()` method runs on
4420+
// the generic executor, so calling it from an actor-isolated context passes
4421+
// non-`Sendable` state across the isolation boundary. `next()` should
4422+
// inherit the isolation of the caller, but for now, use the opt out.
4423+
if (isAsync) {
4424+
auto *nonisolated = new (ctx)
4425+
NonisolatedAttr(/*unsafe=*/true, /*implicit=*/true);
4426+
makeIteratorVar->getAttrs().add(nonisolated);
4427+
}
4428+
44164429
// First, let's form a call from sequence to `.makeIterator()` and save
44174430
// that in a special variable which is going to be used by SILGen.
44184431
{

test/Concurrency/experimental_feature_strictconcurrency.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,4 +91,8 @@ func iterate(stream: AsyncStream<Int>) async {
9191
while let element = await it.next() {
9292
print(element)
9393
}
94+
95+
for await x in stream {
96+
print(x)
97+
}
9498
}

0 commit comments

Comments
 (0)