diff options
| author | Maybe Waffle <waffle.lapkin@gmail.com> | 2022-07-24 21:07:23 +0400 |
|---|---|---|
| committer | Maybe Waffle <waffle.lapkin@gmail.com> | 2022-10-09 13:05:52 +0000 |
| commit | 21ec99b6fa77088b35dc747c42dfdbec3d341545 (patch) | |
| tree | 4d9d96b5d6a733090080db9227ce22eedc0e6bf5 | |
| parent | d030ba52e20da70ddca073bd6795d0c27aff2ddb (diff) | |
| download | rust-21ec99b6fa77088b35dc747c42dfdbec3d341545.tar.gz rust-21ec99b6fa77088b35dc747c42dfdbec3d341545.zip | |
`for_loop_over_fallibles`: Suggest removing `.next()`
| -rw-r--r-- | compiler/rustc_lint/src/for_loop_over_fallibles.rs | 49 |
1 files changed, 38 insertions, 11 deletions
diff --git a/compiler/rustc_lint/src/for_loop_over_fallibles.rs b/compiler/rustc_lint/src/for_loop_over_fallibles.rs index d765131442f..78b6ca6a653 100644 --- a/compiler/rustc_lint/src/for_loop_over_fallibles.rs +++ b/compiler/rustc_lint/src/for_loop_over_fallibles.rs @@ -73,17 +73,30 @@ impl<'tcx> LateLintPass<'tcx> for ForLoopOverFallibles { ); cx.struct_span_lint(FOR_LOOP_OVER_FALLIBLES, arg.span, |diag| { - diag.build(msg) - .multipart_suggestion_verbose( - "consider using `if let` to clear intent", - vec![ - // NB can't use `until` here because `expr.span` and `pat.span` have different syntax contexts - (expr.span.with_hi(pat.span.lo()), format!("if let {var}(")), - (pat.span.between(arg.span), format!(") = ")), - ], - Applicability::MachineApplicable, - ) - .emit() + let mut warn = diag.build(msg); + + if let Some(recv) = extract_iterator_next_call(cx, arg) + && let Ok(recv_snip) = cx.sess().source_map().span_to_snippet(recv.span) + { + warn.span_suggestion( + recv.span.between(arg.span.shrink_to_hi()), + format!("to iterate over `{recv_snip}` remove the call to `next`"), + "", + Applicability::MaybeIncorrect + ); + } + + warn.multipart_suggestion_verbose( + "consider using `if let` to clear intent", + vec![ + // NB can't use `until` here because `expr.span` and `pat.span` have different syntax contexts + (expr.span.with_hi(pat.span.lo()), format!("if let {var}(")), + (pat.span.between(arg.span), format!(") = ")), + ], + Applicability::MachineApplicable, + ); + + warn.emit() }) } } @@ -103,3 +116,17 @@ fn extract_for_loop<'tcx>(expr: &Expr<'tcx>) -> Option<(&'tcx Pat<'tcx>, &'tcx E None } } + +fn extract_iterator_next_call<'tcx>( + cx: &LateContext<'_>, + expr: &Expr<'tcx>, +) -> Option<&'tcx Expr<'tcx>> { + // This won't work for `Iterator::next(iter)`, is this an issue? + if let hir::ExprKind::MethodCall(_, [recv], _) = expr.kind + && cx.typeck_results().type_dependent_def_id(expr.hir_id) == cx.tcx.lang_items().next_fn() + { + Some(recv) + } else { + return None + } +} |
