Skip to content

Commit 9fa4089

Browse files
committed
Auto merge of #10993 - Centri3:iter_nth_zero, r=Manishearth
Don't lint [`iter_nth_zero`] in `next` Closes #9820 This also *slightlyy* modifies the output of `iter_nth`, as I noticed the types' names weren't in backticks changelog: [`iter_nth_zero`]: No longer lints in implementations of `Iterator::next`
2 parents b3fd7b8 + 242807a commit 9fa4089

File tree

5 files changed

+54
-23
lines changed

5 files changed

+54
-23
lines changed

clippy_lints/src/methods/iter_nth.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ pub(super) fn check<'tcx>(
2020
let caller_type = if derefs_to_slice(cx, iter_recv, cx.typeck_results().expr_ty(iter_recv)).is_some() {
2121
"slice"
2222
} else if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(iter_recv), sym::Vec) {
23-
"Vec"
23+
"`Vec`"
2424
} else if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(iter_recv), sym::VecDeque) {
25-
"VecDeque"
25+
"`VecDeque`"
2626
} else {
2727
iter_nth_zero::check(cx, expr, nth_recv, nth_arg);
2828
return; // caller is not a type that we want to lint
Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use clippy_utils::consts::{constant, Constant};
22
use clippy_utils::diagnostics::span_lint_and_sugg;
3-
use clippy_utils::is_trait_method;
43
use clippy_utils::source::snippet_with_applicability;
5-
use if_chain::if_chain;
4+
use clippy_utils::{is_lang_item_or_ctor, is_trait_method};
5+
use hir::{LangItem, OwnerNode};
66
use rustc_errors::Applicability;
77
use rustc_hir as hir;
88
use rustc_lint::LateContext;
@@ -11,20 +11,21 @@ use rustc_span::sym;
1111
use super::ITER_NTH_ZERO;
1212

1313
pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>) {
14-
if_chain! {
15-
if is_trait_method(cx, expr, sym::Iterator);
16-
if let Some(Constant::Int(0)) = constant(cx, cx.typeck_results(), arg);
17-
then {
18-
let mut applicability = Applicability::MachineApplicable;
19-
span_lint_and_sugg(
20-
cx,
21-
ITER_NTH_ZERO,
22-
expr.span,
23-
"called `.nth(0)` on a `std::iter::Iterator`, when `.next()` is equivalent",
24-
"try calling `.next()` instead of `.nth(0)`",
25-
format!("{}.next()", snippet_with_applicability(cx, recv.span, "..", &mut applicability)),
26-
applicability,
27-
);
28-
}
14+
if let OwnerNode::Item(item) = cx.tcx.hir().owner(cx.tcx.hir().get_parent_item(expr.hir_id))
15+
&& let def_id = item.owner_id.to_def_id()
16+
&& is_trait_method(cx, expr, sym::Iterator)
17+
&& let Some(Constant::Int(0)) = constant(cx, cx.typeck_results(), arg)
18+
&& !is_lang_item_or_ctor(cx, def_id, LangItem::IteratorNext)
19+
{
20+
let mut app = Applicability::MachineApplicable;
21+
span_lint_and_sugg(
22+
cx,
23+
ITER_NTH_ZERO,
24+
expr.span,
25+
"called `.nth(0)` on a `std::iter::Iterator`, when `.next()` is equivalent",
26+
"try calling `.next()` instead of `.nth(0)`",
27+
format!("{}.next()", snippet_with_applicability(cx, recv.span, "..", &mut app)),
28+
app,
29+
);
2930
}
3031
}

tests/ui/iter_nth.stderr

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: called `.iter().nth()` on a Vec
1+
error: called `.iter().nth()` on a `Vec`
22
--> $DIR/iter_nth.rs:34:23
33
|
44
LL | let bad_vec = some_vec.iter().nth(3);
@@ -23,15 +23,15 @@ LL | let bad_boxed_slice = boxed_slice.iter().nth(3);
2323
|
2424
= help: calling `.get()` is both faster and more readable
2525

26-
error: called `.iter().nth()` on a VecDeque
26+
error: called `.iter().nth()` on a `VecDeque`
2727
--> $DIR/iter_nth.rs:37:29
2828
|
2929
LL | let bad_vec_deque = some_vec_deque.iter().nth(3);
3030
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3131
|
3232
= help: calling `.get()` is both faster and more readable
3333

34-
error: called `.iter_mut().nth()` on a Vec
34+
error: called `.iter_mut().nth()` on a `Vec`
3535
--> $DIR/iter_nth.rs:42:23
3636
|
3737
LL | let bad_vec = some_vec.iter_mut().nth(3);
@@ -47,7 +47,7 @@ LL | let bad_slice = &some_vec[..].iter_mut().nth(3);
4747
|
4848
= help: calling `.get_mut()` is both faster and more readable
4949

50-
error: called `.iter_mut().nth()` on a VecDeque
50+
error: called `.iter_mut().nth()` on a `VecDeque`
5151
--> $DIR/iter_nth.rs:48:29
5252
|
5353
LL | let bad_vec_deque = some_vec_deque.iter_mut().nth(3);

tests/ui/iter_nth_zero.fixed

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,18 @@ fn main() {
2929
let mut iter2 = s3.iter();
3030
let _unwrapped = iter2.next().unwrap();
3131
}
32+
33+
struct Issue9820;
34+
35+
impl Iterator for Issue9820 {
36+
type Item = ();
37+
38+
fn nth(&mut self, _n: usize) -> Option<Self::Item> {
39+
todo!()
40+
}
41+
42+
// Don't lint in implementations of `next`, as calling `next` in `next` is incorrect
43+
fn next(&mut self) -> Option<Self::Item> {
44+
self.nth(0)
45+
}
46+
}

tests/ui/iter_nth_zero.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,18 @@ fn main() {
2929
let mut iter2 = s3.iter();
3030
let _unwrapped = iter2.nth(0).unwrap();
3131
}
32+
33+
struct Issue9820;
34+
35+
impl Iterator for Issue9820 {
36+
type Item = ();
37+
38+
fn nth(&mut self, _n: usize) -> Option<Self::Item> {
39+
todo!()
40+
}
41+
42+
// Don't lint in implementations of `next`, as calling `next` in `next` is incorrect
43+
fn next(&mut self) -> Option<Self::Item> {
44+
self.nth(0)
45+
}
46+
}

0 commit comments

Comments
 (0)