use clippy_utils::source::{snippet, snippet_with_applicability};
use clippy_utils::{path_def_id, qpath_generic_tys};
use rustc_errors::Applicability;
-use rustc_hir::{self as hir, def, def_id::DefId, PrimTy, QPath, TyKind};
+use rustc_hir::{self as hir, def_id::DefId, QPath, TyKind};
use rustc_lint::LateContext;
use rustc_span::symbol::sym;
+use rustc_typeck::hir_ty_to_ty;
use super::{utils, REDUNDANT_ALLOCATION};
};
let inner_span = match qpath_generic_tys(inner_qpath).next() {
Some(ty) => {
- if alloc_makes_pointer_thin(cx, ty) {
+ // Reallocation of a fat pointer causes it to become thin
+ if !hir_ty_to_ty(cx.tcx, ty).is_sized(cx.tcx.at(ty.span), cx.param_env) {
return false;
}
ty.span
}
true
}
-
-/// Returns `true` if the allocation would make `hir_ty` go from fat to thin.
-fn alloc_makes_pointer_thin(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>) -> bool {
- match &hir_ty.kind {
- TyKind::TraitObject(..) => true,
- TyKind::Path(ty_qpath) => {
- let ty_res = cx.qpath_res(ty_qpath, hir_ty.hir_id);
- if let def::Res::PrimTy(prim_ty) = ty_res {
- if matches!(prim_ty, PrimTy::Str) {
- return true;
- }
- }
- false
- },
- _ => false,
- }
-}
}
// https://github.com/rust-lang/rust-clippy/issues/8604
-mod box_str {
+mod box_fat_ptr {
use std::boxed::Box;
+ use std::path::Path;
use std::rc::Rc;
use std::sync::Arc;
+ pub struct DynSized {
+ foo: [usize],
+ }
+
struct S {
a: Box<Box<str>>,
b: Rc<Box<str>>,
c: Arc<Box<str>>,
+
+ e: Box<Box<[usize]>>,
+ f: Box<Box<Path>>,
+ g: Box<Box<DynSized>>,
}
- pub fn test_box(_: Box<Box<str>>) {}
- pub fn test_rc(_: Rc<Box<str>>) {}
- pub fn test_arc(_: Arc<Box<str>>) {}
- pub fn test_rc_box(_: Rc<Box<Box<str>>>) {}
+ pub fn test_box_str(_: Box<Box<str>>) {}
+ pub fn test_rc_str(_: Rc<Box<str>>) {}
+ pub fn test_arc_str(_: Arc<Box<str>>) {}
+
+ pub fn test_box_slice(_: Box<Box<[usize]>>) {}
+ pub fn test_box_path(_: Box<Box<Path>>) {}
+ pub fn test_box_custom(_: Box<Box<DynSized>>) {}
+
+ pub fn test_rc_box_str(_: Rc<Box<Box<str>>>) {}
+ pub fn test_rc_box_slice(_: Rc<Box<Box<[usize]>>>) {}
+ pub fn test_rc_box_path(_: Rc<Box<Box<Path>>>) {}
+ pub fn test_rc_box_custom(_: Rc<Box<Box<DynSized>>>) {}
}
fn main() {}
= help: consider using just `Rc<Box<dyn T>>` or `Box<Box<dyn T>>`
error: usage of `Rc<Box<Box<str>>>`
- --> $DIR/redundant_allocation.rs:115:27
+ --> $DIR/redundant_allocation.rs:129:31
|
-LL | pub fn test_rc_box(_: Rc<Box<Box<str>>>) {}
- | ^^^^^^^^^^^^^^^^^
+LL | pub fn test_rc_box_str(_: Rc<Box<Box<str>>>) {}
+ | ^^^^^^^^^^^^^^^^^
|
= note: `Box<Box<str>>` is already on the heap, `Rc<Box<Box<str>>>` makes an extra allocation
= help: consider using just `Rc<Box<str>>` or `Box<Box<str>>`
-error: aborting due to 17 previous errors
+error: usage of `Rc<Box<Box<[usize]>>>`
+ --> $DIR/redundant_allocation.rs:130:33
+ |
+LL | pub fn test_rc_box_slice(_: Rc<Box<Box<[usize]>>>) {}
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `Box<Box<[usize]>>` is already on the heap, `Rc<Box<Box<[usize]>>>` makes an extra allocation
+ = help: consider using just `Rc<Box<[usize]>>` or `Box<Box<[usize]>>`
+
+error: usage of `Rc<Box<Box<Path>>>`
+ --> $DIR/redundant_allocation.rs:131:32
+ |
+LL | pub fn test_rc_box_path(_: Rc<Box<Box<Path>>>) {}
+ | ^^^^^^^^^^^^^^^^^^
+ |
+ = note: `Box<Box<Path>>` is already on the heap, `Rc<Box<Box<Path>>>` makes an extra allocation
+ = help: consider using just `Rc<Box<Path>>` or `Box<Box<Path>>`
+
+error: usage of `Rc<Box<Box<DynSized>>>`
+ --> $DIR/redundant_allocation.rs:132:34
+ |
+LL | pub fn test_rc_box_custom(_: Rc<Box<Box<DynSized>>>) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `Box<Box<DynSized>>` is already on the heap, `Rc<Box<Box<DynSized>>>` makes an extra allocation
+ = help: consider using just `Rc<Box<DynSized>>` or `Box<Box<DynSized>>`
+
+error: aborting due to 20 previous errors