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:
parent
5176a5c4b7
commit
4aff8711f0
@ -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();
|
||||
// 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(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::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 {
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
VEC_BOX,
|
||||
hir_ty.span,
|
||||
"`Vec<T>` is already on the heap, the boxing is unnecessary.",
|
||||
"try",
|
||||
format!("Vec<{}>", boxed_type),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
return; // don't recurse into the type
|
||||
let ty_ty = hir_ty_to_ty(cx.tcx, boxed_ty);
|
||||
if ty_ty.is_sized(cx.tcx.at(ty.span), cx.param_env) {
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
VEC_BOX,
|
||||
hir_ty.span,
|
||||
"`Vec<T>` is already on the heap, the boxing is unnecessary.",
|
||||
"try",
|
||||
format!("Vec<{}>", ty_ty),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
return; // don't recurse into the type
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if match_def_path(cx.tcx, def_id, &paths::OPTION) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
#![warn(clippy::all)]
|
||||
#![allow(unused, clippy::needless_pass_by_value)]
|
||||
#![allow(unused, clippy::needless_pass_by_value, clippy::vec_box)]
|
||||
#![feature(associated_type_defaults)]
|
||||
|
||||
type Alias = Vec<Vec<Box<(u32, u32, u32, u32)>>>; // no warning here
|
||||
|
36
tests/ui/vec_box_sized.fixed
Normal file
36
tests/ui/vec_box_sized.fixed
Normal 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() {}
|
@ -1,17 +1,36 @@
|
||||
struct SizedStruct {
|
||||
_a: i32,
|
||||
// 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<Box<SizedStruct>>,
|
||||
}
|
||||
|
||||
struct A(Vec<Box<SizedStruct>>);
|
||||
struct B(Vec<Vec<Box<(u32)>>>);
|
||||
}
|
||||
|
||||
struct UnsizedStruct {
|
||||
_a: [i32],
|
||||
}
|
||||
/// The following should not trigger the lint
|
||||
mod should_not_trigger {
|
||||
use super::UnsizedStruct;
|
||||
|
||||
struct StructWithVecBox {
|
||||
sized_type: Vec<Box<SizedStruct>>,
|
||||
}
|
||||
struct C(Vec<Box<UnsizedStruct>>);
|
||||
|
||||
struct StructWithVecBoxButItsUnsized {
|
||||
unsized_type: 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() {}
|
||||
|
@ -1,10 +1,22 @@
|
||||
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>>,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec<SizedStruct>`
|
||||
LL | sized_type: Vec<Box<SizedStruct>>,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec<SizedStruct>`
|
||||
|
|
||||
= 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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user