diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index 3e9f9b43623..72dc52a6329 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -108,7 +108,7 @@ pub struct BaseExpressionDoubleDot { pub struct AwaitOnlyInAsyncFnAndBlocks { #[primary_span] #[label] - pub dot_await_span: Span, + pub await_kw_span: Span, #[label(ast_lowering_this_not_async)] pub item_span: Option, } diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 8a5b26476c2..5e0ab80c6ac 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -185,15 +185,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::AsyncGeneratorKind::Block, |this| this.with_new_scopes(|this| this.lower_block_expr(block)), ), - ExprKind::Await(expr, await_kw_span) => { - let await_kw_span = if expr.span.hi() < await_kw_span.hi() { - *await_kw_span - } else { - // this is a recovered `await expr` - e.span - }; - self.lower_expr_await(await_kw_span, expr) - } + ExprKind::Await(expr, await_kw_span) => self.lower_expr_await(*await_kw_span, expr), ExprKind::Closure(box Closure { binder, capture_clause, @@ -710,7 +702,7 @@ impl<'hir> LoweringContext<'_, 'hir> { Some(hir::GeneratorKind::Async(_)) => {} Some(hir::GeneratorKind::Gen) | None => { self.tcx.sess.emit_err(AwaitOnlyInAsyncFnAndBlocks { - dot_await_span: await_kw_span, + await_kw_span, item_span: self.current_item, }); } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 7e5e266569d..595f6e0b927 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1592,23 +1592,25 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // could also check if it is an fn call (very likely) and suggest changing *that*, if // it is from the local crate. - if let hir::Node::Expr(parent_expr) = hir.get_parent(*hir_id) - // Peel off the DesugaringKind from the span - && let Some(desugar_parent_span) = parent_expr.span.parent_callsite() + // use nth(1) to skip one layer of desugaring from `IntoIter::into_iter` + if let Some((_, hir::Node::Expr(await_expr))) = hir.parent_iter(*hir_id).nth(1) + && let Some(expr_span) = expr.span.find_ancestor_inside(await_expr.span) { let removal_span = self.tcx .sess .source_map() - .span_extend_while(expr.span, char::is_whitespace) - .unwrap_or(expr.span) + .span_extend_while(expr_span, char::is_whitespace) + .unwrap_or(expr_span) .shrink_to_hi() - .to(desugar_parent_span); + .to(await_expr.span.shrink_to_hi()); err.span_suggestion( removal_span, "remove the `.await`", "", Applicability::MachineApplicable, ); + } else { + err.span_label(obligation.cause.span, "remove the `.await`"); } // FIXME: account for associated `async fn`s. if let hir::Expr { span, kind: hir::ExprKind::Call(base, _), .. } = expr { diff --git a/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir b/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir index cefb8ff3ca9..a9d1477b9fe 100644 --- a/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir +++ b/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir @@ -12,7 +12,7 @@ _1: GeneratorSavedTy { ty: impl std::future::Future, source_info: SourceInfo { - span: $DIR/async_await.rs:16:8: 16:14 (#10), + span: $DIR/async_await.rs:16:9: 16:14 (#10), scope: scope[0], }, ignore_for_traits: false, diff --git a/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr b/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr index 59630e837b7..7b03e56662a 100644 --- a/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr +++ b/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr @@ -143,7 +143,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks LL | fn foo9() -> Result<(), ()> { | ---- this is not `async` LL | let _ = await bar(); - | ^^^^^^^^^^^ only allowed inside `async` functions and blocks + | ^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks --> $DIR/incorrect-syntax-suggestions.rs:57:13 @@ -151,7 +151,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks LL | fn foo10() -> Result<(), ()> { | ----- this is not `async` LL | let _ = await? bar(); - | ^^^^^^^^^^^^ only allowed inside `async` functions and blocks + | ^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks --> $DIR/incorrect-syntax-suggestions.rs:66:14 @@ -159,7 +159,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks LL | fn foo12() -> Result<(), ()> { | ----- this is not `async` LL | let _ = (await bar())?; - | ^^^^^^^^^^^ only allowed inside `async` functions and blocks + | ^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks --> $DIR/incorrect-syntax-suggestions.rs:71:19 @@ -215,7 +215,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks LL | fn foo() -> Result<(), ()> { | --- this is not `async` LL | let _ = await!(bar())?; - | ^^^^^^^^^^^^^ only allowed inside `async` functions and blocks + | ^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks --> $DIR/incorrect-syntax-suggestions.rs:121:17 @@ -223,7 +223,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks LL | let foo = || { | -- this is not `async` LL | let _ = await!(bar())?; - | ^^^^^^^^^^^^^ only allowed inside `async` functions and blocks + | ^^^^^ only allowed inside `async` functions and blocks error: aborting due to 33 previous errors diff --git a/tests/ui/async-await/unnecessary-await.rs b/tests/ui/async-await/unnecessary-await.rs index 24673777b80..cd1e2871432 100644 --- a/tests/ui/async-await/unnecessary-await.rs +++ b/tests/ui/async-await/unnecessary-await.rs @@ -11,4 +11,24 @@ async fn baz() -> std::io::Result<()> { std::io::Result::Ok(()) } +macro_rules! e { + () => { + () + }; +} + +macro_rules! f { + ($expr:expr) => { + $expr.await + //~^ ERROR `()` is not a future + }; +} + +async fn with_macros() { + e!().await; + //~^ ERROR `()` is not a future + + f!(()); +} + fn main() {} diff --git a/tests/ui/async-await/unnecessary-await.stderr b/tests/ui/async-await/unnecessary-await.stderr index f1b358ed68a..9a2a035b2dd 100644 --- a/tests/ui/async-await/unnecessary-await.stderr +++ b/tests/ui/async-await/unnecessary-await.stderr @@ -19,6 +19,36 @@ help: alternatively, consider making `fn boo` asynchronous LL | async fn boo() {} | +++++ -error: aborting due to previous error +error[E0277]: `()` is not a future + --> $DIR/unnecessary-await.rs:28:10 + | +LL | e!().await; + | -^^^^^ + | || + | |`()` is not a future + | help: remove the `.await` + | + = help: the trait `Future` is not implemented for `()` + = note: () must be a future or must implement `IntoFuture` to be awaited + = note: required for `()` to implement `IntoFuture` + +error[E0277]: `()` is not a future + --> $DIR/unnecessary-await.rs:22:15 + | +LL | $expr.await + | ^^^^^ + | | + | `()` is not a future + | remove the `.await` +... +LL | f!(()); + | ------ in this macro invocation + | + = help: the trait `Future` is not implemented for `()` + = note: () must be a future or must implement `IntoFuture` to be awaited + = note: required for `()` to implement `IntoFuture` + = note: this error originates in the macro `f` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`.