mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-24 05:33:27 +00:00
Auto merge of #8631 - Alexendoo:splitn-overlap, r=xFrednet
Remove overlap between `manual_split_once` and `needless_splitn` changelog: Remove overlap between [`manual_split_once`] and [`needless_splitn`]. Fixes some incorrect `rsplitn` suggestions for [`manual_split_once`] Things that can trigger `needless_splitn` no longer trigger `manual_split_once`, e.g. ```rust s.[r]splitn(2, '=').next(); s.[r]splitn(2, '=').nth(0); s.[r]splitn(3, '=').next_tuple(); ``` Fixes some suggestions: ```rust let s = "should not match"; s.rsplitn(2, '.').nth(1); // old -> Some("should not match") Some(s.rsplit_once('.').map_or(s, |x| x.0)); // new -> None s.rsplit_once('.').map(|x| x.0); s.rsplitn(2, '.').nth(1)?; // old -> "should not match" s.rsplit_once('.').map_or(s, |x| x.0); // new -> early returns s.rsplit_once('.')?.0; ```
This commit is contained in:
commit
5344236715
9 changed files with 221 additions and 264 deletions
|
@ -2574,12 +2574,7 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio
|
||||||
("splitn" | "rsplitn", [count_arg, pat_arg]) => {
|
("splitn" | "rsplitn", [count_arg, pat_arg]) => {
|
||||||
if let Some((Constant::Int(count), _)) = constant(cx, cx.typeck_results(), count_arg) {
|
if let Some((Constant::Int(count), _)) = constant(cx, cx.typeck_results(), count_arg) {
|
||||||
suspicious_splitn::check(cx, name, expr, recv, count);
|
suspicious_splitn::check(cx, name, expr, recv, count);
|
||||||
if count == 2 && meets_msrv(msrv, &msrvs::STR_SPLIT_ONCE) {
|
str_splitn::check(cx, name, expr, recv, pat_arg, count, msrv);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
("splitn_mut" | "rsplitn_mut", [count_arg, _]) => {
|
("splitn_mut" | "rsplitn_mut", [count_arg, _]) => {
|
||||||
|
|
|
@ -1,36 +1,77 @@
|
||||||
use clippy_utils::consts::{constant, Constant};
|
use clippy_utils::consts::{constant, Constant};
|
||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
use clippy_utils::source::snippet_with_context;
|
use clippy_utils::source::snippet_with_context;
|
||||||
use clippy_utils::{is_diag_item_method, match_def_path, paths};
|
use clippy_utils::{is_diag_item_method, match_def_path, meets_msrv, msrvs, paths};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::{Expr, ExprKind, HirId, LangItem, Node, QPath};
|
use rustc_hir::{Expr, ExprKind, HirId, LangItem, Node, QPath};
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
use rustc_middle::ty::{self, adjustment::Adjust};
|
use rustc_middle::ty;
|
||||||
|
use rustc_semver::RustcVersion;
|
||||||
use rustc_span::{symbol::sym, Span, SyntaxContext};
|
use rustc_span::{symbol::sym, Span, SyntaxContext};
|
||||||
|
|
||||||
use super::MANUAL_SPLIT_ONCE;
|
use super::{MANUAL_SPLIT_ONCE, NEEDLESS_SPLITN};
|
||||||
|
|
||||||
pub(super) fn check_manual_split_once(
|
pub(super) fn check(
|
||||||
cx: &LateContext<'_>,
|
cx: &LateContext<'_>,
|
||||||
method_name: &str,
|
method_name: &str,
|
||||||
expr: &Expr<'_>,
|
expr: &Expr<'_>,
|
||||||
self_arg: &Expr<'_>,
|
self_arg: &Expr<'_>,
|
||||||
pat_arg: &Expr<'_>,
|
pat_arg: &Expr<'_>,
|
||||||
|
count: u128,
|
||||||
|
msrv: Option<&RustcVersion>,
|
||||||
) {
|
) {
|
||||||
if !cx.typeck_results().expr_ty_adjusted(self_arg).peel_refs().is_str() {
|
if count < 2 || !cx.typeck_results().expr_ty_adjusted(self_arg).peel_refs().is_str() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let ctxt = expr.span.ctxt();
|
let ctxt = expr.span.ctxt();
|
||||||
let (method_name, msg, reverse) = if method_name == "splitn" {
|
let Some(usage) = parse_iter_usage(cx, ctxt, cx.tcx.hir().parent_iter(expr.hir_id)) else { return };
|
||||||
("split_once", "manual implementation of `split_once`", false)
|
|
||||||
} else {
|
let needless = match usage.kind {
|
||||||
("rsplit_once", "manual implementation of `rsplit_once`", true)
|
IterUsageKind::Nth(n) => count > n + 1,
|
||||||
|
IterUsageKind::NextTuple => count > 2,
|
||||||
};
|
};
|
||||||
let usage = match parse_iter_usage(cx, ctxt, cx.tcx.hir().parent_iter(expr.hir_id), reverse) {
|
|
||||||
Some(x) => x,
|
if needless {
|
||||||
None => return,
|
let mut app = Applicability::MachineApplicable;
|
||||||
|
let (r, message) = if method_name == "splitn" {
|
||||||
|
("", "unnecessary use of `splitn`")
|
||||||
|
} else {
|
||||||
|
("r", "unnecessary use of `rsplitn`")
|
||||||
|
};
|
||||||
|
|
||||||
|
span_lint_and_sugg(
|
||||||
|
cx,
|
||||||
|
NEEDLESS_SPLITN,
|
||||||
|
expr.span,
|
||||||
|
message,
|
||||||
|
"try this",
|
||||||
|
format!(
|
||||||
|
"{}.{r}split({})",
|
||||||
|
snippet_with_context(cx, self_arg.span, ctxt, "..", &mut app).0,
|
||||||
|
snippet_with_context(cx, pat_arg.span, ctxt, "..", &mut app).0,
|
||||||
|
),
|
||||||
|
app,
|
||||||
|
);
|
||||||
|
} else if count == 2 && meets_msrv(msrv, &msrvs::STR_SPLIT_ONCE) {
|
||||||
|
check_manual_split_once(cx, method_name, expr, self_arg, pat_arg, &usage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_manual_split_once(
|
||||||
|
cx: &LateContext<'_>,
|
||||||
|
method_name: &str,
|
||||||
|
expr: &Expr<'_>,
|
||||||
|
self_arg: &Expr<'_>,
|
||||||
|
pat_arg: &Expr<'_>,
|
||||||
|
usage: &IterUsage,
|
||||||
|
) {
|
||||||
|
let ctxt = expr.span.ctxt();
|
||||||
|
let (msg, reverse) = if method_name == "splitn" {
|
||||||
|
("manual implementation of `split_once`", false)
|
||||||
|
} else {
|
||||||
|
("manual implementation of `rsplit_once`", true)
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut app = Applicability::MachineApplicable;
|
let mut app = Applicability::MachineApplicable;
|
||||||
|
@ -39,77 +80,36 @@ pub(super) fn check_manual_split_once(
|
||||||
|
|
||||||
let sugg = match usage.kind {
|
let sugg = match usage.kind {
|
||||||
IterUsageKind::NextTuple => {
|
IterUsageKind::NextTuple => {
|
||||||
format!("{}.{}({})", self_snip, method_name, pat_snip)
|
if reverse {
|
||||||
},
|
format!("{self_snip}.rsplit_once({pat_snip}).map(|(x, y)| (y, x))")
|
||||||
IterUsageKind::RNextTuple => format!("{}.{}({}).map(|(x, y)| (y, x))", self_snip, method_name, pat_snip),
|
|
||||||
IterUsageKind::Next | IterUsageKind::Second => {
|
|
||||||
let self_deref = {
|
|
||||||
let adjust = cx.typeck_results().expr_adjustments(self_arg);
|
|
||||||
if adjust.len() < 2 {
|
|
||||||
String::new()
|
|
||||||
} else if cx.typeck_results().expr_ty(self_arg).is_box()
|
|
||||||
|| adjust
|
|
||||||
.iter()
|
|
||||||
.any(|a| matches!(a.kind, Adjust::Deref(Some(_))) || a.target.is_box())
|
|
||||||
{
|
|
||||||
format!("&{}", "*".repeat(adjust.len().saturating_sub(1)))
|
|
||||||
} else {
|
|
||||||
"*".repeat(adjust.len().saturating_sub(2))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
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 {
|
} else {
|
||||||
match usage.unwrap_kind {
|
format!("{self_snip}.split_once({pat_snip})")
|
||||||
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::Nth(1) => {
|
||||||
|
let (r, field) = if reverse { ("r", 0) } else { ("", 1) };
|
||||||
|
|
||||||
|
match usage.unwrap_kind {
|
||||||
|
Some(UnwrapKind::Unwrap) => {
|
||||||
|
format!("{self_snip}.{r}split_once({pat_snip}).unwrap().{field}")
|
||||||
|
},
|
||||||
|
Some(UnwrapKind::QuestionMark) => {
|
||||||
|
format!("{self_snip}.{r}split_once({pat_snip})?.{field}")
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
format!("{self_snip}.{r}split_once({pat_snip}).map(|x| x.{field})")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
IterUsageKind::Nth(_) => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
span_lint_and_sugg(cx, MANUAL_SPLIT_ONCE, usage.span, msg, "try this", sugg, app);
|
span_lint_and_sugg(cx, MANUAL_SPLIT_ONCE, usage.span, msg, "try this", sugg, app);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum IterUsageKind {
|
enum IterUsageKind {
|
||||||
Next,
|
Nth(u128),
|
||||||
Second,
|
|
||||||
NextTuple,
|
NextTuple,
|
||||||
RNextTuple,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum UnwrapKind {
|
enum UnwrapKind {
|
||||||
|
@ -128,7 +128,6 @@ fn parse_iter_usage<'tcx>(
|
||||||
cx: &LateContext<'tcx>,
|
cx: &LateContext<'tcx>,
|
||||||
ctxt: SyntaxContext,
|
ctxt: SyntaxContext,
|
||||||
mut iter: impl Iterator<Item = (HirId, Node<'tcx>)>,
|
mut iter: impl Iterator<Item = (HirId, Node<'tcx>)>,
|
||||||
reverse: bool,
|
|
||||||
) -> Option<IterUsage> {
|
) -> Option<IterUsage> {
|
||||||
let (kind, span) = match iter.next() {
|
let (kind, span) = match iter.next() {
|
||||||
Some((_, Node::Expr(e))) if e.span.ctxt() == ctxt => {
|
Some((_, Node::Expr(e))) if e.span.ctxt() == ctxt => {
|
||||||
|
@ -141,13 +140,7 @@ fn parse_iter_usage<'tcx>(
|
||||||
let iter_id = cx.tcx.get_diagnostic_item(sym::Iterator)?;
|
let iter_id = cx.tcx.get_diagnostic_item(sym::Iterator)?;
|
||||||
|
|
||||||
match (name.ident.as_str(), args) {
|
match (name.ident.as_str(), args) {
|
||||||
("next", []) if cx.tcx.trait_of_item(did) == Some(iter_id) => {
|
("next", []) if cx.tcx.trait_of_item(did) == Some(iter_id) => (IterUsageKind::Nth(0), e.span),
|
||||||
if reverse {
|
|
||||||
(IterUsageKind::Second, e.span)
|
|
||||||
} else {
|
|
||||||
(IterUsageKind::Next, e.span)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
("next_tuple", []) => {
|
("next_tuple", []) => {
|
||||||
return if_chain! {
|
return if_chain! {
|
||||||
if match_def_path(cx, did, &paths::ITERTOOLS_NEXT_TUPLE);
|
if match_def_path(cx, did, &paths::ITERTOOLS_NEXT_TUPLE);
|
||||||
|
@ -157,7 +150,7 @@ fn parse_iter_usage<'tcx>(
|
||||||
if subs.len() == 2;
|
if subs.len() == 2;
|
||||||
then {
|
then {
|
||||||
Some(IterUsage {
|
Some(IterUsage {
|
||||||
kind: if reverse { IterUsageKind::RNextTuple } else { IterUsageKind::NextTuple },
|
kind: IterUsageKind::NextTuple,
|
||||||
span: e.span,
|
span: e.span,
|
||||||
unwrap_kind: None
|
unwrap_kind: None
|
||||||
})
|
})
|
||||||
|
@ -185,11 +178,7 @@ fn parse_iter_usage<'tcx>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
match if reverse { idx ^ 1 } else { idx } {
|
(IterUsageKind::Nth(idx), span)
|
||||||
0 => (IterUsageKind::Next, span),
|
|
||||||
1 => (IterUsageKind::Second, span),
|
|
||||||
_ => return None,
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
@ -238,86 +227,3 @@ fn parse_iter_usage<'tcx>(
|
||||||
span,
|
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<'tcx>(
|
|
||||||
cx: &LateContext<'tcx>,
|
|
||||||
ctxt: SyntaxContext,
|
|
||||||
mut iter: impl Iterator<Item = (HirId, Node<'tcx>)>,
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,11 +1,3 @@
|
||||||
error: manual implementation of `split_once`
|
|
||||||
--> $DIR/ice-8250.rs:2:13
|
|
||||||
|
|
|
||||||
LL | let _ = s[1..].splitn(2, '.').next()?;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s[1..].split_once('.').map_or(s[1..], |x| x.0)`
|
|
||||||
|
|
|
||||||
= note: `-D clippy::manual-split-once` implied by `-D warnings`
|
|
||||||
|
|
||||||
error: unnecessary use of `splitn`
|
error: unnecessary use of `splitn`
|
||||||
--> $DIR/ice-8250.rs:2:13
|
--> $DIR/ice-8250.rs:2:13
|
||||||
|
|
|
|
||||||
|
@ -14,5 +6,5 @@ LL | let _ = s[1..].splitn(2, '.').next()?;
|
||||||
|
|
|
|
||||||
= note: `-D clippy::needless-splitn` implied by `-D warnings`
|
= note: `-D clippy::needless-splitn` implied by `-D warnings`
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#![feature(custom_inner_attributes)]
|
#![feature(custom_inner_attributes)]
|
||||||
#![warn(clippy::manual_split_once)]
|
#![warn(clippy::manual_split_once)]
|
||||||
#![allow(clippy::iter_skip_next, clippy::iter_nth_zero, clippy::needless_splitn)]
|
#![allow(clippy::iter_skip_next, clippy::iter_nth_zero)]
|
||||||
|
|
||||||
extern crate itertools;
|
extern crate itertools;
|
||||||
|
|
||||||
|
@ -10,27 +10,25 @@ extern crate itertools;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let _ = Some("key=value".split_once('=').map_or("key=value", |x| x.0));
|
|
||||||
let _ = "key=value".splitn(2, '=').nth(2);
|
let _ = "key=value".splitn(2, '=').nth(2);
|
||||||
let _ = "key=value".split_once('=').map_or("key=value", |x| x.0);
|
|
||||||
let _ = "key=value".split_once('=').map_or("key=value", |x| x.0);
|
|
||||||
let _ = "key=value".split_once('=').unwrap().1;
|
let _ = "key=value".split_once('=').unwrap().1;
|
||||||
let _ = "key=value".split_once('=').unwrap().1;
|
let _ = "key=value".split_once('=').unwrap().1;
|
||||||
let (_, _) = "key=value".split_once('=').unwrap();
|
let (_, _) = "key=value".split_once('=').unwrap();
|
||||||
|
|
||||||
let s = String::from("key=value");
|
let s = String::from("key=value");
|
||||||
let _ = s.split_once('=').map_or(&*s, |x| x.0);
|
let _ = s.split_once('=').unwrap().1;
|
||||||
|
|
||||||
let s = Box::<str>::from("key=value");
|
let s = Box::<str>::from("key=value");
|
||||||
let _ = s.split_once('=').map_or(&*s, |x| x.0);
|
let _ = s.split_once('=').unwrap().1;
|
||||||
|
|
||||||
let s = &"key=value";
|
let s = &"key=value";
|
||||||
let _ = s.split_once('=').map_or(*s, |x| x.0);
|
let _ = s.split_once('=').unwrap().1;
|
||||||
|
|
||||||
fn _f(s: &str) -> Option<&str> {
|
fn _f(s: &str) -> Option<&str> {
|
||||||
let _ = s.split_once("key=value").map_or(s, |x| x.0);
|
let _ = s.split_once('=')?.1;
|
||||||
let _ = s.split_once("key=value")?.1;
|
let _ = s.split_once('=')?.1;
|
||||||
let _ = s.split_once("key=value")?.1;
|
let _ = s.rsplit_once('=')?.0;
|
||||||
|
let _ = s.rsplit_once('=')?.0;
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,10 +36,9 @@ fn main() {
|
||||||
let _ = [0, 1, 2].splitn(2, |&x| x == 1).nth(1).unwrap();
|
let _ = [0, 1, 2].splitn(2, |&x| x == 1).nth(1).unwrap();
|
||||||
|
|
||||||
// `rsplitn` gives the results in the reverse order of `rsplit_once`
|
// `rsplitn` gives the results in the reverse order of `rsplit_once`
|
||||||
let _ = "key=value".rsplitn(2, '=').next().unwrap();
|
|
||||||
let _ = "key=value".rsplit_once('=').unwrap().0;
|
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();
|
let (_, _) = "key=value".rsplit_once('=').map(|(x, y)| (y, x)).unwrap();
|
||||||
|
let _ = s.rsplit_once('=').map(|x| x.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _msrv_1_51() {
|
fn _msrv_1_51() {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#![feature(custom_inner_attributes)]
|
#![feature(custom_inner_attributes)]
|
||||||
#![warn(clippy::manual_split_once)]
|
#![warn(clippy::manual_split_once)]
|
||||||
#![allow(clippy::iter_skip_next, clippy::iter_nth_zero, clippy::needless_splitn)]
|
#![allow(clippy::iter_skip_next, clippy::iter_nth_zero)]
|
||||||
|
|
||||||
extern crate itertools;
|
extern crate itertools;
|
||||||
|
|
||||||
|
@ -10,27 +10,25 @@ extern crate itertools;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let _ = "key=value".splitn(2, '=').next();
|
|
||||||
let _ = "key=value".splitn(2, '=').nth(2);
|
let _ = "key=value".splitn(2, '=').nth(2);
|
||||||
let _ = "key=value".splitn(2, '=').next().unwrap();
|
|
||||||
let _ = "key=value".splitn(2, '=').nth(0).unwrap();
|
|
||||||
let _ = "key=value".splitn(2, '=').nth(1).unwrap();
|
let _ = "key=value".splitn(2, '=').nth(1).unwrap();
|
||||||
let _ = "key=value".splitn(2, '=').skip(1).next().unwrap();
|
let _ = "key=value".splitn(2, '=').skip(1).next().unwrap();
|
||||||
let (_, _) = "key=value".splitn(2, '=').next_tuple().unwrap();
|
let (_, _) = "key=value".splitn(2, '=').next_tuple().unwrap();
|
||||||
|
|
||||||
let s = String::from("key=value");
|
let s = String::from("key=value");
|
||||||
let _ = s.splitn(2, '=').next().unwrap();
|
let _ = s.splitn(2, '=').nth(1).unwrap();
|
||||||
|
|
||||||
let s = Box::<str>::from("key=value");
|
let s = Box::<str>::from("key=value");
|
||||||
let _ = s.splitn(2, '=').nth(0).unwrap();
|
let _ = s.splitn(2, '=').nth(1).unwrap();
|
||||||
|
|
||||||
let s = &"key=value";
|
let s = &"key=value";
|
||||||
let _ = s.splitn(2, '=').skip(0).next().unwrap();
|
let _ = s.splitn(2, '=').skip(1).next().unwrap();
|
||||||
|
|
||||||
fn _f(s: &str) -> Option<&str> {
|
fn _f(s: &str) -> Option<&str> {
|
||||||
let _ = s.splitn(2, "key=value").next()?;
|
let _ = s.splitn(2, '=').nth(1)?;
|
||||||
let _ = s.splitn(2, "key=value").nth(1)?;
|
let _ = s.splitn(2, '=').skip(1).next()?;
|
||||||
let _ = s.splitn(2, "key=value").skip(1).next()?;
|
let _ = s.rsplitn(2, '=').nth(1)?;
|
||||||
|
let _ = s.rsplitn(2, '=').skip(1).next()?;
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,10 +36,9 @@ fn main() {
|
||||||
let _ = [0, 1, 2].splitn(2, |&x| x == 1).nth(1).unwrap();
|
let _ = [0, 1, 2].splitn(2, |&x| x == 1).nth(1).unwrap();
|
||||||
|
|
||||||
// `rsplitn` gives the results in the reverse order of `rsplit_once`
|
// `rsplitn` gives the results in the reverse order of `rsplit_once`
|
||||||
let _ = "key=value".rsplitn(2, '=').next().unwrap();
|
|
||||||
let _ = "key=value".rsplitn(2, '=').nth(1).unwrap();
|
let _ = "key=value".rsplitn(2, '=').nth(1).unwrap();
|
||||||
let _ = "key=value".rsplitn(2, '=').nth(0);
|
|
||||||
let (_, _) = "key=value".rsplitn(2, '=').next_tuple().unwrap();
|
let (_, _) = "key=value".rsplitn(2, '=').next_tuple().unwrap();
|
||||||
|
let _ = s.rsplitn(2, '=').nth(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _msrv_1_51() {
|
fn _msrv_1_51() {
|
||||||
|
|
|
@ -1,100 +1,88 @@
|
||||||
error: manual implementation of `split_once`
|
error: manual implementation of `split_once`
|
||||||
--> $DIR/manual_split_once.rs:13:13
|
--> $DIR/manual_split_once.rs:14:13
|
||||||
|
|
|
|
||||||
LL | let _ = "key=value".splitn(2, '=').next();
|
LL | let _ = "key=value".splitn(2, '=').nth(1).unwrap();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `Some("key=value".split_once('=').map_or("key=value", |x| x.0))`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".split_once('=').unwrap().1`
|
||||||
|
|
|
|
||||||
= note: `-D clippy::manual-split-once` implied by `-D warnings`
|
= note: `-D clippy::manual-split-once` implied by `-D warnings`
|
||||||
|
|
||||||
error: manual implementation of `split_once`
|
error: manual implementation of `split_once`
|
||||||
--> $DIR/manual_split_once.rs:15:13
|
--> $DIR/manual_split_once.rs:15:13
|
||||||
|
|
|
|
||||||
LL | let _ = "key=value".splitn(2, '=').next().unwrap();
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".split_once('=').map_or("key=value", |x| x.0)`
|
|
||||||
|
|
||||||
error: manual implementation of `split_once`
|
|
||||||
--> $DIR/manual_split_once.rs:16:13
|
|
||||||
|
|
|
||||||
LL | let _ = "key=value".splitn(2, '=').nth(0).unwrap();
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".split_once('=').map_or("key=value", |x| x.0)`
|
|
||||||
|
|
||||||
error: manual implementation of `split_once`
|
|
||||||
--> $DIR/manual_split_once.rs:17:13
|
|
||||||
|
|
|
||||||
LL | let _ = "key=value".splitn(2, '=').nth(1).unwrap();
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".split_once('=').unwrap().1`
|
|
||||||
|
|
||||||
error: manual implementation of `split_once`
|
|
||||||
--> $DIR/manual_split_once.rs:18:13
|
|
||||||
|
|
|
||||||
LL | let _ = "key=value".splitn(2, '=').skip(1).next().unwrap();
|
LL | let _ = "key=value".splitn(2, '=').skip(1).next().unwrap();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".split_once('=').unwrap().1`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".split_once('=').unwrap().1`
|
||||||
|
|
||||||
error: manual implementation of `split_once`
|
error: manual implementation of `split_once`
|
||||||
--> $DIR/manual_split_once.rs:19:18
|
--> $DIR/manual_split_once.rs:16:18
|
||||||
|
|
|
|
||||||
LL | let (_, _) = "key=value".splitn(2, '=').next_tuple().unwrap();
|
LL | let (_, _) = "key=value".splitn(2, '=').next_tuple().unwrap();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".split_once('=')`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".split_once('=')`
|
||||||
|
|
||||||
|
error: manual implementation of `split_once`
|
||||||
|
--> $DIR/manual_split_once.rs:19:13
|
||||||
|
|
|
||||||
|
LL | let _ = s.splitn(2, '=').nth(1).unwrap();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.split_once('=').unwrap().1`
|
||||||
|
|
||||||
error: manual implementation of `split_once`
|
error: manual implementation of `split_once`
|
||||||
--> $DIR/manual_split_once.rs:22:13
|
--> $DIR/manual_split_once.rs:22:13
|
||||||
|
|
|
|
||||||
LL | let _ = s.splitn(2, '=').next().unwrap();
|
LL | let _ = s.splitn(2, '=').nth(1).unwrap();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.split_once('=').map_or(&*s, |x| x.0)`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.split_once('=').unwrap().1`
|
||||||
|
|
||||||
error: manual implementation of `split_once`
|
error: manual implementation of `split_once`
|
||||||
--> $DIR/manual_split_once.rs:25:13
|
--> $DIR/manual_split_once.rs:25:13
|
||||||
|
|
|
|
||||||
LL | let _ = s.splitn(2, '=').nth(0).unwrap();
|
LL | let _ = s.splitn(2, '=').skip(1).next().unwrap();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.split_once('=').map_or(&*s, |x| x.0)`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.split_once('=').unwrap().1`
|
||||||
|
|
||||||
error: manual implementation of `split_once`
|
error: manual implementation of `split_once`
|
||||||
--> $DIR/manual_split_once.rs:28:13
|
--> $DIR/manual_split_once.rs:28:17
|
||||||
|
|
|
|
||||||
LL | let _ = s.splitn(2, '=').skip(0).next().unwrap();
|
LL | let _ = s.splitn(2, '=').nth(1)?;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.split_once('=').map_or(*s, |x| x.0)`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.split_once('=')?.1`
|
||||||
|
|
||||||
error: manual implementation of `split_once`
|
error: manual implementation of `split_once`
|
||||||
--> $DIR/manual_split_once.rs:31:17
|
--> $DIR/manual_split_once.rs:29:17
|
||||||
|
|
|
|
||||||
LL | let _ = s.splitn(2, "key=value").next()?;
|
LL | let _ = s.splitn(2, '=').skip(1).next()?;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.split_once("key=value").map_or(s, |x| x.0)`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.split_once('=')?.1`
|
||||||
|
|
||||||
error: manual implementation of `split_once`
|
|
||||||
--> $DIR/manual_split_once.rs:32:17
|
|
||||||
|
|
|
||||||
LL | let _ = s.splitn(2, "key=value").nth(1)?;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.split_once("key=value")?.1`
|
|
||||||
|
|
||||||
error: manual implementation of `split_once`
|
|
||||||
--> $DIR/manual_split_once.rs:33:17
|
|
||||||
|
|
|
||||||
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`
|
error: manual implementation of `rsplit_once`
|
||||||
--> $DIR/manual_split_once.rs:42:13
|
--> $DIR/manual_split_once.rs:30:17
|
||||||
|
|
|
||||||
|
LL | let _ = s.rsplitn(2, '=').nth(1)?;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.rsplit_once('=')?.0`
|
||||||
|
|
||||||
|
error: manual implementation of `rsplit_once`
|
||||||
|
--> $DIR/manual_split_once.rs:31:17
|
||||||
|
|
|
||||||
|
LL | let _ = s.rsplitn(2, '=').skip(1).next()?;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.rsplit_once('=')?.0`
|
||||||
|
|
||||||
|
error: manual implementation of `rsplit_once`
|
||||||
|
--> $DIR/manual_split_once.rs:39:13
|
||||||
|
|
|
|
||||||
LL | let _ = "key=value".rsplitn(2, '=').nth(1).unwrap();
|
LL | let _ = "key=value".rsplitn(2, '=').nth(1).unwrap();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".rsplit_once('=').unwrap().0`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".rsplit_once('=').unwrap().0`
|
||||||
|
|
||||||
error: manual implementation of `rsplit_once`
|
error: manual implementation of `rsplit_once`
|
||||||
--> $DIR/manual_split_once.rs:43:13
|
--> $DIR/manual_split_once.rs:40:18
|
||||||
|
|
|
||||||
LL | let _ = "key=value".rsplitn(2, '=').nth(0);
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".rsplit_once('=').map(|x| x.1)`
|
|
||||||
|
|
||||||
error: manual implementation of `rsplit_once`
|
|
||||||
--> $DIR/manual_split_once.rs:44:18
|
|
||||||
|
|
|
|
||||||
LL | let (_, _) = "key=value".rsplitn(2, '=').next_tuple().unwrap();
|
LL | let (_, _) = "key=value".rsplitn(2, '=').next_tuple().unwrap();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".rsplit_once('=').map(|(x, y)| (y, x))`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".rsplit_once('=').map(|(x, y)| (y, x))`
|
||||||
|
|
||||||
|
error: manual implementation of `rsplit_once`
|
||||||
|
--> $DIR/manual_split_once.rs:41:13
|
||||||
|
|
|
||||||
|
LL | let _ = s.rsplitn(2, '=').nth(1);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.rsplit_once('=').map(|x| x.0)`
|
||||||
|
|
||||||
error: manual implementation of `split_once`
|
error: manual implementation of `split_once`
|
||||||
--> $DIR/manual_split_once.rs:55:13
|
--> $DIR/manual_split_once.rs:52:13
|
||||||
|
|
|
|
||||||
LL | let _ = "key=value".splitn(2, '=').nth(1).unwrap();
|
LL | let _ = "key=value".splitn(2, '=').nth(1).unwrap();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".split_once('=').unwrap().1`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".split_once('=').unwrap().1`
|
||||||
|
|
||||||
error: aborting due to 16 previous errors
|
error: aborting due to 14 previous errors
|
||||||
|
|
||||||
|
|
|
@ -24,4 +24,24 @@ fn main() {
|
||||||
let _ = str.rsplitn(2, '=').nth(1);
|
let _ = str.rsplitn(2, '=').nth(1);
|
||||||
let (_, _) = str.rsplitn(2, '=').next_tuple().unwrap();
|
let (_, _) = str.rsplitn(2, '=').next_tuple().unwrap();
|
||||||
let (_, _) = str.rsplit('=').next_tuple().unwrap();
|
let (_, _) = str.rsplit('=').next_tuple().unwrap();
|
||||||
|
|
||||||
|
let _ = str.split('=').next();
|
||||||
|
let _ = str.split('=').nth(3);
|
||||||
|
let _ = str.splitn(5, '=').nth(4);
|
||||||
|
let _ = str.splitn(5, '=').nth(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _question_mark(s: &str) -> Option<()> {
|
||||||
|
let _ = s.split('=').next()?;
|
||||||
|
let _ = s.split('=').nth(0)?;
|
||||||
|
let _ = s.rsplit('=').next()?;
|
||||||
|
let _ = s.rsplit('=').nth(0)?;
|
||||||
|
|
||||||
|
Some(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _test_msrv() {
|
||||||
|
#![clippy::msrv = "1.51"]
|
||||||
|
// `manual_split_once` MSRV shouldn't apply to `needless_splitn`
|
||||||
|
let _ = "key=value".split('=').nth(0).unwrap();
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,4 +24,24 @@ fn main() {
|
||||||
let _ = str.rsplitn(2, '=').nth(1);
|
let _ = str.rsplitn(2, '=').nth(1);
|
||||||
let (_, _) = str.rsplitn(2, '=').next_tuple().unwrap();
|
let (_, _) = str.rsplitn(2, '=').next_tuple().unwrap();
|
||||||
let (_, _) = str.rsplitn(3, '=').next_tuple().unwrap();
|
let (_, _) = str.rsplitn(3, '=').next_tuple().unwrap();
|
||||||
|
|
||||||
|
let _ = str.splitn(5, '=').next();
|
||||||
|
let _ = str.splitn(5, '=').nth(3);
|
||||||
|
let _ = str.splitn(5, '=').nth(4);
|
||||||
|
let _ = str.splitn(5, '=').nth(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _question_mark(s: &str) -> Option<()> {
|
||||||
|
let _ = s.splitn(2, '=').next()?;
|
||||||
|
let _ = s.splitn(2, '=').nth(0)?;
|
||||||
|
let _ = s.rsplitn(2, '=').next()?;
|
||||||
|
let _ = s.rsplitn(2, '=').nth(0)?;
|
||||||
|
|
||||||
|
Some(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _test_msrv() {
|
||||||
|
#![clippy::msrv = "1.51"]
|
||||||
|
// `manual_split_once` MSRV shouldn't apply to `needless_splitn`
|
||||||
|
let _ = "key=value".splitn(2, '=').nth(0).unwrap();
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,5 +36,47 @@ error: unnecessary use of `rsplitn`
|
||||||
LL | let (_, _) = str.rsplitn(3, '=').next_tuple().unwrap();
|
LL | let (_, _) = str.rsplitn(3, '=').next_tuple().unwrap();
|
||||||
| ^^^^^^^^^^^^^^^^^^^ help: try this: `str.rsplit('=')`
|
| ^^^^^^^^^^^^^^^^^^^ help: try this: `str.rsplit('=')`
|
||||||
|
|
||||||
error: aborting due to 6 previous errors
|
error: unnecessary use of `splitn`
|
||||||
|
--> $DIR/needless_splitn.rs:28:13
|
||||||
|
|
|
||||||
|
LL | let _ = str.splitn(5, '=').next();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^ help: try this: `str.split('=')`
|
||||||
|
|
||||||
|
error: unnecessary use of `splitn`
|
||||||
|
--> $DIR/needless_splitn.rs:29:13
|
||||||
|
|
|
||||||
|
LL | let _ = str.splitn(5, '=').nth(3);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^ help: try this: `str.split('=')`
|
||||||
|
|
||||||
|
error: unnecessary use of `splitn`
|
||||||
|
--> $DIR/needless_splitn.rs:35:13
|
||||||
|
|
|
||||||
|
LL | let _ = s.splitn(2, '=').next()?;
|
||||||
|
| ^^^^^^^^^^^^^^^^ help: try this: `s.split('=')`
|
||||||
|
|
||||||
|
error: unnecessary use of `splitn`
|
||||||
|
--> $DIR/needless_splitn.rs:36:13
|
||||||
|
|
|
||||||
|
LL | let _ = s.splitn(2, '=').nth(0)?;
|
||||||
|
| ^^^^^^^^^^^^^^^^ help: try this: `s.split('=')`
|
||||||
|
|
||||||
|
error: unnecessary use of `rsplitn`
|
||||||
|
--> $DIR/needless_splitn.rs:37:13
|
||||||
|
|
|
||||||
|
LL | let _ = s.rsplitn(2, '=').next()?;
|
||||||
|
| ^^^^^^^^^^^^^^^^^ help: try this: `s.rsplit('=')`
|
||||||
|
|
||||||
|
error: unnecessary use of `rsplitn`
|
||||||
|
--> $DIR/needless_splitn.rs:38:13
|
||||||
|
|
|
||||||
|
LL | let _ = s.rsplitn(2, '=').nth(0)?;
|
||||||
|
| ^^^^^^^^^^^^^^^^^ help: try this: `s.rsplit('=')`
|
||||||
|
|
||||||
|
error: unnecessary use of `splitn`
|
||||||
|
--> $DIR/needless_splitn.rs:46:13
|
||||||
|
|
|
||||||
|
LL | let _ = "key=value".splitn(2, '=').nth(0).unwrap();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".split('=')`
|
||||||
|
|
||||||
|
error: aborting due to 13 previous errors
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue