From f79d91aeb5b6c7baac71ac8e3648f979131ee779 Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Mon, 31 Oct 2022 23:04:59 -0700 Subject: [PATCH] Sema: Fix crash when diagnosing async let bindings in illegal contexts. Resolves rdar://101673476 --- include/swift/AST/DiagnosticsSema.def | 34 +++++++++++++++++++-------- lib/Sema/TypeCheckEffects.cpp | 7 +++--- test/expr/unary/async_await.swift | 7 ++++++ 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index be216d0112a7f..8b85e16a5a14c 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -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{<>|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{<>|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", @@ -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{<>|" \ + "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{<>|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 " diff --git a/lib/Sema/TypeCheckEffects.cpp b/lib/Sema/TypeCheckEffects.cpp index dacd0cdc010bb..6e2c897b7d998 100644 --- a/lib/Sema/TypeCheckEffects.cpp +++ b/lib/Sema/TypeCheckEffects.cpp @@ -1930,10 +1930,9 @@ class Context { } else if (auto patternBinding = dyn_cast_or_null( node.dyn_cast())) { if (patternBinding->isAsyncLet()) { - auto var = patternBinding->getAnchoringVarDecl(0); - Diags.diagnose( - e->getLoc(), diag::async_let_in_illegal_context, - var->getName(), static_cast(getKind())); + Diags.diagnose(patternBinding->getLoc(), + diag::async_let_binding_illegal_context, + static_cast(getKind())); return; } } diff --git a/test/expr/unary/async_await.swift b/test/expr/unary/async_await.swift index 1a2edebd9ee5b..64ffbbe5ea5c1 100644 --- a/test/expr/unary/async_await.swift +++ b/test/expr/unary/async_await.swift @@ -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