Make async removal span more resilient to macro expansions
This commit is contained in:
parent
d4200276f2
commit
6d6c904431
7 changed files with 68 additions and 24 deletions
|
@ -108,7 +108,7 @@ pub struct BaseExpressionDoubleDot {
|
||||||
pub struct AwaitOnlyInAsyncFnAndBlocks {
|
pub struct AwaitOnlyInAsyncFnAndBlocks {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
#[label]
|
#[label]
|
||||||
pub dot_await_span: Span,
|
pub await_kw_span: Span,
|
||||||
#[label(ast_lowering_this_not_async)]
|
#[label(ast_lowering_this_not_async)]
|
||||||
pub item_span: Option<Span>,
|
pub item_span: Option<Span>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -185,15 +185,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
hir::AsyncGeneratorKind::Block,
|
hir::AsyncGeneratorKind::Block,
|
||||||
|this| this.with_new_scopes(|this| this.lower_block_expr(block)),
|
|this| this.with_new_scopes(|this| this.lower_block_expr(block)),
|
||||||
),
|
),
|
||||||
ExprKind::Await(expr, await_kw_span) => {
|
ExprKind::Await(expr, await_kw_span) => self.lower_expr_await(*await_kw_span, expr),
|
||||||
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::Closure(box Closure {
|
ExprKind::Closure(box Closure {
|
||||||
binder,
|
binder,
|
||||||
capture_clause,
|
capture_clause,
|
||||||
|
@ -710,7 +702,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
Some(hir::GeneratorKind::Async(_)) => {}
|
Some(hir::GeneratorKind::Async(_)) => {}
|
||||||
Some(hir::GeneratorKind::Gen) | None => {
|
Some(hir::GeneratorKind::Gen) | None => {
|
||||||
self.tcx.sess.emit_err(AwaitOnlyInAsyncFnAndBlocks {
|
self.tcx.sess.emit_err(AwaitOnlyInAsyncFnAndBlocks {
|
||||||
dot_await_span: await_kw_span,
|
await_kw_span,
|
||||||
item_span: self.current_item,
|
item_span: self.current_item,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
// could also check if it is an fn call (very likely) and suggest changing *that*, if
|
||||||
// it is from the local crate.
|
// it is from the local crate.
|
||||||
|
|
||||||
if let hir::Node::Expr(parent_expr) = hir.get_parent(*hir_id)
|
// use nth(1) to skip one layer of desugaring from `IntoIter::into_iter`
|
||||||
// Peel off the DesugaringKind from the span
|
if let Some((_, hir::Node::Expr(await_expr))) = hir.parent_iter(*hir_id).nth(1)
|
||||||
&& let Some(desugar_parent_span) = parent_expr.span.parent_callsite()
|
&& let Some(expr_span) = expr.span.find_ancestor_inside(await_expr.span)
|
||||||
{
|
{
|
||||||
let removal_span = self.tcx
|
let removal_span = self.tcx
|
||||||
.sess
|
.sess
|
||||||
.source_map()
|
.source_map()
|
||||||
.span_extend_while(expr.span, char::is_whitespace)
|
.span_extend_while(expr_span, char::is_whitespace)
|
||||||
.unwrap_or(expr.span)
|
.unwrap_or(expr_span)
|
||||||
.shrink_to_hi()
|
.shrink_to_hi()
|
||||||
.to(desugar_parent_span);
|
.to(await_expr.span.shrink_to_hi());
|
||||||
err.span_suggestion(
|
err.span_suggestion(
|
||||||
removal_span,
|
removal_span,
|
||||||
"remove the `.await`",
|
"remove the `.await`",
|
||||||
"",
|
"",
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
err.span_label(obligation.cause.span, "remove the `.await`");
|
||||||
}
|
}
|
||||||
// FIXME: account for associated `async fn`s.
|
// FIXME: account for associated `async fn`s.
|
||||||
if let hir::Expr { span, kind: hir::ExprKind::Call(base, _), .. } = expr {
|
if let hir::Expr { span, kind: hir::ExprKind::Call(base, _), .. } = expr {
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
_1: GeneratorSavedTy {
|
_1: GeneratorSavedTy {
|
||||||
ty: impl std::future::Future<Output = ()>,
|
ty: impl std::future::Future<Output = ()>,
|
||||||
source_info: SourceInfo {
|
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],
|
scope: scope[0],
|
||||||
},
|
},
|
||||||
ignore_for_traits: false,
|
ignore_for_traits: false,
|
||||||
|
|
|
@ -143,7 +143,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks
|
||||||
LL | fn foo9() -> Result<(), ()> {
|
LL | fn foo9() -> Result<(), ()> {
|
||||||
| ---- this is not `async`
|
| ---- this is not `async`
|
||||||
LL | let _ = await bar();
|
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
|
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
||||||
--> $DIR/incorrect-syntax-suggestions.rs:57:13
|
--> $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<(), ()> {
|
LL | fn foo10() -> Result<(), ()> {
|
||||||
| ----- this is not `async`
|
| ----- this is not `async`
|
||||||
LL | let _ = await? bar();
|
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
|
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
||||||
--> $DIR/incorrect-syntax-suggestions.rs:66:14
|
--> $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<(), ()> {
|
LL | fn foo12() -> Result<(), ()> {
|
||||||
| ----- this is not `async`
|
| ----- this is not `async`
|
||||||
LL | let _ = (await bar())?;
|
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
|
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
||||||
--> $DIR/incorrect-syntax-suggestions.rs:71:19
|
--> $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<(), ()> {
|
LL | fn foo() -> Result<(), ()> {
|
||||||
| --- this is not `async`
|
| --- this is not `async`
|
||||||
LL | let _ = await!(bar())?;
|
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
|
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
||||||
--> $DIR/incorrect-syntax-suggestions.rs:121:17
|
--> $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 = || {
|
LL | let foo = || {
|
||||||
| -- this is not `async`
|
| -- this is not `async`
|
||||||
LL | let _ = await!(bar())?;
|
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
|
error: aborting due to 33 previous errors
|
||||||
|
|
||||||
|
|
|
@ -11,4 +11,24 @@ async fn baz() -> std::io::Result<()> {
|
||||||
std::io::Result::Ok(())
|
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() {}
|
fn main() {}
|
||||||
|
|
|
@ -19,6 +19,36 @@ help: alternatively, consider making `fn boo` asynchronous
|
||||||
LL | async fn boo() {}
|
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`.
|
For more information about this error, try `rustc --explain E0277`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue