diff --git a/clippy_lints/src/types/redundant_allocation.rs b/clippy_lints/src/types/redundant_allocation.rs index 10d2ae2eb1d..5fdf1731495 100644 --- a/clippy_lints/src/types/redundant_allocation.rs +++ b/clippy_lints/src/types/redundant_allocation.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then; 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_id::DefId, QPath, TyKind}; +use rustc_hir::{self as hir, def, def_id::DefId, PrimTy, QPath, TyKind}; use rustc_lint::LateContext; use rustc_span::symbol::sym; @@ -54,8 +54,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_ }; let inner_span = match qpath_generic_tys(inner_qpath).next() { Some(ty) => { - // Box<Box<dyn T>> is smaller than Box<dyn T> because of wide pointers - if matches!(ty.kind, TyKind::TraitObject(..)) { + if alloc_makes_pointer_thin(cx, ty) { return false; } ty.span @@ -110,3 +109,20 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_ } 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, + } +} diff --git a/tests/ui/redundant_allocation.rs b/tests/ui/redundant_allocation.rs index 80f94e5f3cb..b830a3771d5 100644 --- a/tests/ui/redundant_allocation.rs +++ b/tests/ui/redundant_allocation.rs @@ -97,4 +97,22 @@ mod box_dyn { pub fn test_rc_box(_: Rc<Box<Box<dyn T>>>) {} } +// https://github.com/rust-lang/rust-clippy/issues/8604 +mod box_str { + use std::boxed::Box; + use std::rc::Rc; + use std::sync::Arc; + + struct S { + a: Box<Box<str>>, + b: Rc<Box<str>>, + c: Arc<Box<str>>, + } + + 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>>>) {} +} + fn main() {} diff --git a/tests/ui/redundant_allocation.stderr b/tests/ui/redundant_allocation.stderr index c3b10e5f5e6..ae213cb8975 100644 --- a/tests/ui/redundant_allocation.stderr +++ b/tests/ui/redundant_allocation.stderr @@ -143,5 +143,14 @@ LL | pub fn test_rc_box(_: Rc<Box<Box<dyn T>>>) {} = note: `Box<Box<dyn T>>` is already on the heap, `Rc<Box<Box<dyn T>>>` makes an extra allocation = help: consider using just `Rc<Box<dyn T>>` or `Box<Box<dyn T>>` -error: aborting due to 16 previous errors +error: usage of `Rc<Box<Box<str>>>` + --> $DIR/redundant_allocation.rs:115:27 + | +LL | pub fn test_rc_box(_: 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