mirror of
https://github.com/rust-lang/rust-clippy
synced 2025-02-17 14:38:46 +00:00
Evaluate constant expressions in suspicious_splitn
This commit is contained in:
parent
898b6a0e07
commit
5fa08eaf53
4 changed files with 34 additions and 9 deletions
|
@ -1635,8 +1635,9 @@ declare_clippy_lint! {
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_clippy_lint! {
|
declare_clippy_lint! {
|
||||||
/// **What it does:** Checks for calls to `splitn` and related functions with
|
/// **What it does:** Checks for calls to [`splitn`]
|
||||||
/// either zero or one splits.
|
/// (https://doc.rust-lang.org/std/primitive.str.html#method.splitn) and
|
||||||
|
/// related functions with either zero or one splits.
|
||||||
///
|
///
|
||||||
/// **Why is this bad?** These calls don't actually split the value and are
|
/// **Why is this bad?** These calls don't actually split the value and are
|
||||||
/// likely to be intended as a different number.
|
/// likely to be intended as a different number.
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use clippy_utils::consts::{constant, Constant};
|
||||||
use clippy_utils::diagnostics::span_lint_and_note;
|
use clippy_utils::diagnostics::span_lint_and_note;
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc_ast::LitKind;
|
use rustc_ast::LitKind;
|
||||||
|
@ -15,18 +16,21 @@ pub(super) fn check(
|
||||||
count_arg: &Expr<'_>,
|
count_arg: &Expr<'_>,
|
||||||
) {
|
) {
|
||||||
if_chain! {
|
if_chain! {
|
||||||
// Ignore empty slice literal
|
if let Some((Constant::Int(count), _)) = constant(cx, cx.typeck_results(), count_arg);
|
||||||
if !matches!(self_arg.kind, ExprKind::Array([]));
|
|
||||||
// Ignore empty string literal
|
|
||||||
if !matches!(self_arg.kind, ExprKind::Lit(Spanned { node: LitKind::Str(s, _), .. }) if s.is_empty());
|
|
||||||
if let ExprKind::Lit(count_lit) = &count_arg.kind;
|
|
||||||
if let LitKind::Int(count, _) = count_lit.node;
|
|
||||||
if count <= 1;
|
if count <= 1;
|
||||||
if let Some(call_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
|
if let Some(call_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
|
||||||
if let Some(impl_id) = cx.tcx.impl_of_method(call_id);
|
if let Some(impl_id) = cx.tcx.impl_of_method(call_id);
|
||||||
let lang_items = cx.tcx.lang_items();
|
let lang_items = cx.tcx.lang_items();
|
||||||
if lang_items.slice_impl() == Some(impl_id) || lang_items.str_impl() == Some(impl_id);
|
if lang_items.slice_impl() == Some(impl_id) || lang_items.str_impl() == Some(impl_id);
|
||||||
then {
|
then {
|
||||||
|
// Ignore empty slice and string literals when used with a literal count.
|
||||||
|
if (matches!(self_arg.kind, ExprKind::Array([]))
|
||||||
|
|| matches!(self_arg.kind, ExprKind::Lit(Spanned { node: LitKind::Str(s, _), .. }) if s.is_empty())
|
||||||
|
) && matches!(count_arg.kind, ExprKind::Lit(_))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let (msg, note_msg) = if count == 0 {
|
let (msg, note_msg) = if count == 0 {
|
||||||
(format!("`{}` called with `0` splits", method_name),
|
(format!("`{}` called with `0` splits", method_name),
|
||||||
"the resulting iterator will always return `None`")
|
"the resulting iterator will always return `None`")
|
||||||
|
|
|
@ -13,4 +13,8 @@ fn main() {
|
||||||
let _ = [0, 1, 2].splitn_mut(0, |&x| x == 1);
|
let _ = [0, 1, 2].splitn_mut(0, |&x| x == 1);
|
||||||
let _ = [0, 1, 2].splitn(1, |&x| x == 1);
|
let _ = [0, 1, 2].splitn(1, |&x| x == 1);
|
||||||
let _ = [0, 1, 2].rsplitn_mut(1, |&x| x == 1);
|
let _ = [0, 1, 2].rsplitn_mut(1, |&x| x == 1);
|
||||||
|
|
||||||
|
const X: usize = 0;
|
||||||
|
let _ = "a,b".splitn(X + 1, ',');
|
||||||
|
let _ = "a,b".splitn(X, ',');
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,5 +55,21 @@ LL | let _ = [0, 1, 2].rsplitn_mut(1, |&x| x == 1);
|
||||||
|
|
|
|
||||||
= note: the resulting iterator will always return the entire slice followed by `None`
|
= note: the resulting iterator will always return the entire slice followed by `None`
|
||||||
|
|
||||||
error: aborting due to 7 previous errors
|
error: `splitn` called with `1` split
|
||||||
|
--> $DIR/suspicious_splitn.rs:18:13
|
||||||
|
|
|
||||||
|
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
|
||||||
|
|
|
||||||
|
LL | let _ = "a,b".splitn(X, ',');
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: the resulting iterator will always return `None`
|
||||||
|
|
||||||
|
error: aborting due to 9 previous errors
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue