From 7227a87371f2e6c394d7a79905347fef3c249a63 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Tue, 16 Nov 2021 00:57:53 +0000 Subject: 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 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'compiler/rustc_ast_lowering/src/expr.rs') diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index c9578c2f50f..2cf0dbaf425 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) }; -- cgit 1.4.1-3-g733a5 From f640438b402b6507e734862026b0b004090c8ac0 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Tue, 16 Nov 2021 20:07:23 +0000 Subject: 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 +-- compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs | 3 +- compiler/rustc_typeck/src/check/fn_ctxt/checks.rs | 4 +- src/test/ui/async-await/unnecessary-await.rs | 14 ++++++ src/test/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 (limited to 'compiler/rustc_ast_lowering/src/expr.rs') diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 2cf0dbaf425..16fdd714575 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 c04b0471cb7..e03e82b2b77 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2127,21 +2127,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( @@ -2164,8 +2164,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 fdf7a8102a0..01d95f71c9b 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1627,13 +1627,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, @@ -1788,8 +1788,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> { @@ -1798,7 +1798,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, } } @@ -1808,7 +1808,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, } } @@ -1818,7 +1818,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 65cdf10f901..389e3845c56 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1731,7 +1731,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 4a24f803e84..b6151757588 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 079899ac494..a5bd246712b 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 7864b47ab0a..1d9c44bffa3 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 9893e5143fc..ede8511d815 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 752183365d6..8a44874bb47 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -2362,7 +2362,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 311106474be..bc6ad3c9686 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 b437d4c5c2e..ab2d5286907 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -791,6 +791,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); @@ -809,7 +810,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 4cb597cb6d6..b2641726075 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 00000000000..70c38aaeb25 --- /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 00000000000..4caa15e67b7 --- /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`. -- cgit 1.4.1-3-g733a5 From b825b0fe6333ff08552aefa1fb25dfdc932b8bca Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Tue, 16 Nov 2021 22:06:25 +0000 Subject: 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 +++++++++++----------- compiler/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 ++---- src/test/ui/async-await/issues/issue-51719.stderr | 4 +- src/test/ui/async-await/issues/issue-51751.stderr | 4 +- src/test/ui/async-await/issues/issue-62009-1.rs | 1 - .../ui/async-await/issues/issue-62009-1.stderr | 25 +++---- .../ui/async-await/issues/issue-62009-2.stderr | 4 +- .../issues/non-async-enclosing-span.stderr | 4 +- .../ui/async-await/suggest-missing-await.stderr | 8 +-- src/test/ui/async-await/unnecessary-await.stderr | 2 + src/test/ui/issues/issue-33941.stderr | 14 ---- .../clippy/clippy_lints/src/needless_late_init.rs | 11 ++- .../tests/ui/needless_late_init_fixable.fixed | 38 ----------- .../clippy/tests/ui/needless_late_init_fixable.rs | 2 - .../tests/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 (limited to 'compiler/rustc_ast_lowering/src/expr.rs') diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 16fdd714575..75a45a437e7 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 babeafff820..0f8c0e1b8cf 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1153,7 +1153,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; @@ -2838,8 +2838,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 ae423070392..8968c163987 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 ede8511d815..67088ec83fa 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 ab2d5286907..738af9bfb8c 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -810,7 +810,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 27f4b0dac61..b4323c314ba 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 bfed4b0b05c..9e7c5847b3b 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 a2d4257577e..40570928682 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 19cc339ec0a..f3ce5d1c897 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 6dd3726608b..8696a5b798b 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 71108b4e1d8..40ccf25712e 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 c09903e48c6..3ea5dac76d4 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 9c2f20df657..92e9a8a69a8 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 b6583022c16..20b827479fa 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 a812840d40b..3cca9616a35 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 4caa15e67b7..fc22ebc5972 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 52341517756..c6650d60c21 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 e0522f3fe0b..5b098659377 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 32d5d04fde4..00000000000 --- 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 6bc85f68632..76099df0e06 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 a0ce4f812f4..728e19252ea 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; | ^^^^^^ -- cgit 1.4.1-3-g733a5