clean-up
- move `is_allowed_vec_method` (a stripped-down version of it, anyway, as the function doesn't make sense as is out of context) to utils, as it's shared between `useless_vec` and `ptr_arg` - add another test for non-standard macro brace case - rm unneeded `allow`s - rm duplicated tests - add comments to some tests
This commit is contained in:
parent
91779ae78f
commit
bbb251a25f
8 changed files with 85 additions and 104 deletions
|
|
@ -2,7 +2,7 @@ use super::PTR_ARG;
|
|||
use clippy_utils::diagnostics::span_lint_hir_and_then;
|
||||
use clippy_utils::res::MaybeResPath;
|
||||
use clippy_utils::source::SpanRangeExt;
|
||||
use clippy_utils::{get_expr_use_or_unification_node, is_lint_allowed, sym};
|
||||
use clippy_utils::{VEC_METHODS_SHADOWING_SLICE_METHODS, get_expr_use_or_unification_node, is_lint_allowed, sym};
|
||||
use hir::LifetimeKind;
|
||||
use rustc_abi::ExternAbi;
|
||||
use rustc_errors::Applicability;
|
||||
|
|
@ -23,8 +23,6 @@ use rustc_trait_selection::infer::InferCtxtExt as _;
|
|||
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
|
||||
use std::{fmt, iter};
|
||||
|
||||
use crate::useless_vec::is_allowed_vec_method;
|
||||
|
||||
pub(super) fn check_body<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
|
|
@ -383,7 +381,7 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &Body<'tcx>, args: &[
|
|||
// Some methods exist on both `[T]` and `Vec<T>`, such as `len`, where the receiver type
|
||||
// doesn't coerce to a slice and our adjusted type check below isn't enough,
|
||||
// but it would still be valid to call with a slice
|
||||
if is_allowed_vec_method(use_expr) {
|
||||
if VEC_METHODS_SHADOWING_SLICE_METHODS.contains(&name) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use clippy_utils::msrvs::{self, Msrv};
|
|||
use clippy_utils::source::SpanRangeExt;
|
||||
use clippy_utils::ty::is_copy;
|
||||
use clippy_utils::visitors::for_each_local_use_after_expr;
|
||||
use clippy_utils::{get_parent_expr, higher, is_in_test, span_contains_comment, sym};
|
||||
use clippy_utils::{VEC_METHODS_SHADOWING_SLICE_METHODS, get_parent_expr, higher, is_in_test, span_contains_comment};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{BorrowKind, Expr, ExprKind, HirId, LetStmt, Mutability, Node, Pat, PatKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
|
|
@ -123,8 +123,16 @@ impl UselessVec {
|
|||
// allow indexing into a vec and some set of allowed method calls that exist on slices, too
|
||||
if let Some(parent) = get_parent_expr(cx, expr)
|
||||
&& (adjusts_to_slice(cx, expr)
|
||||
|| matches!(parent.kind, ExprKind::Index(..))
|
||||
|| is_allowed_vec_method(parent))
|
||||
|| match parent.kind {
|
||||
ExprKind::Index(..) => true,
|
||||
ExprKind::MethodCall(path, _, [], _) => {
|
||||
// If the given expression is a method call to a `Vec` method that also exists on
|
||||
// slices, it means that this expression does not actually require a `Vec` and could
|
||||
// just work with an array.
|
||||
VEC_METHODS_SHADOWING_SLICE_METHODS.contains(&path.ident.name)
|
||||
},
|
||||
_ => false,
|
||||
})
|
||||
{
|
||||
ControlFlow::Continue(())
|
||||
} else {
|
||||
|
|
@ -144,8 +152,9 @@ impl UselessVec {
|
|||
VecToArray::Impossible
|
||||
},
|
||||
// search for `for _ in vec![...]`
|
||||
Node::Expr(Expr { span, .. })
|
||||
if span.is_desugaring(DesugaringKind::ForLoop) && self.msrv.meets(cx, msrvs::ARRAY_INTO_ITERATOR) =>
|
||||
Node::Expr(expr)
|
||||
if expr.span.is_desugaring(DesugaringKind::ForLoop)
|
||||
&& self.msrv.meets(cx, msrvs::ARRAY_INTO_ITERATOR) =>
|
||||
{
|
||||
VecToArray::Possible
|
||||
},
|
||||
|
|
@ -276,9 +285,8 @@ impl SuggestedType {
|
|||
assert!(args_span.is_none_or(|s| !s.from_expansion()));
|
||||
assert!(len_span.is_none_or(|s| !s.from_expansion()));
|
||||
|
||||
let maybe_args = args_span
|
||||
.map(|sp| sp.get_source_text(cx).expect("spans are always crate-local"))
|
||||
.map_or(String::new(), |x| x.to_owned());
|
||||
let maybe_args = args_span.map(|sp| sp.get_source_text(cx).expect("spans are always crate-local"));
|
||||
let maybe_args = maybe_args.as_deref().unwrap_or_default();
|
||||
let maybe_len = len_span
|
||||
.map(|sp| sp.get_source_text(cx).expect("spans are always crate-local"))
|
||||
.map(|st| format!("; {st}"))
|
||||
|
|
@ -301,17 +309,6 @@ fn adjusts_to_slice(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
|
|||
matches!(cx.typeck_results().expr_ty_adjusted(e).kind(), ty::Ref(_, ty, _) if ty.is_slice())
|
||||
}
|
||||
|
||||
/// Checks if the given expression is a method call to a `Vec` method
|
||||
/// that also exists on slices. If this returns true, it means that
|
||||
/// this expression does not actually require a `Vec` and could just work with an array.
|
||||
pub fn is_allowed_vec_method(e: &Expr<'_>) -> bool {
|
||||
if let ExprKind::MethodCall(path, _, [], _) = e.kind {
|
||||
matches!(path.ident.name, sym::as_ptr | sym::is_empty | sym::len)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn suggest_type(expr: &Expr<'_>) -> SuggestedType {
|
||||
if let ExprKind::AddrOf(BorrowKind::Ref, mutability, _) = expr.kind {
|
||||
// `expr` is `&vec![_]`, so suggest `&[_]` (or `&mut[_]` resp.)
|
||||
|
|
|
|||
|
|
@ -136,6 +136,9 @@ use crate::res::{MaybeDef, MaybeQPath, MaybeResPath};
|
|||
use crate::ty::{adt_and_variant_of_res, can_partially_move_ty, expr_sig, is_copy, is_recursively_primitive_type};
|
||||
use crate::visitors::for_each_expr_without_closures;
|
||||
|
||||
/// Methods on `Vec` that also exists on slices.
|
||||
pub const VEC_METHODS_SHADOWING_SLICE_METHODS: [Symbol; 3] = [sym::as_ptr, sym::is_empty, sym::len];
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! extract_msrv_attr {
|
||||
() => {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
#![warn(clippy::useless_vec)]
|
||||
#![allow(clippy::nonstandard_macro_braces, clippy::uninlined_format_args, unused)]
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
|
|
@ -39,17 +38,14 @@ fn main() {
|
|||
on_mut_slice(&mut [1, 2]);
|
||||
//~^ useless_vec
|
||||
|
||||
on_slice(&[1, 2]);
|
||||
//~^ useless_vec
|
||||
on_slice(&[1, 2]);
|
||||
on_mut_slice(&mut [1, 2]);
|
||||
//~^ useless_vec
|
||||
#[rustfmt::skip]
|
||||
on_slice(&[1, 2]);
|
||||
//~^ useless_vec
|
||||
on_slice(&[1, 2]);
|
||||
on_mut_slice(&mut [1, 2]);
|
||||
//~^ useless_vec
|
||||
#[allow(clippy::nonstandard_macro_braces)] // not an `expect` as it will only lint _before_ the fix
|
||||
{
|
||||
on_slice(&[1, 2]);
|
||||
//~^ useless_vec
|
||||
on_mut_slice(&mut [1, 2]);
|
||||
//~^ useless_vec
|
||||
};
|
||||
|
||||
on_slice(&[1; 2]);
|
||||
//~^ useless_vec
|
||||
|
|
@ -75,22 +71,24 @@ fn main() {
|
|||
on_vec(&vec![1; 201]); // Ok, size of `vec` higher than `too_large_for_stack`
|
||||
on_mut_vec(&mut vec![1; 201]); // Ok, size of `vec` higher than `too_large_for_stack`
|
||||
|
||||
// Ok
|
||||
// Ok, size of `vec` higher than `too_large_for_stack`
|
||||
for a in vec![1; 201] {
|
||||
println!("{:?}", a);
|
||||
println!("{a:?}");
|
||||
}
|
||||
|
||||
// https://github.com/rust-lang/rust-clippy/issues/2262#issuecomment-783979246
|
||||
let _x: i32 = [1, 2, 3].iter().sum();
|
||||
//~^ useless_vec
|
||||
|
||||
// Do lint
|
||||
let mut x = [1, 2, 3];
|
||||
//~^ useless_vec
|
||||
x.fill(123);
|
||||
dbg!(x[0]);
|
||||
dbg!(x.len());
|
||||
dbg!(x.iter().sum::<i32>());
|
||||
// Do lint, only used as slice
|
||||
{
|
||||
let mut x = [1, 2, 3];
|
||||
//~^ useless_vec
|
||||
x.fill(123);
|
||||
dbg!(x[0]);
|
||||
dbg!(x.len());
|
||||
dbg!(x.iter().sum::<i32>());
|
||||
}
|
||||
|
||||
let _x: &[i32] = &[1, 2, 3];
|
||||
//~^ useless_vec
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
#![warn(clippy::useless_vec)]
|
||||
#![allow(clippy::nonstandard_macro_braces, clippy::uninlined_format_args, unused)]
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
|
|
@ -39,17 +38,14 @@ fn main() {
|
|||
on_mut_slice(&mut vec![1, 2]);
|
||||
//~^ useless_vec
|
||||
|
||||
on_slice(&vec![1, 2]);
|
||||
//~^ useless_vec
|
||||
on_slice(&[1, 2]);
|
||||
on_mut_slice(&mut vec![1, 2]);
|
||||
//~^ useless_vec
|
||||
#[rustfmt::skip]
|
||||
on_slice(&vec!(1, 2));
|
||||
//~^ useless_vec
|
||||
on_slice(&[1, 2]);
|
||||
on_mut_slice(&mut vec![1, 2]);
|
||||
//~^ useless_vec
|
||||
#[allow(clippy::nonstandard_macro_braces)] // not an `expect` as it will only lint _before_ the fix
|
||||
{
|
||||
on_slice(&vec!(1, 2));
|
||||
//~^ useless_vec
|
||||
on_mut_slice(&mut vec!(1, 2));
|
||||
//~^ useless_vec
|
||||
};
|
||||
|
||||
on_slice(&vec![1; 2]);
|
||||
//~^ useless_vec
|
||||
|
|
@ -75,22 +71,24 @@ fn main() {
|
|||
on_vec(&vec![1; 201]); // Ok, size of `vec` higher than `too_large_for_stack`
|
||||
on_mut_vec(&mut vec![1; 201]); // Ok, size of `vec` higher than `too_large_for_stack`
|
||||
|
||||
// Ok
|
||||
// Ok, size of `vec` higher than `too_large_for_stack`
|
||||
for a in vec![1; 201] {
|
||||
println!("{:?}", a);
|
||||
println!("{a:?}");
|
||||
}
|
||||
|
||||
// https://github.com/rust-lang/rust-clippy/issues/2262#issuecomment-783979246
|
||||
let _x: i32 = vec![1, 2, 3].iter().sum();
|
||||
//~^ useless_vec
|
||||
|
||||
// Do lint
|
||||
let mut x = vec![1, 2, 3];
|
||||
//~^ useless_vec
|
||||
x.fill(123);
|
||||
dbg!(x[0]);
|
||||
dbg!(x.len());
|
||||
dbg!(x.iter().sum::<i32>());
|
||||
// Do lint, only used as slice
|
||||
{
|
||||
let mut x = vec![1, 2, 3];
|
||||
//~^ useless_vec
|
||||
x.fill(123);
|
||||
dbg!(x[0]);
|
||||
dbg!(x.len());
|
||||
dbg!(x.iter().sum::<i32>());
|
||||
}
|
||||
|
||||
let _x: &[i32] = &vec![1, 2, 3];
|
||||
//~^ useless_vec
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error: useless use of `vec!`
|
||||
--> tests/ui/useless_vec.rs:30:14
|
||||
--> tests/ui/useless_vec.rs:29:14
|
||||
|
|
||||
LL | on_slice(&vec![]);
|
||||
| ^^^^^^^ help: you can use a slice directly: `&[]`
|
||||
|
|
@ -8,130 +8,118 @@ LL | on_slice(&vec![]);
|
|||
= help: to override `-D warnings` add `#[allow(clippy::useless_vec)]`
|
||||
|
||||
error: useless use of `vec!`
|
||||
--> tests/ui/useless_vec.rs:33:18
|
||||
--> tests/ui/useless_vec.rs:32:18
|
||||
|
|
||||
LL | on_mut_slice(&mut vec![]);
|
||||
| ^^^^^^^^^^^ help: you can use a slice directly: `&mut []`
|
||||
|
||||
error: useless use of `vec!`
|
||||
--> tests/ui/useless_vec.rs:36:14
|
||||
--> tests/ui/useless_vec.rs:35:14
|
||||
|
|
||||
LL | on_slice(&vec![1, 2]);
|
||||
| ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]`
|
||||
|
||||
error: useless use of `vec!`
|
||||
--> tests/ui/useless_vec.rs:39:18
|
||||
--> tests/ui/useless_vec.rs:38:18
|
||||
|
|
||||
LL | on_mut_slice(&mut vec![1, 2]);
|
||||
| ^^^^^^^^^^^^^^^ help: you can use a slice directly: `&mut [1, 2]`
|
||||
|
||||
error: useless use of `vec!`
|
||||
--> tests/ui/useless_vec.rs:42:14
|
||||
--> tests/ui/useless_vec.rs:44:18
|
||||
|
|
||||
LL | on_slice(&vec![1, 2]);
|
||||
| ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]`
|
||||
LL | on_slice(&vec!(1, 2));
|
||||
| ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]`
|
||||
|
||||
error: useless use of `vec!`
|
||||
--> tests/ui/useless_vec.rs:45:18
|
||||
--> tests/ui/useless_vec.rs:46:22
|
||||
|
|
||||
LL | on_mut_slice(&mut vec![1, 2]);
|
||||
| ^^^^^^^^^^^^^^^ help: you can use a slice directly: `&mut [1, 2]`
|
||||
LL | on_mut_slice(&mut vec!(1, 2));
|
||||
| ^^^^^^^^^^^^^^^ help: you can use a slice directly: `&mut [1, 2]`
|
||||
|
||||
error: useless use of `vec!`
|
||||
--> tests/ui/useless_vec.rs:48:14
|
||||
|
|
||||
LL | on_slice(&vec!(1, 2));
|
||||
| ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]`
|
||||
|
||||
error: useless use of `vec!`
|
||||
--> tests/ui/useless_vec.rs:51:18
|
||||
|
|
||||
LL | on_mut_slice(&mut vec![1, 2]);
|
||||
| ^^^^^^^^^^^^^^^ help: you can use a slice directly: `&mut [1, 2]`
|
||||
|
||||
error: useless use of `vec!`
|
||||
--> tests/ui/useless_vec.rs:54:14
|
||||
--> tests/ui/useless_vec.rs:50:14
|
||||
|
|
||||
LL | on_slice(&vec![1; 2]);
|
||||
| ^^^^^^^^^^^ help: you can use a slice directly: `&[1; 2]`
|
||||
|
||||
error: useless use of `vec!`
|
||||
--> tests/ui/useless_vec.rs:57:18
|
||||
--> tests/ui/useless_vec.rs:53:18
|
||||
|
|
||||
LL | on_mut_slice(&mut vec![1; 2]);
|
||||
| ^^^^^^^^^^^^^^^ help: you can use a slice directly: `&mut [1; 2]`
|
||||
|
||||
error: useless use of `vec!`
|
||||
--> tests/ui/useless_vec.rs:84:19
|
||||
--> tests/ui/useless_vec.rs:80:19
|
||||
|
|
||||
LL | let _x: i32 = vec![1, 2, 3].iter().sum();
|
||||
| ^^^^^^^^^^^^^ help: you can use an array directly: `[1, 2, 3]`
|
||||
|
||||
error: useless use of `vec!`
|
||||
--> tests/ui/useless_vec.rs:88:17
|
||||
--> tests/ui/useless_vec.rs:85:21
|
||||
|
|
||||
LL | let mut x = vec![1, 2, 3];
|
||||
| ^^^^^^^^^^^^^ help: you can use an array directly: `[1, 2, 3]`
|
||||
LL | let mut x = vec![1, 2, 3];
|
||||
| ^^^^^^^^^^^^^ help: you can use an array directly: `[1, 2, 3]`
|
||||
|
||||
error: useless use of `vec!`
|
||||
--> tests/ui/useless_vec.rs:95:22
|
||||
--> tests/ui/useless_vec.rs:93:22
|
||||
|
|
||||
LL | let _x: &[i32] = &vec![1, 2, 3];
|
||||
| ^^^^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2, 3]`
|
||||
|
||||
error: useless use of `vec!`
|
||||
--> tests/ui/useless_vec.rs:98:14
|
||||
--> tests/ui/useless_vec.rs:96:14
|
||||
|
|
||||
LL | for _ in vec![1, 2, 3] {}
|
||||
| ^^^^^^^^^^^^^ help: you can use an array directly: `[1, 2, 3]`
|
||||
|
||||
error: useless use of `vec!`
|
||||
--> tests/ui/useless_vec.rs:138:20
|
||||
--> tests/ui/useless_vec.rs:136:20
|
||||
|
|
||||
LL | for _string in vec![repro!(true), repro!(null)] {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can use an array directly: `[repro!(true), repro!(null)]`
|
||||
|
||||
error: useless use of `vec!`
|
||||
--> tests/ui/useless_vec.rs:156:18
|
||||
--> tests/ui/useless_vec.rs:154:18
|
||||
|
|
||||
LL | in_macro!(1, vec![1, 2], vec![1; 2]);
|
||||
| ^^^^^^^^^^ help: you can use an array directly: `[1, 2]`
|
||||
|
||||
error: useless use of `vec!`
|
||||
--> tests/ui/useless_vec.rs:156:30
|
||||
--> tests/ui/useless_vec.rs:154:30
|
||||
|
|
||||
LL | in_macro!(1, vec![1, 2], vec![1; 2]);
|
||||
| ^^^^^^^^^^ help: you can use an array directly: `[1; 2]`
|
||||
|
||||
error: useless use of `vec!`
|
||||
--> tests/ui/useless_vec.rs:177:14
|
||||
--> tests/ui/useless_vec.rs:175:14
|
||||
|
|
||||
LL | for a in vec![1, 2, 3] {
|
||||
| ^^^^^^^^^^^^^ help: you can use an array directly: `[1, 2, 3]`
|
||||
|
||||
error: useless use of `vec!`
|
||||
--> tests/ui/useless_vec.rs:182:14
|
||||
--> tests/ui/useless_vec.rs:180:14
|
||||
|
|
||||
LL | for a in vec![String::new(), String::new()] {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can use an array directly: `[String::new(), String::new()]`
|
||||
|
||||
error: useless use of `vec!`
|
||||
--> tests/ui/useless_vec.rs:215:33
|
||||
--> tests/ui/useless_vec.rs:213:33
|
||||
|
|
||||
LL | this_macro_doesnt_need_vec!(vec![1]);
|
||||
| ^^^^^^^ help: you can use an array directly: `[1]`
|
||||
|
||||
error: useless use of `vec!`
|
||||
--> tests/ui/useless_vec.rs:242:14
|
||||
--> tests/ui/useless_vec.rs:240:14
|
||||
|
|
||||
LL | for a in &(vec![1, 2]) {}
|
||||
| ^^^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]`
|
||||
|
||||
error: useless use of `vec!`
|
||||
--> tests/ui/useless_vec.rs:250:13
|
||||
--> tests/ui/useless_vec.rs:248:13
|
||||
|
|
||||
LL | let v = &vec![];
|
||||
| ^^^^^^^ help: you can use a slice directly: `&[]`
|
||||
|
||||
error: aborting due to 22 previous errors
|
||||
error: aborting due to 20 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
//@no-rustfix: no suggestions
|
||||
|
||||
#![warn(clippy::useless_vec)]
|
||||
|
||||
// Regression test for <https://github.com/rust-lang/rust-clippy/issues/13692>.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error: useless use of `vec!`
|
||||
--> tests/ui/useless_vec_unfixable.rs:8:26
|
||||
--> tests/ui/useless_vec_unfixable.rs:7:26
|
||||
|
|
||||
LL | let _some_variable = vec![
|
||||
| __________________________^
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue