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) {
#![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
--- /dev/null
+// 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() {}
-struct SizedStruct {
- _a: i32,
-}
+// run-rustfix
-struct UnsizedStruct {
- _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 StructWithVecBox {
+ sized_type: Vec<Box<SizedStruct>>,
+ }
+
+ struct A(Vec<Box<SizedStruct>>);
+ struct B(Vec<Vec<Box<(u32)>>>);
}
-struct StructWithVecBoxButItsUnsized {
- unsized_type: Vec<Box<UnsizedStruct>>,
+/// 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() {}
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