Skip to content

Commit f19700b

Browse files
committed
box_vec: dont use Box<&T>
1 parent 0e5e2c4 commit f19700b

File tree

7 files changed

+140
-3
lines changed

7 files changed

+140
-3
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -1195,6 +1195,7 @@ Released 2018-09-13
11951195
[`bool_comparison`]: https://rust-lang.github.io/rust-clippy/master/index.html#bool_comparison
11961196
[`borrow_interior_mutable_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrow_interior_mutable_const
11971197
[`borrowed_box`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrowed_box
1198+
[`box_borrows`]: https://rust-lang.github.io/rust-clippy/master/index.html#box_borrows
11981199
[`box_vec`]: https://rust-lang.github.io/rust-clippy/master/index.html#box_vec
11991200
[`boxed_local`]: https://rust-lang.github.io/rust-clippy/master/index.html#boxed_local
12001201
[`builtin_type_shadow`]: https://rust-lang.github.io/rust-clippy/master/index.html#builtin_type_shadow

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code.
77

8-
[There are 361 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
8+
[There are 362 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
99

1010
We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you:
1111

clippy_lints/src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -788,6 +788,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
788788
&try_err::TRY_ERR,
789789
&types::ABSURD_EXTREME_COMPARISONS,
790790
&types::BORROWED_BOX,
791+
&types::BOX_BORROWS,
791792
&types::BOX_VEC,
792793
&types::CAST_LOSSLESS,
793794
&types::CAST_POSSIBLE_TRUNCATION,
@@ -1358,6 +1359,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
13581359
LintId::of(&try_err::TRY_ERR),
13591360
LintId::of(&types::ABSURD_EXTREME_COMPARISONS),
13601361
LintId::of(&types::BORROWED_BOX),
1362+
LintId::of(&types::BOX_BORROWS),
13611363
LintId::of(&types::BOX_VEC),
13621364
LintId::of(&types::CAST_PTR_ALIGNMENT),
13631365
LintId::of(&types::CAST_REF_TO_MUT),
@@ -1650,6 +1652,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
16501652
LintId::of(&redundant_clone::REDUNDANT_CLONE),
16511653
LintId::of(&slow_vector_initialization::SLOW_VECTOR_INITIALIZATION),
16521654
LintId::of(&trivially_copy_pass_by_ref::TRIVIALLY_COPY_PASS_BY_REF),
1655+
LintId::of(&types::BOX_BORROWS),
16531656
LintId::of(&types::BOX_VEC),
16541657
LintId::of(&vec::USELESS_VEC),
16551658
]);

clippy_lints/src/types.rs

+46-1
Original file line numberDiff line numberDiff line change
@@ -171,11 +171,34 @@ declare_clippy_lint! {
171171
"a borrow of a boxed type"
172172
}
173173

174+
declare_clippy_lint! {
175+
/// **What it does:** Checks for use of `Box<&T>` anywhere in the code.
176+
///
177+
/// **Why is this bad?** Any `Box<&T>` can also be a `&T`, which is more
178+
/// general.
179+
///
180+
/// **Known problems:** None.
181+
///
182+
/// **Example:**
183+
/// ```rust
184+
/// fn foo(bar: Box<&usize>) {}
185+
/// ```
186+
///
187+
/// Better:
188+
///
189+
/// ```rust
190+
/// fn foo(bar: &usize) {}
191+
/// ```
192+
pub BOX_BORROWS,
193+
perf,
194+
"a box of borrowed type"
195+
}
196+
174197
pub struct Types {
175198
vec_box_size_threshold: u64,
176199
}
177200

178-
impl_lint_pass!(Types => [BOX_VEC, VEC_BOX, OPTION_OPTION, LINKEDLIST, BORROWED_BOX]);
201+
impl_lint_pass!(Types => [BOX_VEC, VEC_BOX, OPTION_OPTION, LINKEDLIST, BORROWED_BOX, BOX_BORROWS]);
179202

