From c051656c836bf11335781afbabe1690ea7542f49 Mon Sep 17 00:00:00 2001 From: surechen Date: Fri, 29 Oct 2021 11:32:37 +0800 Subject: [PATCH] fixes: #7889 1. Fix the problem of manual_split_once changing the original behavior. 2. Add a new lint needless_splitn. changelog: Fix the problem of manual_split_once changing the original behavior and add a new lint needless_splitn. --- CHANGELOG.md | 1 + clippy_lints/src/lib.register_all.rs | 1 + clippy_lints/src/lib.register_complexity.rs | 1 + clippy_lints/src/lib.register_lints.rs | 1 + clippy_lints/src/methods/mod.rs | 34 +++- .../{manual_split_once.rs => str_splitn.rs} | 150 +++++++++++++++--- tests/ui/manual_split_once.fixed | 6 +- tests/ui/manual_split_once.rs | 2 +- tests/ui/manual_split_once.stderr | 10 +- tests/ui/needless_splitn.fixed | 27 ++++ tests/ui/needless_splitn.rs | 27 ++++ tests/ui/needless_splitn.stderr | 40 +++++ tests/ui/suspicious_splitn.rs | 1 + tests/ui/suspicious_splitn.stderr | 18 +-- 14 files changed, 276 insertions(+), 43 deletions(-) rename clippy_lints/src/methods/{manual_split_once.rs => str_splitn.rs} (60%) create mode 100644 tests/ui/needless_splitn.fixed create mode 100644 tests/ui/needless_splitn.rs create mode 100644 tests/ui/needless_splitn.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 267bc07d8fa61..55c4c4c7a27c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3038,6 +3038,7 @@ Released 2018-09-13 [`needless_question_mark`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_question_mark [`needless_range_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_range_loop [`needless_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_return +[`needless_splitn`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_splitn [`needless_update`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_update [`neg_cmp_op_on_partial_ord`]: https://rust-lang.github.io/rust-clippy/master/index.html#neg_cmp_op_on_partial_ord [`neg_multiply`]: https://rust-lang.github.io/rust-clippy/master/index.html#neg_multiply diff --git a/clippy_lints/src/lib.register_all.rs b/clippy_lints/src/lib.register_all.rs index 4e123f27ec0a6..32c24a4aade0d 100644 --- a/clippy_lints/src/lib.register_all.rs +++ b/clippy_lints/src/lib.register_all.rs @@ -160,6 +160,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![ LintId::of(methods::MANUAL_STR_REPEAT), LintId::of(methods::MAP_COLLECT_RESULT_UNIT), LintId::of(methods::MAP_IDENTITY), + LintId::of(methods::NEEDLESS_SPLITN), LintId::of(methods::NEW_RET_NO_SELF), LintId::of(methods::OK_EXPECT), LintId::of(methods::OPTION_AS_REF_DEREF), diff --git a/clippy_lints/src/lib.register_complexity.rs b/clippy_lints/src/lib.register_complexity.rs index c51341bdf0c23..dcc95cf6c074d 100644 --- a/clippy_lints/src/lib.register_complexity.rs +++ b/clippy_lints/src/lib.register_complexity.rs @@ -42,6 +42,7 @@ store.register_group(true, "clippy::complexity", Some("clippy_complexity"), vec! LintId::of(methods::MANUAL_FIND_MAP), LintId::of(methods::MANUAL_SPLIT_ONCE), LintId::of(methods::MAP_IDENTITY), + LintId::of(methods::NEEDLESS_SPLITN), LintId::of(methods::OPTION_AS_REF_DEREF), LintId::of(methods::OPTION_FILTER_MAP), LintId::of(methods::SEARCH_IS_SOME), diff --git a/clippy_lints/src/lib.register_lints.rs b/clippy_lints/src/lib.register_lints.rs index 249bf77a8f288..872e86ffcfbed 100644 --- a/clippy_lints/src/lib.register_lints.rs +++ b/clippy_lints/src/lib.register_lints.rs @@ -288,6 +288,7 @@ store.register_lints(&[ methods::MAP_FLATTEN, methods::MAP_IDENTITY, methods::MAP_UNWRAP_OR, + methods::NEEDLESS_SPLITN, methods::NEW_RET_NO_SELF, methods::OK_EXPECT, methods::OPTION_AS_REF_DEREF, diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 26c29fbb289cb..d36d84c9c43c0 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -33,7 +33,6 @@ mod iter_nth_zero; mod iter_skip_next; mod iterator_step_by_zero; mod manual_saturating_arithmetic; -mod manual_split_once; mod manual_str_repeat; mod map_collect_result_unit; mod map_flatten; @@ -50,6 +49,7 @@ mod single_char_insert_string; mod single_char_pattern; mod single_char_push_string; mod skip_while_next; +mod str_splitn; mod string_extend_chars; mod suspicious_map; mod suspicious_splitn; @@ -1798,6 +1798,30 @@ declare_clippy_lint! { "replace `.splitn(2, pat)` with `.split_once(pat)`" } +declare_clippy_lint! { + /// ### What it does + /// Checks for usages of `str::splitn` (or `str::rsplitn`) where using `str::split` would be the same. + /// ### Why is this bad? + /// The function `split` is simpler and there is no performance difference in these cases, considering + /// that both functions return a lazy iterator. + /// ### Example + /// ```rust + /// // Bad + /// let str = "key=value=add"; + /// let _ = str.splitn(3, '=').next().unwrap(); + /// ``` + /// Use instead: + /// ```rust + /// // Good + /// let str = "key=value=add"; + /// let _ = str.split('=').next().unwrap(); + /// ``` + #[clippy::version = "1.58.0"] + pub NEEDLESS_SPLITN, + complexity, + "usages of `str::splitn` that can be replaced with `str::split`" +} + pub struct Methods { avoid_breaking_exported_api: bool, msrv: Option, @@ -1876,7 +1900,8 @@ impl_lint_pass!(Methods => [ SUSPICIOUS_SPLITN, MANUAL_STR_REPEAT, EXTEND_WITH_DRAIN, - MANUAL_SPLIT_ONCE + MANUAL_SPLIT_ONCE, + NEEDLESS_SPLITN ]); /// Extracts a method call name, args, and `Span` of the method name. @@ -2208,7 +2233,10 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio if let Some((Constant::Int(count), _)) = constant(cx, cx.typeck_results(), count_arg) { suspicious_splitn::check(cx, name, expr, recv, count); if count == 2 && meets_msrv(msrv, &msrvs::STR_SPLIT_ONCE) { - manual_split_once::check(cx, name, expr, recv, pat_arg); + str_splitn::check_manual_split_once(cx, name, expr, recv, pat_arg); + } + if count >= 2 { + str_splitn::check_needless_splitn(cx, name, expr, recv, pat_arg, count); } } }, diff --git a/clippy_lints/src/methods/manual_split_once.rs b/clippy_lints/src/methods/str_splitn.rs similarity index 60% rename from clippy_lints/src/methods/manual_split_once.rs rename to clippy_lints/src/methods/str_splitn.rs index 13eb72251bb14..2595f734f1151 100644 --- a/clippy_lints/src/methods/manual_split_once.rs +++ b/clippy_lints/src/methods/str_splitn.rs @@ -11,7 +11,13 @@ use rustc_span::{symbol::sym, Span, SyntaxContext}; use super::MANUAL_SPLIT_ONCE; -pub(super) fn check(cx: &LateContext<'_>, method_name: &str, expr: &Expr<'_>, self_arg: &Expr<'_>, pat_arg: &Expr<'_>) { +pub(super) fn check_manual_split_once( + cx: &LateContext<'_>, + method_name: &str, + expr: &Expr<'_>, + self_arg: &Expr<'_>, + pat_arg: &Expr<'_>, +) { if !cx.typeck_results().expr_ty_adjusted(self_arg).peel_refs().is_str() { return; } @@ -36,7 +42,7 @@ pub(super) fn check(cx: &LateContext<'_>, method_name: &str, expr: &Expr<'_>, se format!("{}.{}({})", self_snip, method_name, pat_snip) }, IterUsageKind::RNextTuple => format!("{}.{}({}).map(|(x, y)| (y, x))", self_snip, method_name, pat_snip), - IterUsageKind::Next => { + IterUsageKind::Next | IterUsageKind::Second => { let self_deref = { let adjust = cx.typeck_results().expr_adjustments(self_arg); if adjust.is_empty() { @@ -51,26 +57,49 @@ pub(super) fn check(cx: &LateContext<'_>, method_name: &str, expr: &Expr<'_>, se "*".repeat(adjust.len() - 2) } }; - if usage.unwrap_kind.is_some() { - format!( - "{}.{}({}).map_or({}{}, |x| x.0)", - &self_snip, method_name, pat_snip, self_deref, &self_snip - ) + if matches!(usage.kind, IterUsageKind::Next) { + match usage.unwrap_kind { + Some(UnwrapKind::Unwrap) => { + if reverse { + format!("{}.{}({}).unwrap().0", self_snip, method_name, pat_snip) + } else { + format!( + "{}.{}({}).map_or({}{}, |x| x.0)", + self_snip, method_name, pat_snip, self_deref, &self_snip + ) + } + }, + Some(UnwrapKind::QuestionMark) => { + format!( + "{}.{}({}).map_or({}{}, |x| x.0)", + self_snip, method_name, pat_snip, self_deref, &self_snip + ) + }, + None => { + format!( + "Some({}.{}({}).map_or({}{}, |x| x.0))", + &self_snip, method_name, pat_snip, self_deref, &self_snip + ) + }, + } } else { - format!( - "Some({}.{}({}).map_or({}{}, |x| x.0))", - &self_snip, method_name, pat_snip, self_deref, &self_snip - ) + match usage.unwrap_kind { + Some(UnwrapKind::Unwrap) => { + if reverse { + // In this case, no better suggestion is offered. + return; + } + format!("{}.{}({}).unwrap().1", self_snip, method_name, pat_snip) + }, + Some(UnwrapKind::QuestionMark) => { + format!("{}.{}({})?.1", self_snip, method_name, pat_snip) + }, + None => { + format!("{}.{}({}).map(|x| x.1)", self_snip, method_name, pat_snip) + }, + } } }, - IterUsageKind::Second => { - let access_str = match usage.unwrap_kind { - Some(UnwrapKind::Unwrap) => ".unwrap().1", - Some(UnwrapKind::QuestionMark) => "?.1", - None => ".map(|x| x.1)", - }; - format!("{}.{}({}){}", self_snip, method_name, pat_snip, access_str) - }, }; span_lint_and_sugg(cx, MANUAL_SPLIT_ONCE, usage.span, msg, "try this", sugg, app); @@ -209,3 +238,86 @@ fn parse_iter_usage( span, }) } + +use super::NEEDLESS_SPLITN; + +pub(super) fn check_needless_splitn( + cx: &LateContext<'_>, + method_name: &str, + expr: &Expr<'_>, + self_arg: &Expr<'_>, + pat_arg: &Expr<'_>, + count: u128, +) { + if !cx.typeck_results().expr_ty_adjusted(self_arg).peel_refs().is_str() { + return; + } + let ctxt = expr.span.ctxt(); + let mut app = Applicability::MachineApplicable; + let (reverse, message) = if method_name == "splitn" { + (false, "unnecessary use of `splitn`") + } else { + (true, "unnecessary use of `rsplitn`") + }; + if_chain! { + if count >= 2; + if check_iter(cx, ctxt, cx.tcx.hir().parent_iter(expr.hir_id), count); + then { + span_lint_and_sugg( + cx, + NEEDLESS_SPLITN, + expr.span, + message, + "try this", + format!( + "{}.{}({})", + snippet_with_context(cx, self_arg.span, ctxt, "..", &mut app).0, + if reverse {"rsplit"} else {"split"}, + snippet_with_context(cx, pat_arg.span, ctxt, "..", &mut app).0 + ), + app, + ); + } + } +} + +fn check_iter( + cx: &LateContext<'tcx>, + ctxt: SyntaxContext, + mut iter: impl Iterator)>, + count: u128, +) -> bool { + match iter.next() { + Some((_, Node::Expr(e))) if e.span.ctxt() == ctxt => { + let (name, args) = if let ExprKind::MethodCall(name, _, [_, args @ ..], _) = e.kind { + (name, args) + } else { + return false; + }; + if_chain! { + if let Some(did) = cx.typeck_results().type_dependent_def_id(e.hir_id); + if let Some(iter_id) = cx.tcx.get_diagnostic_item(sym::Iterator); + then { + match (&*name.ident.as_str(), args) { + ("next", []) if cx.tcx.trait_of_item(did) == Some(iter_id) => { + return true; + }, + ("next_tuple", []) if count > 2 => { + return true; + }, + ("nth", [idx_expr]) if cx.tcx.trait_of_item(did) == Some(iter_id) => { + if let Some((Constant::Int(idx), _)) = constant(cx, cx.typeck_results(), idx_expr) { + if count > idx + 1 { + return true; + } + } + }, + _ => return false, + } + } + } + }, + _ => return false, + }; + false +} diff --git a/tests/ui/manual_split_once.fixed b/tests/ui/manual_split_once.fixed index 992baf1f185a7..d5113df569a08 100644 --- a/tests/ui/manual_split_once.fixed +++ b/tests/ui/manual_split_once.fixed @@ -2,7 +2,7 @@ #![feature(custom_inner_attributes)] #![warn(clippy::manual_split_once)] -#![allow(clippy::iter_skip_next, clippy::iter_nth_zero)] +#![allow(clippy::iter_skip_next, clippy::iter_nth_zero, clippy::needless_splitn)] extern crate itertools; @@ -38,8 +38,8 @@ fn main() { let _ = [0, 1, 2].splitn(2, |&x| x == 1).nth(1).unwrap(); // `rsplitn` gives the results in the reverse order of `rsplit_once` - let _ = "key=value".rsplit_once('=').unwrap().1; - let _ = "key=value".rsplit_once('=').map_or("key=value", |x| x.0); + let _ = "key=value".rsplitn(2, '=').next().unwrap(); + let _ = "key=value".rsplit_once('=').unwrap().0; let _ = "key=value".rsplit_once('=').map(|x| x.1); let (_, _) = "key=value".rsplit_once('=').map(|(x, y)| (y, x)).unwrap(); } diff --git a/tests/ui/manual_split_once.rs b/tests/ui/manual_split_once.rs index 4f92ab6b812bd..80e02952dbd07 100644 --- a/tests/ui/manual_split_once.rs +++ b/tests/ui/manual_split_once.rs @@ -2,7 +2,7 @@ #![feature(custom_inner_attributes)] #![warn(clippy::manual_split_once)] -#![allow(clippy::iter_skip_next, clippy::iter_nth_zero)] +#![allow(clippy::iter_skip_next, clippy::iter_nth_zero, clippy::needless_splitn)] extern crate itertools; diff --git a/tests/ui/manual_split_once.stderr b/tests/ui/manual_split_once.stderr index 7bea2303d9213..af9c7a2d41bff 100644 --- a/tests/ui/manual_split_once.stderr +++ b/tests/ui/manual_split_once.stderr @@ -72,17 +72,11 @@ error: manual implementation of `split_once` LL | let _ = s.splitn(2, "key=value").skip(1).next()?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.split_once("key=value")?.1` -error: manual implementation of `rsplit_once` - --> $DIR/manual_split_once.rs:41:13 - | -LL | let _ = "key=value".rsplitn(2, '=').next().unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".rsplit_once('=').unwrap().1` - error: manual implementation of `rsplit_once` --> $DIR/manual_split_once.rs:42:13 | LL | let _ = "key=value".rsplitn(2, '=').nth(1).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".rsplit_once('=').map_or("key=value", |x| x.0)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".rsplit_once('=').unwrap().0` error: manual implementation of `rsplit_once` --> $DIR/manual_split_once.rs:43:13 @@ -102,5 +96,5 @@ error: manual implementation of `split_once` LL | let _ = "key=value".splitn(2, '=').nth(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".split_once('=').unwrap().1` -error: aborting due to 17 previous errors +error: aborting due to 16 previous errors diff --git a/tests/ui/needless_splitn.fixed b/tests/ui/needless_splitn.fixed new file mode 100644 index 0000000000000..f6a4b2f17d33d --- /dev/null +++ b/tests/ui/needless_splitn.fixed @@ -0,0 +1,27 @@ +// run-rustfix +// edition:2018 + +#![feature(custom_inner_attributes)] +#![warn(clippy::needless_splitn)] +#![allow(clippy::iter_skip_next, clippy::iter_nth_zero, clippy::manual_split_once)] + +extern crate itertools; + +#[allow(unused_imports)] +use itertools::Itertools; + +fn main() { + let str = "key=value=end"; + let _ = str.split('=').next(); + let _ = str.split('=').nth(0); + let _ = str.splitn(2, '=').nth(1); + let (_, _) = str.splitn(2, '=').next_tuple().unwrap(); + let (_, _) = str.split('=').next_tuple().unwrap(); + let _: Vec<&str> = str.splitn(3, '=').collect(); + + let _ = str.rsplit('=').next(); + let _ = str.rsplit('=').nth(0); + let _ = str.rsplitn(2, '=').nth(1); + let (_, _) = str.rsplitn(2, '=').next_tuple().unwrap(); + let (_, _) = str.rsplit('=').next_tuple().unwrap(); +} diff --git a/tests/ui/needless_splitn.rs b/tests/ui/needless_splitn.rs new file mode 100644 index 0000000000000..6ba32255bb2d7 --- /dev/null +++ b/tests/ui/needless_splitn.rs @@ -0,0 +1,27 @@ +// run-rustfix +// edition:2018 + +#![feature(custom_inner_attributes)] +#![warn(clippy::needless_splitn)] +#![allow(clippy::iter_skip_next, clippy::iter_nth_zero, clippy::manual_split_once)] + +extern crate itertools; + +#[allow(unused_imports)] +use itertools::Itertools; + +fn main() { + let str = "key=value=end"; + let _ = str.splitn(2, '=').next(); + let _ = str.splitn(2, '=').nth(0); + let _ = str.splitn(2, '=').nth(1); + let (_, _) = str.splitn(2, '=').next_tuple().unwrap(); + let (_, _) = str.splitn(3, '=').next_tuple().unwrap(); + let _: Vec<&str> = str.splitn(3, '=').collect(); + + let _ = str.rsplitn(2, '=').next(); + let _ = str.rsplitn(2, '=').nth(0); + let _ = str.rsplitn(2, '=').nth(1); + let (_, _) = str.rsplitn(2, '=').next_tuple().unwrap(); + let (_, _) = str.rsplitn(3, '=').next_tuple().unwrap(); +} diff --git a/tests/ui/needless_splitn.stderr b/tests/ui/needless_splitn.stderr new file mode 100644 index 0000000000000..66de2256554e3 --- /dev/null +++ b/tests/ui/needless_splitn.stderr @@ -0,0 +1,40 @@ +error: unnecessary use of `splitn` + --> $DIR/needless_splitn.rs:15:13 + | +LL | let _ = str.splitn(2, '=').next(); + | ^^^^^^^^^^^^^^^^^^ help: try this: `str.split('=')` + | + = note: `-D clippy::needless-splitn` implied by `-D warnings` + +error: unnecessary use of `splitn` + --> $DIR/needless_splitn.rs:16:13 + | +LL | let _ = str.splitn(2, '=').nth(0); + | ^^^^^^^^^^^^^^^^^^ help: try this: `str.split('=')` + +error: unnecessary use of `splitn` + --> $DIR/needless_splitn.rs:19:18 + | +LL | let (_, _) = str.splitn(3, '=').next_tuple().unwrap(); + | ^^^^^^^^^^^^^^^^^^ help: try this: `str.split('=')` + +error: unnecessary use of `rsplitn` + --> $DIR/needless_splitn.rs:22:13 + | +LL | let _ = str.rsplitn(2, '=').next(); + | ^^^^^^^^^^^^^^^^^^^ help: try this: `str.rsplit('=')` + +error: unnecessary use of `rsplitn` + --> $DIR/needless_splitn.rs:23:13 + | +LL | let _ = str.rsplitn(2, '=').nth(0); + | ^^^^^^^^^^^^^^^^^^^ help: try this: `str.rsplit('=')` + +error: unnecessary use of `rsplitn` + --> $DIR/needless_splitn.rs:26:18 + | +LL | let (_, _) = str.rsplitn(3, '=').next_tuple().unwrap(); + | ^^^^^^^^^^^^^^^^^^^ help: try this: `str.rsplit('=')` + +error: aborting due to 6 previous errors + diff --git a/tests/ui/suspicious_splitn.rs b/tests/ui/suspicious_splitn.rs index a21d94cf20bb1..528f2ddcc8624 100644 --- a/tests/ui/suspicious_splitn.rs +++ b/tests/ui/suspicious_splitn.rs @@ -1,4 +1,5 @@ #![warn(clippy::suspicious_splitn)] +#![allow(clippy::needless_splitn)] fn main() { let _ = "a,b,c".splitn(3, ','); diff --git a/tests/ui/suspicious_splitn.stderr b/tests/ui/suspicious_splitn.stderr index b6220ae239339..3bcd681fa49d8 100644 --- a/tests/ui/suspicious_splitn.stderr +++ b/tests/ui/suspicious_splitn.stderr @@ -1,5 +1,5 @@ error: `splitn` called with `0` splits - --> $DIR/suspicious_splitn.rs:9:13 + --> $DIR/suspicious_splitn.rs:10:13 | LL | let _ = "a,b".splitn(0, ','); | ^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | let _ = "a,b".splitn(0, ','); = note: the resulting iterator will always return `None` error: `rsplitn` called with `0` splits - --> $DIR/suspicious_splitn.rs:10:13 + --> $DIR/suspicious_splitn.rs:11:13 | LL | let _ = "a,b".rsplitn(0, ','); | ^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | let _ = "a,b".rsplitn(0, ','); = note: the resulting iterator will always return `None` error: `splitn` called with `1` split - --> $DIR/suspicious_splitn.rs:11:13 + --> $DIR/suspicious_splitn.rs:12:13 | LL | let _ = "a,b".splitn(1, ','); | ^^^^^^^^^^^^^^^^^^^^ @@ -24,7 +24,7 @@ LL | let _ = "a,b".splitn(1, ','); = note: the resulting iterator will always return the entire string followed by `None` error: `splitn` called with `0` splits - --> $DIR/suspicious_splitn.rs:12:13 + --> $DIR/suspicious_splitn.rs:13:13 | LL | let _ = [0, 1, 2].splitn(0, |&x| x == 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -32,7 +32,7 @@ LL | let _ = [0, 1, 2].splitn(0, |&x| x == 1); = note: the resulting iterator will always return `None` error: `splitn_mut` called with `0` splits - --> $DIR/suspicious_splitn.rs:13:13 + --> $DIR/suspicious_splitn.rs:14:13 | LL | let _ = [0, 1, 2].splitn_mut(0, |&x| x == 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -40,7 +40,7 @@ LL | let _ = [0, 1, 2].splitn_mut(0, |&x| x == 1); = note: the resulting iterator will always return `None` error: `splitn` called with `1` split - --> $DIR/suspicious_splitn.rs:14:13 + --> $DIR/suspicious_splitn.rs:15:13 | LL | let _ = [0, 1, 2].splitn(1, |&x| x == 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -48,7 +48,7 @@ LL | let _ = [0, 1, 2].splitn(1, |&x| x == 1); = note: the resulting iterator will always return the entire slice followed by `None` error: `rsplitn_mut` called with `1` split - --> $DIR/suspicious_splitn.rs:15:13 + --> $DIR/suspicious_splitn.rs:16:13 | LL | let _ = [0, 1, 2].rsplitn_mut(1, |&x| x == 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -56,7 +56,7 @@ LL | let _ = [0, 1, 2].rsplitn_mut(1, |&x| x == 1); = note: the resulting iterator will always return the entire slice followed by `None` error: `splitn` called with `1` split - --> $DIR/suspicious_splitn.rs:18:13 + --> $DIR/suspicious_splitn.rs:19:13 | LL | let _ = "a,b".splitn(X + 1, ','); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -64,7 +64,7 @@ LL | let _ = "a,b".splitn(X + 1, ','); = note: the resulting iterator will always return the entire string followed by `None` error: `splitn` called with `0` splits - --> $DIR/suspicious_splitn.rs:19:13 + --> $DIR/suspicious_splitn.rs:20:13 | LL | let _ = "a,b".splitn(X, ','); | ^^^^^^^^^^^^^^^^^^^^