Skip to content

Commit 18785b8

Browse files
authored
Merge pull request #61841 from tshortli/diagnose-async-let-crash
Sema: Fix crash when diagnosing async let bindings in illegal contexts
2 parents f02b298 + f79d91a commit 18785b8

File tree

3 files changed

+34
-14
lines changed

3 files changed

+34
-14
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4576,14 +4576,6 @@ NOTE(async_call_without_await_in_async_let,none,
45764576

45774577
WARNING(no_async_in_await,none,
45784578
"no 'async' operations occur within 'await' expression", ())
4579-
ERROR(async_call_in_illegal_context,none,
4580-
"'async' call cannot occur in "
4581-
"%select{<<ERROR>>|a default argument|a property wrapper initializer|a property initializer|a global variable initializer|an enum case raw value|a catch pattern|a catch guard expression|a defer body}0",
4582-
(unsigned))
4583-
ERROR(await_in_illegal_context,none,
4584-
"'await' operation cannot occur in "
4585-
"%select{<<ERROR>>|a default argument|a property wrapper initializer|a property initializer|a global variable initializer|an enum case raw value|a catch pattern|a catch guard expression|a defer body}0",
4586-
(unsigned))
45874579
ERROR(async_in_nonasync_function,none,
45884580
"%select{'async'|'async' call|'await'|'async let'|'async' property access|'async' subscript access}0 in "
45894581
"%select{a function|an autoclosure}1 that does not support concurrency",
@@ -4631,10 +4623,32 @@ ERROR(async_let_no_variables,none,
46314623
"'async let' requires at least one named variable", ())
46324624
NOTE(async_let_without_await,none,
46334625
"reference to async let %0 is 'async'", (DeclName))
4626+
4627+
#define EFFECTS_CONTEXT_KIND \
4628+
"%select{<<ERROR>>|" \
4629+
"a default argument|" \
4630+
"a property wrapper initializer|" \
4631+
"a property initializer|" \
4632+
"a global variable initializer|" \
4633+
"an enum case raw value|" \
4634+
"a catch pattern|" \
4635+
"a catch guard expression|" \
4636+
"a defer body}" \
4637+
4638+
ERROR(async_call_in_illegal_context,none,
4639+
"'async' call cannot occur in " EFFECTS_CONTEXT_KIND "0",
4640+
(unsigned))
4641+
ERROR(await_in_illegal_context,none,
4642+
"'await' operation cannot occur in " EFFECTS_CONTEXT_KIND "0",
4643+
(unsigned))
46344644
ERROR(async_let_in_illegal_context,none,
4635-
"async let %0 cannot be referenced in "
4636-
"%select{<<ERROR>>|a default argument|a property wrapper initializer|a property initializer|a global variable initializer|an enum case raw value|a catch pattern|a catch guard expression|a defer body}1",
4645+
"async let %0 cannot be referenced in " EFFECTS_CONTEXT_KIND "1",
46374646
(DeclName, unsigned))
4647+
ERROR(async_let_binding_illegal_context,none,
4648+
"'async let' cannot be used on declarations in " EFFECTS_CONTEXT_KIND "0",
4649+
(unsigned))
4650+
4651+
#undef EFFECTS_CONTEXT_KIND
46384652

46394653
ERROR(objc_ambiguous_async_convention,none,
46404654
"%0 overrides or implements protocol requirements for Objective-C "

lib/Sema/TypeCheckEffects.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1930,10 +1930,9 @@ class Context {
19301930
} else if (auto patternBinding = dyn_cast_or_null<PatternBindingDecl>(
19311931
node.dyn_cast<Decl *>())) {
19321932
if (patternBinding->isAsyncLet()) {
1933-
auto var = patternBinding->getAnchoringVarDecl(0);
1934-
Diags.diagnose(
1935-
e->getLoc(), diag::async_let_in_illegal_context,
1936-
var->getName(), static_cast<unsigned>(getKind()));
1933+
Diags.diagnose(patternBinding->getLoc(),
1934+
diag::async_let_binding_illegal_context,
1935+
static_cast<unsigned>(getKind()));
19371936
return;
19381937
}
19391938
}

test/expr/unary/async_await.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,13 @@ func testAsyncLet() async throws {
181181
} catch {
182182
}
183183

184+
defer {
185+
async let deferX: Int = await getInt() // expected-error {{'async let' cannot be used on declarations in a defer body}}
186+
_ = await deferX // expected-error {{async let 'deferX' cannot be referenced in a defer body}}
187+
async let _: Int = await getInt() // expected-error {{'async let' cannot be used on declarations in a defer body}}
188+
async let _ = await getInt() // expected-error {{'async let' cannot be used on declarations in a defer body}}
189+
}
190+
184191
async let x1 = getIntUnsafely() // okay, try is implicit here
185192

186193
async let x2 = getInt() // okay, await is implicit here

0 commit comments

Comments
 (0)