Move VecResizeToZero into Methods lint pass

This commit is contained in:
Jason Newcomb 2022-06-06 11:17:38 -04:00
parent d8d4a135ea
commit 8acc4d2f1e
9 changed files with 88 additions and 78 deletions

View file

@ -217,6 +217,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
LintId::of(methods::UNNECESSARY_TO_OWNED),
LintId::of(methods::UNWRAP_OR_ELSE_DEFAULT),
LintId::of(methods::USELESS_ASREF),
LintId::of(methods::VEC_RESIZE_TO_ZERO),
LintId::of(methods::WRONG_SELF_CONVENTION),
LintId::of(methods::ZST_OFFSET),
LintId::of(minmax::MIN_MAX),
@ -344,7 +345,6 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
LintId::of(useless_conversion::USELESS_CONVERSION),
LintId::of(vec::USELESS_VEC),
LintId::of(vec_init_then_push::VEC_INIT_THEN_PUSH),
LintId::of(vec_resize_to_zero::VEC_RESIZE_TO_ZERO),
LintId::of(write::POSITIONAL_NAMED_FORMAT_PARAMETERS),
LintId::of(write::PRINTLN_EMPTY_STRING),
LintId::of(write::PRINT_LITERAL),

View file

@ -43,6 +43,7 @@ store.register_group(true, "clippy::correctness", Some("clippy_correctness"), ve
LintId::of(methods::SUSPICIOUS_SPLITN),
LintId::of(methods::UNINIT_ASSUMED_INIT),
LintId::of(methods::UNIT_HASH),
LintId::of(methods::VEC_RESIZE_TO_ZERO),
LintId::of(methods::ZST_OFFSET),
LintId::of(minmax::MIN_MAX),
LintId::of(non_octal_unix_permissions::NON_OCTAL_UNIX_PERMISSIONS),
@ -74,5 +75,4 @@ store.register_group(true, "clippy::correctness", Some("clippy_correctness"), ve
LintId::of(unnamed_address::VTABLE_ADDRESS_COMPARISONS),
LintId::of(unused_io_amount::UNUSED_IO_AMOUNT),
LintId::of(unwrap::PANICKING_UNWRAP),
LintId::of(vec_resize_to_zero::VEC_RESIZE_TO_ZERO),
])

View file

