Suggest using Vec::extend() in same_item_push
Using `Vec::extend(std::iter::repeat_n(item, N))` allows to use the more natural number of elements to add `N`, as is probably done in the original loop, instead of computing the difference between the existing number of elements and the wanted one. Before MSRV 1.82, the older suggestion to use `Vec::resize()` is still issued.
This commit is contained in:
parent
ab55d3fc62
commit
ded9354dcf
6 changed files with 66 additions and 28 deletions
|
|
@ -767,6 +767,7 @@ The minimum rust version that the project supports. Defaults to the `rust-versio
|
|||
* [`ptr_as_ptr`](https://rust-lang.github.io/rust-clippy/master/index.html#ptr_as_ptr)
|
||||
* [`redundant_field_names`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_field_names)
|
||||
* [`redundant_static_lifetimes`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes)
|
||||
* [`same_item_push`](https://rust-lang.github.io/rust-clippy/master/index.html#same_item_push)
|
||||
* [`seek_from_current`](https://rust-lang.github.io/rust-clippy/master/index.html#seek_from_current)
|
||||
* [`seek_rewind`](https://rust-lang.github.io/rust-clippy/master/index.html#seek_rewind)
|
||||
* [`transmute_ptr_to_ref`](https://rust-lang.github.io/rust-clippy/master/index.html#transmute_ptr_to_ref)
|
||||
|
|
|
|||
|
|
@ -636,6 +636,7 @@ define_Conf! {
|
|||
ptr_as_ptr,
|
||||
redundant_field_names,
|
||||
redundant_static_lifetimes,
|
||||
same_item_push,
|
||||
seek_from_current,
|
||||
seek_rewind,
|
||||
transmute_ptr_to_ref,
|
||||
|
|
|
|||
|
|
@ -830,7 +830,7 @@ impl Loops {
|
|||
for_kv_map::check(cx, pat, arg, body);
|
||||
mut_range_bound::check(cx, arg, body);
|
||||
single_element_loop::check(cx, pat, arg, body, expr);
|
||||
same_item_push::check(cx, pat, arg, body, expr);
|
||||
same_item_push::check(cx, pat, arg, body, expr, &self.msrv);
|
||||
manual_flatten::check(cx, pat, arg, body, span);
|
||||
manual_find::check(cx, pat, arg, body, span, expr);
|
||||
unused_enumerate_index::check(cx, pat, arg, body);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
use super::SAME_ITEM_PUSH;
|
||||
use clippy_utils::diagnostics::span_lint_and_help;
|
||||
use clippy_utils::path_to_local;
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::msrvs::Msrv;
|
||||
use clippy_utils::source::snippet_with_context;
|
||||
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
|
||||
use clippy_utils::{msrvs, path_to_local, std_or_core};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
|
|
@ -19,19 +20,30 @@ pub(super) fn check<'tcx>(
|
|||
_: &'tcx Expr<'_>,
|
||||
body: &'tcx Expr<'_>,
|
||||
_: &'tcx Expr<'_>,
|
||||
msrv: &Msrv,
|
||||
) {
|
||||
fn emit_lint(cx: &LateContext<'_>, vec: &Expr<'_>, pushed_item: &Expr<'_>, ctxt: SyntaxContext) {
|
||||
fn emit_lint(cx: &LateContext<'_>, vec: &Expr<'_>, pushed_item: &Expr<'_>, ctxt: SyntaxContext, msrv: &Msrv) {
|
||||
let mut app = Applicability::Unspecified;
|
||||
let vec_str = snippet_with_context(cx, vec.span, ctxt, "", &mut app).0;
|
||||
let item_str = snippet_with_context(cx, pushed_item.span, ctxt, "", &mut app).0;
|
||||
|
||||
span_lint_and_help(
|
||||
let secondary_help = if msrv.meets(msrvs::REPEAT_N)
|
||||
&& let Some(std_or_core) = std_or_core(cx)
|
||||
{
|
||||
format!("or `{vec_str}.extend({std_or_core}::iter::repeat_n({item_str}, SIZE))`")
|
||||
} else {
|
||||
format!("or `{vec_str}.resize(NEW_SIZE, {item_str})`")
|
||||
};
|
||||
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
SAME_ITEM_PUSH,
|
||||
vec.span,
|
||||
"it looks like the same item is being pushed into this Vec",
|
||||
None,
|
||||
format!("consider using vec![{item_str};SIZE] or {vec_str}.resize(NEW_SIZE, {item_str})"),
|
||||
"it looks like the same item is being pushed into this `Vec`",
|
||||
|diag| {
|
||||
diag.help(format!("consider using `vec![{item_str};SIZE]`"))
|
||||
.help(secondary_help);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -67,11 +79,11 @@ pub(super) fn check<'tcx>(
|
|||
{
|
||||
match init.kind {
|
||||
// immutable bindings that are initialized with literal
|
||||
ExprKind::Lit(..) => emit_lint(cx, vec, pushed_item, ctxt),
|
||||
ExprKind::Lit(..) => emit_lint(cx, vec, pushed_item, ctxt, msrv),
|
||||
// immutable bindings that are initialized with constant
|
||||
ExprKind::Path(ref path) => {
|
||||
if let Res::Def(DefKind::Const, ..) = cx.qpath_res(path, init.hir_id) {
|
||||
emit_lint(cx, vec, pushed_item, ctxt);
|
||||
emit_lint(cx, vec, pushed_item, ctxt, msrv);
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
|
|
@ -79,11 +91,11 @@ pub(super) fn check<'tcx>(
|
|||
}
|
||||
},
|
||||
// constant
|
||||
Res::Def(DefKind::Const, ..) => emit_lint(cx, vec, pushed_item, ctxt),
|
||||
Res::Def(DefKind::Const, ..) => emit_lint(cx, vec, pushed_item, ctxt, msrv),
|
||||
_ => {},
|
||||
}
|
||||
},
|
||||
ExprKind::Lit(..) => emit_lint(cx, vec, pushed_item, ctxt),
|
||||
ExprKind::Lit(..) => emit_lint(cx, vec, pushed_item, ctxt, msrv),
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,33 +21,43 @@ fn main() {
|
|||
let item = 2;
|
||||
for _ in 5..=20 {
|
||||
vec.push(item);
|
||||
//~^ ERROR: it looks like the same item is being pushed into this Vec
|
||||
//~^ ERROR: it looks like the same item is being pushed into this `Vec`
|
||||
}
|
||||
|
||||
let mut vec: Vec<u8> = Vec::new();
|
||||
for _ in 0..15 {
|
||||
let item = 2;
|
||||
vec.push(item);
|
||||
//~^ ERROR: it looks like the same item is being pushed into this Vec
|
||||
//~^ ERROR: it looks like the same item is being pushed into this `Vec`
|
||||
}
|
||||
|
||||
let mut vec: Vec<u8> = Vec::new();
|
||||
for _ in 0..15 {
|
||||
vec.push(13);
|
||||
//~^ ERROR: it looks like the same item is being pushed into this Vec
|
||||
//~^ ERROR: it looks like the same item is being pushed into this `Vec`
|
||||
}
|
||||
|
||||
let mut vec = Vec::new();
|
||||
for _ in 0..20 {
|
||||
vec.push(VALUE);
|
||||
//~^ ERROR: it looks like the same item is being pushed into this Vec
|
||||
//~^ ERROR: it looks like the same item is being pushed into this `Vec`
|
||||
}
|
||||
|
||||
let mut vec = Vec::new();
|
||||
let item = VALUE;
|
||||
for _ in 0..20 {
|
||||
vec.push(item);
|
||||
//~^ ERROR: it looks like the same item is being pushed into this Vec
|
||||
//~^ ERROR: it looks like the same item is being pushed into this `Vec`
|
||||
}
|
||||
|
||||
#[clippy::msrv = "1.81"]
|
||||
fn older_msrv() {
|
||||
let mut vec = Vec::new();
|
||||
let item = VALUE;
|
||||
for _ in 0..20 {
|
||||
vec.push(item);
|
||||
//~^ ERROR: it looks like the same item is being pushed into this `Vec`
|
||||
}
|
||||
}
|
||||
|
||||
// ** non-linted cases **
|
||||
|
|
|
|||
|
|
@ -1,44 +1,58 @@
|
|||
error: it looks like the same item is being pushed into this Vec
|
||||
error: it looks like the same item is being pushed into this `Vec`
|
||||
--> tests/ui/same_item_push.rs:23:9
|
||||
|
|
||||
LL | vec.push(item);
|
||||
| ^^^
|
||||
|
|
||||
= help: consider using vec![item;SIZE] or vec.resize(NEW_SIZE, item)
|
||||
= help: consider using `vec![item;SIZE]`
|
||||
= help: or `vec.extend(std::iter::repeat_n(item, SIZE))`
|
||||
= note: `-D clippy::same-item-push` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::same_item_push)]`
|
||||
|
||||
error: it looks like the same item is being pushed into this Vec
|
||||
error: it looks like the same item is being pushed into this `Vec`
|
||||
--> tests/ui/same_item_push.rs:30:9
|
||||
|
|
||||
LL | vec.push(item);
|
||||
| ^^^
|
||||
|
|
||||
= help: consider using vec![item;SIZE] or vec.resize(NEW_SIZE, item)
|
||||
= help: consider using `vec![item;SIZE]`
|
||||
= help: or `vec.extend(std::iter::repeat_n(item, SIZE))`
|
||||
|
||||
error: it looks like the same item is being pushed into this Vec
|
||||
error: it looks like the same item is being pushed into this `Vec`
|
||||
--> tests/ui/same_item_push.rs:36:9
|
||||
|
|
||||
LL | vec.push(13);
|
||||
| ^^^
|
||||
|
|
||||
= help: consider using vec![13;SIZE] or vec.resize(NEW_SIZE, 13)
|
||||
= help: consider using `vec![13;SIZE]`
|
||||
= help: or `vec.extend(std::iter::repeat_n(13, SIZE))`
|
||||
|
||||
error: it looks like the same item is being pushed into this Vec
|
||||
error: it looks like the same item is being pushed into this `Vec`
|
||||
--> tests/ui/same_item_push.rs:42:9
|
||||
|
|
||||
LL | vec.push(VALUE);
|
||||
| ^^^
|
||||
|
|
||||
= help: consider using vec![VALUE;SIZE] or vec.resize(NEW_SIZE, VALUE)
|
||||
= help: consider using `vec![VALUE;SIZE]`
|
||||
= help: or `vec.extend(std::iter::repeat_n(VALUE, SIZE))`
|
||||
|
||||
error: it looks like the same item is being pushed into this Vec
|
||||
error: it looks like the same item is being pushed into this `Vec`
|
||||
--> tests/ui/same_item_push.rs:49:9
|
||||
|
|
||||
LL | vec.push(item);
|
||||
| ^^^
|
||||
|
|
||||
= help: consider using vec![item;SIZE] or vec.resize(NEW_SIZE, item)
|
||||
= help: consider using `vec![item;SIZE]`
|
||||
= help: or `vec.extend(std::iter::repeat_n(item, SIZE))`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
error: it looks like the same item is being pushed into this `Vec`
|
||||
--> tests/ui/same_item_push.rs:58:13
|
||||
|
|
||||
LL | vec.push(item);
|
||||
| ^^^
|
||||
|
|
||||
= help: consider using `vec![item;SIZE]`
|
||||
= help: or `vec.resize(NEW_SIZE, item)`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue