mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
Make async removal span more resilient to macro expansions
This commit is contained in:
parent
d4200276f2
commit
6d6c904431
@ -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<Span>,
|
||||
}
|
||||
|
@ -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,
|
||||
});
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -12,7 +12,7 @@
|
||||
_1: GeneratorSavedTy {
|
||||
ty: impl std::future::Future<Output = ()>,
|
||||
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,
|
||||
|
@ -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
|
||||
|
||||
|
@ -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() {}
|
||||
|
@ -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`.
|
||||
|
Loading…
Reference in New Issue
Block a user