Change:
This code: produces: Which is invalid. Looks like the span of the desugaring of uses only the part, instead of the span of the entire expression. This results in invalid suggestions when used by the code in .
I'm not entirely sure if this means that desugaring should use a bigger span, or if the suggestion diagnostic needs to be interpreted differently.
hmm.. is the only case where the desugared expr's span doesn't cover the whole piece of code it comes from? That doesn't sound right. If wonder if the expr should have the bigger span by default, and then async-specific code could grab the tighter span for diagnostics that need to point at the operator.
Some of the desugaring only uses the span, but the parts relevant for diagnostics like this do use the full span. Not sure if there's a problem there too.
I thought I might have accidentally introduced this bug in , but right after that PR was merged, the output was correct: So something changed in the last two months in what spans are used for await desugarings, it seems.
actually I think it was introduced in in , cc Do you need someone to fix this? I'm happy to put up a quick PR.
Yeah, looks like it: I just finished bisecting, which pointed at a rollup involving .
this was introduced in the PR linked earlier to try and improve other errors. It is tricky because reducing the span to only incurs these kind of bugs. On the other hand, the errors that got improved there became much less noisy, so I wouldn't want to revert the whole change. My fix above will solve this issue, but I'm sure there will be others in the future :-/

Discussion:
///     } /// } /// ``` <del> fn lower_expr_await(&mut self, await_span: Span, expr: &Expr) -> hir::ExprKind<'hir> { let dot_await_span = expr.span.shrink_to_hi().to(await_span); </del> <ins> fn lower_expr_await(&mut self, dot_await_span: Span, expr: &Expr) -> hir::ExprKind<'hir> { let full_span = expr.span.to(dot_await_span); </ins> match self.generator_kind { Some(hir::GeneratorKind::Async(_)) => {} Some(hir::GeneratorKind::Gen) | None => { let mut err = struct_span_err!( self.sess, <del> await_span, </del> <ins> dot_await_span, </ins> E0728, "`await` is only allowed inside `async` functions and blocks" ); <del> err.span_label(await_span, "only allowed inside `async` functions and blocks"); </del> <ins> err.span_label(dot_await_span, "only allowed inside `async` functions and blocks"); </ins> if let Some(item_sp) = self.current_item { err.span_label(item_sp, "this is not `async`"); }

let span = self.mark_span_with_reason(DesugaringKind::Await, dot_await_span, None); let gen_future_span = self.mark_span_with_reason( DesugaringKind::Await, <del> await_span, </del> <ins> full_span, </ins> self.allow_gen_future.clone(), ); let expr = self.lower_expr_mut(expr);

let loop_hir_id = self.lower_node_id(loop_node_id); let ready_arm = { let x_ident = Ident::with_dummy_span(sym::result); <del> let (x_pat, x_pat_hid) = self.pat_ident(span, x_ident); let x_expr = self.expr_ident(span, x_ident, x_pat_hid); let ready_field = self.single_pat_field(span, x_pat); </del> <ins> let (x_pat, x_pat_hid) = self.pat_ident(gen_future_span, x_ident); let x_expr = self.expr_ident(gen_future_span, x_ident, x_pat_hid); let ready_field = self.single_pat_field(gen_future_span, x_pat); </ins> let ready_pat = self.pat_lang_item_variant( span, hir::LangItem::PollReady,

let break_x = self.with_loop_scope(loop_node_id, move |this| { let expr_break = hir::ExprKind::Break(this.lower_loop_destination(None), Some(x_expr)); <del> this.arena.alloc(this.expr(span, expr_break, ThinVec::new())) </del> <ins> this.arena.alloc(this.expr(gen_future_span, expr_break, ThinVec::new())) </ins> }); self.arm(ready_pat, break_x) };

// `match ::std::future::IntoFuture::into_future(<expr>) { ... }` let into_future_span = self.mark_span_with_reason( DesugaringKind::Await, <del> await_span, </del> <ins> dot_await_span, </ins> self.allow_into_future.clone(), ); let into_future_expr = self.expr_call_lang_item_fn(

<ins> // edition:2021 // run-rustfix #![allow(dead_code)] async fn a() {} async fn foo() -> Result<(), i32> { Ok(a().await) //~ ERROR mismatched types } fn main() {} </ins>

<ins> // edition:2021 // run-rustfix #![allow(dead_code)] async fn a() {} async fn foo() -> Result<(), i32> { a().await //~ ERROR mismatched types } fn main() {} </ins>

<ins> error[E0308]: mismatched types --> $DIR/proper-span-for-type-error.rs:8:5 | LL |     a().await |     ^^^^^^^^^ expected enum `Result`, found `()` | = note:   expected enum `Result<(), i32>` found unit type `()` help: try wrapping the expression in `Ok` | LL |     Ok(a().await) |     +++         + error: aborting due to previous error For more information about this error, try `rustc --explain E0308`. </ins>