Skip to content

Commit b661157

Browse files
committed
for_loop_over_fallibles: Suggest removing .next()
1 parent 810cf60 commit b661157

File tree

1 file changed

+38
-11
lines changed

1 file changed

+38
-11
lines changed

compiler/rustc_lint/src/for_loop_over_fallibles.rs

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -73,17 +73,30 @@ impl<'tcx> LateLintPass<'tcx> for ForLoopOverFallibles {
7373
);
7474

7575
cx.struct_span_lint(FOR_LOOP_OVER_FALLIBLES, arg.span, |diag| {
76-
diag.build(msg)
77-
.multipart_suggestion_verbose(
78-
"consider using `if let` to clear intent",
79-
vec![
80-
// NB can't use `until` here because `expr.span` and `pat.span` have different syntax contexts
81-
(expr.span.with_hi(pat.span.lo()), format!("if let {var}(")),
82-
(pat.span.between(arg.span), format!(") = ")),
83-
],
84-
Applicability::MachineApplicable,
85-
)
86-
.emit()
76+
let mut warn = diag.build(msg);
77+
78+
if let Some(recv) = extract_iterator_next_call(cx, arg)
79+
&& let Ok(recv_snip) = cx.sess().source_map().span_to_snippet(recv.span)
80+
{
81+
warn.span_suggestion(
82+
recv.span.between(arg.span.shrink_to_hi()),
83+
format!("to iterate over `{recv_snip}` remove the call to `next`"),
84+
"",
85+
Applicability::MaybeIncorrect
86+
);
87+
}
88+
89+
warn.multipart_suggestion_verbose(
90+
"consider using `if let` to clear intent",
91+
vec![
92+
// NB can't use `until` here because `expr.span` and `pat.span` have different syntax contexts
93+
(expr.span.with_hi(pat.span.lo()), format!("if let {var}(")),
94+
(pat.span.between(arg.span), format!(") = ")),
95+
],
96+
Applicability::MachineApplicable,
97+
);
98+
99+
warn.emit()
87100
})
88101
}
89102
}
@@ -103,3 +116,17 @@ fn extract_for_loop<'tcx>(expr: &Expr<'tcx>) -> Option<(&'tcx Pat<'tcx>, &'tcx E
103116
None
104117
}
105118
}
119+
120+
fn extract_iterator_next_call<'tcx>(
121+
cx: &LateContext<'_>,
122+
expr: &Expr<'tcx>,
123+
) -> Option<&'tcx Expr<'tcx>> {
124+
// This won't work for `Iterator::next(iter)`, is this an issue?
125+
if let hir::ExprKind::MethodCall(_, [recv], _) = expr.kind
126+
&& cx.typeck_results().type_dependent_def_id(expr.hir_id) == cx.tcx.lang_items().next_fn()
127+
{
128+
Some(recv)
129+
} else {
130+
return None
131+
}
132+
}

0 commit comments

Comments
 (0)