Skip to content

Commit 6d6c904

Browse files
Make async removal span more resilient to macro expansions
1 parent d420027 commit 6d6c904

File tree

7 files changed

+68
-24
lines changed

7 files changed

+68
-24
lines changed

compiler/rustc_ast_lowering/src/errors.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ pub struct BaseExpressionDoubleDot {
108108
pub struct AwaitOnlyInAsyncFnAndBlocks {
109109
#[primary_span]
110110
#[label]
111-
pub dot_await_span: Span,
111+
pub await_kw_span: Span,
112112
#[label(ast_lowering_this_not_async)]
113113
pub item_span: Option<Span>,
114114
}

compiler/rustc_ast_lowering/src/expr.rs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -185,15 +185,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
185185
hir::AsyncGeneratorKind::Block,
186186
|this| this.with_new_scopes(|this| this.lower_block_expr(block)),
187187
),
188-
ExprKind::Await(expr, await_kw_span) => {
189-
let await_kw_span = if expr.span.hi() < await_kw_span.hi() {
190-
*await_kw_span
191-
} else {
192-
// this is a recovered `await expr`
193-
e.span
194-
};
195-
self.lower_expr_await(await_kw_span, expr)
196-
}
188+
ExprKind::Await(expr, await_kw_span) => self.lower_expr_await(*await_kw_span, expr),
197189
ExprKind::Closure(box Closure {
198190
binder,
199191
capture_clause,
@@ -710,7 +702,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
710702
Some(hir::GeneratorKind::Async(_)) => {}
711703
Some(hir::GeneratorKind::Gen) | None => {
712704
self.tcx.sess.emit_err(AwaitOnlyInAsyncFnAndBlocks {
713-
dot_await_span: await_kw_span,
705+
await_kw_span,
714706
item_span: self.current_item,
715707
});
716708
}

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1592,23 +1592,25 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
15921592
// could also check if it is an fn call (very likely) and suggest changing *that*, if
15931593
// it is from the local crate.
15941594

1595-
if let hir::Node::Expr(parent_expr) = hir.get_parent(*hir_id)
1596-
// Peel off the DesugaringKind from the span
1597-
&& let Some(desugar_parent_span) = parent_expr.span.parent_callsite()
1595+
// use nth(1) to skip one layer of desugaring from `IntoIter::into_iter`
1596+
if let Some((_, hir::Node::Expr(await_expr))) = hir.parent_iter(*hir_id).nth(1)
1597+
&& let Some(expr_span) = expr.span.find_ancestor_inside(await_expr.span)
15981598
{
15991599
let removal_span = self.tcx
16001600
.sess
16011601
.source_map()
1602-
.span_extend_while(expr.span, char::is_whitespace)
1603-
.unwrap_or(expr.span)
1602+
.span_extend_while(expr_span, char::is_whitespace)
1603+
.unwrap_or(expr_span)
16041604
.shrink_to_hi()
1605-
.to(desugar_parent_span);
1605+
.to(await_expr.span.shrink_to_hi());
16061606
err.span_suggestion(
16071607
removal_span,
16081608
"remove the `.await`",
16091609
"",
16101610
Applicability::MachineApplicable,
16111611
);
1612+
} else {
1613+
err.span_label(obligation.cause.span, "remove the `.await`");
16121614
}
16131615
// FIXME: account for associated `async fn`s.
16141616
if let hir::Expr { span, kind: hir::ExprKind::Call(base, _), .. } = expr {

tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
_1: GeneratorSavedTy {
1313
ty: impl std::future::Future<Output = ()>,
1414
source_info: SourceInfo {
15-
span: $DIR/async_await.rs:16:8: 16:14 (#10),
15+
span: $DIR/async_await.rs:16:9: 16:14 (#10),
1616
scope: scope[0],
1717
},
1818
ignore_for_traits: false,

tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -143,23 +143,23 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks
143143
LL | fn foo9() -> Result<(), ()> {
144144
| ---- this is not `async`
145145
LL | let _ = await bar();
146-
| ^^^^^^^^^^^ only allowed inside `async` functions and blocks
146+
| ^^^^^ only allowed inside `async` functions and blocks
147147

148148
error[E0728]: `await` is only allowed inside `async` functions and blocks
149149
--> $DIR/incorrect-syntax-suggestions.rs:57:13
150150
|
151151
LL | fn foo10() -> Result<(), ()> {
152152
| ----- this is not `async`
153153
LL | let _ = await? bar();
154-
| ^^^^^^^^^^^^ only allowed inside `async` functions and blocks
154+
| ^^^^^ only allowed inside `async` functions and blocks
155155

156156
error[E0728]: `await` is only allowed inside `async` functions and blocks
157157
--> $DIR/incorrect-syntax-suggestions.rs:66:14
158158
|
159159
LL | fn foo12() -> Result<(), ()> {
160160
| ----- this is not `async`
161161
LL | let _ = (await bar())?;
162-
| ^^^^^^^^^^^ only allowed inside `async` functions and blocks
162+
| ^^^^^ only allowed inside `async` functions and blocks
163163

164164
error[E0728]: `await` is only allowed inside `async` functions and blocks
165165
--> $DIR/incorrect-syntax-suggestions.rs:71:19
@@ -215,15 +215,15 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks
215215
LL | fn foo() -> Result<(), ()> {
216216
| --- this is not `async`
217217
LL | let _ = await!(bar())?;
218-
| ^^^^^^^^^^^^^ only allowed inside `async` functions and blocks
218+
| ^^^^^ only allowed inside `async` functions and blocks
219219

220220
error[E0728]: `await` is only allowed inside `async` functions and blocks
221221
--> $DIR/incorrect-syntax-suggestions.rs:121:17
222222
|
223223
LL | let foo = || {
224224
| -- this is not `async`
225225
LL | let _ = await!(bar())?;
226-
| ^^^^^^^^^^^^^ only allowed inside `async` functions and blocks
226+
| ^^^^^ only allowed inside `async` functions and blocks
227227

228228
error: aborting due to 33 previous errors
229229

tests/ui/async-await/unnecessary-await.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,24 @@ async fn baz() -> std::io::Result<()> {
1111
std::io::Result::Ok(())
1212
}
1313

14+
macro_rules! e {
15+
() => {
16+
()
17+
};
18+
}
19+
20+
macro_rules! f {
21+
($expr:expr) => {
22+
$expr.await
23+
//~^ ERROR `()` is not a future
24+
};
25+
}
26+
27+
async fn with_macros() {
28+
e!().await;
29+
//~^ ERROR `()` is not a future
30+
31+
f!(());
32+
}
33+
1434
fn main() {}

tests/ui/async-await/unnecessary-await.stderr

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,36 @@ help: alternatively, consider making `fn boo` asynchronous
1919
LL | async fn boo() {}
2020
| +++++
2121

22-
error: aborting due to previous error
22+
error[E0277]: `()` is not a future
23+
--> $DIR/unnecessary-await.rs:28:10
24+
|
25+
LL | e!().await;
26+
| -^^^^^
27+
| ||
28+
| |`()` is not a future
29+
| help: remove the `.await`
30+
|
31+
= help: the trait `Future` is not implemented for `()`
32+
= note: () must be a future or must implement `IntoFuture` to be awaited
33+
= note: required for `()` to implement `IntoFuture`
34+
35+
error[E0277]: `()` is not a future
36+
--> $DIR/unnecessary-await.rs:22:15
37+
|
38+
LL | $expr.await
39+
| ^^^^^
40+
| |
41+
| `()` is not a future
42+
| remove the `.await`
43+
...
44+
LL | f!(());
45+
| ------ in this macro invocation
46+
|
47+
= help: the trait `Future` is not implemented for `()`
48+
= note: () must be a future or must implement `IntoFuture` to be awaited
49+
= note: required for `()` to implement `IntoFuture`
50+
= note: this error originates in the macro `f` (in Nightly builds, run with -Z macro-backtrace for more info)
51+
52+
error: aborting due to 3 previous errors
2353

2454
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)