From 7e298937c8c0c33f2bb4e10f9fcb505bcb089bb7 Mon Sep 17 00:00:00 2001 From: Mu001999 Date: Tue, 24 Jun 2025 00:06:56 +0800 Subject: [PATCH] Extend dead code analysis of impls and impl items to non-ADTs --- compiler/rustc_passes/src/dead.rs | 2 + compiler/rustc_privacy/src/lib.rs | 20 ++++- .../dead-code/unused-impl-for-non-adts.rs | 89 +++++++++++++++++++ .../dead-code/unused-impl-for-non-adts.stderr | 20 +++++ 4 files changed, 128 insertions(+), 3 deletions(-) create mode 100644 tests/ui/lint/dead-code/unused-impl-for-non-adts.rs create mode 100644 tests/ui/lint/dead-code/unused-impl-for-non-adts.stderr diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 4738036318d30..32717c535ce64 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -58,6 +58,8 @@ fn local_adt_def_of_ty<'tcx>(ty: &hir::Ty<'tcx>) -> Option { None } } + TyKind::Slice(ty) | TyKind::Array(ty, _) => local_adt_def_of_ty(ty), + TyKind::Ptr(ty) | TyKind::Ref(_, ty) => local_adt_def_of_ty(ty.ty), _ => None, } } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 963f4c77d809d..f8633b47fa420 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -699,17 +699,31 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { // `impl ReachableTrait for ReachableTy { ... }` // can be usable from other crates (#57264). So we skip args when calculating // reachability and consider an impl reachable if its "shallow" type and trait are - // reachable. + // reachable if there were no private types. // // The assumption we make here is that type-inference won't let you use an impl // without knowing both "shallow" version of its self type and "shallow" version of // its trait if it exists (which require reaching the `DefId`s in them). - let item_ev = EffectiveVisibility::of_impl::( + let impl_vis = ty::Visibility::of_impl::( item.owner_id.def_id, self.tcx, - &self.effective_visibilities, + &Default::default(), ); + let item_ev = if impl_vis.is_public() { + EffectiveVisibility::of_impl::( + item.owner_id.def_id, + self.tcx, + &self.effective_visibilities, + ) + } else { + EffectiveVisibility::of_impl::( + item.owner_id.def_id, + self.tcx, + &self.effective_visibilities, + ) + }; + self.update_eff_vis(item.owner_id.def_id, item_ev, None, Level::Direct); self.reach(item.owner_id.def_id, item_ev).generics().predicates().ty().trait_ref(); diff --git a/tests/ui/lint/dead-code/unused-impl-for-non-adts.rs b/tests/ui/lint/dead-code/unused-impl-for-non-adts.rs new file mode 100644 index 0000000000000..75547739cfccd --- /dev/null +++ b/tests/ui/lint/dead-code/unused-impl-for-non-adts.rs @@ -0,0 +1,89 @@ +#![deny(dead_code)] + +struct Foo; //~ ERROR struct `Foo` is never constructed + +trait Trait { //~ ERROR trait `Trait` is never used + fn foo(&self); +} + +impl Trait for Foo { + fn foo(&self) {} +} + +impl Trait for [Foo] { + fn foo(&self) {} +} +impl Trait for [Foo; N] { + fn foo(&self) {} +} + +impl Trait for *const Foo { + fn foo(&self) {} +} +impl Trait for *mut Foo { + fn foo(&self) {} +} + +impl Trait for &Foo { + fn foo(&self) {} +} +impl Trait for &&Foo { + fn foo(&self) {} +} +impl Trait for &mut Foo { + fn foo(&self) {} +} + +impl Trait for [&Foo] { + fn foo(&self) {} +} +impl Trait for &[Foo] { + fn foo(&self) {} +} +impl Trait for &*const Foo { + fn foo(&self) {} +} + +pub trait Trait2 { + fn foo(&self); +} + +impl Trait2 for Foo { + fn foo(&self) {} +} + +impl Trait2 for [Foo] { + fn foo(&self) {} +} +impl Trait2 for [Foo; N] { + fn foo(&self) {} +} + +impl Trait2 for *const Foo { + fn foo(&self) {} +} +impl Trait2 for *mut Foo { + fn foo(&self) {} +} + +impl Trait2 for &Foo { + fn foo(&self) {} +} +impl Trait2 for &&Foo { + fn foo(&self) {} +} +impl Trait2 for &mut Foo { + fn foo(&self) {} +} + +impl Trait2 for [&Foo] { + fn foo(&self) {} +} +impl Trait2 for &[Foo] { + fn foo(&self) {} +} +impl Trait2 for &*const Foo { + fn foo(&self) {} +} + +fn main() {} diff --git a/tests/ui/lint/dead-code/unused-impl-for-non-adts.stderr b/tests/ui/lint/dead-code/unused-impl-for-non-adts.stderr new file mode 100644 index 0000000000000..e61fc403e810d --- /dev/null +++ b/tests/ui/lint/dead-code/unused-impl-for-non-adts.stderr @@ -0,0 +1,20 @@ +error: struct `Foo` is never constructed + --> $DIR/unused-impl-for-non-adts.rs:3:8 + | +LL | struct Foo; + | ^^^ + | +note: the lint level is defined here + --> $DIR/unused-impl-for-non-adts.rs:1:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: trait `Trait` is never used + --> $DIR/unused-impl-for-non-adts.rs:5:7 + | +LL | trait Trait { + | ^^^^^ + +error: aborting due to 2 previous errors +