diff options
| author | Camille GILLOT <gillot.camille@gmail.com> | 2022-01-29 21:10:41 +0100 |
|---|---|---|
| committer | Camille GILLOT <gillot.camille@gmail.com> | 2022-02-01 13:11:03 +0100 |
| commit | 4e7d47bb6c91f6db5d043a152d11ab7528266d25 (patch) | |
| tree | 6b2e6ee3b86790ba76e3c98fceb366e91c5dc4f6 | |
| parent | 312a7995e73e390646bc61920ffead7a640addc6 (diff) | |
| download | rust-4e7d47bb6c91f6db5d043a152d11ab7528266d25.tar.gz rust-4e7d47bb6c91f6db5d043a152d11ab7528266d25.zip | |
Make dead code check a query.
| -rw-r--r-- | compiler/rustc_interface/src/passes.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/query/mod.rs | 16 | ||||
| -rw-r--r-- | compiler/rustc_passes/src/dead.rs | 55 | ||||
| -rw-r--r-- | compiler/rustc_passes/src/lib.rs | 1 | ||||
| -rw-r--r-- | src/test/ui/lint/dead-code/lint-dead-code-1.stderr | 20 |
5 files changed, 62 insertions, 33 deletions
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index be31eb89f1b..7a3d77466c5 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -999,7 +999,8 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { tcx.ensure().check_private_in_public(()); }, { - sess.time("death_checking", || rustc_passes::dead::check_crate(tcx)); + tcx.hir() + .par_for_each_module(|module| tcx.ensure().check_mod_deathness(module)); }, { sess.time("unused_lib_feature_checking", || { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 715a1fa25a1..73128de9848 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -750,6 +750,22 @@ rustc_queries! { desc { |tcx| "checking liveness of variables in {}", describe_as_module(key, tcx) } } + /// Return the live symbols in the crate for dead code check. + /// + /// The second return value maps from ADTs to ignored derived traits (e.g. Debug and Clone) and + /// their respective impl (i.e., part of the derive macro) + query live_symbols_and_ignored_derived_traits(_: ()) -> ( + FxHashSet<LocalDefId>, + FxHashMap<LocalDefId, Vec<(DefId, DefId)>> + ) { + storage(ArenaCacheSelector<'tcx>) + desc { "find live symbols in crate" } + } + + query check_mod_deathness(key: LocalDefId) -> () { + desc { |tcx| "checking deathness of variables in {}", describe_as_module(key, tcx) } + } + query check_mod_impl_wf(key: LocalDefId) -> () { desc { |tcx| "checking that impls are well-formed in {}", describe_as_module(key, tcx) } } diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 7f15aacc532..e7e56711b33 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -13,6 +13,7 @@ use rustc_hir::{Node, PatKind, TyKind}; use rustc_middle::hir::nested_filter; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::privacy; +use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, DefIdTree, TyCtxt}; use rustc_session::lint; use rustc_span::symbol::{sym, Symbol}; @@ -52,7 +53,7 @@ struct MarkSymbolVisitor<'tcx> { // maps from ADTs to ignored derived traits (e.g. Debug and Clone) // and the span of their respective impl (i.e., part of the derive // macro) - ignored_derived_traits: FxHashMap<DefId, Vec<(Span, DefId)>>, + ignored_derived_traits: FxHashMap<LocalDefId, Vec<(DefId, DefId)>>, } impl<'tcx> MarkSymbolVisitor<'tcx> { @@ -258,12 +259,11 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { if self.tcx.has_attr(trait_of, sym::rustc_trivial_field_reads) { let trait_ref = self.tcx.impl_trait_ref(impl_of).unwrap(); if let ty::Adt(adt_def, _) = trait_ref.self_ty().kind() { - let impl_span = self.tcx.def_span(impl_of); - if let Some(v) = self.ignored_derived_traits.get_mut(&adt_def.did) { - v.push((impl_span, trait_of)); - } else { + if let Some(adt_def_id) = adt_def.did.as_local() { self.ignored_derived_traits - .insert(adt_def.did, vec![(impl_span, trait_of)]); + .entry(adt_def_id) + .or_default() + .push((trait_of, impl_of)); } } return true; @@ -563,8 +563,8 @@ impl<'v, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'tcx> { fn create_and_seed_worklist<'tcx>( tcx: TyCtxt<'tcx>, - access_levels: &privacy::AccessLevels, ) -> (Vec<LocalDefId>, FxHashMap<LocalDefId, LocalDefId>) { + let access_levels = &tcx.privacy_access_levels(()); let worklist = access_levels .map .iter() @@ -584,11 +584,11 @@ fn create_and_seed_worklist<'tcx>( (life_seeder.worklist, life_seeder.struct_constructors) } -fn find_live<'tcx>( +fn live_symbols_and_ignored_derived_traits<'tcx>( tcx: TyCtxt<'tcx>, - access_levels: &privacy::AccessLevels, -) -> (FxHashSet<LocalDefId>, FxHashMap<DefId, Vec<(Span, DefId)>>) { - let (worklist, struct_constructors) = create_and_seed_worklist(tcx, access_levels); + (): (), +) -> (FxHashSet<LocalDefId>, FxHashMap<LocalDefId, Vec<(DefId, DefId)>>) { + let (worklist, struct_constructors) = create_and_seed_worklist(tcx); let mut symbol_visitor = MarkSymbolVisitor { worklist, tcx, @@ -608,8 +608,8 @@ fn find_live<'tcx>( struct DeadVisitor<'tcx> { tcx: TyCtxt<'tcx>, - live_symbols: FxHashSet<LocalDefId>, - ignored_derived_traits: FxHashMap<DefId, Vec<(Span, DefId)>>, + live_symbols: &'tcx FxHashSet<LocalDefId>, + ignored_derived_traits: &'tcx FxHashMap<LocalDefId, Vec<(DefId, DefId)>>, } impl<'tcx> DeadVisitor<'tcx> { @@ -682,12 +682,10 @@ impl<'tcx> DeadVisitor<'tcx> { let hir = self.tcx.hir(); if let Some(encl_scope) = hir.get_enclosing_scope(id) { if let Some(encl_def_id) = hir.opt_local_def_id(encl_scope) { - if let Some(ign_traits) = - self.ignored_derived_traits.get(&encl_def_id.to_def_id()) - { + if let Some(ign_traits) = self.ignored_derived_traits.get(&encl_def_id) { let traits_str = ign_traits .iter() - .map(|(_, t)| format!("`{}`", self.tcx.item_name(*t))) + .map(|(trait_id, _)| format!("`{}`", self.tcx.item_name(*trait_id))) .collect::<Vec<_>>() .join(" and "); let plural_s = pluralize!(ign_traits.len()); @@ -703,7 +701,10 @@ impl<'tcx> DeadVisitor<'tcx> { traits_str, is_are ); - let multispan = ign_traits.iter().map(|(s, _)| *s).collect::<Vec<_>>(); + let multispan = ign_traits + .iter() + .map(|(_, impl_id)| self.tcx.def_span(*impl_id)) + .collect::<Vec<_>>(); err.span_note(multispan, &msg); } } @@ -761,6 +762,9 @@ impl<'tcx> Visitor<'tcx> for DeadVisitor<'tcx> { } } + // This visitor should only visit a single module at a time. + fn visit_mod(&mut self, _: &'tcx hir::Mod<'tcx>, _: Span, _: hir::HirId) {} + fn visit_variant( &mut self, variant: &'tcx hir::Variant<'tcx>, @@ -836,9 +840,16 @@ impl<'tcx> Visitor<'tcx> for DeadVisitor<'tcx> { } } -pub fn check_crate(tcx: TyCtxt<'_>) { - let access_levels = &tcx.privacy_access_levels(()); - let (live_symbols, ignored_derived_traits) = find_live(tcx, access_levels); +fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalDefId) { + let (live_symbols, ignored_derived_traits) = tcx.live_symbols_and_ignored_derived_traits(()); let mut visitor = DeadVisitor { tcx, live_symbols, ignored_derived_traits }; - tcx.hir().walk_toplevel_module(&mut visitor); + let (module, _, module_id) = tcx.hir().get_module(module); + // Do not use an ItemLikeVisitor since we may want to skip visiting some items + // when a surrounding one is warned against or `_`. + intravisit::walk_mod(&mut visitor, module, module_id); +} + +pub(crate) fn provide(providers: &mut Providers) { + *providers = + Providers { live_symbols_and_ignored_derived_traits, check_mod_deathness, ..*providers }; } diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index 2075fee7171..554701ee90f 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -44,6 +44,7 @@ mod weak_lang_items; pub fn provide(providers: &mut Providers) { check_attr::provide(providers); check_const::provide(providers); + dead::provide(providers); diagnostic_items::provide(providers); entry::provide(providers); lang_items::provide(providers); diff --git a/src/test/ui/lint/dead-code/lint-dead-code-1.stderr b/src/test/ui/lint/dead-code/lint-dead-code-1.stderr index af97ea98b2b..72e28e7940e 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-1.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-1.stderr @@ -1,8 +1,8 @@ -error: struct is never constructed: `Bar` - --> $DIR/lint-dead-code-1.rs:12:16 +error: static is never used: `priv_static` + --> $DIR/lint-dead-code-1.rs:20:1 | -LL | pub struct Bar; - | ^^^ +LL | static priv_static: isize = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here --> $DIR/lint-dead-code-1.rs:5:9 @@ -10,12 +10,6 @@ note: the lint level is defined here LL | #![deny(dead_code)] | ^^^^^^^^^ -error: static is never used: `priv_static` - --> $DIR/lint-dead-code-1.rs:20:1 - | -LL | static priv_static: isize = 0; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error: constant is never used: `priv_const` --> $DIR/lint-dead-code-1.rs:27:1 | @@ -64,5 +58,11 @@ error: function is never used: `baz` LL | fn baz() -> impl Copy { | ^^^ +error: struct is never constructed: `Bar` + --> $DIR/lint-dead-code-1.rs:12:16 + | +LL | pub struct Bar; + | ^^^ + error: aborting due to 10 previous errors |
