Skip to content

Commit

Permalink
Merge pull request swiftlang#61841 from tshortli/diagnose-async-let-c…
Browse files Browse the repository at this point in the history
…rash

Sema: Fix crash when diagnosing async let bindings in illegal contexts
  • Loading branch information
tshortli authored Nov 2, 2022
2 parents f02b298 + f79d91a commit 18785b8
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 14 deletions.
34 changes: 24 additions & 10 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -4576,14 +4576,6 @@ NOTE(async_call_without_await_in_async_let,none,

WARNING(no_async_in_await,none,
"no 'async' operations occur within 'await' expression", ())
ERROR(async_call_in_illegal_context,none,
"'async' call cannot occur in "
"%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",
(unsigned))
ERROR(await_in_illegal_context,none,
"'await' operation cannot occur in "
"%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",
(unsigned))
ERROR(async_in_nonasync_function,none,
"%select{'async'|'async' call|'await'|'async let'|'async' property access|'async' subscript access}0 in "
"%select{a function|an autoclosure}1 that does not support concurrency",
Expand Down Expand Up @@ -4631,10 +4623,32 @@ ERROR(async_let_no_variables,none,
"'async let' requires at least one named variable", ())
NOTE(async_let_without_await,none,
"reference to async let %0 is 'async'", (DeclName))

#define EFFECTS_CONTEXT_KIND \
"%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}" \

ERROR(async_call_in_illegal_context,none,
"'async' call cannot occur in " EFFECTS_CONTEXT_KIND "0",
(unsigned))
ERROR(await_in_illegal_context,none,
"'await' operation cannot occur in " EFFECTS_CONTEXT_KIND "0",
(unsigned))
ERROR(async_let_in_illegal_context,none,
"async let %0 cannot be referenced in "
"%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",
"async let %0 cannot be referenced in " EFFECTS_CONTEXT_KIND "1",
(DeclName, unsigned))
ERROR(async_let_binding_illegal_context,none,
"'async let' cannot be used on declarations in " EFFECTS_CONTEXT_KIND "0",
(unsigned))

#undef EFFECTS_CONTEXT_KIND

ERROR(objc_ambiguous_async_convention,none,
"%0 overrides or implements protocol requirements for Objective-C "
Expand Down
7 changes: 3 additions & 4 deletions lib/Sema/TypeCheckEffects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1930,10 +1930,9 @@ class Context {
} else if (auto patternBinding = dyn_cast_or_null<PatternBindingDecl>(
node.dyn_cast<Decl *>())) {
if (patternBinding->isAsyncLet()) {
auto var = patternBinding->getAnchoringVarDecl(0);
Diags.diagnose(
e->getLoc(), diag::async_let_in_illegal_context,
var->getName(), static_cast<unsigned>(getKind()));
Diags.diagnose(patternBinding->getLoc(),
diag::async_let_binding_illegal_context,
static_cast<unsigned>(getKind()));
return;
}
}
Expand Down
7 changes: 7 additions & 0 deletions test/expr/unary/async_await.swift
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,13 @@ func testAsyncLet() async throws {
} catch {
}

defer {
async let deferX: Int = await getInt() // expected-error {{'async let' cannot be used on declarations in a defer body}}
_ = await deferX // expected-error {{async let 'deferX' cannot be referenced in a defer body}}
async let _: Int = await getInt() // expected-error {{'async let' cannot be used on declarations in a defer body}}
async let _ = await getInt() // expected-error {{'async let' cannot be used on declarations in a defer body}}
}

async let x1 = getIntUnsafely() // okay, try is implicit here

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

0 comments on commit 18785b8

Please sign in to comment.