Skip to content

Commit f9067f4

Browse files
committed
Cache the result of check_impl_or_impl_item_live
1 parent 36f0e5c commit f9067f4

1 file changed

Lines changed: 57 additions & 24 deletions

File tree

compiler/rustc_passes/src/dead.rs

Lines changed: 57 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use std::sync::atomic::Ordering;
99

1010
use hir::def_id::{LocalDefIdMap, LocalDefIdSet};
1111
use rustc_abi::FieldIdx;
12-
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
12+
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
1313
use rustc_errors::{ErrorGuaranteed, MultiSpan};
1414
use rustc_hir::def::{CtorOf, DefKind, Res};
1515
use rustc_hir::def_id::{DefId, LocalDefId, LocalModId};
@@ -113,6 +113,11 @@ struct WorkItem {
113113
own: ComesFromAllowExpect,
114114
}
115115

116+
enum ImplItemCheckResult {
117+
Live(ComesFromAllowExpect),
118+
Dead { require: LocalDefId },
119+
}
120+
116121
struct MarkSymbolVisitor<'tcx> {
117122
worklist: Vec<WorkItem>,
118123
tcx: TyCtxt<'tcx>,
@@ -554,7 +559,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
554559
&self,
555560
local_def_id: LocalDefId,
556561
defer_seeds_come_from_allow: bool,
557-
) -> Option<ComesFromAllowExpect> {
562+
) -> ImplItemCheckResult {
558563
let (impl_block_id, trait_def_id) = match self.tcx.def_kind(local_def_id) {
559564
// assoc impl items of traits are live if the corresponding trait items are live
560565
DefKind::AssocConst { .. } | DefKind::AssocTy | DefKind::AssocFn => {
@@ -573,14 +578,17 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
573578
if let Some(trait_def_id) = trait_def_id {
574579
if defer_seeds_come_from_allow {
575580
if !self.live_symbols.contains(&trait_def_id) {
576-
return None;
581+
return ImplItemCheckResult::Dead { require: trait_def_id };
577582
}
578583
} else {
584+
trait_comes_from_allow = has_allow_dead_code_or_lang_attr(self.tcx, trait_def_id);
585+
579586
if !self.live_symbols.contains(&trait_def_id) {
580-
return has_allow_dead_code_or_lang_attr(self.tcx, trait_def_id);
587+
return match trait_comes_from_allow {
588+
Some(comes_from_allow) => ImplItemCheckResult::Live(comes_from_allow),
589+
None => ImplItemCheckResult::Dead { require: trait_def_id },
590+
};
581591
}
582-
583-
trait_comes_from_allow = has_allow_dead_code_or_lang_attr(self.tcx, trait_def_id);
584592
}
585593
}
586594

@@ -591,36 +599,46 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
591599
&& !self.live_symbols.contains(&adt_def_id)
592600
{
593601
if defer_seeds_come_from_allow {
594-
return None;
602+
return ImplItemCheckResult::Dead { require: adt_def_id };
595603
} else {
596-
return trait_comes_from_allow
604+
let comes_from_allow = trait_comes_from_allow
597605
.or_else(|| has_allow_dead_code_or_lang_attr(self.tcx, adt_def_id));
606+
607+
return match comes_from_allow {
608+
Some(comes_from_allow) => ImplItemCheckResult::Live(comes_from_allow),
609+
None => ImplItemCheckResult::Dead { require: adt_def_id },
610+
};
598611
}
599612
}
600613

601-
Some(ComesFromAllowExpect::No)
614+
ImplItemCheckResult::Live(ComesFromAllowExpect::No)
602615
}
603616

604617
fn collect_live_items_from_unsolved_items(
605618
&mut self,
606619
defer_seeds_come_from_allow: bool,
620+
unsolved_items: Vec<LocalDefId>,
621+
unsolved_map: &mut FxHashMap<LocalDefId, Vec<LocalDefId>>,
607622
) -> Vec<(LocalDefId, ComesFromAllowExpect)> {
608-
let mut unsolved_items = std::mem::take(&mut self.unsolved_items);
609623
let mut items_to_check = vec![];
610-
unsolved_items.retain(|&def_id| {
611-
let Some(comes_from_allow) =
612-
self.check_impl_or_impl_item_live(def_id, defer_seeds_come_from_allow)
613-
else {
614-
return true;
615-
};
616624

617-
items_to_check.push((def_id, comes_from_allow));
618-
false
619-
});
620-
self.unsolved_items = unsolved_items;
625+
for def_id in unsolved_items {
626+
match self.check_impl_or_impl_item_live(def_id, defer_seeds_come_from_allow) {
627+
ImplItemCheckResult::Live(comes_from_allow) => {
628+
items_to_check.push((def_id, comes_from_allow));
629+
}
630+
ImplItemCheckResult::Dead { require } => {
631+
unsolved_map.entry(require).or_default().push(def_id);
632+
}
633+
}
634+
}
621635
items_to_check
622636
}
623637

638+
#[expect(
639+
rustc::potential_query_instability,
640+
reason = "The order of the unsolved items is not important, so we can just collect them into a vector."
641+
)]
624642
fn mark_live_symbols_and_ignored_derived_traits(
625643
&mut self,
626644
defer_seeds_come_from_allow: bool,
@@ -631,8 +649,13 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
631649

632650
// We have marked the primary seeds as live. We now need to process unsolved items from traits
633651
// and trait impls: add them to the work list if the trait or the implemented type is live.
634-
let mut items_to_check =
635-
self.collect_live_items_from_unsolved_items(defer_seeds_come_from_allow);
652+
let unsolved_items = std::mem::take(&mut self.unsolved_items);
653+
let mut unsolved_map = FxHashMap::default();
654+
let mut items_to_check = self.collect_live_items_from_unsolved_items(
655+
defer_seeds_come_from_allow,
656+
unsolved_items,
657+
&mut unsolved_map,
658+
);
636659

637660
while !items_to_check.is_empty() {
638661
self.worklist.extend(items_to_check.into_iter().map(|(id, comes_from_allow)| {
@@ -649,10 +672,20 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
649672
return Err(guar);
650673
}
651674

652-
items_to_check =
653-
self.collect_live_items_from_unsolved_items(defer_seeds_come_from_allow);
675+
let unsolved_items = unsolved_map
676+
.extract_if(|require, _| self.live_symbols.contains(require))
677+
.flat_map(|(_, items)| items)
678+
.collect();
679+
680+
items_to_check = self.collect_live_items_from_unsolved_items(
681+
defer_seeds_come_from_allow,
682+
unsolved_items,
683+
&mut unsolved_map,
684+
);
654685
}
655686

687+
self.unsolved_items = unsolved_map.into_values().flatten().collect();
688+
656689
Ok(())
657690
}
658691
}

0 commit comments

Comments
 (0)