Skip to content

Commit

Permalink
Expand BOX_VEC to BOX_COLLECTION
Browse files Browse the repository at this point in the history
  • Loading branch information
F3real committed Sep 20, 2021
1 parent 871ad80 commit 63ed2f9
Show file tree
Hide file tree
Showing 9 changed files with 97 additions and 48 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Expand Up @@ -2570,7 +2570,7 @@ Released 2018-09-13
[`bool_comparison`]: https://rust-lang.github.io/rust-clippy/master/index.html#bool_comparison
[`borrow_interior_mutable_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrow_interior_mutable_const
[`borrowed_box`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrowed_box
[`box_vec`]: https://rust-lang.github.io/rust-clippy/master/index.html#box_vec
[`box_collection`]: https://rust-lang.github.io/rust-clippy/master/index.html#box_collection
[`boxed_local`]: https://rust-lang.github.io/rust-clippy/master/index.html#boxed_local
[`branches_sharing_code`]: https://rust-lang.github.io/rust-clippy/master/index.html#branches_sharing_code
[`builtin_type_shadow`]: https://rust-lang.github.io/rust-clippy/master/index.html#builtin_type_shadow
Expand Down
6 changes: 3 additions & 3 deletions clippy_lints/src/lib.rs
Expand Up @@ -956,7 +956,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
transmuting_null::TRANSMUTING_NULL,
try_err::TRY_ERR,
types::BORROWED_BOX,
types::BOX_VEC,
types::BOX_COLLECTION,
types::LINKEDLIST,
types::OPTION_OPTION,
types::RC_BUFFER,
Expand Down Expand Up @@ -1454,7 +1454,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(transmuting_null::TRANSMUTING_NULL),
LintId::of(try_err::TRY_ERR),
LintId::of(types::BORROWED_BOX),
LintId::of(types::BOX_VEC),
LintId::of(types::BOX_COLLECTION),
LintId::of(types::REDUNDANT_ALLOCATION),
LintId::of(types::TYPE_COMPLEXITY),
LintId::of(types::VEC_BOX),
Expand Down Expand Up @@ -1792,7 +1792,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(redundant_clone::REDUNDANT_CLONE),
LintId::of(slow_vector_initialization::SLOW_VECTOR_INITIALIZATION),
LintId::of(stable_sort_primitive::STABLE_SORT_PRIMITIVE),
LintId::of(types::BOX_VEC),
LintId::of(types::BOX_COLLECTION),
LintId::of(types::REDUNDANT_ALLOCATION),
LintId::of(vec::USELESS_VEC),
LintId::of(vec_init_then_push::VEC_INIT_THEN_PUSH),
Expand Down
50 changes: 50 additions & 0 deletions clippy_lints/src/types/box_collection.rs
@@ -0,0 +1,50 @@
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::is_ty_param_diagnostic_item;
use rustc_hir::{self as hir, def_id::DefId, QPath};
use rustc_lint::LateContext;
use rustc_span::symbol::sym;

use super::BOX_COLLECTION;

pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool {
if_chain! {
if Some(def_id) == cx.tcx.lang_items().owned_box();
if let Some(item_type) = get_std_collection(cx, qpath);
then {
let generic = if item_type == "String" {
""
} else {
"<..>"
};
span_lint_and_help(
cx,
BOX_COLLECTION,
hir_ty.span,
&format!(
"you seem to be trying to use `Box<{outer}{generic}>`. Consider using just `{outer}{generic}`",
outer=item_type,
generic = generic),
None,
&format!(
"`{outer}{generic}` is already on the heap, `Box<{outer}{generic}>` makes an extra allocation",
outer=item_type,
generic = generic)
);
true
} else {
false
}
}
}

fn get_std_collection(cx: &LateContext<'_>, qpath: &QPath<'_>) -> Option<String> {
if is_ty_param_diagnostic_item(cx, qpath, sym::vec_type).is_some() {
Some(String::from("Vec"))
} else if is_ty_param_diagnostic_item(cx, qpath, sym::string_type).is_some() {
Some(String::from("String"))
} else if is_ty_param_diagnostic_item(cx, qpath, sym::hashmap_type).is_some() {
Some(String::from("HashMap"))
} else {
None
}
}
25 changes: 0 additions & 25 deletions clippy_lints/src/types/box_vec.rs

This file was deleted.

14 changes: 7 additions & 7 deletions clippy_lints/src/types/mod.rs
@@ -1,5 +1,5 @@
mod borrowed_box;
mod box_vec;
mod box_collection;
mod linked_list;
mod option_option;
mod rc_buffer;
Expand All @@ -21,12 +21,12 @@ use rustc_span::source_map::Span;

declare_clippy_lint! {
/// ### What it does
/// Checks for use of `Box<Vec<_>>` anywhere in the code.
/// Checks for use of `Box<T>` where T is a collection such as Vec anywhere in the code.
/// Check the [Box documentation](https://doc.rust-lang.org/std/boxed/index.html) for more information.
///
/// ### Why is this bad?
/// `Vec` already keeps its contents in a separate area on
/// the heap. So if you `Box` it, you just add another level of indirection
/// Collections already keeps their contents in a separate area on
/// the heap. So if you `Box` them, you just add another level of indirection
/// without any benefit whatsoever.
///
/// ### Example
Expand All @@ -43,7 +43,7 @@ declare_clippy_lint! {
/// values: Vec<Foo>,
/// }
/// ```
pub BOX_VEC,
pub BOX_COLLECTION,
perf,
"usage of `Box<Vec<T>>`, vector elements are already on the heap"
}
Expand Down Expand Up @@ -298,7 +298,7 @@ pub struct Types {
avoid_breaking_exported_api: bool,
}

