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.
This commit is contained in:
Philipp Hansch 2019-02-01 08:21:32 +01:00
parent 5176a5c4b7
commit 4aff8711f0
No known key found for this signature in database
GPG key ID: B6FA06A6E0E2665B
5 changed files with 96 additions and 31 deletions

View file

@ -275,26 +275,24 @@ fn check_ty(cx: &LateContext<'_, '_>, hir_ty: &hir::Ty, is_local: bool) {
if Some(def_id) == cx.tcx.lang_items().owned_box(); if Some(def_id) == cx.tcx.lang_items().owned_box();
// At this point, we know ty is Box<T>, now get T // At this point, we know ty is Box<T>, now get T
if let Some(ref last) = last_path_segment(ty_qpath).args; if let Some(ref last) = last_path_segment(ty_qpath).args;
if let Some(ty) = last.args.iter().find_map(|arg| match arg { if let Some(boxed_ty) = last.args.iter().find_map(|arg| match arg {
GenericArg::Type(ty) => Some(ty), GenericArg::Type(ty) => Some(ty),
GenericArg::Lifetime(_) => None, GenericArg::Lifetime(_) => None,
}); });
if let TyKind::Path(ref ty_qpath) = ty.node;
let def = cx.tables.qpath_def(ty_qpath, ty.hir_id);
if let Some(def_id) = opt_def_id(def);
let boxed_type = cx.tcx.type_of(def_id);
if boxed_type.is_sized(cx.tcx.at(ty.span), cx.param_env);
then { then {
span_lint_and_sugg( let ty_ty = hir_ty_to_ty(cx.tcx, boxed_ty);
cx, if ty_ty.is_sized(cx.tcx.at(ty.span), cx.param_env) {
VEC_BOX, span_lint_and_sugg(
hir_ty.span, cx,
"`Vec<T>` is already on the heap, the boxing is unnecessary.", VEC_BOX,
"try", hir_ty.span,
format!("Vec<{}>", boxed_type), "`Vec<T>` is already on the heap, the boxing is unnecessary.",
Applicability::MaybeIncorrect, "try",
); format!("Vec<{}>", ty_ty),
return; // don't recurse into the type Applicability::MaybeIncorrect,
);
return; // don't recurse into the type
}
} }
} }
} else if match_def_path(cx.tcx, def_id, &paths::OPTION) { } else if match_def_path(cx.tcx, def_id, &paths::OPTION) {

View file

@ -1,5 +1,5 @@
#![warn(clippy::all)] #![warn(clippy::all)]
#![allow(unused, clippy::needless_pass_by_value)] #![allow(unused, clippy::needless_pass_by_value, clippy::vec_box)]
#![feature(associated_type_defaults)] #![feature(associated_type_defaults)]
type Alias = Vec<Vec<Box<(u32, u32, u32, u32)>>>; // no warning here type Alias = Vec<Vec<Box<(u32, u32, u32, u32)>>>; // no warning here

View file

@ -0,0 +1,36 @@
// run-rustfix
#![allow(dead_code)]
struct SizedStruct(i32);
struct UnsizedStruct([i32]);
/// The following should trigger the lint
mod should_trigger {
use super::SizedStruct;
struct StructWithVecBox {
sized_type: Vec<SizedStruct>,
}
struct A(Vec<SizedStruct>);
struct B(Vec<Vec<u32>>);
}
/// The following should not trigger the lint
mod should_not_trigger {
use super::UnsizedStruct;
struct C(Vec<Box<UnsizedStruct>>);
struct StructWithVecBoxButItsUnsized {
unsized_type: Vec<Box<UnsizedStruct>>,
}
struct TraitVec<T: ?Sized> {
// Regression test for #3720. This was causing an ICE.
inner: Vec<Box<T>>,
}
}
fn main() {}

View file

@ -1,17 +1,36 @@
struct SizedStruct { // run-rustfix
_a: i32,
#![allow(dead_code)]
struct SizedStruct(i32);
struct UnsizedStruct([i32]);
/// The following should trigger the lint
mod should_trigger {
use super::SizedStruct;
struct StructWithVecBox {
sized_type: Vec<Box<SizedStruct>>,
}
struct A(Vec<Box<SizedStruct>>);
struct B(Vec<Vec<Box<(u32)>>>);
} }
struct UnsizedStruct { /// The following should not trigger the lint
_a: [i32], mod should_not_trigger {
} use super::UnsizedStruct;
struct StructWithVecBox { struct C(Vec<Box<UnsizedStruct>>);
sized_type: Vec<Box<SizedStruct>>,
}
struct StructWithVecBoxButItsUnsized { struct StructWithVecBoxButItsUnsized {
unsized_type: Vec<Box<UnsizedStruct>>, unsized_type: Vec<Box<UnsizedStruct>>,
}
struct TraitVec<T: ?Sized> {
// Regression test for #3720. This was causing an ICE.
inner: Vec<Box<T>>,
}
} }
fn main() {} fn main() {}

View file

@ -1,10 +1,22 @@
error: `Vec<T>` is already on the heap, the boxing is unnecessary. error: `Vec<T>` is already on the heap, the boxing is unnecessary.
--> $DIR/vec_box_sized.rs:10:17 --> $DIR/vec_box_sized.rs:13:21
| |
LL | sized_type: Vec<Box<SizedStruct>>, LL | sized_type: Vec<Box<SizedStruct>>,
| ^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec<SizedStruct>` | ^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec<SizedStruct>`
| |
= note: `-D clippy::vec-box` implied by `-D warnings` = note: `-D clippy::vec-box` implied by `-D warnings`
error: aborting due to previous error error: `Vec<T>` is already on the heap, the boxing is unnecessary.
--> $DIR/vec_box_sized.rs:16:14
|
LL | struct A(Vec<Box<SizedStruct>>);
| ^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec<SizedStruct>`
error: `Vec<T>` is already on the heap, the boxing is unnecessary.
--> $DIR/vec_box_sized.rs:17:18
|
LL | struct B(Vec<Vec<Box<(u32)>>>);
| ^^^^^^^^^^^^^^^ help: try: `Vec<u32>`
error: aborting due to 3 previous errors