about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAndre Bogus <bogusandre@gmail.com>2024-04-28 00:01:14 +0200
committerblyxyas <blyxyas@gmail.com>2024-04-28 22:07:56 +0200
commit87efce4fa22f51075e1fd25904f757f783eebfdc (patch)
treee195fd5cf9ef50ad05d866818f5161544f988332
parentc6bf9548d53233f8a08928955a996f4bf30ea1bd (diff)
downloadrust-87efce4fa22f51075e1fd25904f757f783eebfdc.tar.gz
rust-87efce4fa22f51075e1fd25904f757f783eebfdc.zip
configurably allow `useless_vec` in tests
This adds a `àllow-useless-vec-in-test` configuration which, when set
to `true` will allow the `useless_vec` lint in `#[test]` functions and
code within `#[cfg(test)]`. It also moves a `is_in_test` helper to
`clippy_utils`.
-rw-r--r--CHANGELOG.md1
-rw-r--r--book/src/lint_configuration.md10
-rw-r--r--clippy_config/src/conf.rs4
-rw-r--r--clippy_lints/src/dbg_macro.rs10
-rw-r--r--clippy_lints/src/lib.rs2
-rw-r--r--clippy_lints/src/vec.rs6
-rw-r--r--clippy_utils/src/lib.rs5
-rw-r--r--tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr3
-rw-r--r--tests/ui-toml/useless_vec/clippy.toml1
-rw-r--r--tests/ui-toml/useless_vec/useless_vec.fixed26
-rw-r--r--tests/ui-toml/useless_vec/useless_vec.rs26
-rw-r--r--tests/ui-toml/useless_vec/useless_vec.stderr11
12 files changed, 97 insertions, 8 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index bd3a04e34ae..12d4918ca55 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5891,6 +5891,7 @@ Released 2018-09-13
 [`allow-print-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-print-in-tests
 [`allow-private-module-inception`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-private-module-inception
 [`allow-unwrap-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-unwrap-in-tests
+[`allow-useless-vec-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-useless-vec-in-tests
 [`allowed-dotfiles`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-dotfiles
 [`allowed-duplicate-crates`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-duplicate-crates
 [`allowed-idents-below-min-chars`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-idents-below-min-chars
diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md
index fe0e9b80b11..f6af9810ca1 100644
--- a/book/src/lint_configuration.md
+++ b/book/src/lint_configuration.md
@@ -132,6 +132,16 @@ Whether `unwrap` should be allowed in test functions or `#[cfg(test)]`
 * [`unwrap_used`](https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used)
 
 
+## `allow-useless-vec-in-tests`
+Whether `useless_vec` should ignore test functions or `#[cfg(test)]`
+
+**Default Value:** `false`
+
+---
+**Affected lints:**
+* [`useless_vec`](https://rust-lang.github.io/rust-clippy/master/index.html#useless_vec)
+
+
 ## `allowed-dotfiles`
 Additional dotfiles (files or directories starting with a dot) to allow
 
diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs
index bbce4180dc4..5cfcbdb57d7 100644
--- a/clippy_config/src/conf.rs
+++ b/clippy_config/src/conf.rs
@@ -463,6 +463,10 @@ define_Conf! {
     ///
     /// Whether print macros (ex. `println!`) should be allowed in test functions or `#[cfg(test)]`
     (allow_print_in_tests: bool = false),
+    /// Lint: USELESS_VEC.
+    ///
+    /// Whether `useless_vec` should ignore test functions or `#[cfg(test)]`
+    (allow_useless_vec_in_tests: bool = false),
     /// Lint: RESULT_LARGE_ERR.
     ///
     /// The maximum size of the `Err`-variant in a `Result` returned from a function
diff --git a/clippy_lints/src/dbg_macro.rs b/clippy_lints/src/dbg_macro.rs
index e2296767431..db593726604 100644
--- a/clippy_lints/src/dbg_macro.rs
+++ b/clippy_lints/src/dbg_macro.rs
@@ -1,10 +1,10 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::is_in_test;
 use clippy_utils::macros::{macro_backtrace, MacroCall};
 use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::{is_in_cfg_test, is_in_test_function};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind, HirId, Node};
+use rustc_hir::{Expr, ExprKind, Node};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::impl_lint_pass;
@@ -63,7 +63,7 @@ impl LateLintPass<'_> for DbgMacro {
             !in_external_macro(cx.sess(), macro_call.span) &&
             self.checked_dbg_call_site.insert(macro_call.span) &&
             // allows `dbg!` in test code if allow-dbg-in-test is set to true in clippy.toml
-            !(self.allow_dbg_in_tests && is_in_test(cx, expr.hir_id))
+            !(self.allow_dbg_in_tests && is_in_test(cx.tcx, expr.hir_id))
         {
             let mut applicability = Applicability::MachineApplicable;
 
@@ -129,10 +129,6 @@ impl LateLintPass<'_> for DbgMacro {
     }
 }
 
-fn is_in_test(cx: &LateContext<'_>, hir_id: HirId) -> bool {
-    is_in_test_function(cx.tcx, hir_id) || is_in_cfg_test(cx.tcx, hir_id)
-}
-
 fn first_dbg_macro_in_expansion(cx: &LateContext<'_>, span: Span) -> Option<MacroCall> {
     macro_backtrace(span).find(|mc| cx.tcx.is_diagnostic_item(sym::dbg_macro, mc.def_id))
 }
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index e2aac58bf97..2c44c3881aa 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -535,6 +535,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
         allow_print_in_tests,
         allow_private_module_inception,
         allow_unwrap_in_tests,
+        allow_useless_vec_in_tests,
         ref allowed_dotfiles,
         ref allowed_idents_below_min_chars,
         ref allowed_scripts,
@@ -754,6 +755,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
             too_large_for_stack,
             msrv: msrv(),
             span_to_lint_map: BTreeMap::new(),
+            allow_in_test: allow_useless_vec_in_tests,
         })
     });
     store.register_late_pass(|_| Box::new(panic_unimplemented::PanicUnimplemented));
diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs
index 27ead55bf39..9edf7579d48 100644
--- a/clippy_lints/src/vec.rs
+++ b/clippy_lints/src/vec.rs
@@ -7,7 +7,7 @@ use clippy_utils::diagnostics::span_lint_hir_and_then;
 use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::is_copy;
 use clippy_utils::visitors::for_each_local_use_after_expr;
-use clippy_utils::{get_parent_expr, higher, is_trait_method};
+use clippy_utils::{get_parent_expr, higher, is_in_test, is_trait_method};
 use rustc_errors::Applicability;
 use rustc_hir::{BorrowKind, Expr, ExprKind, HirId, LetStmt, Mutability, Node, Pat, PatKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -22,6 +22,7 @@ pub struct UselessVec {
     pub too_large_for_stack: u64,
     pub msrv: Msrv,
     pub span_to_lint_map: BTreeMap<Span, Option<(HirId, SuggestedType, String, Applicability)>>,
+    pub allow_in_test: bool,
 }
 
 declare_clippy_lint! {
@@ -57,6 +58,9 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec {
         let Some(vec_args) = higher::VecArgs::hir(cx, expr.peel_borrows()) else {
             return;
         };
+        if self.allow_in_test && is_in_test(cx.tcx, expr.hir_id) {
+            return;
+        };
         // the parent callsite of this `vec!` expression, or span to the borrowed one such as `&vec!`
         let callsite = expr.span.parent_callsite().unwrap_or(expr.span);
 
diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs
index fccd75d8153..26ee5225f99 100644
--- a/clippy_utils/src/lib.rs
+++ b/clippy_utils/src/lib.rs
@@ -2548,6 +2548,11 @@ pub fn is_in_cfg_test(tcx: TyCtxt<'_>, id: HirId) -> bool {
         .any(|parent_id| is_cfg_test(tcx, parent_id))
 }
 
+/// Checks if the node is in a `#[test]` function or has any parent node marked `#[cfg(test)]`
+pub fn is_in_test(tcx: TyCtxt<'_>, hir_id: HirId) -> bool {
+    is_in_test_function(tcx, hir_id) || is_in_cfg_test(tcx, hir_id)
+}
+
 /// Checks if the item of any of its parents has `#[cfg(...)]` attribute applied.
 pub fn inherits_cfg(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
     let hir = tcx.hir();
diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
index 24645b61fdb..722e9b3bc8d 100644
--- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
+++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
@@ -11,6 +11,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect
            allow-print-in-tests
            allow-private-module-inception
            allow-unwrap-in-tests
+           allow-useless-vec-in-tests
            allowed-dotfiles
            allowed-duplicate-crates
            allowed-idents-below-min-chars
@@ -91,6 +92,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect
            allow-print-in-tests
            allow-private-module-inception
            allow-unwrap-in-tests
+           allow-useless-vec-in-tests
            allowed-dotfiles
            allowed-duplicate-crates
            allowed-idents-below-min-chars
@@ -171,6 +173,7 @@ error: error reading Clippy's configuration file: unknown field `allow_mixed_uni
            allow-print-in-tests
            allow-private-module-inception
            allow-unwrap-in-tests
+           allow-useless-vec-in-tests
            allowed-dotfiles
            allowed-duplicate-crates
            allowed-idents-below-min-chars
diff --git a/tests/ui-toml/useless_vec/clippy.toml b/tests/ui-toml/useless_vec/clippy.toml
new file mode 100644
index 00000000000..230ca2d0ab7
--- /dev/null
+++ b/tests/ui-toml/useless_vec/clippy.toml
@@ -0,0 +1 @@
+allow-useless-vec-in-tests = true
diff --git a/tests/ui-toml/useless_vec/useless_vec.fixed b/tests/ui-toml/useless_vec/useless_vec.fixed
new file mode 100644
index 00000000000..08323a0dcc9
--- /dev/null
+++ b/tests/ui-toml/useless_vec/useless_vec.fixed
@@ -0,0 +1,26 @@
+//@compile-flags: --test
+#![warn(clippy::useless_vec)]
+#![allow(clippy::unnecessary_operation, clippy::no_effect)]
+
+fn foo(_: &[u32]) {}
+
+fn main() {
+    foo(&[1_u32]);
+}
+
+#[test]
+pub fn in_test() {
+    foo(&vec![2_u32]);
+}
+
+#[cfg(test)]
+fn in_cfg_test() {
+    foo(&vec![3_u32]);
+}
+
+#[cfg(test)]
+mod mod1 {
+    fn in_cfg_test_mod() {
+        super::foo(&vec![4_u32]);
+    }
+}
diff --git a/tests/ui-toml/useless_vec/useless_vec.rs b/tests/ui-toml/useless_vec/useless_vec.rs
new file mode 100644
index 00000000000..1f4b27c5342
--- /dev/null
+++ b/tests/ui-toml/useless_vec/useless_vec.rs
@@ -0,0 +1,26 @@
+//@compile-flags: --test
+#![warn(clippy::useless_vec)]
+#![allow(clippy::unnecessary_operation, clippy::no_effect)]
+
+fn foo(_: &[u32]) {}
+
+fn main() {
+    foo(&vec![1_u32]);
+}
+
+#[test]
+pub fn in_test() {
+    foo(&vec![2_u32]);
+}
+
+#[cfg(test)]
+fn in_cfg_test() {
+    foo(&vec![3_u32]);
+}
+
+#[cfg(test)]
+mod mod1 {
+    fn in_cfg_test_mod() {
+        super::foo(&vec![4_u32]);
+    }
+}
diff --git a/tests/ui-toml/useless_vec/useless_vec.stderr b/tests/ui-toml/useless_vec/useless_vec.stderr
new file mode 100644
index 00000000000..633110c3c8d
--- /dev/null
+++ b/tests/ui-toml/useless_vec/useless_vec.stderr
@@ -0,0 +1,11 @@
+error: useless use of `vec!`
+  --> tests/ui-toml/useless_vec/useless_vec.rs:8:9
+   |
+LL |     foo(&vec![1_u32]);
+   |         ^^^^^^^^^^^^ help: you can use a slice directly: `&[1_u32]`
+   |
+   = note: `-D clippy::useless-vec` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::useless_vec)]`
+
+error: aborting due to 1 previous error
+