Skip to content

Commit 4aff871

Browse files
committed
Fix ICE in vec_box lint and add run-rustfix
`hir::Ty` doesn't seem to know anything about type bounds and `cx.tcx.type_of(def_id)` caused an ICE when it was passed a generic type with a bound: ``` src/librustc_typeck/collect.rs:1311: unexpected non-type Node::GenericParam: Type { default: None, synthetic: None } ``` Converting it to a proper `Ty` fixes the ICE and catches a few more places where the lint applies.
1 parent 5176a5c commit 4aff871

File tree

5 files changed

+96
-31
lines changed

5 files changed

+96
-31
lines changed

clippy_lints/src/types.rs

+14-16
Original file line numberDiff line numberDiff line change
@@ -275,26 +275,24 @@ fn check_ty(cx: &LateContext<'_, '_>, hir_ty: &hir::Ty, is_local: bool) {
275275
if Some(def_id) == cx.tcx.lang_items().owned_box();
276276
// At this point, we know ty is Box<T>, now get T
277277
if let Some(ref last) = last_path_segment(ty_qpath).args;
278-
if let Some(ty) = last.args.iter().find_map(|arg| match arg {
278+
if let Some(boxed_ty) = last.args.iter().find_map(|arg| match arg {
279279
GenericArg::Type(ty) => Some(ty),
280280
GenericArg::Lifetime(_) => None,
281281
});
282-
if let TyKind::Path(ref ty_qpath) = ty.node;
283-
let def = cx.tables.qpath_def(ty_qpath, ty.hir_id);
284-
if let Some(def_id) = opt_def_id(def);
285-
let boxed_type = cx.tcx.type_of(def_id);
286-
if boxed_type.is_sized(cx.tcx.at(ty.span), cx.param_env);
287282
then {
288-
span_lint_and_sugg(
289-
cx,
290-
VEC_BOX,
291-
hir_ty.span,
292-
"`Vec<T>` is already on the heap, the boxing is unnecessary.",
293-
"try",
294-
format!("Vec<{}>", boxed_type),
295-
Applicability::MaybeIncorrect,
296-
);
297-
return; // don't recurse into the type
283+
let ty_ty = hir_ty_to_ty(cx.tcx, boxed_ty);
284+
if ty_ty.is_sized(cx.tcx.at(ty.span), cx.param_env) {
285+
span_lint_and_sugg(
286+
cx,
287+
VEC_BOX,
288+
hir_ty.span,
289+
"`Vec<T>` is already on the heap, the boxing is unnecessary.",
290+
"try",
291+
format!("Vec<{}>", ty_ty),
292+
Applicability::MaybeIncorrect,
293+
);
294+
return; // don't recurse into the type
295+
}
298296
}
299297
}
300298
} else if match_def_path(cx.tcx, def_id, &paths::OPTION) {

tests/ui/complex_types.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#![warn(clippy::all)]
2-
#![allow(unused, clippy::needless_pass_by_value)]
2+
#![allow(unused, clippy::needless_pass_by_value, clippy::vec_box)]
33
#![feature(associated_type_defaults)]
44

55
type Alias = Vec<Vec<Box<(u32, u32, u32, u32)>>>; // no warning here

tests/ui/vec_box_sized.fixed

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// run-rustfix
2+
3+
#![allow(dead_code)]
4+
5+
struct SizedStruct(i32);
6+
struct UnsizedStruct([i32]);
7+
8+
/// The following should trigger the lint
9+
mod should_trigger {
10+
use super::SizedStruct;
11+
12+
struct StructWithVecBox {
13+
sized_type: Vec<SizedStruct>,
14+
}
15+
16+
struct A(Vec<SizedStruct>);
17+
struct B(Vec<Vec<u32>>);
18+
}
19+
20+
/// The following should not trigger the lint
21+
mod should_not_trigger {
22+
use super::UnsizedStruct;
23+
24+
struct C(Vec<Box<UnsizedStruct>>);
25+
26+
struct StructWithVecBoxButItsUnsized {
27+
unsized_type: Vec<Box<UnsizedStruct>>,
28+
}
29+
30+
struct TraitVec<T: ?Sized> {
31+
// Regression test for #3720. This was causing an ICE.
32+
inner: Vec<Box<T>>,
33+
}
34+
}
35+
36+
fn main() {}

tests/ui/vec_box_sized.rs

+29-10
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,36 @@
1-
struct SizedStruct {
2-
_a: i32,
3-
}
1+
// run-rustfix
42

5-
struct UnsizedStruct {
6-
_a: [i32],
7-
}
3+
#![allow(dead_code)]
4+
5+
struct SizedStruct(i32);
6+
struct UnsizedStruct([i32]);
7+
8+
/// The following should trigger the lint
9+
mod should_trigger {
10+
use super::SizedStruct;
811

9-
struct StructWithVecBox {
10-
sized_type: Vec<Box<SizedStruct>>,
12+
struct StructWithVecBox {
13+
sized_type: Vec<Box<SizedStruct>>,
14+
}
15+
16+
struct A(Vec<Box<SizedStruct>>);
17+
struct B(Vec<Vec<Box<(u32)>>>);
1118
}
1219

13-
struct StructWithVecBoxButItsUnsized {
14-
unsized_type: Vec<Box<UnsizedStruct>>,
20+
/// The following should not trigger the lint
21+
mod should_not_trigger {
22+
use super::UnsizedStruct;
23+
24+
struct C(Vec<Box<UnsizedStruct>>);
25+
26+
struct StructWithVecBoxButItsUnsized {
27+
unsized_type: Vec<Box<UnsizedStruct>>,
28+
}
29+
30+
struct TraitVec<T: ?Sized> {
31+
// Regression test for #3720. This was causing an ICE.
32+
inner: Vec<Box<T>>,
33+
}
1534
}
1635

1736
fn main() {}

tests/ui/vec_box_sized.stderr

+16-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,22 @@
11
error: `Vec<T>` is already on the heap, the boxing is unnecessary.
2-
--> $DIR/vec_box_sized.rs:10:17
2+
--> $DIR/vec_box_sized.rs:13:21
33
|
4-
LL | sized_type: Vec<Box<SizedStruct>>,
5-
| ^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec<SizedStruct>`
4+
LL | sized_type: Vec<Box<SizedStruct>>,
5+
| ^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec<SizedStruct>`
66
|
77
= note: `-D clippy::vec-box` implied by `-D warnings`
88

9-
error: aborting due to previous error
9+
error: `Vec<T>` is already on the heap, the boxing is unnecessary.
10+
--> $DIR/vec_box_sized.rs:16:14
11+
|
12+
LL | struct A(Vec<Box<SizedStruct>>);
13+
| ^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec<SizedStruct>`
14+
15+
error: `Vec<T>` is already on the heap, the boxing is unnecessary.
16+
--> $DIR/vec_box_sized.rs:17:18
17+
|
18+
LL | struct B(Vec<Vec<Box<(u32)>>>);
19+
| ^^^^^^^^^^^^^^^ help: try: `Vec<u32>`
20+
21+
error: aborting due to 3 previous errors
1022

0 commit comments

Comments
 (0)