mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-10 23:24:24 +00:00
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
5 changed files with 96 additions and 31 deletions
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
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 {
|
// 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() {}
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue