Skip to content

Commit 7470155

Browse files
committed
Sema: Reject captures of async let bindings.
This isn't implemented. It would never make sense for escaping captures of `async let` values, because doing so would either involve an implicit awaiting of the value on capture, or else stretching the lifetime of the task past its scope. In nonescaping contexts, and in nested `async let` expressions, it might be implementable in the future. rdar://80043610
1 parent 439edbc commit 7470155

File tree

3 files changed

+29
-0
lines changed

3 files changed

+29
-0
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3709,6 +3709,10 @@ WARNING(partial_application_of_function_invalid_swift4,none,
37093709
"be an error in future Swift versions",
37103710
(unsigned))
37113711

3712+
// Cannot capture `async let`
3713+
ERROR(capture_async_let_not_supported,none,
3714+
"capturing 'async let' variables is not supported", ())
3715+
37123716
ERROR(self_assignment_var,none,
37133717
"assigning a variable to itself", ())
37143718
ERROR(self_assignment_prop,none,

lib/Sema/TypeCheckCaptures.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,14 @@ class FindCapturedVars : public ASTWalker {
177177
/// if invalid.
178178
void addCapture(CapturedValue capture) {
179179
auto VD = capture.getDecl();
180+
181+
if (auto var = dyn_cast<VarDecl>(VD)) {
182+
// `async let` variables cannot currently be captured.
183+
if (var->isAsyncLet()) {
184+
Context.Diags.diagnose(capture.getLoc(), diag::capture_async_let_not_supported);
185+
return;
186+
}
187+
}
180188

181189
// Check to see if we already have an entry for this decl.
182190
unsigned &entryNumber = captureEntryNumber[VD];
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %target-typecheck-verify-swift -disable-availability-checking -enable-experimental-concurrency
2+
// REQUIRES: concurrency
3+
4+
func autoclosureCapture(_: @autoclosure () async throws -> Int) async {}
5+
func nonescapingCapture(_: () async throws -> Int) {}
6+
func escapingCapture(_: @escaping () async throws -> Int) {}
7+
8+
func foo() async {
9+
async let x = 32
10+
11+
async let y = x // expected-error{{not supported}}
12+
_ = await y
13+
14+
await autoclosureCapture(await x)// expected-error{{not supported}}
15+
nonescapingCapture { await x }// expected-error{{not supported}}
16+
escapingCapture { await x }// expected-error{{not supported}}
17+
}

0 commit comments

Comments
 (0)