Skip to content

Commit f601717

Browse files
committed
Use less HIR when seeding work list.
1 parent 6c39b30 commit f601717

File tree

1 file changed

+50
-90
lines changed

1 file changed

+50
-90
lines changed

compiler/rustc_passes/src/dead.rs

Lines changed: 50 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -718,113 +718,81 @@ fn has_allow_dead_code_or_lang_attr(
718718
}
719719
}
720720

721-
// These check_* functions seeds items that
722-
// 1) We want to explicitly consider as live:
723-
// * Item annotated with #[allow(dead_code)]
724-
// - This is done so that if we want to suppress warnings for a
725-
// group of dead functions, we only have to annotate the "root".
726-
// For example, if both `f` and `g` are dead and `f` calls `g`,
727-
// then annotating `f` with `#[allow(dead_code)]` will suppress
728-
// warning for both `f` and `g`.
729-
// * Item annotated with #[lang=".."]
730-
// - This is because lang items are always callable from elsewhere.
731-
// or
732-
// 2) We are not sure to be live or not
733-
// * Implementations of traits and trait methods
734-
fn check_item<'tcx>(
721+
/// Examine the given definition and record it in the worklist if it should be considered live.
722+
///
723+
/// We want to explicitly consider as live:
724+
/// * Item annotated with #[allow(dead_code)]
725+
/// This is done so that if we want to suppress warnings for a
726+
/// group of dead functions, we only have to annotate the "root".
727+
/// For example, if both `f` and `g` are dead and `f` calls `g`,
728+
/// then annotating `f` with `#[allow(dead_code)]` will suppress
729+
/// warning for both `f` and `g`.
730+
///
731+
/// * Item annotated with #[lang=".."]
732+
/// Lang items are always callable from elsewhere.
733+
///
734+
/// For trait methods and implementations of traits, we are not certain that the definitions are
735+
/// live at this stage. We record them in `unsolved_items` for later examination.
736+
fn maybe_record_as_seed<'tcx>(
735737
tcx: TyCtxt<'tcx>,
738+
owner_id: hir::OwnerId,
736739
worklist: &mut Vec<(LocalDefId, ComesFromAllowExpect)>,
737740
unsolved_items: &mut Vec<LocalDefId>,
738-
id: hir::ItemId,
739741
) {
740-
let allow_dead_code = has_allow_dead_code_or_lang_attr(tcx, id.owner_id.def_id);
742+
let allow_dead_code = has_allow_dead_code_or_lang_attr(tcx, owner_id.def_id);
741743
if let Some(comes_from_allow) = allow_dead_code {
742-
worklist.push((id.owner_id.def_id, comes_from_allow));
744+
worklist.push((owner_id.def_id, comes_from_allow));
743745
}
744746

745-
match tcx.def_kind(id.owner_id) {
747+
match tcx.def_kind(owner_id) {
746748
DefKind::Enum => {
747-
let item = tcx.hir_item(id);
748-
if let hir::ItemKind::Enum(_, _, ref enum_def) = item.kind {
749-
if let Some(comes_from_allow) = allow_dead_code {
750-
worklist.extend(
751-
enum_def.variants.iter().map(|variant| (variant.def_id, comes_from_allow)),
752-
);
749+
let adt = tcx.adt_def(owner_id);
750+
if let Some(comes_from_allow) = allow_dead_code {
751+
worklist.extend(
752+
adt.variants()
753+
.iter()
754+
.map(|variant| (variant.def_id.expect_local(), comes_from_allow)),
755+
);
756+
}
757+
}
758+
DefKind::AssocFn | DefKind::AssocConst | DefKind::AssocTy => {
759+
if allow_dead_code.is_none() {
760+
let parent = tcx.local_parent(owner_id.def_id);
761+
match tcx.def_kind(parent) {
762+
DefKind::Impl { of_trait: false } | DefKind::Trait => {}
763+
DefKind::Impl { of_trait: true } => {
764+
// We only care about associated items of traits,
765+
// because they cannot be visited directly,
766+
// so we later mark them as live if their corresponding traits
767+
// or trait items and self types are both live,
768+
// but inherent associated items can be visited and marked directly.
769+
unsolved_items.push(owner_id.def_id);
770+
}
771+
_ => bug!(),
753772
}
754773
}
755774
}
756775
DefKind::Impl { of_trait } => {
757-
if let Some(comes_from_allow) =
758-
has_allow_dead_code_or_lang_attr(tcx, id.owner_id.def_id)
759-
{
760-
worklist.push((id.owner_id.def_id, comes_from_allow));
761-
} else if of_trait {
762-
unsolved_items.push(id.owner_id.def_id);
763-
}
764-
765-
for def_id in tcx.associated_item_def_ids(id.owner_id) {
766-
let local_def_id = def_id.expect_local();
767-
768-
if let Some(comes_from_allow) = has_allow_dead_code_or_lang_attr(tcx, local_def_id)
769-
{
770-
worklist.push((local_def_id, comes_from_allow));
771-
} else if of_trait {
772-
// We only care about associated items of traits,
773-
// because they cannot be visited directly,
774-
// so we later mark them as live if their corresponding traits
775-
// or trait items and self types are both live,
776-
// but inherent associated items can be visited and marked directly.
777-
unsolved_items.push(local_def_id);
778-
}
776+
if allow_dead_code.is_none() && of_trait {
777+
unsolved_items.push(owner_id.def_id);
779778
}
780779
}
781780
DefKind::GlobalAsm => {
782781
// global_asm! is always live.
783-
worklist.push((id.owner_id.def_id, ComesFromAllowExpect::No));
782+
worklist.push((owner_id.def_id, ComesFromAllowExpect::No));
784783
}
785784
DefKind::Const => {
786-
let item = tcx.hir_item(id);
787-
if let hir::ItemKind::Const(ident, ..) = item.kind
788-
&& ident.name == kw::Underscore
789-
{
785+
if tcx.item_name(owner_id.def_id) == kw::Underscore {
790786
// `const _` is always live, as that syntax only exists for the side effects
791787
// of type checking and evaluating the constant expression, and marking them
792788
// as dead code would defeat that purpose.
793-
worklist.push((id.owner_id.def_id, ComesFromAllowExpect::No));
789+
worklist.push((owner_id.def_id, ComesFromAllowExpect::No));
794790
}
795791
}
796792
_ => {}
797793
}
798794
}
799795

800-
fn check_trait_item(
801-
tcx: TyCtxt<'_>,
802-
worklist: &mut Vec<(LocalDefId, ComesFromAllowExpect)>,
803-
id: hir::TraitItemId,
804-
) {
805-
use hir::TraitItemKind::{Const, Fn, Type};
806-
807-
let trait_item = tcx.hir_trait_item(id);
808-
if matches!(trait_item.kind, Const(_, Some(_)) | Type(_, Some(_)) | Fn(..))
809-
&& let Some(comes_from_allow) =
810-
has_allow_dead_code_or_lang_attr(tcx, trait_item.owner_id.def_id)
811-
{
812-
worklist.push((trait_item.owner_id.def_id, comes_from_allow));
813-
}
814-
}
815-
816-
fn check_foreign_item(
817-
tcx: TyCtxt<'_>,
818-
worklist: &mut Vec<(LocalDefId, ComesFromAllowExpect)>,
819-
id: hir::ForeignItemId,
820-
) {
821-
if matches!(tcx.def_kind(id.owner_id), DefKind::Static { .. } | DefKind::Fn)
822-
&& let Some(comes_from_allow) = has_allow_dead_code_or_lang_attr(tcx, id.owner_id.def_id)
823-
{
824-
worklist.push((id.owner_id.def_id, comes_from_allow));
825-
}
826-
}
827-
828796
fn create_and_seed_worklist(
829797
tcx: TyCtxt<'_>,
830798
) -> (Vec<(LocalDefId, ComesFromAllowExpect)>, Vec<LocalDefId>) {
@@ -846,16 +814,8 @@ fn create_and_seed_worklist(
846814
.collect::<Vec<_>>();
847815

848816
let crate_items = tcx.hir_crate_items(());
849-
for id in crate_items.free_items() {
850-
check_item(tcx, &mut worklist, &mut unsolved_impl_item, id);
851-
}
852-
853-
for id in crate_items.trait_items() {
854-
check_trait_item(tcx, &mut worklist, id);
855-
}
856-
857-
for id in crate_items.foreign_items() {
858-
check_foreign_item(tcx, &mut worklist, id);
817+
for id in crate_items.owners() {
818+
maybe_record_as_seed(tcx, id, &mut worklist, &mut unsolved_impl_item);
859819
}
860820

861821
(worklist, unsolved_impl_item)

0 commit comments

Comments
 (0)