diff options
| author | Mara Bos <m-ou.se@m-ou.se> | 2021-05-25 19:15:27 +0200 |
|---|---|---|
| committer | Mara Bos <m-ou.se@m-ou.se> | 2021-06-26 12:14:22 +0000 |
| commit | ef152d9b9fe9899a8e0ba14d11fa1d75ef56b1d6 (patch) | |
| tree | 632fca2d45d6ad3971357ed334ad27e16b5b9719 | |
| parent | aec2c5b2b61a5c69742e5e408aa5e64477be6eb3 (diff) | |
| download | rust-ef152d9b9fe9899a8e0ba14d11fa1d75ef56b1d6.tar.gz rust-ef152d9b9fe9899a8e0ba14d11fa1d75ef56b1d6.zip | |
Better suggestion for array_into_iter in for loop.
| -rw-r--r-- | compiler/rustc_lint/src/array_into_iter.rs | 61 | ||||
| -rw-r--r-- | compiler/rustc_lint/src/lib.rs | 2 |
2 files changed, 45 insertions, 18 deletions
diff --git a/compiler/rustc_lint/src/array_into_iter.rs b/compiler/rustc_lint/src/array_into_iter.rs index 738c63c3b8b..77741c7240b 100644 --- a/compiler/rustc_lint/src/array_into_iter.rs +++ b/compiler/rustc_lint/src/array_into_iter.rs @@ -6,6 +6,7 @@ use rustc_middle::ty::adjustment::{Adjust, Adjustment}; use rustc_session::lint::FutureIncompatibilityReason; use rustc_span::edition::Edition; use rustc_span::symbol::sym; +use rustc_span::Span; declare_lint! { /// The `array_into_iter` lint detects calling `into_iter` on arrays. @@ -36,13 +37,29 @@ declare_lint! { }; } -declare_lint_pass!( - /// Checks for instances of calling `into_iter` on arrays. - ArrayIntoIter => [ARRAY_INTO_ITER] -); +#[derive(Copy, Clone, Default)] +pub struct ArrayIntoIter { + for_expr_span: Span, +} + +impl_lint_pass!(ArrayIntoIter => [ARRAY_INTO_ITER]); impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { + // Save the span of expressions in `for _ in expr` syntax, + // so we can give a better suggestion for those later. + if let hir::ExprKind::Match(arg, [_], hir::MatchSource::ForLoopDesugar) = &expr.kind { + 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; + } + } + } + // We only care about method call expressions. if let hir::ExprKind::MethodCall(call, span, args, _) = &expr.kind { if call.ident.name != sym::into_iter { @@ -98,27 +115,37 @@ impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter { _ => bug!("array type coerced to something other than array or slice"), }; cx.struct_span_lint(ARRAY_INTO_ITER, *span, |lint| { - lint.build(&format!( + let mut diag = lint.build(&format!( "this method call resolves to `<&{} as IntoIterator>::into_iter` \ (due to backwards compatibility), \ but will resolve to <{} as IntoIterator>::into_iter in Rust 2021.", target, target, - )) - .span_suggestion( + )); + diag.span_suggestion( call.ident.span, "use `.iter()` instead of `.into_iter()` to avoid ambiguity", "iter".into(), Applicability::MachineApplicable, - ) - .multipart_suggestion( - "or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value", - vec![ - (expr.span.shrink_to_lo(), "IntoIterator::into_iter(".into()), - (receiver_arg.span.shrink_to_hi().to(expr.span.shrink_to_hi()), ")".into()), - ], - Applicability::MaybeIncorrect, - ) - .emit(); + ); + if self.for_expr_span == expr.span { + let expr_span = expr.span.ctxt().outer_expn_data().call_site; + diag.span_suggestion( + receiver_arg.span.shrink_to_hi().to(expr_span.shrink_to_hi()), + "or remove `.into_iter()` to iterate by value", + String::new(), + Applicability::MaybeIncorrect, + ); + } else { + diag.multipart_suggestion( + "or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value", + vec![ + (expr.span.shrink_to_lo(), "IntoIterator::into_iter(".into()), + (receiver_arg.span.shrink_to_hi().to(expr.span.shrink_to_hi()), ")".into()), + ], + Applicability::MaybeIncorrect, + ); + } + diag.emit(); }) } } diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 4f59460aa82..89f9809d643 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -163,7 +163,7 @@ macro_rules! late_lint_passes { // FIXME: Turn the computation of types which implement Debug into a query // and change this to a module lint pass MissingDebugImplementations: MissingDebugImplementations::default(), - ArrayIntoIter: ArrayIntoIter, + ArrayIntoIter: ArrayIntoIter::default(), ClashingExternDeclarations: ClashingExternDeclarations::new(), DropTraitConstraints: DropTraitConstraints, TemporaryCStringAsPtr: TemporaryCStringAsPtr, |
