Skip to content

Commit

Permalink
useless Rc<Rc<T>>, Rc<Box<T>>, Rc<&T>
Browse files Browse the repository at this point in the history
  • Loading branch information
jpospychala committed Apr 1, 2020
1 parent 3abac0a commit 4128b1d
Show file tree
Hide file tree
Showing 12 changed files with 241 additions and 127 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -1195,7 +1195,6 @@ 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_borrows`]: https://rust-lang.github.io/rust-clippy/master/index.html#box_borrows
[`box_vec`]: https://rust-lang.github.io/rust-clippy/master/index.html#box_vec
[`boxed_local`]: https://rust-lang.github.io/rust-clippy/master/index.html#boxed_local
[`builtin_type_shadow`]: https://rust-lang.github.io/rust-clippy/master/index.html#builtin_type_shadow
Expand Down Expand Up @@ -1434,6 +1433,7 @@ Released 2018-09-13
[`range_plus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_plus_one
[`range_step_by_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_step_by_zero
[`range_zip_with_len`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_zip_with_len
[`redundant_allocation`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_allocation
[`redundant_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_clone
[`redundant_closure`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure
[`redundant_closure_call`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure_call
Expand Down
6 changes: 3 additions & 3 deletions clippy_lints/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -795,7 +795,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
&try_err::TRY_ERR,
&types::ABSURD_EXTREME_COMPARISONS,
&types::BORROWED_BOX,
&types::BOX_BORROWS,
&types::BOX_VEC,
&types::CAST_LOSSLESS,
&types::CAST_POSSIBLE_TRUNCATION,
Expand All @@ -812,6 +811,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
&types::LET_UNIT_VALUE,
&types::LINKEDLIST,
&types::OPTION_OPTION,
&types::REDUNDANT_ALLOCATION,
&types::TYPE_COMPLEXITY,
&types::UNIT_ARG,
&types::UNIT_CMP,
Expand Down Expand Up @@ -1368,7 +1368,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(&try_err::TRY_ERR),
LintId::of(&types::ABSURD_EXTREME_COMPARISONS),
LintId::of(&types::BORROWED_BOX),
LintId::of(&types::BOX_BORROWS),
LintId::of(&types::BOX_VEC),
LintId::of(&types::CAST_PTR_ALIGNMENT),
LintId::of(&types::CAST_REF_TO_MUT),
Expand All @@ -1378,6 +1377,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(&types::IMPLICIT_HASHER),
LintId::of(&types::LET_UNIT_VALUE),
LintId::of(&types::OPTION_OPTION),
LintId::of(&types::REDUNDANT_ALLOCATION),
LintId::of(&types::TYPE_COMPLEXITY),
LintId::of(&types::UNIT_ARG),
LintId::of(&types::UNIT_CMP),
Expand Down Expand Up @@ -1662,8 +1662,8 @@ 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(&trivially_copy_pass_by_ref::TRIVIALLY_COPY_PASS_BY_REF),
LintId::of(&types::BOX_BORROWS),
LintId::of(&types::BOX_VEC),
LintId::of(&types::REDUNDANT_ALLOCATION),
LintId::of(&vec::USELESS_VEC),
]);

Expand Down
112 changes: 79 additions & 33 deletions clippy_lints/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,33 +172,35 @@ declare_clippy_lint! {
}

declare_clippy_lint! {
/// **What it does:** Checks for use of `Box<&T>` anywhere in the code.
/// **What it does:** Checks for use of redundant allocations anywhere in the code.
///
/// **Why is this bad?** Any `Box<&T>` can also be a `&T`, which is more
/// general.
/// **Why is this bad?** Expressions such as `Rc<&T>`, `Rc<Rc<T>>`, `Rc<Box<T>>`, `Box<&T>`
/// add an unnecessary level of indirection.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// fn foo(bar: Box<&usize>) {}
/// # use std::rc::Rc;
/// fn foo(bar: Rc<&usize>) {}
/// ```
///
/// Better:
///
/// ```rust
/// # use std::rc::Rc;
/// fn foo(bar: &usize) {}
/// ```
pub BOX_BORROWS,
pub REDUNDANT_ALLOCATION,
perf,
"a box of borrowed type"
"redundant allocation"
}

pub struct Types {
vec_box_size_threshold: u64,
}

impl_lint_pass!(Types => [BOX_VEC, VEC_BOX, OPTION_OPTION, LINKEDLIST, BORROWED_BOX, BOX_BORROWS]);
impl_lint_pass!(Types => [BOX_VEC, VEC_BOX, OPTION_OPTION, LINKEDLIST, BORROWED_BOX, REDUNDANT_ALLOCATION]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Types {
fn check_fn(
Expand Down Expand Up @@ -240,7 +242,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Types {
}

/// Checks if `qpath` has last segment with type parameter matching `path`
fn match_type_parameter(cx: &LateContext<'_, '_>, qpath: &QPath<'_>, path: &[&str]) -> bool {
fn match_type_parameter(cx: &LateContext<'_, '_>, qpath: &QPath<'_>, path: &[&str]) -> Option<Span> {
let last = last_path_segment(qpath);
if_chain! {
if let Some(ref params) = last.args;
Expand All @@ -253,10 +255,27 @@ fn match_type_parameter(cx: &LateContext<'_, '_>, qpath: &QPath<'_>, path: &[&st
if let Some(did) = qpath_res(cx, qpath, ty.hir_id).opt_def_id();
if match_def_path(cx, did, path);
then {
return true;
return Some(ty.span);
}
}
false
None
}

fn match_borrows_parameter(_cx: &LateContext<'_, '_>, qpath: &QPath<'_>) -> Option<Span> {
let last = last_path_segment(qpath);
if_chain! {
if let Some(ref params) = last.args;
if !params.parenthesized;
if let Some(ty) = params.args.iter().find_map(|arg| match arg {
GenericArg::Type(ty) => Some(ty),
_ => None,
});
if let TyKind::Rptr(..) = ty.kind;
then {
return Some(ty.span);
}
}
None
}

impl Types {
Expand All @@ -280,7 +299,6 @@ impl Types {
/// The parameter `is_local` distinguishes the context of the type; types from
/// local bindings should only be checked for the `BORROWED_BOX` lint.
#[allow(clippy::too_many_lines)]
#[allow(clippy::cognitive_complexity)]
fn check_ty(&mut self, cx: &LateContext<'_, '_>, hir_ty: &hir::Ty<'_>, is_local: bool) {
if hir_ty.span.from_expansion() {
return;
Expand All @@ -291,28 +309,19 @@ impl Types {
let res = qpath_res(cx, qpath, hir_id);
if let Some(def_id) = res.opt_def_id() {
if Some(def_id) == cx.tcx.lang_items().owned_box() {
if_chain! {
let last = last_path_segment(qpath);
if let Some(ref params) = last.args;
if !params.parenthesized;
if let Some(ty) = params.args.iter().find_map(|arg| match arg {
GenericArg::Type(ty) => Some(ty),
_ => None,
});
if let TyKind::Rptr(..) = ty.kind;
let ty_ty = hir_ty_to_ty(cx.tcx, ty);
then {
span_lint_and_help(
cx,
BOX_BORROWS,
hir_ty.span,
"usage of `Box<&T>`",
format!("try `{}`", ty_ty).as_str(),
);
return; // don't recurse into the type
}
if let Some(span) = match_borrows_parameter(cx, qpath) {
span_lint_and_sugg(
cx,
REDUNDANT_ALLOCATION,
hir_ty.span,
"usage of `Box<&T>`",
"try",
snippet(cx, span, "..").to_string(),
Applicability::MachineApplicable,
);
return; // don't recurse into the type
}
if match_type_parameter(cx, qpath, &paths::VEC) {
if let Some(_) = match_type_parameter(cx, qpath, &paths::VEC) {
span_lint_and_help(
cx,
BOX_VEC,
Expand All @@ -322,6 +331,43 @@ impl Types {
);
return; // don't recurse into the type
}
} else if Some(def_id) == cx.tcx.lang_items().rc() {
if let Some(span) = match_type_parameter(cx, qpath, &paths::RC) {
span_lint_and_sugg(
cx,
REDUNDANT_ALLOCATION,
hir_ty.span,
"usage of `Rc<Rc<T>>`",
"try",
snippet(cx, span, "..").to_string(),
Applicability::MachineApplicable,
);
return; // don't recurse into the type
}
if let Some(span) = match_type_parameter(cx, qpath, &paths::BOX) {
span_lint_and_sugg(
cx,
REDUNDANT_ALLOCATION,
hir_ty.span,
"usage of `Rc<Box<T>>`",
"try",
snippet(cx, span, "..").to_string(),
Applicability::MachineApplicable,
);
return; // don't recurse into the type
}
if let Some(span) = match_borrows_parameter(cx, qpath) {
span_lint_and_sugg(
cx,
REDUNDANT_ALLOCATION,
hir_ty.span,
"usage of `Rc<&T>`",
"try",
snippet(cx, span, "..").to_string(),
Applicability::MachineApplicable,
);
return; // don't recurse into the type
}
} else if cx.tcx.is_diagnostic_item(Symbol::intern("vec_type"), def_id) {
if_chain! {
// Get the _ part of Vec<_>
Expand Down Expand Up @@ -359,7 +405,7 @@ impl Types {
}
}
} else if match_def_path(cx, def_id, &paths::OPTION) {
if match_type_parameter(cx, qpath, &paths::OPTION) {
if let Some(_) = match_type_parameter(cx, qpath, &paths::OPTION) {
span_lint(
cx,
OPTION_OPTION,
Expand Down
1 change: 1 addition & 0 deletions clippy_lints/src/utils/paths.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub const BEGIN_PANIC: [&str; 3] = ["std", "panicking", "begin_panic"];
pub const BEGIN_PANIC_FMT: [&str; 3] = ["std", "panicking", "begin_panic_fmt"];
pub const BINARY_HEAP: [&str; 4] = ["alloc", "collections", "binary_heap", "BinaryHeap"];
pub const BORROW_TRAIT: [&str; 3] = ["core", "borrow", "Borrow"];
pub const BOX: [&str; 3] = ["alloc", "boxed", "Box"];
pub const BTREEMAP: [&str; 5] = ["alloc", "collections", "btree", "map", "BTreeMap"];
pub const BTREEMAP_ENTRY: [&str; 5] = ["alloc", "collections", "btree", "map", "Entry"];
pub const BTREESET: [&str; 5] = ["alloc", "collections", "btree", "set", "BTreeSet"];
Expand Down
14 changes: 7 additions & 7 deletions src/lintlist/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,13 +101,6 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![
deprecation: None,
module: "types",
},
Lint {
name: "box_borrows",
group: "perf",
desc: "a box of borrowed type",
deprecation: None,
module: "types",
},
Lint {
name: "box_vec",
group: "perf",
Expand Down Expand Up @@ -1732,6 +1725,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![
deprecation: None,
module: "ranges",
},
Lint {
name: "redundant_allocation",
group: "perf",
desc: "redundant allocation",
deprecation: None,
module: "types",
},
Lint {
name: "redundant_clone",
group: "perf",
Expand Down
30 changes: 0 additions & 30 deletions tests/ui/box_borrows.rs

This file was deleted.

51 changes: 0 additions & 51 deletions tests/ui/box_borrows.stderr

This file was deleted.

2 changes: 1 addition & 1 deletion tests/ui/must_use_candidates.fixed
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// run-rustfix
#![feature(never_type)]
#![allow(unused_mut)]
#![allow(unused_mut, clippy::redundant_allocation)]
#![warn(clippy::must_use_candidate)]
use std::rc::Rc;
use std::sync::atomic::{AtomicBool, Ordering};
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/must_use_candidates.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// run-rustfix
#![feature(never_type)]
#![allow(unused_mut)]
#![allow(unused_mut, clippy::redundant_allocation)]
#![warn(clippy::must_use_candidate)]
use std::rc::Rc;
use std::sync::atomic::{AtomicBool, Ordering};
Expand Down
Loading

0 comments on commit 4128b1d

Please sign in to comment.