180203
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Types {
181204
fn check_fn(
@@ -257,6 +280,7 @@ impl Types {
257280
/// The parameter `is_local` distinguishes the context of the type; types from
258281
/// local bindings should only be checked for the `BORROWED_BOX` lint.
259282
#[allow(clippy::too_many_lines)]
283+
#[allow(clippy::cognitive_complexity)]
260284
fn check_ty(&mut self, cx: &LateContext<'_, '_>, hir_ty: &hir::Ty<'_>, is_local: bool) {
261285
if hir_ty.span.from_expansion() {
262286
return;
@@ -267,6 +291,27 @@ impl Types {
267291
let res = qpath_res(cx, qpath, hir_id);
268292
if let Some(def_id) = res.opt_def_id() {
269293
if Some(def_id) == cx.tcx.lang_items().owned_box() {
294+
if_chain! {
295+
let last = last_path_segment(qpath);
296+
if let Some(ref params) = last.args;
297+
if !params.parenthesized;
298+
if let Some(ty) = params.args.iter().find_map(|arg| match arg {
299+
GenericArg::Type(ty) => Some(ty),
300+
_ => None,
301+
});
302+
if let TyKind::Rptr(..) = ty.kind;
303+
let ty_ty = hir_ty_to_ty(cx.tcx, ty);
304+
then {
305+
span_lint_and_help(
306+
cx,
307+
BOX_BORROWS,
308+
hir_ty.span,
309+
"usage of `Box<&T>`",
310+
format!("try `{}`", ty_ty).as_str(),
311+
);
312+
return; // don't recurse into the type
313+
}
314+
}
270315
if match_type_parameter(cx, qpath, &paths::VEC) {
271316
span_lint_and_help(
272317
cx,

src/lintlist/mod.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ pub use lint::Lint;
66
pub use lint::LINT_LEVELS;
77

88
// begin lint list, do not remove this comment, it’s used in `update_lints`
9-
pub const ALL_LINTS: [Lint; 361] = [
9+
pub const ALL_LINTS: [Lint; 362] = [
1010
Lint {
1111
name: "absurd_extreme_comparisons",
1212
group: "correctness",
@@ -98,6 +98,13 @@ pub const ALL_LINTS: [Lint; 361] = [
9898
deprecation: None,
9999
module: "types",
100100
},
101+
Lint {
102+
name: "box_borrows",
103+
group: "perf",
104+
desc: "a box of borrowed type",
105+
deprecation: None,
106+
module: "types",
107+
},
101108
Lint {
102109
name: "box_vec",
103110
group: "perf",

tests/ui/box_borrows.rs

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#![warn(clippy::all)]
2+
#![allow(clippy::boxed_local, clippy::needless_pass_by_value)]
3+
#![allow(clippy::blacklisted_name)]
4+
5+
pub struct MyStruct {}
6+
7+
pub struct SubT<T> {
8+
foo: T,
9+
}
10+
11+
pub enum MyEnum {
12+
One,
13+
Two,
14+
}
15+
16+
pub fn test<T>(foo: Box<&T>) {}
17+
18+
pub fn test1(foo: Box<&usize>) {}
19+
20+
pub fn test2(foo: Box<&MyStruct>) {}
21+
22+
pub fn test3(foo: Box<&MyEnum>) {}
23+
24+
pub fn test4(foo: Box<&&MyEnum>) {}
25+
26+
pub fn test5(foo: Box<Box<&usize>>) {}
27+
28+
pub fn test6(foo: Box<SubT<&usize>>) {}
29+
30+
fn main() {}

tests/ui/box_borrows.stderr

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
error: usage of `Box<&T>`
2+
--> $DIR/box_borrows.rs:16:21
3+
|
4+
LL | pub fn test<T>(foo: Box<&T>) {}
5+
| ^^^^^^^
6+
|
7+
= note: `-D clippy::box-borrows` implied by `-D warnings`
8+
= help: try `&T`
9+
10+
error: usage of `Box<&T>`
11+
--> $DIR/box_borrows.rs:18:19
12+
|
13+
LL | pub fn test1(foo: Box<&usize>) {}
14+
| ^^^^^^^^^^^
15+
|
16+
= help: try `&usize`
17+
18+
error: usage of `Box<&T>`
19+
--> $DIR/box_borrows.rs:20:19
20+
|
21+
LL | pub fn test2(foo: Box<&MyStruct>) {}
22+
| ^^^^^^^^^^^^^^
23+
|
24+
= help: try `&MyStruct`
25+
26+
error: usage of `Box<&T>`
27+
--> $DIR/box_borrows.rs:22:19
28+
|
29+
LL | pub fn test3(foo: Box<&MyEnum>) {}
30+
| ^^^^^^^^^^^^
31+
|
32+
= help: try `&MyEnum`
33+
34+
error: usage of `Box<&T>`
35+
--> $DIR/box_borrows.rs:24:19
36+
|
37+
LL | pub fn test4(foo: Box<&&MyEnum>) {}
38+
| ^^^^^^^^^^^^^
39+
|
40+
= help: try `&&MyEnum`
41+
42+
error: usage of `Box<&T>`
43+
--> $DIR/box_borrows.rs:26:23
44+
|
45+
LL | pub fn test5(foo: Box<Box<&usize>>) {}
46+
| ^^^^^^^^^^^
47+
|
48+
= help: try `&usize`
49+
50+
error: aborting due to 6 previous errors
51+

0 commit comments

Comments
 (0)