impl_lint_pass!(Types => [BOX_VEC, VEC_BOX, OPTION_OPTION, LINKEDLIST, BORROWED_BOX, REDUNDANT_ALLOCATION, RC_BUFFER, RC_MUTEX, TYPE_COMPLEXITY]);
impl_lint_pass!(Types => [BOX_COLLECTION, VEC_BOX, OPTION_OPTION, LINKEDLIST, BORROWED_BOX, REDUNDANT_ALLOCATION, RC_BUFFER, RC_MUTEX, TYPE_COMPLEXITY]);

impl<'tcx> LateLintPass<'tcx> for Types {
fn check_fn(&mut self, cx: &LateContext<'_>, _: FnKind<'_>, decl: &FnDecl<'_>, _: &Body<'_>, _: Span, id: HirId) {
Expand Down Expand Up @@ -447,7 +447,7 @@ impl Types {
// in `clippy_lints::utils::conf.rs`

let mut triggered = false;
triggered |= box_vec::check(cx, hir_ty, qpath, def_id);
triggered |= box_collection::check(cx, hir_ty, qpath, def_id);
triggered |= redundant_allocation::check(cx, hir_ty, qpath, def_id);
triggered |= rc_buffer::check(cx, hir_ty, qpath, def_id);
triggered |= vec_box::check(cx, hir_ty, qpath, def_id, self.vec_box_size_threshold);
Expand Down
2 changes: 1 addition & 1 deletion clippy_lints/src/utils/conf.rs
Expand Up @@ -136,7 +136,7 @@ macro_rules! define_Conf {
}

define_Conf! {
/// Lint: ENUM_VARIANT_NAMES, LARGE_TYPES_PASSED_BY_VALUE, TRIVIALLY_COPY_PASS_BY_REF, UNNECESSARY_WRAPS, UPPER_CASE_ACRONYMS, WRONG_SELF_CONVENTION, BOX_VEC, REDUNDANT_ALLOCATION, RC_BUFFER, VEC_BOX, OPTION_OPTION, LINKEDLIST, RC_MUTEX.
/// Lint: ENUM_VARIANT_NAMES, LARGE_TYPES_PASSED_BY_VALUE, TRIVIALLY_COPY_PASS_BY_REF, UNNECESSARY_WRAPS, UPPER_CASE_ACRONYMS, WRONG_SELF_CONVENTION, BOX_COLLECTION, REDUNDANT_ALLOCATION, RC_BUFFER, VEC_BOX, OPTION_OPTION, LINKEDLIST, RC_MUTEX.
///
/// Suppress lints whenever the suggested change would cause breakage for other crates.
(avoid_breaking_exported_api: bool = true),
Expand Down
8 changes: 8 additions & 0 deletions tests/ui/box_vec.rs → tests/ui/box_collection.rs
Expand Up @@ -6,6 +6,8 @@
unused
)]

use std::collections::HashMap;

macro_rules! boxit {
($init:expr, $x:ty) => {
let _: Box<$x> = Box::new($init);
Expand All @@ -15,20 +17,26 @@ macro_rules! boxit {
fn test_macro() {
boxit!(Vec::new(), Vec<u8>);
}

fn test(foo: Box<Vec<bool>>) {}

fn test2(foo: Box<dyn Fn(Vec<u32>)>) {
// pass if #31 is fixed
foo(vec![1, 2, 3])
}

fn test3(foo: Box<String>) {}

fn test4(foo: Box<HashMap<String, String>>) {}

fn test_local_not_linted() {
let _: Box<Vec<bool>>;
}

// All of these test should be allowed because they are part of the
// public api and `avoid_breaking_exported_api` is `false` by default.
pub fn pub_test(foo: Box<Vec<bool>>) {}

pub fn pub_test_ret() -> Box<Vec<bool>> {
Box::new(Vec::new())
}
Expand Down
27 changes: 27 additions & 0 deletions tests/ui/box_collection.stderr
@@ -0,0 +1,27 @@
error: you seem to be trying to use `Box<Vec<..>>`. Consider using just `Vec<..>`
--> $DIR/box_collection.rs:21:14
|
LL | fn test(foo: Box<Vec<bool>>) {}
| ^^^^^^^^^^^^^^
|
= note: `-D clippy::box-collection` implied by `-D warnings`
= help: `Vec<..>` is already on the heap, `Box<Vec<..>>` makes an extra allocation

error: you seem to be trying to use `Box<String>`. Consider using just `String`
--> $DIR/box_collection.rs:28:15
|
LL | fn test3(foo: Box<String>) {}
| ^^^^^^^^^^^
|
= help: `String` is already on the heap, `Box<String>` makes an extra allocation

error: you seem to be trying to use `Box<HashMap<..>>`. Consider using just `HashMap<..>`
--> $DIR/box_collection.rs:30:15
|
LL | fn test4(foo: Box<HashMap<String, String>>) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: `HashMap<..>` is already on the heap, `Box<HashMap<..>>` makes an extra allocation

error: aborting due to 3 previous errors

11 changes: 0 additions & 11 deletions tests/ui/box_vec.stderr

This file was deleted.

0 comments on commit 63ed2f9

Please sign in to comment.