@ -369,6 +369,7 @@ store.register_lints(&[
methods::UNWRAP_OR_ELSE_DEFAULT,
methods::UNWRAP_USED,
methods::USELESS_ASREF,
methods::VEC_RESIZE_TO_ZERO,
methods::WRONG_SELF_CONVENTION,
methods::ZST_OFFSET,
minmax::MIN_MAX,
@ -584,7 +585,6 @@ store.register_lints(&[
useless_conversion::USELESS_CONVERSION,
vec::USELESS_VEC,
vec_init_then_push::VEC_INIT_THEN_PUSH,
vec_resize_to_zero::VEC_RESIZE_TO_ZERO,
verbose_file_reads::VERBOSE_FILE_READS,
wildcard_imports::ENUM_GLOB_USE,
wildcard_imports::WILDCARD_IMPORTS,

View file

@ -391,7 +391,6 @@ mod use_self;
mod useless_conversion;
mod vec;
mod vec_init_then_push;
mod vec_resize_to_zero;
mod verbose_file_reads;
mod wildcard_imports;
mod write;
@ -803,7 +802,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(|| Box::new(if_not_else::IfNotElse));
store.register_late_pass(|| Box::new(equatable_if_let::PatternEquality));
store.register_late_pass(|| Box::new(manual_async_fn::ManualAsyncFn));
store.register_late_pass(|| Box::new(vec_resize_to_zero::VecResizeToZero));
store.register_late_pass(|| Box::new(panic_in_result_fn::PanicInResultFn));
let single_char_binding_names_threshold = conf.single_char_binding_names_threshold;
store.register_early_pass(move || {

View file

@ -90,6 +90,7 @@ mod unwrap_or_else_default;
mod unwrap_used;
mod useless_asref;
mod utils;
mod vec_resize_to_zero;
mod wrong_self_convention;
mod zst_offset;
@ -2907,6 +2908,28 @@ declare_clippy_lint! {
"Use of `Vec::sort_by` when `Vec::sort_by_key` or `Vec::sort` would be clearer"
}
declare_clippy_lint! {
/// ### What it does
/// Finds occurrences of `Vec::resize(0, an_int)`
///
/// ### Why is this bad?
/// This is probably an argument inversion mistake.
///
/// ### Example
/// ```rust
/// vec!(1, 2, 3, 4, 5).resize(0, 5)
/// ```
///
/// Use instead:
/// ```rust
/// vec!(1, 2, 3, 4, 5).clear()
/// ```
#[clippy::version = "1.46.0"]
pub VEC_RESIZE_TO_ZERO,
correctness,
"emptying a vector with `resize(0, an_int)` instead of `clear()` is probably an argument inversion mistake"
}
pub struct Methods {
avoid_breaking_exported_api: bool,
msrv: Option<RustcVersion>,
@ -3026,6 +3049,7 @@ impl_lint_pass!(Methods => [
STABLE_SORT_PRIMITIVE,
UNIT_HASH,
UNNECESSARY_SORT_BY,
VEC_RESIZE_TO_ZERO,
]);
/// Extracts a method call name, args, and `Span` of the method name.
@ -3420,6 +3444,9 @@ impl Methods {
("repeat", [arg]) => {
repeat_once::check(cx, expr, recv, arg);
},
("resize", [count_arg, default_arg]) => {
vec_resize_to_zero::check(cx, expr, count_arg, default_arg, span);
},
("sort", []) => {
stable_sort_primitive::check(cx, expr, recv);
},

View file

@ -0,0 +1,45 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::ty::is_type_diagnostic_item;
use if_chain::if_chain;
use rustc_ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::LateContext;
use rustc_span::source_map::Spanned;
use rustc_span::{sym, Span};
use super::VEC_RESIZE_TO_ZERO;
pub(super) fn check<'tcx>(
cx: &LateContext<'tcx>,
expr: &'tcx Expr<'_>,
count_arg: &'tcx Expr<'_>,
default_arg: &'tcx Expr<'_>,
name_span: Span,
) {
if_chain! {
if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
if let Some(impl_id) = cx.tcx.impl_of_method(method_id);
if is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id), sym::Vec);
if let ExprKind::Lit(Spanned { node: LitKind::Int(0, _), .. }) = count_arg.kind;
if let ExprKind::Lit(Spanned { node: LitKind::Int(..), .. }) = default_arg.kind;
then {
let method_call_span = expr.span.with_lo(name_span.lo());
span_lint_and_then(
cx,
VEC_RESIZE_TO_ZERO,
expr.span,
"emptying a vector with `resize`",
|db| {
db.help("the arguments may be inverted...");
db.span_suggestion(
method_call_span,
"...or you can empty the vector with",
"clear()".to_string(),
Applicability::MaybeIncorrect,
);
},
);
}
}
}

View file

@ -1,64 +0,0 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::{match_def_path, paths};
use if_chain::if_chain;
use rustc_ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Spanned;
declare_clippy_lint! {
/// ### What it does
/// Finds occurrences of `Vec::resize(0, an_int)`
///
/// ### Why is this bad?
/// This is probably an argument inversion mistake.
///
/// ### Example
/// ```rust
/// vec!(1, 2, 3, 4, 5).resize(0, 5)
/// ```
///
/// Use instead:
/// ```rust
/// vec!(1, 2, 3, 4, 5).clear()
/// ```
#[clippy::version = "1.46.0"]
pub VEC_RESIZE_TO_ZERO,
correctness,
"emptying a vector with `resize(0, an_int)` instead of `clear()` is probably an argument inversion mistake"
}
declare_lint_pass!(VecResizeToZero => [VEC_RESIZE_TO_ZERO]);
impl<'tcx> LateLintPass<'tcx> for VecResizeToZero {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
if_chain! {
if let hir::ExprKind::MethodCall(path_segment, args, _) = expr.kind;
if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
if match_def_path(cx, method_def_id, &paths::VEC_RESIZE) && args.len() == 3;
if let ExprKind::Lit(Spanned { node: LitKind::Int(0, _), .. }) = args[1].kind;
if let ExprKind::Lit(Spanned { node: LitKind::Int(..), .. }) = args[2].kind;
then {
let method_call_span = expr.span.with_lo(path_segment.ident.span.lo());
span_lint_and_then(
cx,
VEC_RESIZE_TO_ZERO,
expr.span,
"emptying a vector with `resize`",
|db| {
db.help("the arguments may be inverted...");
db.span_suggestion(
method_call_span,
"...or you can empty the vector with",
"clear()".to_string(),
Applicability::MaybeIncorrect,
);
},
);
}
}
}
}

View file

@ -1,15 +1,19 @@
#![warn(clippy::vec_resize_to_zero)]
fn main() {
let mut v = vec![1, 2, 3, 4, 5];
// applicable here
vec![1, 2, 3, 4, 5].resize(0, 5);
v.resize(0, 5);
// not applicable
vec![1, 2, 3, 4, 5].resize(2, 5);
v.resize(2, 5);
let mut v = vec!["foo", "bar", "baz"];
// applicable here, but only implemented for integer literals for now
vec!["foo", "bar", "baz"].resize(0, "bar");
v.resize(0, "bar");
// not applicable
vec!["foo", "bar", "baz"].resize(2, "bar")
v.resize(2, "bar")
}

View file

@ -1,10 +1,10 @@
error: emptying a vector with `resize`
--> $DIR/vec_resize_to_zero.rs:5:5
--> $DIR/vec_resize_to_zero.rs:7:5
|
LL | vec![1, 2, 3, 4, 5].resize(0, 5);
| ^^^^^^^^^^^^^^^^^^^^------------
| |
| help: ...or you can empty the vector with: `clear()`
LL | v.resize(0, 5);
| ^^------------
| |
| help: ...or you can empty the vector with: `clear()`
|
= note: `-D clippy::vec-resize-to-zero` implied by `-D warnings`
= help: the arguments may be inverted...