Skip to content

Commit b1a9253

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 cc9bb7a commit b1a9253

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
@@ -3698,6 +3698,10 @@ WARNING(partial_application_of_function_invalid_swift4,none,
36983698
"be an error in future Swift versions",
36993699
(unsigned))
37003700

3701+
// Cannot capture `async let`
3702+
ERROR(capture_async_let_not_supported,none,
3703+
"capturing 'async let' variables is not supported", ())
3704+
37013705
ERROR(self_assignment_var,none,
37023706
"assigning a variable to itself", ())
37033707
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)