From f4f3b2d7bcbed614b224dd429eedc50980b29ac9 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Tue, 16 Nov 2021 00:57:53 +0000 Subject: [PATCH 01/15] When `.await` is called on a non-`Future` expression, suggest removal Keep track of the origin of a `T: Future` obligation when caused by an `.await` expression. Address #66731. --- compiler/rustc_ast_lowering/src/expr.rs | 5 ++- compiler/rustc_middle/src/traits/mod.rs | 2 + compiler/rustc_parse/src/parser/expr.rs | 4 +- .../src/traits/error_reporting/mod.rs | 1 + .../src/traits/error_reporting/suggestions.rs | 26 ++++++++++++ .../rustc_typeck/src/check/fn_ctxt/_impl.rs | 31 ++++++++++++-- .../ui/async-await/async-error-span.stderr | 4 +- .../ui/async-await/async-fn-nonsend.stderr | 12 +++--- .../incorrect-syntax-suggestions.stderr | 24 +++++------ .../ui/async-await/issue-64130-1-sync.stderr | 4 +- .../ui/async-await/issue-64130-2-send.stderr | 4 +- .../ui/async-await/issue-64130-3-other.stderr | 4 +- .../issue-64130-4-async-move.stderr | 4 +- .../issue-64130-non-send-future-diags.stderr | 4 +- .../issue-67252-unnamed-future.stderr | 4 +- src/test/ui/async-await/issue-70594.rs | 1 + src/test/ui/async-await/issue-70594.stderr | 32 +++++++++++---- .../issue-70935-complex-spans.stderr | 21 +++------- src/test/ui/async-await/issue-71137.stderr | 4 +- .../ui/async-await/issues/issue-51719.stderr | 4 +- .../ui/async-await/issues/issue-51751.stderr | 4 +- .../ui/async-await/issues/issue-62009-1.rs | 5 ++- .../async-await/issues/issue-62009-1.stderr | 41 ++++++++++++------- .../async-await/issues/issue-62009-2.stderr | 4 +- .../issue-65436-raw-ptr-not-send.stderr | 12 ++---- .../issues/non-async-enclosing-span.stderr | 4 +- .../async-await/suggest-missing-await.stderr | 8 ++-- .../async-await/unresolved_type_param.stderr | 20 ++++----- .../ui/lint/must_not_suspend/boxed.stderr | 2 +- .../ui/lint/must_not_suspend/dedup.stderr | 2 +- .../ui/lint/must_not_suspend/gated.stderr | 2 +- .../ui/lint/must_not_suspend/mutex.stderr | 2 +- src/test/ui/lint/must_not_suspend/ref.stderr | 2 +- .../ui/lint/must_not_suspend/trait.stderr | 4 +- src/test/ui/lint/must_not_suspend/unit.stderr | 2 +- src/test/ui/lint/must_not_suspend/warn.stderr | 2 +- 36 files changed, 190 insertions(+), 121 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index c9578c2f50f90..2cf0dbaf425b8 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -607,6 +607,7 @@ impl<'hir> LoweringContext<'_, 'hir> { /// } /// ``` 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); match self.generator_kind { Some(hir::GeneratorKind::Async(_)) => {} Some(hir::GeneratorKind::Gen) | None => { @@ -623,7 +624,7 @@ impl<'hir> LoweringContext<'_, 'hir> { err.emit(); } } - let span = self.mark_span_with_reason(DesugaringKind::Await, await_span, None); + let span = self.mark_span_with_reason(DesugaringKind::Await, dot_await_span, None); let gen_future_span = self.mark_span_with_reason( DesugaringKind::Await, await_span, @@ -682,7 +683,7 @@ impl<'hir> LoweringContext<'_, 'hir> { 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)); - this.arena.alloc(this.expr(await_span, expr_break, ThinVec::new())) + this.arena.alloc(this.expr(span, expr_break, ThinVec::new())) }); self.arm(ready_pat, break_x) }; diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 49a64cb246ad0..5173d7e2a51dc 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -348,6 +348,8 @@ pub enum ObligationCauseCode<'tcx> { /// If `X` is the concrete type of an opaque type `impl Y`, then `X` must implement `Y` OpaqueType, + AwaitableExpr, + /// Well-formed checking. If a `WellFormedLoc` is provided, /// then it will be used to eprform HIR-based wf checking /// after an error occurs, in order to generate a more precise error span. diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 1dbd7bad0f023..791053670ad26 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2831,8 +2831,8 @@ impl<'a> Parser<'a> { ExprKind::Call(f, args) } - fn mk_await_expr(&mut self, self_arg: P, lo: Span) -> P { - let span = lo.to(self.prev_token.span); + fn mk_await_expr(&mut self, self_arg: P, _lo: Span) -> P { + let span = self.prev_token.span; let await_expr = self.mk_expr(span, ExprKind::Await(self_arg), AttrVec::new()); self.recover_from_await_method_call(); await_expr diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index d9f86fbc23b5d..df8c6ef69b20c 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -439,6 +439,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { self.suggest_remove_reference(&obligation, &mut err, trait_ref); self.suggest_semicolon_removal(&obligation, &mut err, span, trait_ref); self.note_version_mismatch(&mut err, &trait_ref); + self.suggest_remove_await(&obligation, &mut err); if Some(trait_ref.def_id()) == tcx.lang_items().try_trait() { self.suggest_await_before_try(&mut err, &obligation, trait_ref, span); 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 2e87d6fdd3dc2..957b8c379a39b 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -89,6 +89,12 @@ pub trait InferCtxtExt<'tcx> { trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, ); + fn suggest_remove_await( + &self, + obligation: &PredicateObligation<'tcx>, + err: &mut DiagnosticBuilder<'_>, + ); + fn suggest_change_mut( &self, obligation: &PredicateObligation<'tcx>, @@ -873,6 +879,25 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } } + fn suggest_remove_await( + &self, + obligation: &PredicateObligation<'tcx>, + err: &mut DiagnosticBuilder<'_>, + ) { + let span = obligation.cause.span; + + if let ObligationCauseCode::AwaitableExpr = obligation.cause.code { + // FIXME: use `trait_ref.self_ty().no_bound_vars()` to typecheck if `()` and if not + // maybe suggest returning instead? + err.span_suggestion_verbose( + span, + "do not `.await` the expression", + String::new(), + Applicability::MachineApplicable, + ); + } + } + /// Check if the trait bound is implemented for a different mutability and note it in the /// final error. fn suggest_change_mut( @@ -1935,6 +1960,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { | ObligationCauseCode::ReturnType | ObligationCauseCode::ReturnValue(_) | ObligationCauseCode::BlockTailExpression(_) + | ObligationCauseCode::AwaitableExpr | ObligationCauseCode::LetElse => {} ObligationCauseCode::SliceOrArrayElem => { err.note("slice and array elements must have `Sized` type"); diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index a02a7d7cbfeb2..de713b7de2e5f 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -810,7 +810,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty = item_ty.subst(self.tcx, substs); self.write_resolution(hir_id, Ok((def_kind, def_id))); - self.add_required_obligations(span, def_id, &substs); + self.add_required_obligations_with_code( + span, + def_id, + &substs, + match lang_item { + hir::LangItem::FuturePoll => ObligationCauseCode::AwaitableExpr, + // FIXME: see if there are other obligation specializations we could do here beyond + // what we do above for `.await`. + _ => traits::ItemObligation(def_id), + }, + ); (Res::Def(def_kind, def_id), ty) } @@ -1492,12 +1502,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } /// Add all the obligations that are required, substituting and normalized appropriately. - #[tracing::instrument(level = "debug", skip(self, span, def_id, substs))] crate fn add_required_obligations(&self, span: Span, def_id: DefId, substs: &SubstsRef<'tcx>) { + self.add_required_obligations_with_code( + span, + def_id, + substs, + traits::ItemObligation(def_id), + ) + } + + #[tracing::instrument(level = "debug", skip(self, span, def_id, substs))] + fn add_required_obligations_with_code( + &self, + span: Span, + def_id: DefId, + substs: &SubstsRef<'tcx>, + code: ObligationCauseCode<'tcx>, + ) { let (bounds, _) = self.instantiate_bounds(span, def_id, &substs); for obligation in traits::predicates_for_generics( - traits::ObligationCause::new(span, self.body_id, traits::ItemObligation(def_id)), + traits::ObligationCause::new(span, self.body_id, code), self.param_env, bounds, ) { diff --git a/src/test/ui/async-await/async-error-span.stderr b/src/test/ui/async-await/async-error-span.stderr index 2e3f8bb52560a..7d4447b6d5578 100644 --- a/src/test/ui/async-await/async-error-span.stderr +++ b/src/test/ui/async-await/async-error-span.stderr @@ -14,10 +14,10 @@ LL | let a; | ^ cannot infer type | note: the type is part of the `async fn` body because of this `await` - --> $DIR/async-error-span.rs:14:5 + --> $DIR/async-error-span.rs:14:17 | LL | get_future().await; - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/async-await/async-fn-nonsend.stderr b/src/test/ui/async-await/async-fn-nonsend.stderr index bf7ab148e23df..bff282085735c 100644 --- a/src/test/ui/async-await/async-fn-nonsend.stderr +++ b/src/test/ui/async-await/async-fn-nonsend.stderr @@ -6,13 +6,13 @@ LL | assert_send(local_dropped_before_await()); | = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` note: future is not `Send` as this value is used across an await - --> $DIR/async-fn-nonsend.rs:24:5 + --> $DIR/async-fn-nonsend.rs:24:10 | LL | let x = non_send(); | - has type `impl Debug` which is not `Send` LL | drop(x); LL | fut().await; - | ^^^^^^^^^^^ await occurs here, with `x` maybe used later + | ^^^^^^ await occurs here, with `x` maybe used later LL | } | - `x` is later dropped here note: required by a bound in `assert_send` @@ -29,12 +29,12 @@ LL | assert_send(non_send_temporary_in_match()); | = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` note: future is not `Send` as this value is used across an await - --> $DIR/async-fn-nonsend.rs:33:20 + --> $DIR/async-fn-nonsend.rs:33:25 | LL | match Some(non_send()) { | ---------- has type `impl Debug` which is not `Send` LL | Some(_) => fut().await, - | ^^^^^^^^^^^ await occurs here, with `non_send()` maybe used later + | ^^^^^^ await occurs here, with `non_send()` maybe used later ... LL | } | - `non_send()` is later dropped here @@ -52,13 +52,13 @@ LL | assert_send(non_sync_with_method_call()); | = help: the trait `Send` is not implemented for `dyn std::fmt::Write` note: future is not `Send` as this value is used across an await - --> $DIR/async-fn-nonsend.rs:42:9 + --> $DIR/async-fn-nonsend.rs:42:14 | LL | let f: &mut std::fmt::Formatter = panic!(); | - has type `&mut Formatter<'_>` which is not `Send` LL | if non_sync().fmt(f).unwrap() == () { LL | fut().await; - | ^^^^^^^^^^^ await occurs here, with `f` maybe used later + | ^^^^^^ await occurs here, with `f` maybe used later LL | } LL | } | - `f` is later dropped here diff --git a/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr b/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr index 52615df6008ff..27f4b0dac618b 100644 --- a/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr +++ b/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr @@ -162,52 +162,52 @@ LL | let _ = (await bar())?; | ^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:71:13 + --> $DIR/incorrect-syntax-suggestions.rs:71:19 | LL | fn foo13() -> Result<(), ()> { | ----- this is not `async` LL | let _ = bar().await(); - | ^^^^^^^^^^^ 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:76:13 + --> $DIR/incorrect-syntax-suggestions.rs:76:19 | LL | fn foo14() -> Result<(), ()> { | ----- this is not `async` LL | let _ = bar().await()?; - | ^^^^^^^^^^^ 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:81:13 + --> $DIR/incorrect-syntax-suggestions.rs:81:19 | LL | fn foo15() -> Result<(), ()> { | ----- this is not `async` LL | let _ = bar().await; - | ^^^^^^^^^^^ 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:85:13 + --> $DIR/incorrect-syntax-suggestions.rs:85:19 | LL | fn foo16() -> Result<(), ()> { | ----- this is not `async` LL | let _ = bar().await?; - | ^^^^^^^^^^^ 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:90:17 + --> $DIR/incorrect-syntax-suggestions.rs:90:23 | LL | fn foo() -> Result<(), ()> { | --- this is not `async` LL | let _ = bar().await?; - | ^^^^^^^^^^^ 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:97:17 + --> $DIR/incorrect-syntax-suggestions.rs:97:23 | LL | let foo = || { | -- this is not `async` LL | let _ = bar().await?; - | ^^^^^^^^^^^ 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:113:17 diff --git a/src/test/ui/async-await/issue-64130-1-sync.stderr b/src/test/ui/async-await/issue-64130-1-sync.stderr index 010611fae4381..e205de4738f24 100644 --- a/src/test/ui/async-await/issue-64130-1-sync.stderr +++ b/src/test/ui/async-await/issue-64130-1-sync.stderr @@ -6,12 +6,12 @@ LL | is_sync(bar()); | = help: within `impl Future`, the trait `Sync` is not implemented for `Foo` note: future is not `Sync` as this value is used across an await - --> $DIR/issue-64130-1-sync.rs:15:5 + --> $DIR/issue-64130-1-sync.rs:15:10 | LL | let x = Foo; | - has type `Foo` which is not `Sync` LL | baz().await; - | ^^^^^^^^^^^ await occurs here, with `x` maybe used later + | ^^^^^^ await occurs here, with `x` maybe used later LL | } | - `x` is later dropped here note: required by a bound in `is_sync` diff --git a/src/test/ui/async-await/issue-64130-2-send.stderr b/src/test/ui/async-await/issue-64130-2-send.stderr index bb598b53594e9..2225000e2e579 100644 --- a/src/test/ui/async-await/issue-64130-2-send.stderr +++ b/src/test/ui/async-await/issue-64130-2-send.stderr @@ -6,12 +6,12 @@ LL | is_send(bar()); | = help: within `impl Future`, the trait `Send` is not implemented for `Foo` note: future is not `Send` as this value is used across an await - --> $DIR/issue-64130-2-send.rs:15:5 + --> $DIR/issue-64130-2-send.rs:15:10 | LL | let x = Foo; | - has type `Foo` which is not `Send` LL | baz().await; - | ^^^^^^^^^^^ await occurs here, with `x` maybe used later + | ^^^^^^ await occurs here, with `x` maybe used later LL | } | - `x` is later dropped here note: required by a bound in `is_send` diff --git a/src/test/ui/async-await/issue-64130-3-other.stderr b/src/test/ui/async-await/issue-64130-3-other.stderr index 4de7929e18149..17867a6a3f62e 100644 --- a/src/test/ui/async-await/issue-64130-3-other.stderr +++ b/src/test/ui/async-await/issue-64130-3-other.stderr @@ -8,12 +8,12 @@ LL | is_qux(bar()); | ^^^^^ within `impl Future`, the trait `Qux` is not implemented for `Foo` | note: future does not implement `Qux` as this value is used across an await - --> $DIR/issue-64130-3-other.rs:18:5 + --> $DIR/issue-64130-3-other.rs:18:10 | LL | let x = Foo; | - has type `Foo` which does not implement `Qux` LL | baz().await; - | ^^^^^^^^^^^ await occurs here, with `x` maybe used later + | ^^^^^^ await occurs here, with `x` maybe used later LL | } | - `x` is later dropped here note: required by a bound in `is_qux` diff --git a/src/test/ui/async-await/issue-64130-4-async-move.stderr b/src/test/ui/async-await/issue-64130-4-async-move.stderr index 2d46dfb7269d1..d631e6dc7f7e9 100644 --- a/src/test/ui/async-await/issue-64130-4-async-move.stderr +++ b/src/test/ui/async-await/issue-64130-4-async-move.stderr @@ -6,13 +6,13 @@ LL | pub fn foo() -> impl Future + Send { | = help: the trait `Sync` is not implemented for `(dyn Any + Send + 'static)` note: future is not `Send` as this value is used across an await - --> $DIR/issue-64130-4-async-move.rs:21:26 + --> $DIR/issue-64130-4-async-move.rs:21:31 | LL | match client.status() { | ------ has type `&Client` which is not `Send` LL | 200 => { LL | let _x = get().await; - | ^^^^^^^^^^^ await occurs here, with `client` maybe used later + | ^^^^^^ await occurs here, with `client` maybe used later ... LL | } | - `client` is later dropped here diff --git a/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr b/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr index 8eedb3597330e..1da80d98bf8fc 100644 --- a/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr +++ b/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr @@ -6,12 +6,12 @@ LL | is_send(foo()); | = help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, u32>` note: future is not `Send` as this value is used across an await - --> $DIR/issue-64130-non-send-future-diags.rs:17:5 + --> $DIR/issue-64130-non-send-future-diags.rs:17:10 | LL | let g = x.lock().unwrap(); | - has type `MutexGuard<'_, u32>` which is not `Send` LL | baz().await; - | ^^^^^^^^^^^ await occurs here, with `g` maybe used later + | ^^^^^^ await occurs here, with `g` maybe used later LL | } | - `g` is later dropped here note: required by a bound in `is_send` diff --git a/src/test/ui/async-await/issue-67252-unnamed-future.stderr b/src/test/ui/async-await/issue-67252-unnamed-future.stderr index b61694ad53e5b..f32e074d75d62 100644 --- a/src/test/ui/async-await/issue-67252-unnamed-future.stderr +++ b/src/test/ui/async-await/issue-67252-unnamed-future.stderr @@ -6,12 +6,12 @@ LL | spawn(async { | = help: within `impl Future`, the trait `Send` is not implemented for `*mut ()` note: future is not `Send` as this value is used across an await - --> $DIR/issue-67252-unnamed-future.rs:20:9 + --> $DIR/issue-67252-unnamed-future.rs:20:16 | LL | let _a = std::ptr::null_mut::<()>(); // `*mut ()` is not `Send` | -- has type `*mut ()` which is not `Send` LL | AFuture.await; - | ^^^^^^^^^^^^^ await occurs here, with `_a` maybe used later + | ^^^^^^ await occurs here, with `_a` maybe used later LL | }); | - `_a` is later dropped here note: required by a bound in `spawn` diff --git a/src/test/ui/async-await/issue-70594.rs b/src/test/ui/async-await/issue-70594.rs index 9e7c5847b3b2e..bfed4b0b05c6e 100644 --- a/src/test/ui/async-await/issue-70594.rs +++ b/src/test/ui/async-await/issue-70594.rs @@ -6,6 +6,7 @@ async fn fun() { //~| error: `.await` is not allowed in a `const` //~| error: `.await` is not allowed in a `const` //~| error: `()` is not a future + //~| error: `()` is not a future } fn main() {} diff --git a/src/test/ui/async-await/issue-70594.stderr b/src/test/ui/async-await/issue-70594.stderr index ab05251526b0d..a2d4257577e32 100644 --- a/src/test/ui/async-await/issue-70594.stderr +++ b/src/test/ui/async-await/issue-70594.stderr @@ -1,34 +1,48 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/issue-70594.rs:4:9 + --> $DIR/issue-70594.rs:4:12 | LL | async fn fun() { | --- this is not `async` LL | [1; ().await]; - | ^^^^^^^^ only allowed inside `async` functions and blocks + | ^^^^^ only allowed inside `async` functions and blocks error[E0744]: `.await` is not allowed in a `const` - --> $DIR/issue-70594.rs:4:9 + --> $DIR/issue-70594.rs:4:12 | LL | [1; ().await]; - | ^^^^^^^^ + | ^^^^^ error[E0744]: `.await` is not allowed in a `const` - --> $DIR/issue-70594.rs:4:9 + --> $DIR/issue-70594.rs:4:11 | LL | [1; ().await]; - | ^^^^^^^^ + | ^^^^^^ error[E0277]: `()` is not a future - --> $DIR/issue-70594.rs:4:9 + --> $DIR/issue-70594.rs:4:12 | LL | [1; ().await]; - | ^^^^^^^^ `()` is not a future + | ^^^^^ `()` is not a future | = help: the trait `Future` is not implemented for `()` = note: () must be a future or must implement `IntoFuture` to be awaited = note: required because of the requirements on the impl of `IntoFuture` for `()` -error: aborting due to 4 previous errors +error[E0277]: `()` is not a future + --> $DIR/issue-70594.rs:4:11 + | +LL | [1; ().await]; + | ^^^^^^ `()` is not a future + | + = help: the trait `Future` is not implemented for `()` + = note: () must be a future or must implement `IntoFuture` to be awaited +help: do not `.await` the expression + | +LL - [1; ().await]; +LL + [1; ()]; + | + +error: aborting due to 5 previous errors Some errors have detailed explanations: E0277, E0728, E0744. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/async-await/issue-70935-complex-spans.stderr b/src/test/ui/async-await/issue-70935-complex-spans.stderr index 8451fb840992c..4929aa29d0f40 100644 --- a/src/test/ui/async-await/issue-70935-complex-spans.stderr +++ b/src/test/ui/async-await/issue-70935-complex-spans.stderr @@ -6,25 +6,16 @@ LL | fn foo(tx: std::sync::mpsc::Sender) -> impl Future + Send { | = help: the trait `Sync` is not implemented for `Sender` note: future is not `Send` as this value is used across an await - --> $DIR/issue-70935-complex-spans.rs:13:9 - | -LL | / baz(|| async{ -LL | | foo(tx.clone()); -LL | | }).await; - | |________________^ first, await occurs here, with the value maybe used later... -note: the value is later dropped here - --> $DIR/issue-70935-complex-spans.rs:15:17 - | -LL | }).await; - | ^ -note: this has type `[closure@$DIR/issue-70935-complex-spans.rs:13:13: 15:10]` which is not `Send` - --> $DIR/issue-70935-complex-spans.rs:13:13 + --> $DIR/issue-70935-complex-spans.rs:15:11 | LL | baz(|| async{ - | _____________^ + | _____________- LL | | foo(tx.clone()); LL | | }).await; - | |_________^ + | | - ^^^^^^- the value is later dropped here + | | | | + | |_________| await occurs here, with the value maybe used later + | has type `[closure@$DIR/issue-70935-complex-spans.rs:13:13: 15:10]` which is not `Send` error: aborting due to previous error diff --git a/src/test/ui/async-await/issue-71137.stderr b/src/test/ui/async-await/issue-71137.stderr index dddea12162a0b..eade6aa2d3dcc 100644 --- a/src/test/ui/async-await/issue-71137.stderr +++ b/src/test/ui/async-await/issue-71137.stderr @@ -6,12 +6,12 @@ LL | fake_spawn(wrong_mutex()); | = help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, i32>` note: future is not `Send` as this value is used across an await - --> $DIR/issue-71137.rs:14:5 + --> $DIR/issue-71137.rs:14:25 | LL | let mut guard = m.lock().unwrap(); | --------- has type `MutexGuard<'_, i32>` which is not `Send` LL | (async { "right"; }).await; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ await occurs here, with `mut guard` maybe used later + | ^^^^^^ await occurs here, with `mut guard` maybe used later LL | *guard += 1; LL | } | - `mut guard` is later dropped here diff --git a/src/test/ui/async-await/issues/issue-51719.stderr b/src/test/ui/async-await/issues/issue-51719.stderr index 5b9adb253d968..19cc339ec0a07 100644 --- a/src/test/ui/async-await/issues/issue-51719.stderr +++ b/src/test/ui/async-await/issues/issue-51719.stderr @@ -1,8 +1,8 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/issue-51719.rs:8:19 + --> $DIR/issue-51719.rs:8:25 | LL | let _gen = || foo().await; - | -- ^^^^^^^^^^^ only allowed inside `async` functions and blocks + | -- ^^^^^ only allowed inside `async` functions and blocks | | | this is not `async` diff --git a/src/test/ui/async-await/issues/issue-51751.stderr b/src/test/ui/async-await/issues/issue-51751.stderr index f120bd119c540..6dd3726608ba8 100644 --- a/src/test/ui/async-await/issues/issue-51751.stderr +++ b/src/test/ui/async-await/issues/issue-51751.stderr @@ -1,11 +1,11 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/issue-51751.rs:9:20 + --> $DIR/issue-51751.rs:9:27 | LL | fn main() { | ---- this is not `async` LL | let result = inc(10000); LL | let finished = result.await; - | ^^^^^^^^^^^^ only allowed inside `async` functions and blocks + | ^^^^^ only allowed inside `async` functions and blocks error: aborting due to previous error diff --git a/src/test/ui/async-await/issues/issue-62009-1.rs b/src/test/ui/async-await/issues/issue-62009-1.rs index 3ee7ab2e9d12f..71108b4e1d856 100644 --- a/src/test/ui/async-await/issues/issue-62009-1.rs +++ b/src/test/ui/async-await/issues/issue-62009-1.rs @@ -6,10 +6,11 @@ fn main() { async { let (); }.await; //~^ ERROR `await` is only allowed inside `async` functions and blocks async { - //~^ ERROR `await` is only allowed inside `async` functions and blocks let task1 = print_dur().await; }.await; + //~^ ERROR `await` is only allowed inside `async` functions and blocks (|_| 2333).await; //~^ ERROR `await` is only allowed inside `async` functions and blocks - //~^^ ERROR + //~| ERROR is not a future + //~| ERROR is not a future } diff --git a/src/test/ui/async-await/issues/issue-62009-1.stderr b/src/test/ui/async-await/issues/issue-62009-1.stderr index 19d6f9bc43866..c09903e48c602 100644 --- a/src/test/ui/async-await/issues/issue-62009-1.stderr +++ b/src/test/ui/async-await/issues/issue-62009-1.stderr @@ -1,43 +1,54 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/issue-62009-1.rs:6:5 + --> $DIR/issue-62009-1.rs:6:23 | LL | fn main() { | ---- this is not `async` LL | async { let (); }.await; - | ^^^^^^^^^^^^^^^^^^^^^^^ 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/issue-62009-1.rs:8:5 + --> $DIR/issue-62009-1.rs:10:7 | -LL | fn main() { - | ---- this is not `async` +LL | fn main() { + | ---- this is not `async` ... -LL | / async { -LL | | -LL | | let task1 = print_dur().await; -LL | | }.await; - | |___________^ only allowed inside `async` functions and blocks +LL | }.await; + | ^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/issue-62009-1.rs:12:5 + --> $DIR/issue-62009-1.rs:12:16 | LL | fn main() { | ---- this is not `async` ... LL | (|_| 2333).await; - | ^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks + | ^^^^^ only allowed inside `async` functions and blocks error[E0277]: `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]` is not a future - --> $DIR/issue-62009-1.rs:12:5 + --> $DIR/issue-62009-1.rs:12:16 | LL | (|_| 2333).await; - | ^^^^^^^^^^^^^^^^ `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]` is not a future + | ^^^^^ `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]` is not a future | = help: the trait `Future` is not implemented for `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]` = note: [closure@$DIR/issue-62009-1.rs:12:5: 12:15] must be a future or must implement `IntoFuture` to be awaited = note: required because of the requirements on the impl of `IntoFuture` for `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]` -error: aborting due to 4 previous errors +error[E0277]: `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]` is not a future + --> $DIR/issue-62009-1.rs:12:15 + | +LL | (|_| 2333).await; + | ^^^^^^ `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]` is not a future + | + = help: the trait `Future` is not implemented for `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]` + = note: [closure@$DIR/issue-62009-1.rs:12:5: 12:15] must be a future or must implement `IntoFuture` to be awaited +help: do not `.await` the expression + | +LL - (|_| 2333).await; +LL + (|_| 2333); + | + +error: aborting due to 5 previous errors Some errors have detailed explanations: E0277, E0728. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/async-await/issues/issue-62009-2.stderr b/src/test/ui/async-await/issues/issue-62009-2.stderr index 47b74b5574fea..9c2f20df6576f 100644 --- a/src/test/ui/async-await/issues/issue-62009-2.stderr +++ b/src/test/ui/async-await/issues/issue-62009-2.stderr @@ -1,10 +1,10 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/issue-62009-2.rs:8:5 + --> $DIR/issue-62009-2.rs:8:23 | LL | fn main() { | ---- this is not `async` LL | (async || 2333)().await; - | ^^^^^^^^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks + | ^^^^^ only allowed inside `async` functions and blocks error: aborting due to previous error diff --git a/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr index 6ebefbebe5362..cac174061a2b5 100644 --- a/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr +++ b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr @@ -6,16 +6,12 @@ LL | assert_send(async { | = help: within `impl Future`, the trait `Send` is not implemented for `*const u8` note: future is not `Send` as this value is used across an await - --> $DIR/issue-65436-raw-ptr-not-send.rs:14:9 + --> $DIR/issue-65436-raw-ptr-not-send.rs:14:35 | LL | bar(Foo(std::ptr::null())).await; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ first, await occurs here, with `std::ptr::null()` maybe used later... -note: `std::ptr::null()` is later dropped here - --> $DIR/issue-65436-raw-ptr-not-send.rs:14:41 - | -LL | bar(Foo(std::ptr::null())).await; - | ---------------- ^ - | | + | ---------------- ^^^^^^- `std::ptr::null()` is later dropped here + | | | + | | await occurs here, with `std::ptr::null()` maybe used later | has type `*const u8` which is not `Send` help: consider moving this into a `let` binding to create a shorter lived borrow --> $DIR/issue-65436-raw-ptr-not-send.rs:14:13 diff --git a/src/test/ui/async-await/issues/non-async-enclosing-span.stderr b/src/test/ui/async-await/issues/non-async-enclosing-span.stderr index f826a86f08985..b6583022c161a 100644 --- a/src/test/ui/async-await/issues/non-async-enclosing-span.stderr +++ b/src/test/ui/async-await/issues/non-async-enclosing-span.stderr @@ -1,11 +1,11 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/non-async-enclosing-span.rs:9:13 + --> $DIR/non-async-enclosing-span.rs:9:28 | LL | fn main() { | ---- this is not `async` LL | let x = move || {}; LL | let y = do_the_thing().await; - | ^^^^^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks + | ^^^^^ only allowed inside `async` functions and blocks error: aborting due to previous error diff --git a/src/test/ui/async-await/suggest-missing-await.stderr b/src/test/ui/async-await/suggest-missing-await.stderr index 3cca9616a358a..a812840d40b88 100644 --- a/src/test/ui/async-await/suggest-missing-await.stderr +++ b/src/test/ui/async-await/suggest-missing-await.stderr @@ -39,7 +39,7 @@ LL | dummy(); | + error[E0308]: `if` and `else` have incompatible types - --> $DIR/suggest-missing-await.rs:35:9 + --> $DIR/suggest-missing-await.rs:35:17 | LL | let _x = if true { | ______________- @@ -48,7 +48,7 @@ LL | | dummy() LL | | LL | | } else { LL | | dummy().await - | | ^^^^^^^^^^^^^ expected opaque type, found `()` + | | ^^^^^ expected opaque type, found `()` LL | | LL | | }; | |_____- `if` and `else` have incompatible types @@ -61,7 +61,7 @@ LL | dummy().await | ++++++ error[E0308]: `match` arms have incompatible types - --> $DIR/suggest-missing-await.rs:45:14 + --> $DIR/suggest-missing-await.rs:45:22 | LL | let _x = match 0usize { | ______________- @@ -70,7 +70,7 @@ LL | | 0 => dummy(), LL | | 1 => dummy(), | | ------- this is found to be of type `impl Future` LL | | 2 => dummy().await, - | | ^^^^^^^^^^^^^ expected opaque type, found `()` + | | ^^^^^ expected opaque type, found `()` LL | | LL | | }; | |_____- `match` arms have incompatible types diff --git a/src/test/ui/async-await/unresolved_type_param.stderr b/src/test/ui/async-await/unresolved_type_param.stderr index 130667a49c53a..8c0ecb8785d33 100644 --- a/src/test/ui/async-await/unresolved_type_param.stderr +++ b/src/test/ui/async-await/unresolved_type_param.stderr @@ -5,10 +5,10 @@ LL | bar().await; | ^^^ cannot infer type for type parameter `T` declared on the function `bar` | note: the type is part of the `async fn` body because of this `await` - --> $DIR/unresolved_type_param.rs:9:5 + --> $DIR/unresolved_type_param.rs:9:10 | LL | bar().await; - | ^^^^^^^^^^^ + | ^^^^^^ error[E0698]: type inside `async fn` body must be known in this context --> $DIR/unresolved_type_param.rs:9:5 @@ -17,10 +17,10 @@ LL | bar().await; | ^^^ cannot infer type for type parameter `T` declared on the function `bar` | note: the type is part of the `async fn` body because of this `await` - --> $DIR/unresolved_type_param.rs:9:5 + --> $DIR/unresolved_type_param.rs:9:10 | LL | bar().await; - | ^^^^^^^^^^^ + | ^^^^^^ error[E0698]: type inside `async fn` body must be known in this context --> $DIR/unresolved_type_param.rs:9:5 @@ -29,10 +29,10 @@ LL | bar().await; | ^^^ cannot infer type for type parameter `T` declared on the function `bar` | note: the type is part of the `async fn` body because of this `await` - --> $DIR/unresolved_type_param.rs:9:5 + --> $DIR/unresolved_type_param.rs:9:10 | LL | bar().await; - | ^^^^^^^^^^^ + | ^^^^^^ error[E0698]: type inside `async fn` body must be known in this context --> $DIR/unresolved_type_param.rs:9:5 @@ -41,10 +41,10 @@ LL | bar().await; | ^^^ cannot infer type for type parameter `T` declared on the function `bar` | note: the type is part of the `async fn` body because of this `await` - --> $DIR/unresolved_type_param.rs:9:5 + --> $DIR/unresolved_type_param.rs:9:10 | LL | bar().await; - | ^^^^^^^^^^^ + | ^^^^^^ error[E0698]: type inside `async fn` body must be known in this context --> $DIR/unresolved_type_param.rs:9:5 @@ -53,10 +53,10 @@ LL | bar().await; | ^^^ cannot infer type for type parameter `T` declared on the function `bar` | note: the type is part of the `async fn` body because of this `await` - --> $DIR/unresolved_type_param.rs:9:5 + --> $DIR/unresolved_type_param.rs:9:10 | LL | bar().await; - | ^^^^^^^^^^^ + | ^^^^^^ error: aborting due to 5 previous errors diff --git a/src/test/ui/lint/must_not_suspend/boxed.stderr b/src/test/ui/lint/must_not_suspend/boxed.stderr index edc62b6d687ad..b3c9b43810cd9 100644 --- a/src/test/ui/lint/must_not_suspend/boxed.stderr +++ b/src/test/ui/lint/must_not_suspend/boxed.stderr @@ -4,7 +4,7 @@ error: boxed `Umm` held across a suspend point, but should not be LL | let _guard = bar(); | ^^^^^^ LL | other().await; - | ------------- the value is held across this suspend point + | ------ the value is held across this suspend point | note: the lint level is defined here --> $DIR/boxed.rs:3:9 diff --git a/src/test/ui/lint/must_not_suspend/dedup.stderr b/src/test/ui/lint/must_not_suspend/dedup.stderr index 542b7a3bc7e98..bc1b611299a2b 100644 --- a/src/test/ui/lint/must_not_suspend/dedup.stderr +++ b/src/test/ui/lint/must_not_suspend/dedup.stderr @@ -2,7 +2,7 @@ error: `No` held across a suspend point, but should not be --> $DIR/dedup.rs:16:12 | LL | wheeee(No {}).await; - | -------^^^^^------- the value is held across this suspend point + | ^^^^^ ------ the value is held across this suspend point | note: the lint level is defined here --> $DIR/dedup.rs:3:9 diff --git a/src/test/ui/lint/must_not_suspend/gated.stderr b/src/test/ui/lint/must_not_suspend/gated.stderr index be077deb3f197..0d4319670e662 100644 --- a/src/test/ui/lint/must_not_suspend/gated.stderr +++ b/src/test/ui/lint/must_not_suspend/gated.stderr @@ -31,7 +31,7 @@ error: `MutexGuard` held across a suspend point, but should not be LL | let _guard = m.lock().unwrap(); | ^^^^^^ LL | other().await; - | ------------- the value is held across this suspend point + | ------ the value is held across this suspend point | note: the lint level is defined here --> $DIR/gated.rs:2:9 diff --git a/src/test/ui/lint/must_not_suspend/mutex.stderr b/src/test/ui/lint/must_not_suspend/mutex.stderr index dde506c19e725..a968b7ca0330f 100644 --- a/src/test/ui/lint/must_not_suspend/mutex.stderr +++ b/src/test/ui/lint/must_not_suspend/mutex.stderr @@ -4,7 +4,7 @@ error: `MutexGuard` held across a suspend point, but should not be LL | let _guard = m.lock().unwrap(); | ^^^^^^ LL | other().await; - | ------------- the value is held across this suspend point + | ------ the value is held across this suspend point | note: the lint level is defined here --> $DIR/mutex.rs:3:9 diff --git a/src/test/ui/lint/must_not_suspend/ref.stderr b/src/test/ui/lint/must_not_suspend/ref.stderr index 78b44b00625d1..6d30f134ec421 100644 --- a/src/test/ui/lint/must_not_suspend/ref.stderr +++ b/src/test/ui/lint/must_not_suspend/ref.stderr @@ -5,7 +5,7 @@ LL | let guard = &mut self.u; | ^^^^^^ LL | LL | other().await; - | ------------- the value is held across this suspend point + | ------ the value is held across this suspend point | note: the lint level is defined here --> $DIR/ref.rs:3:9 diff --git a/src/test/ui/lint/must_not_suspend/trait.stderr b/src/test/ui/lint/must_not_suspend/trait.stderr index d19ffddd482e0..dd3978b02a852 100644 --- a/src/test/ui/lint/must_not_suspend/trait.stderr +++ b/src/test/ui/lint/must_not_suspend/trait.stderr @@ -5,7 +5,7 @@ LL | let _guard1 = r#impl(); | ^^^^^^^ ... LL | other().await; - | ------------- the value is held across this suspend point + | ------ the value is held across this suspend point | note: the lint level is defined here --> $DIR/trait.rs:3:9 @@ -25,7 +25,7 @@ LL | let _guard2 = r#dyn(); | ^^^^^^^ LL | LL | other().await; - | ------------- the value is held across this suspend point + | ------ the value is held across this suspend point | help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point --> $DIR/trait.rs:22:9 diff --git a/src/test/ui/lint/must_not_suspend/unit.stderr b/src/test/ui/lint/must_not_suspend/unit.stderr index 425c076823d2f..42d037b350b19 100644 --- a/src/test/ui/lint/must_not_suspend/unit.stderr +++ b/src/test/ui/lint/must_not_suspend/unit.stderr @@ -4,7 +4,7 @@ error: `Umm` held across a suspend point, but should not be LL | let _guard = bar(); | ^^^^^^ LL | other().await; - | ------------- the value is held across this suspend point + | ------ the value is held across this suspend point | note: the lint level is defined here --> $DIR/unit.rs:3:9 diff --git a/src/test/ui/lint/must_not_suspend/warn.stderr b/src/test/ui/lint/must_not_suspend/warn.stderr index 42374d4acac27..417c397dad010 100644 --- a/src/test/ui/lint/must_not_suspend/warn.stderr +++ b/src/test/ui/lint/must_not_suspend/warn.stderr @@ -4,7 +4,7 @@ warning: `Umm` held across a suspend point, but should not be LL | let _guard = bar(); | ^^^^^^ LL | other().await; - | ------------- the value is held across this suspend point + | ------ the value is held across this suspend point | note: the lint level is defined here --> $DIR/warn.rs:4:9 From f0026106470c3a2c452ebe91582ab454062be935 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Tue, 16 Nov 2021 01:46:28 +0000 Subject: [PATCH 02/15] Reduce verbosity when calling `for`-loop on non-`Iterator` expression --- compiler/rustc_middle/src/traits/mod.rs | 2 ++ .../src/traits/error_reporting/suggestions.rs | 7 +++++-- compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs | 4 ++-- src/test/ui/issues/issue-33941.stderr | 6 +++--- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 5173d7e2a51dc..ee7e5a1f78eac 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -350,6 +350,8 @@ pub enum ObligationCauseCode<'tcx> { AwaitableExpr, + ForLoopIterator, + /// Well-formed checking. If a `WellFormedLoc` is provided, /// then it will be used to eprform HIR-based wf checking /// after an error occurs, in order to generate a more precise error span. 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 957b8c379a39b..7bc67ca5380a2 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -887,8 +887,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let span = obligation.cause.span; if let ObligationCauseCode::AwaitableExpr = obligation.cause.code { - // FIXME: use `trait_ref.self_ty().no_bound_vars()` to typecheck if `()` and if not - // maybe suggest returning instead? + // FIXME: use `obligation.predicate.kind()...trait_ref.self_ty()` to see if we have `()` + // and if not maybe suggest doing something else? If we kept the expression around we + // could also check if it is an fn call (very likely) and suggest changing *that*, if + // it is from the local crate. err.span_suggestion_verbose( span, "do not `.await` the expression", @@ -1961,6 +1963,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { | ObligationCauseCode::ReturnValue(_) | ObligationCauseCode::BlockTailExpression(_) | ObligationCauseCode::AwaitableExpr + | ObligationCauseCode::ForLoopIterator | ObligationCauseCode::LetElse => {} ObligationCauseCode::SliceOrArrayElem => { err.note("slice and array elements must have `Sized` type"); diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index de713b7de2e5f..50c2c33349104 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -816,8 +816,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &substs, match lang_item { hir::LangItem::FuturePoll => ObligationCauseCode::AwaitableExpr, - // FIXME: see if there are other obligation specializations we could do here beyond - // what we do above for `.await`. + hir::LangItem::IntoIterIntoIter => ObligationCauseCode::ForLoopIterator, + // FIXME: This could also be used for `?`. See if there are others. _ => traits::ItemObligation(def_id), }, ); diff --git a/src/test/ui/issues/issue-33941.stderr b/src/test/ui/issues/issue-33941.stderr index eb98a3a29a698..c6650d60c21e9 100644 --- a/src/test/ui/issues/issue-33941.stderr +++ b/src/test/ui/issues/issue-33941.stderr @@ -16,10 +16,10 @@ error[E0271]: type mismatch resolving ` $DIR/issue-33941.rs:4:14 | LL | for _ in HashMap::new().iter().cloned() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found tuple + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected tuple, found reference | - = note: expected reference `&_` - found tuple `(&_, &_)` + = note: expected tuple `(&_, &_)` + found reference `&_` = note: required because of the requirements on the impl of `Iterator` for `Cloned>` = note: required because of the requirements on the impl of `IntoIterator` for `Cloned>` From f0608fc34f54c0bb9768403d070175791c720ef5 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Tue, 16 Nov 2021 02:17:57 +0000 Subject: [PATCH 03/15] Reduce verbosity for `?` on non-`Try` expressions --- compiler/rustc_middle/src/traits/mod.rs | 2 ++ .../src/traits/error_reporting/suggestions.rs | 1 + .../rustc_typeck/src/check/fn_ctxt/_impl.rs | 2 +- library/core/src/ops/try_trait.rs | 18 ++++-------------- 4 files changed, 8 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index ee7e5a1f78eac..468b6f379decb 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -352,6 +352,8 @@ pub enum ObligationCauseCode<'tcx> { ForLoopIterator, + QuestionMark, + /// Well-formed checking. If a `WellFormedLoc` is provided, /// then it will be used to eprform HIR-based wf checking /// after an error occurs, in order to generate a more precise error span. 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 7bc67ca5380a2..a2730ecc90d11 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1964,6 +1964,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { | ObligationCauseCode::BlockTailExpression(_) | ObligationCauseCode::AwaitableExpr | ObligationCauseCode::ForLoopIterator + | ObligationCauseCode::QuestionMark | ObligationCauseCode::LetElse => {} ObligationCauseCode::SliceOrArrayElem => { err.note("slice and array elements must have `Sized` type"); diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 50c2c33349104..99c9a3fe827ed 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -817,7 +817,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match lang_item { hir::LangItem::FuturePoll => ObligationCauseCode::AwaitableExpr, hir::LangItem::IntoIterIntoIter => ObligationCauseCode::ForLoopIterator, - // FIXME: This could also be used for `?`. See if there are others. + hir::LangItem::TryTraitBranch => ObligationCauseCode::QuestionMark, _ => traits::ItemObligation(def_id), }, ); diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs index f4f0a5898097f..6a414ae8c4b80 100644 --- a/library/core/src/ops/try_trait.rs +++ b/library/core/src/ops/try_trait.rs @@ -115,15 +115,14 @@ use crate::ops::ControlFlow; #[unstable(feature = "try_trait_v2", issue = "84277")] #[rustc_on_unimplemented( on( - all(from_method = "from_output", from_desugaring = "TryBlock"), + all(from_desugaring = "TryBlock"), message = "a `try` block must return `Result` or `Option` \ (or another type that implements `{Try}`)", label = "could not wrap the final value of the block as `{Self}` doesn't implement `Try`", ), on( - all(from_method = "branch", from_desugaring = "QuestionMark"), - message = "the `?` operator can only be applied to values \ - that implement `{Try}`", + all(from_desugaring = "QuestionMark"), + message = "the `?` operator can only be applied to values that implement `{Try}`", label = "the `?` operator cannot be applied to type `{Self}`" ) )] @@ -226,7 +225,6 @@ pub trait Try: FromResidual { #[rustc_on_unimplemented( on( all( - from_method = "from_residual", from_desugaring = "QuestionMark", _Self = "std::result::Result", R = "std::option::Option" @@ -238,7 +236,6 @@ pub trait Try: FromResidual { ), on( all( - from_method = "from_residual", from_desugaring = "QuestionMark", _Self = "std::result::Result", ), @@ -252,7 +249,6 @@ pub trait Try: FromResidual { ), on( all( - from_method = "from_residual", from_desugaring = "QuestionMark", _Self = "std::option::Option", R = "std::result::Result", @@ -264,7 +260,6 @@ pub trait Try: FromResidual { ), on( all( - from_method = "from_residual", from_desugaring = "QuestionMark", _Self = "std::option::Option", ), @@ -277,7 +272,6 @@ pub trait Try: FromResidual { ), on( all( - from_method = "from_residual", from_desugaring = "QuestionMark", _Self = "std::ops::ControlFlow", R = "std::ops::ControlFlow", @@ -290,7 +284,6 @@ pub trait Try: FromResidual { ), on( all( - from_method = "from_residual", from_desugaring = "QuestionMark", _Self = "std::ops::ControlFlow", // `R` is not a `ControlFlow`, as that case was matched previously @@ -301,10 +294,7 @@ pub trait Try: FromResidual { enclosing_scope = "this function returns a `ControlFlow`", ), on( - all( - from_method = "from_residual", - from_desugaring = "QuestionMark" - ), + all(from_desugaring = "QuestionMark"), message = "the `?` operator can only be used in {ItemContext} \ that returns `Result` or `Option` \ (or another type that implements `{FromResidual}`)", From 51d3489e3d7b527a925f84ffbf04e059c208dccf Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Tue, 16 Nov 2021 02:27:18 +0000 Subject: [PATCH 04/15] Further silence `?` errors --- compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 99c9a3fe827ed..a01b6f95c8918 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -817,7 +817,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match lang_item { hir::LangItem::FuturePoll => ObligationCauseCode::AwaitableExpr, hir::LangItem::IntoIterIntoIter => ObligationCauseCode::ForLoopIterator, - hir::LangItem::TryTraitBranch => ObligationCauseCode::QuestionMark, + hir::LangItem::TryTraitFromResidual | hir::LangItem::TryTraitBranch => { + ObligationCauseCode::QuestionMark + } _ => traits::ItemObligation(def_id), }, ); From 335a6e282638429f6e5a04cbb124e21ca1398360 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Tue, 16 Nov 2021 02:50:30 +0000 Subject: [PATCH 05/15] Remove yet more output from `for`-loop and `?` errors --- compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs | 9 +++++---- src/test/ui/issues/issue-33941.stderr | 14 ++++++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index a01b6f95c8918..fb4ced96b2177 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -816,11 +816,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &substs, match lang_item { hir::LangItem::FuturePoll => ObligationCauseCode::AwaitableExpr, - hir::LangItem::IntoIterIntoIter => ObligationCauseCode::ForLoopIterator, - hir::LangItem::TryTraitFromResidual | hir::LangItem::TryTraitBranch => { - ObligationCauseCode::QuestionMark + hir::LangItem::IteratorNext | hir::LangItem::IntoIterIntoIter => { + ObligationCauseCode::ForLoopIterator } - _ => traits::ItemObligation(def_id), + hir::LangItem::TryTraitFromOutput + | hir::LangItem::TryTraitFromResidual + | hir::LangItem::TryTraitBranch => ObligationCauseCode::QuestionMark, }, ); (Res::Def(def_kind, def_id), ty) diff --git a/src/test/ui/issues/issue-33941.stderr b/src/test/ui/issues/issue-33941.stderr index c6650d60c21e9..52341517756ca 100644 --- a/src/test/ui/issues/issue-33941.stderr +++ b/src/test/ui/issues/issue-33941.stderr @@ -23,6 +23,20 @@ LL | for _ in HashMap::new().iter().cloned() {} = note: required because of the requirements on the impl of `Iterator` for `Cloned>` = note: required because of the requirements on the impl of `IntoIterator` for `Cloned>` +<<<<<<< HEAD error: aborting due to 2 previous errors +======= +error[E0271]: type mismatch resolving ` as Iterator>::Item == &_` + --> $DIR/issue-33941.rs:4:14 + | +LL | for _ in HashMap::new().iter().cloned() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected tuple, found reference + | + = note: expected tuple `(&_, &_)` + found reference `&_` + = note: required because of the requirements on the impl of `Iterator` for `Cloned>` + +error: aborting due to 3 previous errors +>>>>>>> 330b90f5fc1 (Remove yet more output from `for`-loop and `?` errors) For more information about this error, try `rustc --explain E0271`. From 26b1f6c678b91cfe976c1281154c551263f13549 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Tue, 16 Nov 2021 03:03:00 +0000 Subject: [PATCH 06/15] Remove unnecessary argument --- compiler/rustc_parse/src/parser/expr.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 791053670ad26..14fadb51b4b07 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1146,7 +1146,7 @@ impl<'a> Parser<'a> { /// Assuming we have just parsed `.`, continue parsing into an expression. fn parse_dot_suffix(&mut self, self_arg: P, lo: Span) -> PResult<'a, P> { if self.token.uninterpolated_span().rust_2018() && self.eat_keyword(kw::Await) { - return Ok(self.mk_await_expr(self_arg, lo)); + return Ok(self.mk_await_expr(self_arg)); } let fn_span_lo = self.token.span; @@ -2831,7 +2831,7 @@ impl<'a> Parser<'a> { ExprKind::Call(f, args) } - fn mk_await_expr(&mut self, self_arg: P, _lo: Span) -> P { + fn mk_await_expr(&mut self, self_arg: P) -> P { let span = self.prev_token.span; let await_expr = self.mk_expr(span, ExprKind::Await(self_arg), AttrVec::new()); self.recover_from_await_method_call(); From fa156c29531a5d42fb590e8c1ec5797f3e09a32e Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Tue, 16 Nov 2021 03:04:36 +0000 Subject: [PATCH 07/15] Fix mistake --- compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index fb4ced96b2177..f810d8ab478af 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -822,6 +822,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir::LangItem::TryTraitFromOutput | hir::LangItem::TryTraitFromResidual | hir::LangItem::TryTraitBranch => ObligationCauseCode::QuestionMark, + _ => traits::ItemObligation(def_id), }, ); (Res::Def(def_kind, def_id), ty) From 4f5ba7a3c3bb17ef959b679ffb83746ebfa9d93b Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Tue, 16 Nov 2021 20:07:23 +0000 Subject: [PATCH 08/15] Keep info on pre-desugaring expression for better "incorrect `.await`" suggestion Keep the `HirId` of `.await`ed expressions so in the case of a `fn` call on on a sync `fn`, we can suggest maybe turning it into an `async fn`. --- compiler/rustc_ast_lowering/src/expr.rs | 51 +++++++++++++++---- compiler/rustc_ast_lowering/src/lib.rs | 11 ++-- compiler/rustc_hir/src/hir.rs | 14 ++--- compiler/rustc_hir_pretty/src/lib.rs | 2 +- compiler/rustc_lint/src/array_into_iter.rs | 2 +- compiler/rustc_middle/src/traits/mod.rs | 2 +- compiler/rustc_save_analysis/src/sig.rs | 2 +- .../src/traits/error_reporting/suggestions.rs | 38 +++++++++++++- compiler/rustc_typeck/src/astconv/mod.rs | 2 +- compiler/rustc_typeck/src/check/expr.rs | 7 +-- .../rustc_typeck/src/check/fn_ctxt/_impl.rs | 3 +- .../rustc_typeck/src/check/fn_ctxt/checks.rs | 4 +- src/test/ui/async-await/unnecessary-await.rs | 14 +++++ .../ui/async-await/unnecessary-await.stderr | 22 ++++++++ 14 files changed, 138 insertions(+), 36 deletions(-) create mode 100644 src/test/ui/async-await/unnecessary-await.rs create mode 100644 src/test/ui/async-await/unnecessary-await.stderr diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 2cf0dbaf425b8..16fdd714575d4 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -479,8 +479,12 @@ impl<'hir> LoweringContext<'_, 'hir> { expr: &'hir hir::Expr<'hir>, overall_span: Span, ) -> &'hir hir::Expr<'hir> { - let constructor = - self.arena.alloc(self.expr_lang_item_path(method_span, lang_item, ThinVec::new())); + let constructor = self.arena.alloc(self.expr_lang_item_path( + method_span, + lang_item, + ThinVec::new(), + None, + )); self.expr_call(overall_span, constructor, std::slice::from_ref(expr)) } @@ -584,8 +588,12 @@ impl<'hir> LoweringContext<'_, 'hir> { // `future::from_generator`: let unstable_span = self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone()); - let gen_future = - self.expr_lang_item_path(unstable_span, hir::LangItem::FromGenerator, ThinVec::new()); + let gen_future = self.expr_lang_item_path( + unstable_span, + hir::LangItem::FromGenerator, + ThinVec::new(), + None, + ); // `future::from_generator(generator)`: hir::ExprKind::Call(self.arena.alloc(gen_future), arena_vec![self; generator]) @@ -657,16 +665,19 @@ impl<'hir> LoweringContext<'_, 'hir> { span, hir::LangItem::PinNewUnchecked, arena_vec![self; ref_mut_pinned], + Some(expr.hir_id), ); let get_context = self.expr_call_lang_item_fn_mut( gen_future_span, hir::LangItem::GetContext, arena_vec![self; task_context], + Some(expr.hir_id), ); let call = self.expr_call_lang_item_fn( span, hir::LangItem::FuturePoll, arena_vec![self; new_unchecked, get_context], + Some(expr.hir_id), ); self.arena.alloc(self.expr_unsafe(call)) }; @@ -679,7 +690,12 @@ impl<'hir> LoweringContext<'_, 'hir> { 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); - let ready_pat = self.pat_lang_item_variant(span, hir::LangItem::PollReady, ready_field); + let ready_pat = self.pat_lang_item_variant( + span, + hir::LangItem::PollReady, + ready_field, + Some(expr.hir_id), + ); 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)); @@ -690,7 +706,12 @@ impl<'hir> LoweringContext<'_, 'hir> { // `::std::task::Poll::Pending => {}` let pending_arm = { - let pending_pat = self.pat_lang_item_variant(span, hir::LangItem::PollPending, &[]); + let pending_pat = self.pat_lang_item_variant( + span, + hir::LangItem::PollPending, + &[], + Some(expr.hir_id), + ); let empty_block = self.expr_block_empty(span); self.arm(pending_pat, empty_block) }; @@ -1161,7 +1182,8 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_expr_range_closed(&mut self, span: Span, e1: &Expr, e2: &Expr) -> hir::ExprKind<'hir> { let e1 = self.lower_expr_mut(e1); let e2 = self.lower_expr_mut(e2); - let fn_path = hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, self.lower_span(span)); + let fn_path = + hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, self.lower_span(span), None); let fn_expr = self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path), ThinVec::new())); hir::ExprKind::Call(fn_expr, arena_vec![self; e1, e2]) @@ -1195,7 +1217,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ); hir::ExprKind::Struct( - self.arena.alloc(hir::QPath::LangItem(lang_item, self.lower_span(span))), + self.arena.alloc(hir::QPath::LangItem(lang_item, self.lower_span(span), None)), fields, None, ) @@ -1390,6 +1412,7 @@ impl<'hir> LoweringContext<'_, 'hir> { head_span, hir::LangItem::IteratorNext, arena_vec![self; ref_mut_iter], + None, ); let arms = arena_vec![self; none_arm, some_arm]; @@ -1418,6 +1441,7 @@ impl<'hir> LoweringContext<'_, 'hir> { head_span, hir::LangItem::IntoIterIntoIter, arena_vec![self; head], + None, ) }; @@ -1473,6 +1497,7 @@ impl<'hir> LoweringContext<'_, 'hir> { unstable_span, hir::LangItem::TryTraitBranch, arena_vec![self; sub_expr], + None, ) }; @@ -1629,8 +1654,10 @@ impl<'hir> LoweringContext<'_, 'hir> { span: Span, lang_item: hir::LangItem, args: &'hir [hir::Expr<'hir>], + hir_id: Option, ) -> hir::Expr<'hir> { - let path = self.arena.alloc(self.expr_lang_item_path(span, lang_item, ThinVec::new())); + let path = + self.arena.alloc(self.expr_lang_item_path(span, lang_item, ThinVec::new(), hir_id)); self.expr_call_mut(span, path, args) } @@ -1639,8 +1666,9 @@ impl<'hir> LoweringContext<'_, 'hir> { span: Span, lang_item: hir::LangItem, args: &'hir [hir::Expr<'hir>], + hir_id: Option, ) -> &'hir hir::Expr<'hir> { - self.arena.alloc(self.expr_call_lang_item_fn_mut(span, lang_item, args)) + self.arena.alloc(self.expr_call_lang_item_fn_mut(span, lang_item, args, hir_id)) } fn expr_lang_item_path( @@ -1648,10 +1676,11 @@ impl<'hir> LoweringContext<'_, 'hir> { span: Span, lang_item: hir::LangItem, attrs: AttrVec, + hir_id: Option, ) -> hir::Expr<'hir> { self.expr( span, - hir::ExprKind::Path(hir::QPath::LangItem(lang_item, self.lower_span(span))), + hir::ExprKind::Path(hir::QPath::LangItem(lang_item, self.lower_span(span), hir_id)), attrs, ) } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index d0fbc2d0f11d4..55a7e07933159 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2140,21 +2140,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn pat_cf_continue(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> { let field = self.single_pat_field(span, pat); - self.pat_lang_item_variant(span, hir::LangItem::ControlFlowContinue, field) + self.pat_lang_item_variant(span, hir::LangItem::ControlFlowContinue, field, None) } fn pat_cf_break(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> { let field = self.single_pat_field(span, pat); - self.pat_lang_item_variant(span, hir::LangItem::ControlFlowBreak, field) + self.pat_lang_item_variant(span, hir::LangItem::ControlFlowBreak, field, None) } fn pat_some(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> { let field = self.single_pat_field(span, pat); - self.pat_lang_item_variant(span, hir::LangItem::OptionSome, field) + self.pat_lang_item_variant(span, hir::LangItem::OptionSome, field, None) } fn pat_none(&mut self, span: Span) -> &'hir hir::Pat<'hir> { - self.pat_lang_item_variant(span, hir::LangItem::OptionNone, &[]) + self.pat_lang_item_variant(span, hir::LangItem::OptionNone, &[], None) } fn single_pat_field( @@ -2177,8 +2177,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: Span, lang_item: hir::LangItem, fields: &'hir [hir::PatField<'hir>], + hir_id: Option, ) -> &'hir hir::Pat<'hir> { - let qpath = hir::QPath::LangItem(lang_item, self.lower_span(span)); + let qpath = hir::QPath::LangItem(lang_item, self.lower_span(span), hir_id); self.pat(span, hir::PatKind::Struct(qpath, fields, false)) } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 487ae87052ba3..44564b58b145c 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1629,13 +1629,13 @@ pub fn is_range_literal(expr: &Expr<'_>) -> bool { | LangItem::RangeFrom | LangItem::RangeFull | LangItem::RangeToInclusive, - _, + .. ) ), // `..=` desugars into `::std::ops::RangeInclusive::new(...)`. ExprKind::Call(ref func, _) => { - matches!(func.kind, ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, _))) + matches!(func.kind, ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, ..))) } _ => false, @@ -1790,8 +1790,8 @@ pub enum QPath<'hir> { /// the `X` and `Y` nodes each being a `TyKind::Path(QPath::TypeRelative(..))`. TypeRelative(&'hir Ty<'hir>, &'hir PathSegment<'hir>), - /// Reference to a `#[lang = "foo"]` item. - LangItem(LangItem, Span), + /// Reference to a `#[lang = "foo"]` item. `HirId` of the inner expr. + LangItem(LangItem, Span, Option), } impl<'hir> QPath<'hir> { @@ -1800,7 +1800,7 @@ impl<'hir> QPath<'hir> { match *self { QPath::Resolved(_, path) => path.span, QPath::TypeRelative(qself, ps) => qself.span.to(ps.ident.span), - QPath::LangItem(_, span) => span, + QPath::LangItem(_, span, _) => span, } } @@ -1810,7 +1810,7 @@ impl<'hir> QPath<'hir> { match *self { QPath::Resolved(_, path) => path.span, QPath::TypeRelative(qself, _) => qself.span, - QPath::LangItem(_, span) => span, + QPath::LangItem(_, span, _) => span, } } @@ -1820,7 +1820,7 @@ impl<'hir> QPath<'hir> { match *self { QPath::Resolved(_, path) => path.segments.last().unwrap().ident.span, QPath::TypeRelative(_, segment) => segment.ident.span, - QPath::LangItem(_, span) => span, + QPath::LangItem(_, span, _) => span, } } } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 4240a4045a1ec..419d28cfa44de 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1733,7 +1733,7 @@ impl<'a> State<'a> { colons_before_params, ) } - hir::QPath::LangItem(lang_item, span) => { + hir::QPath::LangItem(lang_item, span, _) => { self.word("#[lang = \""); self.print_ident(Ident::new(lang_item.name(), span)); self.word("\"]"); diff --git a/compiler/rustc_lint/src/array_into_iter.rs b/compiler/rustc_lint/src/array_into_iter.rs index 4a24f803e8463..b6151757588dd 100644 --- a/compiler/rustc_lint/src/array_into_iter.rs +++ b/compiler/rustc_lint/src/array_into_iter.rs @@ -52,7 +52,7 @@ impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter { if let hir::ExprKind::Call(path, [arg]) = &arg.kind { if let hir::ExprKind::Path(hir::QPath::LangItem( hir::LangItem::IntoIterIntoIter, - _, + .., )) = &path.kind { self.for_expr_span = arg.span; diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 468b6f379decb..f3c4ade3ba8e3 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -348,7 +348,7 @@ pub enum ObligationCauseCode<'tcx> { /// If `X` is the concrete type of an opaque type `impl Y`, then `X` must implement `Y` OpaqueType, - AwaitableExpr, + AwaitableExpr(Option), ForLoopIterator, diff --git a/compiler/rustc_save_analysis/src/sig.rs b/compiler/rustc_save_analysis/src/sig.rs index 7864b47ab0a7f..1d9c44bffa3fc 100644 --- a/compiler/rustc_save_analysis/src/sig.rs +++ b/compiler/rustc_save_analysis/src/sig.rs @@ -286,7 +286,7 @@ impl<'hir> Sig for hir::Ty<'hir> { refs: vec![SigElement { id, start, end }], }) } - hir::TyKind::Path(hir::QPath::LangItem(lang_item, _)) => { + hir::TyKind::Path(hir::QPath::LangItem(lang_item, _, _)) => { Ok(text_sig(format!("#[lang = \"{}\"]", lang_item.name()))) } hir::TyKind::TraitObject(bounds, ..) => { 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 a2730ecc90d11..34fbff62a65bc 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -886,7 +886,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ) { let span = obligation.cause.span; - if let ObligationCauseCode::AwaitableExpr = obligation.cause.code { + if let ObligationCauseCode::AwaitableExpr(hir_id) = obligation.cause.code { // FIXME: use `obligation.predicate.kind()...trait_ref.self_ty()` to see if we have `()` // and if not maybe suggest doing something else? If we kept the expression around we // could also check if it is an fn call (very likely) and suggest changing *that*, if @@ -897,6 +897,40 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { String::new(), Applicability::MachineApplicable, ); + // FIXME: account for associated `async fn`s. + let hir = self.tcx.hir(); + if let Some(node) = hir_id.and_then(|hir_id| hir.find(hir_id)) { + if let hir::Node::Expr(hir::Expr { + span, kind: hir::ExprKind::Call(base, _), .. + }) = node + { + if let ty::PredicateKind::Trait(pred) = + obligation.predicate.kind().skip_binder() + { + err.span_label(*span, &format!("this call returns `{}`", pred.self_ty())); + } + if let Some(typeck_results) = + self.in_progress_typeck_results.map(|t| t.borrow()) + { + let ty = typeck_results.expr_ty_adjusted(base); + if let ty::FnDef(def_id, _substs) = ty.kind() { + if let Some(hir::Node::Item(hir::Item { span, ident, .. })) = + hir.get_if_local(*def_id) + { + err.span_suggestion_verbose( + span.shrink_to_lo(), + &format!( + "alternatively, consider making `fn {}` asynchronous", + ident + ), + "async ".to_string(), + Applicability::MaybeIncorrect, + ); + } + } + } + } + } } } @@ -1962,7 +1996,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { | ObligationCauseCode::ReturnType | ObligationCauseCode::ReturnValue(_) | ObligationCauseCode::BlockTailExpression(_) - | ObligationCauseCode::AwaitableExpr + | ObligationCauseCode::AwaitableExpr(_) | ObligationCauseCode::ForLoopIterator | ObligationCauseCode::QuestionMark | ObligationCauseCode::LetElse => {} diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 08261fedd4a25..1316b454fa88c 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -2355,7 +2355,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .map(|(ty, _, _)| ty) .unwrap_or_else(|_| tcx.ty_error()) } - hir::TyKind::Path(hir::QPath::LangItem(lang_item, span)) => { + hir::TyKind::Path(hir::QPath::LangItem(lang_item, span, _)) => { let def_id = tcx.require_lang_item(lang_item, Some(span)); let (substs, _) = self.create_substs_for_ast_path( span, diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 311106474bea0..bc6ad3c968671 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -277,8 +277,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ExprKind::AddrOf(kind, mutbl, oprnd) => { self.check_expr_addr_of(kind, mutbl, oprnd, expected, expr) } - ExprKind::Path(QPath::LangItem(lang_item, _)) => { - self.check_lang_item_path(lang_item, expr) + ExprKind::Path(QPath::LangItem(lang_item, _, hir_id)) => { + self.check_lang_item_path(lang_item, expr, hir_id) } ExprKind::Path(ref qpath) => self.check_expr_path(qpath, expr, &[]), ExprKind::InlineAsm(asm) => self.check_expr_asm(asm), @@ -498,8 +498,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, lang_item: hir::LangItem, expr: &'tcx hir::Expr<'tcx>, + hir_id: Option, ) -> Ty<'tcx> { - self.resolve_lang_item_path(lang_item, expr.span, expr.hir_id).1 + self.resolve_lang_item_path(lang_item, expr.span, expr.hir_id, hir_id).1 } pub(crate) fn check_expr_path( diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index f810d8ab478af..a101166fff1b4 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -797,6 +797,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { lang_item: hir::LangItem, span: Span, hir_id: hir::HirId, + expr_hir_id: Option, ) -> (Res, Ty<'tcx>) { let def_id = self.tcx.require_lang_item(lang_item, Some(span)); let def_kind = self.tcx.def_kind(def_id); @@ -815,7 +816,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { def_id, &substs, match lang_item { - hir::LangItem::FuturePoll => ObligationCauseCode::AwaitableExpr, + hir::LangItem::FuturePoll => ObligationCauseCode::AwaitableExpr(expr_hir_id), hir::LangItem::IteratorNext | hir::LangItem::IntoIterIntoIter => { ObligationCauseCode::ForLoopIterator } diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index 74d7f0a80b6ca..3220c1bc2249a 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -938,8 +938,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), ty) } - QPath::LangItem(lang_item, span) => { - self.resolve_lang_item_path(lang_item, span, hir_id) + QPath::LangItem(lang_item, span, id) => { + self.resolve_lang_item_path(lang_item, span, hir_id, id) } } } diff --git a/src/test/ui/async-await/unnecessary-await.rs b/src/test/ui/async-await/unnecessary-await.rs new file mode 100644 index 0000000000000..70c38aaeb2511 --- /dev/null +++ b/src/test/ui/async-await/unnecessary-await.rs @@ -0,0 +1,14 @@ +// edition:2018 + +async fn foo () { } +fn bar () -> impl std::future::Future { async {} } +fn boo () {} + +async fn baz() -> std::io::Result<()> { + foo().await; + boo().await; //~ ERROR `()` is not a future + bar().await; + std::io::Result::Ok(()) +} + +fn main() {} \ No newline at end of file diff --git a/src/test/ui/async-await/unnecessary-await.stderr b/src/test/ui/async-await/unnecessary-await.stderr new file mode 100644 index 0000000000000..4caa15e67b7c9 --- /dev/null +++ b/src/test/ui/async-await/unnecessary-await.stderr @@ -0,0 +1,22 @@ +error[E0277]: `()` is not a future + --> $DIR/unnecessary-await.rs:9:10 + | +LL | boo().await; + | -----^^^^^^ `()` is not a future + | | + | this call returns `()` + | + = help: the trait `Future` is not implemented for `()` +help: do not `.await` the expression + | +LL - boo().await; +LL + boo(); + | +help: alternatively, consider making `fn boo` asynchronous + | +LL | async fn boo () {} + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From fc2298c0052cbfe54c36b775e62772799945096f Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Tue, 16 Nov 2021 20:44:25 +0000 Subject: [PATCH 09/15] Fix clippy uses of QPath::LangItem --- .../clippy/clippy_lints/src/methods/str_splitn.rs | 2 +- .../clippy_lints/src/needless_question_mark.rs | 2 +- src/tools/clippy/clippy_lints/src/strings.rs | 2 +- src/tools/clippy/clippy_lints/src/try_err.rs | 2 +- .../clippy/clippy_lints/src/unused_io_amount.rs | 2 +- src/tools/clippy/clippy_lints/src/utils/author.rs | 2 +- src/tools/clippy/clippy_utils/src/higher.rs | 12 ++++++------ src/tools/clippy/clippy_utils/src/hir_utils.rs | 2 +- 8 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs index 2595f734f1151..e5fafdb075c66 100644 --- a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs +++ b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs @@ -204,7 +204,7 @@ fn parse_iter_usage( match e.kind { ExprKind::Call( Expr { - kind: ExprKind::Path(QPath::LangItem(LangItem::TryTraitBranch, _)), + kind: ExprKind::Path(QPath::LangItem(LangItem::TryTraitBranch, ..)), .. }, _, diff --git a/src/tools/clippy/clippy_lints/src/needless_question_mark.rs b/src/tools/clippy/clippy_lints/src/needless_question_mark.rs index 1ffed6a052499..0e7ae43ce2dd5 100644 --- a/src/tools/clippy/clippy_lints/src/needless_question_mark.rs +++ b/src/tools/clippy/clippy_lints/src/needless_question_mark.rs @@ -105,7 +105,7 @@ fn check(cx: &LateContext<'_>, expr: &Expr<'_>) { }; if let ExprKind::Match(inner_expr_with_q, _, MatchSource::TryDesugar) = &arg.kind; if let ExprKind::Call(called, [inner_expr]) = &inner_expr_with_q.kind; - if let ExprKind::Path(QPath::LangItem(LangItem::TryTraitBranch, _)) = &called.kind; + if let ExprKind::Path(QPath::LangItem(LangItem::TryTraitBranch, ..)) = &called.kind; if expr.span.ctxt() == inner_expr.span.ctxt(); let expr_ty = cx.typeck_results().expr_ty(expr); let inner_ty = cx.typeck_results().expr_ty(inner_expr); diff --git a/src/tools/clippy/clippy_lints/src/strings.rs b/src/tools/clippy/clippy_lints/src/strings.rs index 368274440d5dc..c2163a24b7f44 100644 --- a/src/tools/clippy/clippy_lints/src/strings.rs +++ b/src/tools/clippy/clippy_lints/src/strings.rs @@ -260,7 +260,7 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes { if method_names[0] == sym!(as_bytes); // Check for slicer - if let ExprKind::Struct(QPath::LangItem(LangItem::Range, _), _, _) = right.kind; + if let ExprKind::Struct(QPath::LangItem(LangItem::Range, ..), _, _) = right.kind; then { let mut applicability = Applicability::MachineApplicable; diff --git a/src/tools/clippy/clippy_lints/src/try_err.rs b/src/tools/clippy/clippy_lints/src/try_err.rs index e0e7ec9a452c1..4da32c52e750a 100644 --- a/src/tools/clippy/clippy_lints/src/try_err.rs +++ b/src/tools/clippy/clippy_lints/src/try_err.rs @@ -65,7 +65,7 @@ impl<'tcx> LateLintPass<'tcx> for TryErr { if let ExprKind::Match(match_arg, _, MatchSource::TryDesugar) = expr.kind; if let ExprKind::Call(match_fun, try_args) = match_arg.kind; if let ExprKind::Path(ref match_fun_path) = match_fun.kind; - if matches!(match_fun_path, QPath::LangItem(LangItem::TryTraitBranch, _)); + if matches!(match_fun_path, QPath::LangItem(LangItem::TryTraitBranch, ..)); if let Some(try_arg) = try_args.get(0); if let ExprKind::Call(err_fun, err_args) = try_arg.kind; if let Some(err_arg) = err_args.get(0); diff --git a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs index d4b5c9770a271..111413e51930b 100644 --- a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs +++ b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs @@ -49,7 +49,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedIoAmount { if let hir::ExprKind::Call(func, [ref arg_0, ..]) = res.kind { if matches!( func.kind, - hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::TryTraitBranch, _)) + hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::TryTraitBranch, ..)) ) { check_map_error(cx, arg_0, expr); } diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index d20bf3413185c..f186e1f05a0b4 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -260,7 +260,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { } fn qpath(&self, qpath: &Binding<&QPath<'_>>) { - if let QPath::LangItem(lang_item, _) = *qpath.value { + if let QPath::LangItem(lang_item, ..) = *qpath.value { out!("if matches!({qpath}, QPath::LangItem(LangItem::{lang_item:?}, _));"); } else { out!("if match_qpath({qpath}, &[{}]);", path_to_string(qpath.value)); diff --git a/src/tools/clippy/clippy_utils/src/higher.rs b/src/tools/clippy/clippy_utils/src/higher.rs index 7297265d08cfb..fc32e49420e4b 100644 --- a/src/tools/clippy/clippy_utils/src/higher.rs +++ b/src/tools/clippy/clippy_utils/src/higher.rs @@ -218,7 +218,7 @@ impl<'a> Range<'a> { hir::ExprKind::Call(path, args) if matches!( path.kind, - hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, _)) + hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, ..)) ) => { Some(Range { @@ -228,27 +228,27 @@ impl<'a> Range<'a> { }) }, hir::ExprKind::Struct(path, fields, None) => match &path { - hir::QPath::LangItem(hir::LangItem::RangeFull, _) => Some(Range { + hir::QPath::LangItem(hir::LangItem::RangeFull, ..) => Some(Range { start: None, end: None, limits: ast::RangeLimits::HalfOpen, }), - hir::QPath::LangItem(hir::LangItem::RangeFrom, _) => Some(Range { + hir::QPath::LangItem(hir::LangItem::RangeFrom, ..) => Some(Range { start: Some(get_field("start", fields)?), end: None, limits: ast::RangeLimits::HalfOpen, }), - hir::QPath::LangItem(hir::LangItem::Range, _) => Some(Range { + hir::QPath::LangItem(hir::LangItem::Range, ..) => Some(Range { start: Some(get_field("start", fields)?), end: Some(get_field("end", fields)?), limits: ast::RangeLimits::HalfOpen, }), - hir::QPath::LangItem(hir::LangItem::RangeToInclusive, _) => Some(Range { + hir::QPath::LangItem(hir::LangItem::RangeToInclusive, ..) => Some(Range { start: None, end: Some(get_field("end", fields)?), limits: ast::RangeLimits::Closed, }), - hir::QPath::LangItem(hir::LangItem::RangeTo, _) => Some(Range { + hir::QPath::LangItem(hir::LangItem::RangeTo, ..) => Some(Range { start: None, end: Some(get_field("end", fields)?), limits: ast::RangeLimits::HalfOpen, diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 7438b6eabf9e6..5b059e3788699 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -346,7 +346,7 @@ impl HirEqInterExpr<'_, '_, '_> { (&QPath::TypeRelative(lty, lseg), &QPath::TypeRelative(rty, rseg)) => { self.eq_ty(lty, rty) && self.eq_path_segment(lseg, rseg) }, - (&QPath::LangItem(llang_item, _), &QPath::LangItem(rlang_item, _)) => llang_item == rlang_item, + (&QPath::LangItem(llang_item, ..), &QPath::LangItem(rlang_item, ..)) => llang_item == rlang_item, _ => false, } } From a3cdbc4d91a8fda28c29f171ebf70ff1b522c871 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Tue, 16 Nov 2021 22:06:25 +0000 Subject: [PATCH 10/15] Fix rebase and clippy tests --- compiler/rustc_ast_lowering/src/expr.rs | 24 ++++-- compiler/rustc_parse/src/parser/expr.rs | 6 +- compiler/rustc_passes/src/region.rs | 11 ++- .../src/traits/error_reporting/suggestions.rs | 78 ++++++++++--------- .../rustc_typeck/src/check/fn_ctxt/_impl.rs | 4 +- .../incorrect-syntax-suggestions.stderr | 32 ++++---- src/test/ui/async-await/issue-70594.rs | 1 - src/test/ui/async-await/issue-70594.stderr | 21 ++--- .../ui/async-await/issues/issue-51719.stderr | 4 +- .../ui/async-await/issues/issue-51751.stderr | 4 +- .../ui/async-await/issues/issue-62009-1.rs | 1 - .../async-await/issues/issue-62009-1.stderr | 25 ++---- .../async-await/issues/issue-62009-2.stderr | 4 +- .../issues/non-async-enclosing-span.stderr | 4 +- .../async-await/suggest-missing-await.stderr | 8 +- .../ui/async-await/unnecessary-await.stderr | 2 + src/test/ui/issues/issue-33941.stderr | 14 ---- .../clippy_lints/src/needless_late_init.rs | 11 ++- .../tests/ui/needless_late_init_fixable.fixed | 38 --------- .../tests/ui/needless_late_init_fixable.rs | 2 - .../ui/needless_late_init_fixable.stderr | 26 ++++--- 21 files changed, 136 insertions(+), 184 deletions(-) delete mode 100644 src/tools/clippy/tests/ui/needless_late_init_fixable.fixed diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 16fdd714575d4..75a45a437e77e 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -130,7 +130,15 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::AsyncGeneratorKind::Block, |this| this.with_new_scopes(|this| this.lower_block_expr(block)), ), - ExprKind::Await(ref expr) => self.lower_expr_await(e.span, expr), + ExprKind::Await(ref expr) => { + let span = if expr.span.hi() < e.span.hi() { + expr.span.shrink_to_hi().with_hi(e.span.hi()) + } else { + // this is a recovered `await expr` + e.span + }; + self.lower_expr_await(span, expr) + } ExprKind::Closure( capture_clause, asyncness, @@ -639,6 +647,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self.allow_gen_future.clone(), ); let expr = self.lower_expr_mut(expr); + let expr_hir_id = expr.hir_id; let pinned_ident = Ident::with_dummy_span(sym::pinned); let (pinned_pat, pinned_pat_hid) = @@ -665,19 +674,19 @@ impl<'hir> LoweringContext<'_, 'hir> { span, hir::LangItem::PinNewUnchecked, arena_vec![self; ref_mut_pinned], - Some(expr.hir_id), + Some(expr_hir_id), ); let get_context = self.expr_call_lang_item_fn_mut( gen_future_span, hir::LangItem::GetContext, arena_vec![self; task_context], - Some(expr.hir_id), + Some(expr_hir_id), ); let call = self.expr_call_lang_item_fn( span, hir::LangItem::FuturePoll, arena_vec![self; new_unchecked, get_context], - Some(expr.hir_id), + Some(expr_hir_id), ); self.arena.alloc(self.expr_unsafe(call)) }; @@ -694,7 +703,7 @@ impl<'hir> LoweringContext<'_, 'hir> { span, hir::LangItem::PollReady, ready_field, - Some(expr.hir_id), + Some(expr_hir_id), ); let break_x = self.with_loop_scope(loop_node_id, move |this| { let expr_break = @@ -710,7 +719,7 @@ impl<'hir> LoweringContext<'_, 'hir> { span, hir::LangItem::PollPending, &[], - Some(expr.hir_id), + Some(expr_hir_id), ); let empty_block = self.expr_block_empty(span); self.arm(pending_pat, empty_block) @@ -731,7 +740,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let unit = self.expr_unit(span); let yield_expr = self.expr( span, - hir::ExprKind::Yield(unit, hir::YieldSource::Await { expr: Some(expr.hir_id) }), + hir::ExprKind::Yield(unit, hir::YieldSource::Await { expr: Some(expr_hir_id) }), ThinVec::new(), ); let yield_expr = self.arena.alloc(yield_expr); @@ -778,6 +787,7 @@ impl<'hir> LoweringContext<'_, 'hir> { into_future_span, hir::LangItem::IntoFutureIntoFuture, arena_vec![self; expr], + Some(expr_hir_id), ); // match { diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 14fadb51b4b07..1dbd7bad0f023 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1146,7 +1146,7 @@ impl<'a> Parser<'a> { /// Assuming we have just parsed `.`, continue parsing into an expression. fn parse_dot_suffix(&mut self, self_arg: P, lo: Span) -> PResult<'a, P> { if self.token.uninterpolated_span().rust_2018() && self.eat_keyword(kw::Await) { - return Ok(self.mk_await_expr(self_arg)); + return Ok(self.mk_await_expr(self_arg, lo)); } let fn_span_lo = self.token.span; @@ -2831,8 +2831,8 @@ impl<'a> Parser<'a> { ExprKind::Call(f, args) } - fn mk_await_expr(&mut self, self_arg: P) -> P { - let span = self.prev_token.span; + fn mk_await_expr(&mut self, self_arg: P, lo: Span) -> P { + let span = lo.to(self.prev_token.span); let await_expr = self.mk_expr(span, ExprKind::Await(self_arg), AttrVec::new()); self.recover_from_await_method_call(); await_expr diff --git a/compiler/rustc_passes/src/region.rs b/compiler/rustc_passes/src/region.rs index ae423070392e1..8968c163987dc 100644 --- a/compiler/rustc_passes/src/region.rs +++ b/compiler/rustc_passes/src/region.rs @@ -421,11 +421,14 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h // Mark this expr's scope and all parent scopes as containing `yield`. let mut scope = Scope { id: expr.hir_id.local_id, data: ScopeData::Node }; loop { - let data = YieldData { - span: expr.span, - expr_and_pat_count: visitor.expr_and_pat_count, - source: *source, + let span = match expr.kind { + hir::ExprKind::Yield(expr, hir::YieldSource::Await { .. }) => { + expr.span.shrink_to_hi().to(expr.span) + } + _ => expr.span, }; + let data = + YieldData { span, expr_and_pat_count: visitor.expr_and_pat_count, source: *source }; visitor.scope_tree.yield_in_scope.insert(scope, data); if visitor.pessimistic_yield { debug!("resolve_expr in pessimistic_yield - marking scope {:?} for fixup", scope); 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 34fbff62a65bc..67c0b88d7aad4 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -886,46 +886,48 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ) { let span = obligation.cause.span; - if let ObligationCauseCode::AwaitableExpr(hir_id) = obligation.cause.code { - // FIXME: use `obligation.predicate.kind()...trait_ref.self_ty()` to see if we have `()` - // and if not maybe suggest doing something else? If we kept the expression around we - // could also check if it is an fn call (very likely) and suggest changing *that*, if - // it is from the local crate. - err.span_suggestion_verbose( - span, - "do not `.await` the expression", - String::new(), - Applicability::MachineApplicable, - ); - // FIXME: account for associated `async fn`s. + if let ObligationCauseCode::AwaitableExpr(hir_id) = obligation.cause.code.peel_derives() { let hir = self.tcx.hir(); if let Some(node) = hir_id.and_then(|hir_id| hir.find(hir_id)) { - if let hir::Node::Expr(hir::Expr { - span, kind: hir::ExprKind::Call(base, _), .. - }) = node - { - if let ty::PredicateKind::Trait(pred) = - obligation.predicate.kind().skip_binder() - { - err.span_label(*span, &format!("this call returns `{}`", pred.self_ty())); - } - if let Some(typeck_results) = - self.in_progress_typeck_results.map(|t| t.borrow()) - { - let ty = typeck_results.expr_ty_adjusted(base); - if let ty::FnDef(def_id, _substs) = ty.kind() { - if let Some(hir::Node::Item(hir::Item { span, ident, .. })) = - hir.get_if_local(*def_id) - { - err.span_suggestion_verbose( - span.shrink_to_lo(), - &format!( - "alternatively, consider making `fn {}` asynchronous", - ident - ), - "async ".to_string(), - Applicability::MaybeIncorrect, - ); + if let hir::Node::Expr(expr) = node { + // FIXME: use `obligation.predicate.kind()...trait_ref.self_ty()` to see if we have `()` + // and if not maybe suggest doing something else? If we kept the expression around we + // could also check if it is an fn call (very likely) and suggest changing *that*, if + // it is from the local crate. + err.span_suggestion_verbose( + expr.span.shrink_to_hi().with_hi(span.hi()), + "do not `.await` the expression", + String::new(), + Applicability::MachineApplicable, + ); + // FIXME: account for associated `async fn`s. + if let hir::Expr { span, kind: hir::ExprKind::Call(base, _), .. } = expr { + if let ty::PredicateKind::Trait(pred) = + obligation.predicate.kind().skip_binder() + { + err.span_label( + *span, + &format!("this call returns `{}`", pred.self_ty()), + ); + } + if let Some(typeck_results) = + self.in_progress_typeck_results.map(|t| t.borrow()) + { + let ty = typeck_results.expr_ty_adjusted(base); + if let ty::FnDef(def_id, _substs) = ty.kind() { + if let Some(hir::Node::Item(hir::Item { span, ident, .. })) = + hir.get_if_local(*def_id) + { + err.span_suggestion_verbose( + span.shrink_to_lo(), + &format!( + "alternatively, consider making `fn {}` asynchronous", + ident + ), + "async ".to_string(), + Applicability::MaybeIncorrect, + ); + } } } } diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index a101166fff1b4..b4507c5857b69 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -816,7 +816,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { def_id, &substs, match lang_item { - hir::LangItem::FuturePoll => ObligationCauseCode::AwaitableExpr(expr_hir_id), + hir::LangItem::IntoFutureIntoFuture => { + ObligationCauseCode::AwaitableExpr(expr_hir_id) + } hir::LangItem::IteratorNext | hir::LangItem::IntoIterIntoIter => { ObligationCauseCode::ForLoopIterator } diff --git a/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr b/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr index 27f4b0dac618b..b4323c314badc 100644 --- a/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr +++ b/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr @@ -162,68 +162,68 @@ LL | let _ = (await bar())?; | ^^^^^^^^^^^ 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:18 | LL | fn foo13() -> Result<(), ()> { | ----- this is not `async` LL | let _ = bar().await(); - | ^^^^^ 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:76:19 + --> $DIR/incorrect-syntax-suggestions.rs:76:18 | LL | fn foo14() -> Result<(), ()> { | ----- this is not `async` LL | let _ = bar().await()?; - | ^^^^^ 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:81:19 + --> $DIR/incorrect-syntax-suggestions.rs:81:18 | LL | fn foo15() -> Result<(), ()> { | ----- this is not `async` LL | let _ = bar().await; - | ^^^^^ 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:85:19 + --> $DIR/incorrect-syntax-suggestions.rs:85:18 | LL | fn foo16() -> Result<(), ()> { | ----- this is not `async` LL | let _ = bar().await?; - | ^^^^^ 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:90:23 + --> $DIR/incorrect-syntax-suggestions.rs:90:22 | LL | fn foo() -> Result<(), ()> { | --- this is not `async` LL | let _ = bar().await?; - | ^^^^^ 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:97:23 + --> $DIR/incorrect-syntax-suggestions.rs:97:22 | LL | let foo = || { | -- this is not `async` LL | let _ = bar().await?; - | ^^^^^ 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:113:17 + --> $DIR/incorrect-syntax-suggestions.rs:113:29 | 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 + --> $DIR/incorrect-syntax-suggestions.rs:121:29 | 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/src/test/ui/async-await/issue-70594.rs b/src/test/ui/async-await/issue-70594.rs index bfed4b0b05c6e..9e7c5847b3b2e 100644 --- a/src/test/ui/async-await/issue-70594.rs +++ b/src/test/ui/async-await/issue-70594.rs @@ -6,7 +6,6 @@ async fn fun() { //~| error: `.await` is not allowed in a `const` //~| error: `.await` is not allowed in a `const` //~| error: `()` is not a future - //~| error: `()` is not a future } fn main() {} diff --git a/src/test/ui/async-await/issue-70594.stderr b/src/test/ui/async-await/issue-70594.stderr index a2d4257577e32..405709286822a 100644 --- a/src/test/ui/async-await/issue-70594.stderr +++ b/src/test/ui/async-await/issue-70594.stderr @@ -1,16 +1,16 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/issue-70594.rs:4:12 + --> $DIR/issue-70594.rs:4:11 | LL | async fn fun() { | --- this is not `async` LL | [1; ().await]; - | ^^^^^ only allowed inside `async` functions and blocks + | ^^^^^^ only allowed inside `async` functions and blocks error[E0744]: `.await` is not allowed in a `const` - --> $DIR/issue-70594.rs:4:12 + --> $DIR/issue-70594.rs:4:9 | LL | [1; ().await]; - | ^^^^^ + | ^^^^^^^^ error[E0744]: `.await` is not allowed in a `const` --> $DIR/issue-70594.rs:4:11 @@ -18,16 +18,6 @@ error[E0744]: `.await` is not allowed in a `const` LL | [1; ().await]; | ^^^^^^ -error[E0277]: `()` is not a future - --> $DIR/issue-70594.rs:4:12 - | -LL | [1; ().await]; - | ^^^^^ `()` is not a future - | - = help: the trait `Future` is not implemented for `()` - = note: () must be a future or must implement `IntoFuture` to be awaited - = note: required because of the requirements on the impl of `IntoFuture` for `()` - error[E0277]: `()` is not a future --> $DIR/issue-70594.rs:4:11 | @@ -36,13 +26,14 @@ LL | [1; ().await]; | = help: the trait `Future` is not implemented for `()` = note: () must be a future or must implement `IntoFuture` to be awaited + = note: required because of the requirements on the impl of `IntoFuture` for `()` help: do not `.await` the expression | LL - [1; ().await]; LL + [1; ()]; | -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0277, E0728, E0744. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/async-await/issues/issue-51719.stderr b/src/test/ui/async-await/issues/issue-51719.stderr index 19cc339ec0a07..f3ce5d1c897c3 100644 --- a/src/test/ui/async-await/issues/issue-51719.stderr +++ b/src/test/ui/async-await/issues/issue-51719.stderr @@ -1,8 +1,8 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/issue-51719.rs:8:25 + --> $DIR/issue-51719.rs:8:24 | LL | let _gen = || foo().await; - | -- ^^^^^ only allowed inside `async` functions and blocks + | -- ^^^^^^ only allowed inside `async` functions and blocks | | | this is not `async` diff --git a/src/test/ui/async-await/issues/issue-51751.stderr b/src/test/ui/async-await/issues/issue-51751.stderr index 6dd3726608ba8..8696a5b798b3c 100644 --- a/src/test/ui/async-await/issues/issue-51751.stderr +++ b/src/test/ui/async-await/issues/issue-51751.stderr @@ -1,11 +1,11 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/issue-51751.rs:9:27 + --> $DIR/issue-51751.rs:9:26 | LL | fn main() { | ---- this is not `async` LL | let result = inc(10000); LL | let finished = result.await; - | ^^^^^ only allowed inside `async` functions and blocks + | ^^^^^^ only allowed inside `async` functions and blocks error: aborting due to previous error diff --git a/src/test/ui/async-await/issues/issue-62009-1.rs b/src/test/ui/async-await/issues/issue-62009-1.rs index 71108b4e1d856..40ccf25712e2b 100644 --- a/src/test/ui/async-await/issues/issue-62009-1.rs +++ b/src/test/ui/async-await/issues/issue-62009-1.rs @@ -12,5 +12,4 @@ fn main() { (|_| 2333).await; //~^ ERROR `await` is only allowed inside `async` functions and blocks //~| ERROR is not a future - //~| ERROR is not a future } diff --git a/src/test/ui/async-await/issues/issue-62009-1.stderr b/src/test/ui/async-await/issues/issue-62009-1.stderr index c09903e48c602..3ea5dac76d4c5 100644 --- a/src/test/ui/async-await/issues/issue-62009-1.stderr +++ b/src/test/ui/async-await/issues/issue-62009-1.stderr @@ -1,38 +1,28 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/issue-62009-1.rs:6:23 + --> $DIR/issue-62009-1.rs:6:22 | LL | fn main() { | ---- this is not `async` LL | async { let (); }.await; - | ^^^^^ 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/issue-62009-1.rs:10:7 + --> $DIR/issue-62009-1.rs:10:6 | LL | fn main() { | ---- this is not `async` ... LL | }.await; - | ^^^^^ 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/issue-62009-1.rs:12:16 + --> $DIR/issue-62009-1.rs:12:15 | LL | fn main() { | ---- this is not `async` ... LL | (|_| 2333).await; - | ^^^^^ only allowed inside `async` functions and blocks - -error[E0277]: `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]` is not a future - --> $DIR/issue-62009-1.rs:12:16 - | -LL | (|_| 2333).await; - | ^^^^^ `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]` is not a future - | - = help: the trait `Future` is not implemented for `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]` - = note: [closure@$DIR/issue-62009-1.rs:12:5: 12:15] must be a future or must implement `IntoFuture` to be awaited - = note: required because of the requirements on the impl of `IntoFuture` for `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]` + | ^^^^^^ only allowed inside `async` functions and blocks error[E0277]: `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]` is not a future --> $DIR/issue-62009-1.rs:12:15 @@ -42,13 +32,14 @@ LL | (|_| 2333).await; | = help: the trait `Future` is not implemented for `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]` = note: [closure@$DIR/issue-62009-1.rs:12:5: 12:15] must be a future or must implement `IntoFuture` to be awaited + = note: required because of the requirements on the impl of `IntoFuture` for `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]` help: do not `.await` the expression | LL - (|_| 2333).await; LL + (|_| 2333); | -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0277, E0728. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/async-await/issues/issue-62009-2.stderr b/src/test/ui/async-await/issues/issue-62009-2.stderr index 9c2f20df6576f..92e9a8a69a88b 100644 --- a/src/test/ui/async-await/issues/issue-62009-2.stderr +++ b/src/test/ui/async-await/issues/issue-62009-2.stderr @@ -1,10 +1,10 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/issue-62009-2.rs:8:23 + --> $DIR/issue-62009-2.rs:8:22 | LL | fn main() { | ---- this is not `async` LL | (async || 2333)().await; - | ^^^^^ only allowed inside `async` functions and blocks + | ^^^^^^ only allowed inside `async` functions and blocks error: aborting due to previous error diff --git a/src/test/ui/async-await/issues/non-async-enclosing-span.stderr b/src/test/ui/async-await/issues/non-async-enclosing-span.stderr index b6583022c161a..20b827479fa80 100644 --- a/src/test/ui/async-await/issues/non-async-enclosing-span.stderr +++ b/src/test/ui/async-await/issues/non-async-enclosing-span.stderr @@ -1,11 +1,11 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/non-async-enclosing-span.rs:9:28 + --> $DIR/non-async-enclosing-span.rs:9:27 | LL | fn main() { | ---- this is not `async` LL | let x = move || {}; LL | let y = do_the_thing().await; - | ^^^^^ only allowed inside `async` functions and blocks + | ^^^^^^ only allowed inside `async` functions and blocks error: aborting due to previous error diff --git a/src/test/ui/async-await/suggest-missing-await.stderr b/src/test/ui/async-await/suggest-missing-await.stderr index a812840d40b88..3cca9616a358a 100644 --- a/src/test/ui/async-await/suggest-missing-await.stderr +++ b/src/test/ui/async-await/suggest-missing-await.stderr @@ -39,7 +39,7 @@ LL | dummy(); | + error[E0308]: `if` and `else` have incompatible types - --> $DIR/suggest-missing-await.rs:35:17 + --> $DIR/suggest-missing-await.rs:35:9 | LL | let _x = if true { | ______________- @@ -48,7 +48,7 @@ LL | | dummy() LL | | LL | | } else { LL | | dummy().await - | | ^^^^^ expected opaque type, found `()` + | | ^^^^^^^^^^^^^ expected opaque type, found `()` LL | | LL | | }; | |_____- `if` and `else` have incompatible types @@ -61,7 +61,7 @@ LL | dummy().await | ++++++ error[E0308]: `match` arms have incompatible types - --> $DIR/suggest-missing-await.rs:45:22 + --> $DIR/suggest-missing-await.rs:45:14 | LL | let _x = match 0usize { | ______________- @@ -70,7 +70,7 @@ LL | | 0 => dummy(), LL | | 1 => dummy(), | | ------- this is found to be of type `impl Future` LL | | 2 => dummy().await, - | | ^^^^^ expected opaque type, found `()` + | | ^^^^^^^^^^^^^ expected opaque type, found `()` LL | | LL | | }; | |_____- `match` arms have incompatible types diff --git a/src/test/ui/async-await/unnecessary-await.stderr b/src/test/ui/async-await/unnecessary-await.stderr index 4caa15e67b7c9..fc22ebc5972bc 100644 --- a/src/test/ui/async-await/unnecessary-await.stderr +++ b/src/test/ui/async-await/unnecessary-await.stderr @@ -7,6 +7,8 @@ LL | boo().await; | this call returns `()` | = help: the trait `Future` is not implemented for `()` + = note: () must be a future or must implement `IntoFuture` to be awaited + = note: required because of the requirements on the impl of `IntoFuture` for `()` help: do not `.await` the expression | LL - boo().await; diff --git a/src/test/ui/issues/issue-33941.stderr b/src/test/ui/issues/issue-33941.stderr index 52341517756ca..c6650d60c21e9 100644 --- a/src/test/ui/issues/issue-33941.stderr +++ b/src/test/ui/issues/issue-33941.stderr @@ -23,20 +23,6 @@ LL | for _ in HashMap::new().iter().cloned() {} = note: required because of the requirements on the impl of `Iterator` for `Cloned>` = note: required because of the requirements on the impl of `IntoIterator` for `Cloned>` -<<<<<<< HEAD error: aborting due to 2 previous errors -======= -error[E0271]: type mismatch resolving ` as Iterator>::Item == &_` - --> $DIR/issue-33941.rs:4:14 - | -LL | for _ in HashMap::new().iter().cloned() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected tuple, found reference - | - = note: expected tuple `(&_, &_)` - found reference `&_` - = note: required because of the requirements on the impl of `Iterator` for `Cloned>` - -error: aborting due to 3 previous errors ->>>>>>> 330b90f5fc1 (Remove yet more output from `for`-loop and `?` errors) For more information about this error, try `rustc --explain E0271`. diff --git a/src/tools/clippy/clippy_lints/src/needless_late_init.rs b/src/tools/clippy/clippy_lints/src/needless_late_init.rs index e0522f3fe0b1a..5b098659377c6 100644 --- a/src/tools/clippy/clippy_lints/src/needless_late_init.rs +++ b/src/tools/clippy/clippy_lints/src/needless_late_init.rs @@ -73,7 +73,7 @@ fn contains_assign_expr<'tcx>(cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'tcx>) -> seen } -#[derive(Debug)] +#[derive(Debug, Clone)] struct LocalAssign { lhs_id: HirId, lhs_span: Span, @@ -154,9 +154,14 @@ fn assignment_suggestions<'tcx>( assignments.push(assign); } - let suggestions = assignments + let suggestions = assignments.clone() .into_iter() - .map(|assignment| Some((assignment.span, snippet_opt(cx, assignment.rhs_span)?))) + .map(|assignment| Some((assignment.span.until(assignment.rhs_span), String::new()))) + .chain( + assignments + .into_iter() + .map(|assignment| Some((assignment.rhs_span.shrink_to_hi().with_hi(assignment.span.hi()), String::new()))) + ) .collect::>>()?; let applicability = if suggestions.len() > 1 { diff --git a/src/tools/clippy/tests/ui/needless_late_init_fixable.fixed b/src/tools/clippy/tests/ui/needless_late_init_fixable.fixed deleted file mode 100644 index 32d5d04fde4d5..0000000000000 --- a/src/tools/clippy/tests/ui/needless_late_init_fixable.fixed +++ /dev/null @@ -1,38 +0,0 @@ -// run-rustfix - -#![allow(unused, clippy::assign_op_pattern)] - -fn main() { - - let a = "zero"; - - - - let b = 1; - let c = 2; - - - let d: usize = 1; - - - let mut e = 1; - e = 2; - - - let f = match 1 { - 1 => "three", - _ => return, - }; // has semi - - - let g: usize = if true { - 5 - } else { - panic!(); - }; - - - let h = format!("{}", e); - - println!("{}", a); -} diff --git a/src/tools/clippy/tests/ui/needless_late_init_fixable.rs b/src/tools/clippy/tests/ui/needless_late_init_fixable.rs index 6bc85f686325d..76099df0e0689 100644 --- a/src/tools/clippy/tests/ui/needless_late_init_fixable.rs +++ b/src/tools/clippy/tests/ui/needless_late_init_fixable.rs @@ -1,5 +1,3 @@ -// run-rustfix - #![allow(unused, clippy::assign_op_pattern)] fn main() { diff --git a/src/tools/clippy/tests/ui/needless_late_init_fixable.stderr b/src/tools/clippy/tests/ui/needless_late_init_fixable.stderr index a0ce4f812f4e5..728e19252ea70 100644 --- a/src/tools/clippy/tests/ui/needless_late_init_fixable.stderr +++ b/src/tools/clippy/tests/ui/needless_late_init_fixable.stderr @@ -1,5 +1,5 @@ error: unneeded late initalization - --> $DIR/needless_late_init_fixable.rs:6:5 + --> $DIR/needless_late_init_fixable.rs:4:5 | LL | let a; | ^^^^^^ @@ -11,7 +11,7 @@ LL | let a = "zero"; | ~~~~~ error: unneeded late initalization - --> $DIR/needless_late_init_fixable.rs:9:5 + --> $DIR/needless_late_init_fixable.rs:7:5 | LL | let b; | ^^^^^^ @@ -22,7 +22,7 @@ LL | let b = 1; | ~~~~~ error: unneeded late initalization - --> $DIR/needless_late_init_fixable.rs:10:5 + --> $DIR/needless_late_init_fixable.rs:8:5 | LL | let c; | ^^^^^^ @@ -33,7 +33,7 @@ LL | let c = 2; | ~~~~~ error: unneeded late initalization - --> $DIR/needless_late_init_fixable.rs:14:5 + --> $DIR/needless_late_init_fixable.rs:12:5 | LL | let d: usize; | ^^^^^^^^^^^^^ @@ -44,7 +44,7 @@ LL | let d: usize = 1; | ~~~~~~~~~~~~ error: unneeded late initalization - --> $DIR/needless_late_init_fixable.rs:17:5 + --> $DIR/needless_late_init_fixable.rs:15:5 | LL | let mut e; | ^^^^^^^^^^ @@ -55,7 +55,7 @@ LL | let mut e = 1; | ~~~~~~~~~ error: unneeded late initalization - --> $DIR/needless_late_init_fixable.rs:21:5 + --> $DIR/needless_late_init_fixable.rs:19:5 | LL | let f; | ^^^^^^ @@ -66,11 +66,12 @@ LL | let f = match 1 { | +++++++ help: remove the assignments from the `match` arms | -LL | 1 => "three", - | ~~~~~~~ +LL - 1 => f = "three", +LL + 1 => "three", + | error: unneeded late initalization - --> $DIR/needless_late_init_fixable.rs:27:5 + --> $DIR/needless_late_init_fixable.rs:25:5 | LL | let g: usize; | ^^^^^^^^^^^^^ @@ -81,15 +82,16 @@ LL | let g: usize = if true { | ++++++++++++++ help: remove the assignments from the branches | -LL | 5 - | +LL - g = 5; +LL + 5 + | help: add a semicolon after the `if` expression | LL | }; | + error: unneeded late initalization - --> $DIR/needless_late_init_fixable.rs:34:5 + --> $DIR/needless_late_init_fixable.rs:32:5 | LL | let h; | ^^^^^^ From 4884d8ef45ca035e2b36507d8998785231e7fb8c Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Tue, 16 Nov 2021 23:04:15 +0000 Subject: [PATCH 11/15] tidy fix --- src/test/ui/async-await/unnecessary-await.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/async-await/unnecessary-await.rs b/src/test/ui/async-await/unnecessary-await.rs index 70c38aaeb2511..b994dc82e4d54 100644 --- a/src/test/ui/async-await/unnecessary-await.rs +++ b/src/test/ui/async-await/unnecessary-await.rs @@ -11,4 +11,4 @@ async fn baz() -> std::io::Result<()> { std::io::Result::Ok(()) } -fn main() {} \ No newline at end of file +fn main() {} From d94eaa5f40e08dbe91332523b0a9c78304670bd3 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Wed, 17 Nov 2021 17:33:15 +0000 Subject: [PATCH 12/15] Simplify diagnostic logic The spans no longer overlap, so we no longer need to specialize the output depending on whether they would. --- .../src/traits/error_reporting/suggestions.rs | 167 +++++------------- 1 file changed, 44 insertions(+), 123 deletions(-) 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 67c0b88d7aad4..f7f8a267130f8 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1717,130 +1717,51 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { format!("does not implement `{}`", trait_ref.print_only_trait_path()) }; - let mut explain_yield = - |interior_span: Span, yield_span: Span, scope_span: Option| { - let mut span = MultiSpan::from_span(yield_span); - if let Ok(snippet) = source_map.span_to_snippet(interior_span) { - // #70935: If snippet contains newlines, display "the value" instead - // so that we do not emit complex diagnostics. - let snippet = &format!("`{}`", snippet); - let snippet = if snippet.contains('\n') { "the value" } else { snippet }; - // The multispan can be complex here, like: - // note: future is not `Send` as this value is used across an await - // --> $DIR/issue-70935-complex-spans.rs:13:9 - // | - // LL | baz(|| async{ - // | __________^___- - // | | _________| - // | || - // LL | || foo(tx.clone()); - // LL | || }).await; - // | || - ^- value is later dropped here - // | ||_________|______| - // | |__________| await occurs here, with value maybe used later - // | has type `closure` which is not `Send` - // - // So, detect it and separate into some notes, like: - // - // note: future is not `Send` as this value is used across an await - // --> $DIR/issue-70935-complex-spans.rs:13:9 - // | - // LL | / baz(|| async{ - // LL | | foo(tx.clone()); - // LL | | }).await; - // | |________________^ first, await occurs here, with the value maybe used later... - // note: the value is later dropped here - // --> $DIR/issue-70935-complex-spans.rs:15:17 - // | - // LL | }).await; - // | ^ - // - // If available, use the scope span to annotate the drop location. - if let Some(scope_span) = scope_span { - let scope_span = source_map.end_point(scope_span); - let is_overlapped = - yield_span.overlaps(scope_span) || yield_span.overlaps(interior_span); - if is_overlapped { - span.push_span_label( - yield_span, - format!( - "first, {} occurs here, with {} maybe used later...", - await_or_yield, snippet - ), - ); - err.span_note( - span, - &format!( - "{} {} as this value is used across {}", - future_or_generator, trait_explanation, an_await_or_yield - ), - ); - if source_map.is_multiline(interior_span) { - err.span_note( - scope_span, - &format!("{} is later dropped here", snippet), - ); - err.span_note( - interior_span, - &format!( - "this has type `{}` which {}", - target_ty, trait_explanation - ), - ); - } else { - let mut span = MultiSpan::from_span(scope_span); - span.push_span_label( - interior_span, - format!("has type `{}` which {}", target_ty, trait_explanation), - ); - err.span_note(span, &format!("{} is later dropped here", snippet)); - } - } else { - span.push_span_label( - yield_span, - format!( - "{} occurs here, with {} maybe used later", - await_or_yield, snippet - ), - ); - span.push_span_label( - scope_span, - format!("{} is later dropped here", snippet), - ); - span.push_span_label( - interior_span, - format!("has type `{}` which {}", target_ty, trait_explanation), - ); - err.span_note( - span, - &format!( - "{} {} as this value is used across {}", - future_or_generator, trait_explanation, an_await_or_yield - ), - ); - } - } else { - span.push_span_label( - yield_span, - format!( - "{} occurs here, with {} maybe used later", - await_or_yield, snippet - ), - ); - span.push_span_label( - interior_span, - format!("has type `{}` which {}", target_ty, trait_explanation), - ); - err.span_note( - span, - &format!( - "{} {} as this value is used across {}", - future_or_generator, trait_explanation, an_await_or_yield - ), - ); - } + let mut explain_yield = |interior_span: Span, + yield_span: Span, + scope_span: Option| { + let mut span = MultiSpan::from_span(yield_span); + if let Ok(snippet) = source_map.span_to_snippet(interior_span) { + // #70935: If snippet contains newlines, display "the value" instead + // so that we do not emit complex diagnostics. + let snippet = &format!("`{}`", snippet); + let snippet = if snippet.contains('\n') { "the value" } else { snippet }; + // note: future is not `Send` as this value is used across an await + // --> $DIR/issue-70935-complex-spans.rs:13:9 + // | + // LL | baz(|| async { + // | ______________- + // | | + // | | + // LL | | foo(tx.clone()); + // LL | | }).await; + // | | - ^^^^^^- value is later dropped here + // | | | | + // | |__________| await occurs here, with value maybe used later + // | has type `closure` which is not `Send` + // + // If available, use the scope span to annotate the drop location. + if let Some(scope_span) = scope_span { + let scope_span = source_map.end_point(scope_span); + span.push_span_label(scope_span, format!("{} is later dropped here", snippet)); } - }; + span.push_span_label( + yield_span, + format!("{} occurs here, with {} maybe used later", await_or_yield, snippet), + ); + span.push_span_label( + interior_span, + format!("has type `{}` which {}", target_ty, trait_explanation), + ); + err.span_note( + span, + &format!( + "{} {} as this value is used across {}", + future_or_generator, trait_explanation, an_await_or_yield + ), + ); + } + }; match interior_or_upvar_span { GeneratorInteriorOrUpvar::Interior(interior_span) => { if let Some((scope_span, yield_span, expr, from_awaited_ty)) = interior_extra_info { From df5439cf08cc1ce11ec4068dd772cd072870d807 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Thu, 2 Dec 2021 23:41:45 +0000 Subject: [PATCH 13/15] review comments --- .../src/traits/error_reporting/suggestions.rs | 28 +++++++++++++------ .../issue-70935-complex-spans.stderr | 10 +++++-- .../issue-65436-raw-ptr-not-send.stderr | 10 +++++-- src/test/ui/async-await/unnecessary-await.rs | 4 +-- .../ui/async-await/unnecessary-await.stderr | 2 +- 5 files changed, 37 insertions(+), 17 deletions(-) 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 f7f8a267130f8..1a00b2f3cf713 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1735,16 +1735,13 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { // | | // LL | | foo(tx.clone()); // LL | | }).await; - // | | - ^^^^^^- value is later dropped here - // | | | | - // | |__________| await occurs here, with value maybe used later + // | | - ^^^^^^ await occurs here, with value maybe used later + // | |__________| // | has type `closure` which is not `Send` + // note: value is later dropped here + // LL | | }).await; + // | | ^ // - // If available, use the scope span to annotate the drop location. - if let Some(scope_span) = scope_span { - let scope_span = source_map.end_point(scope_span); - span.push_span_label(scope_span, format!("{} is later dropped here", snippet)); - } span.push_span_label( yield_span, format!("{} occurs here, with {} maybe used later", await_or_yield, snippet), @@ -1753,6 +1750,18 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { interior_span, format!("has type `{}` which {}", target_ty, trait_explanation), ); + // If available, use the scope span to annotate the drop location. + let mut scope_note = None; + if let Some(scope_span) = scope_span { + let scope_span = source_map.end_point(scope_span); + + let msg = format!("{} is later dropped here", snippet); + if source_map.is_multiline(yield_span.between(scope_span)) { + span.push_span_label(scope_span, msg); + } else { + scope_note = Some((scope_span, msg)); + } + } err.span_note( span, &format!( @@ -1760,6 +1769,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { future_or_generator, trait_explanation, an_await_or_yield ), ); + if let Some((span, msg)) = scope_note { + err.span_note(span, &msg); + } } }; match interior_or_upvar_span { diff --git a/src/test/ui/async-await/issue-70935-complex-spans.stderr b/src/test/ui/async-await/issue-70935-complex-spans.stderr index 4929aa29d0f40..db3099381196b 100644 --- a/src/test/ui/async-await/issue-70935-complex-spans.stderr +++ b/src/test/ui/async-await/issue-70935-complex-spans.stderr @@ -12,10 +12,14 @@ LL | baz(|| async{ | _____________- LL | | foo(tx.clone()); LL | | }).await; - | | - ^^^^^^- the value is later dropped here - | | | | - | |_________| await occurs here, with the value maybe used later + | | - ^^^^^^ await occurs here, with the value maybe used later + | |_________| | has type `[closure@$DIR/issue-70935-complex-spans.rs:13:13: 15:10]` which is not `Send` +note: the value is later dropped here + --> $DIR/issue-70935-complex-spans.rs:15:17 + | +LL | }).await; + | ^ error: aborting due to previous error diff --git a/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr index cac174061a2b5..b4d2006480390 100644 --- a/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr +++ b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr @@ -9,10 +9,14 @@ note: future is not `Send` as this value is used across an await --> $DIR/issue-65436-raw-ptr-not-send.rs:14:35 | LL | bar(Foo(std::ptr::null())).await; - | ---------------- ^^^^^^- `std::ptr::null()` is later dropped here - | | | - | | await occurs here, with `std::ptr::null()` maybe used later + | ---------------- ^^^^^^ await occurs here, with `std::ptr::null()` maybe used later + | | | has type `*const u8` which is not `Send` +note: `std::ptr::null()` is later dropped here + --> $DIR/issue-65436-raw-ptr-not-send.rs:14:41 + | +LL | bar(Foo(std::ptr::null())).await; + | ^ help: consider moving this into a `let` binding to create a shorter lived borrow --> $DIR/issue-65436-raw-ptr-not-send.rs:14:13 | diff --git a/src/test/ui/async-await/unnecessary-await.rs b/src/test/ui/async-await/unnecessary-await.rs index b994dc82e4d54..24673777b8039 100644 --- a/src/test/ui/async-await/unnecessary-await.rs +++ b/src/test/ui/async-await/unnecessary-await.rs @@ -1,8 +1,8 @@ // edition:2018 async fn foo () { } -fn bar () -> impl std::future::Future { async {} } -fn boo () {} +fn bar() -> impl std::future::Future { async {} } +fn boo() {} async fn baz() -> std::io::Result<()> { foo().await; diff --git a/src/test/ui/async-await/unnecessary-await.stderr b/src/test/ui/async-await/unnecessary-await.stderr index fc22ebc5972bc..23dea2d3a0c74 100644 --- a/src/test/ui/async-await/unnecessary-await.stderr +++ b/src/test/ui/async-await/unnecessary-await.stderr @@ -16,7 +16,7 @@ LL + boo(); | help: alternatively, consider making `fn boo` asynchronous | -LL | async fn boo () {} +LL | async fn boo() {} | +++++ error: aborting due to previous error From a310dfb4e304c74456501438dc4f68eb64df583e Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Fri, 10 Dec 2021 03:01:37 +0000 Subject: [PATCH 14/15] review comment: change wording of suggestion --- .../src/traits/error_reporting/suggestions.rs | 2 +- src/test/ui/async-await/issue-70594.stderr | 2 +- src/test/ui/async-await/issues/issue-62009-1.stderr | 2 +- src/test/ui/async-await/unnecessary-await.stderr | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) 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 1a00b2f3cf713..d1b436ceb8542 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -896,7 +896,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { // it is from the local crate. err.span_suggestion_verbose( expr.span.shrink_to_hi().with_hi(span.hi()), - "do not `.await` the expression", + "remove the `.await`", String::new(), Applicability::MachineApplicable, ); diff --git a/src/test/ui/async-await/issue-70594.stderr b/src/test/ui/async-await/issue-70594.stderr index 405709286822a..a159edd51187f 100644 --- a/src/test/ui/async-await/issue-70594.stderr +++ b/src/test/ui/async-await/issue-70594.stderr @@ -27,7 +27,7 @@ LL | [1; ().await]; = help: the trait `Future` is not implemented for `()` = note: () must be a future or must implement `IntoFuture` to be awaited = note: required because of the requirements on the impl of `IntoFuture` for `()` -help: do not `.await` the expression +help: remove the `.await` | LL - [1; ().await]; LL + [1; ()]; diff --git a/src/test/ui/async-await/issues/issue-62009-1.stderr b/src/test/ui/async-await/issues/issue-62009-1.stderr index 3ea5dac76d4c5..3d80c34942c1b 100644 --- a/src/test/ui/async-await/issues/issue-62009-1.stderr +++ b/src/test/ui/async-await/issues/issue-62009-1.stderr @@ -33,7 +33,7 @@ LL | (|_| 2333).await; = help: the trait `Future` is not implemented for `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]` = note: [closure@$DIR/issue-62009-1.rs:12:5: 12:15] must be a future or must implement `IntoFuture` to be awaited = note: required because of the requirements on the impl of `IntoFuture` for `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]` -help: do not `.await` the expression +help: remove the `.await` | LL - (|_| 2333).await; LL + (|_| 2333); diff --git a/src/test/ui/async-await/unnecessary-await.stderr b/src/test/ui/async-await/unnecessary-await.stderr index 23dea2d3a0c74..c3d2a6e7b1e1b 100644 --- a/src/test/ui/async-await/unnecessary-await.stderr +++ b/src/test/ui/async-await/unnecessary-await.stderr @@ -9,7 +9,7 @@ LL | boo().await; = help: the trait `Future` is not implemented for `()` = note: () must be a future or must implement `IntoFuture` to be awaited = note: required because of the requirements on the impl of `IntoFuture` for `()` -help: do not `.await` the expression +help: remove the `.await` | LL - boo().await; LL + boo(); From 99789d0168b6f769f4a9a4d13f9ba6b4ff4c2998 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Fri, 10 Dec 2021 17:20:57 +0000 Subject: [PATCH 15/15] fix clippy tests --- .../clippy/tests/ui/future_not_send.stderr | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/tools/clippy/tests/ui/future_not_send.stderr b/src/tools/clippy/tests/ui/future_not_send.stderr index 3cc05e2fdbec6..a9f2ad36d0aba 100644 --- a/src/tools/clippy/tests/ui/future_not_send.stderr +++ b/src/tools/clippy/tests/ui/future_not_send.stderr @@ -6,22 +6,22 @@ LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell) -> bool { | = note: `-D clippy::future-not-send` implied by `-D warnings` note: future is not `Send` as this value is used across an await - --> $DIR/future_not_send.rs:8:5 + --> $DIR/future_not_send.rs:8:19 | LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell) -> bool { | -- has type `std::rc::Rc<[u8]>` which is not `Send` LL | async { true }.await - | ^^^^^^^^^^^^^^^^^^^^ await occurs here, with `rc` maybe used later + | ^^^^^^ await occurs here, with `rc` maybe used later LL | } | - `rc` is later dropped here = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send` note: future is not `Send` as this value is used across an await - --> $DIR/future_not_send.rs:8:5 + --> $DIR/future_not_send.rs:8:19 | LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell) -> bool { | ---- has type `&std::cell::Cell` which is not `Send` LL | async { true }.await - | ^^^^^^^^^^^^^^^^^^^^ await occurs here, with `cell` maybe used later + | ^^^^^^ await occurs here, with `cell` maybe used later LL | } | - `cell` is later dropped here = note: `std::cell::Cell` doesn't implement `std::marker::Sync` @@ -33,12 +33,12 @@ LL | pub async fn public_future(rc: Rc<[u8]>) { | ^ future returned by `public_future` is not `Send` | note: future is not `Send` as this value is used across an await - --> $DIR/future_not_send.rs:12:5 + --> $DIR/future_not_send.rs:12:19 | LL | pub async fn public_future(rc: Rc<[u8]>) { | -- has type `std::rc::Rc<[u8]>` which is not `Send` LL | async { true }.await; - | ^^^^^^^^^^^^^^^^^^^^ await occurs here, with `rc` maybe used later + | ^^^^^^ await occurs here, with `rc` maybe used later LL | } | - `rc` is later dropped here = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send` @@ -82,12 +82,12 @@ LL | async fn private_future(&self) -> usize { | ^^^^^ future returned by `private_future` is not `Send` | note: future is not `Send` as this value is used across an await - --> $DIR/future_not_send.rs:35:9 + --> $DIR/future_not_send.rs:35:23 | LL | async fn private_future(&self) -> usize { | ----- has type `&Dummy` which is not `Send` LL | async { true }.await; - | ^^^^^^^^^^^^^^^^^^^^ await occurs here, with `&self` maybe used later + | ^^^^^^ await occurs here, with `&self` maybe used later LL | self.rc.len() LL | } | - `&self` is later dropped here @@ -100,12 +100,12 @@ LL | pub async fn public_future(&self) { | ^ future returned by `public_future` is not `Send` | note: future is not `Send` as this value is used across an await - --> $DIR/future_not_send.rs:40:9 + --> $DIR/future_not_send.rs:40:30 | LL | pub async fn public_future(&self) { | ----- has type `&Dummy` which is not `Send` LL | self.private_future().await; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ await occurs here, with `&self` maybe used later + | ^^^^^^ await occurs here, with `&self` maybe used later LL | } | - `&self` is later dropped here = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Sync` @@ -117,12 +117,12 @@ LL | async fn generic_future(t: T) -> T | ^ future returned by `generic_future` is not `Send` | note: future is not `Send` as this value is used across an await - --> $DIR/future_not_send.rs:54:5 + --> $DIR/future_not_send.rs:54:19 | LL | let rt = &t; | -- has type `&T` which is not `Send` LL | async { true }.await; - | ^^^^^^^^^^^^^^^^^^^^ await occurs here, with `rt` maybe used later + | ^^^^^^ await occurs here, with `rt` maybe used later LL | t LL | } | - `rt` is later dropped here