mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
avoid processing mentioned items that are also still used
This commit is contained in:
parent
91b35a1b40
commit
ee4b758161
@ -314,7 +314,7 @@ impl<'tcx> CoroutineInfo<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Some item that needs to monomorphize successfully for a MIR body to be considered well-formed.
|
/// Some item that needs to monomorphize successfully for a MIR body to be considered well-formed.
|
||||||
#[derive(Copy, Clone, PartialEq, Debug, HashStable, TyEncodable, TyDecodable)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, HashStable, TyEncodable, TyDecodable)]
|
||||||
#[derive(TypeFoldable, TypeVisitable)]
|
#[derive(TypeFoldable, TypeVisitable)]
|
||||||
pub enum MentionedItem<'tcx> {
|
pub enum MentionedItem<'tcx> {
|
||||||
Fn(DefId, GenericArgsRef<'tcx>),
|
Fn(DefId, GenericArgsRef<'tcx>),
|
||||||
|
@ -720,6 +720,9 @@ struct MirUsedCollector<'a, 'tcx> {
|
|||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
body: &'a mir::Body<'tcx>,
|
body: &'a mir::Body<'tcx>,
|
||||||
used_items: &'a mut MonoItems<'tcx>,
|
used_items: &'a mut MonoItems<'tcx>,
|
||||||
|
/// See the comment in `collect_items_of_instance` for the purpose of this set.
|
||||||
|
/// Note that this contains *not-monomorphized* items!
|
||||||
|
used_mentioned_items: &'a mut FxHashSet<MentionedItem<'tcx>>,
|
||||||
instance: Instance<'tcx>,
|
instance: Instance<'tcx>,
|
||||||
/// Spans for move size lints already emitted. Helps avoid duplicate lints.
|
/// Spans for move size lints already emitted. Helps avoid duplicate lints.
|
||||||
move_size_spans: Vec<Span>,
|
move_size_spans: Vec<Span>,
|
||||||
@ -990,12 +993,18 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
|
|||||||
match terminator.kind {
|
match terminator.kind {
|
||||||
mir::TerminatorKind::Call { ref func, ref args, ref fn_span, .. } => {
|
mir::TerminatorKind::Call { ref func, ref args, ref fn_span, .. } => {
|
||||||
let callee_ty = func.ty(self.body, tcx);
|
let callee_ty = func.ty(self.body, tcx);
|
||||||
|
// *Before* monomorphizing, record that we already handled this mention.
|
||||||
|
if let ty::FnDef(def_id, args) = callee_ty.kind() {
|
||||||
|
self.used_mentioned_items.insert(MentionedItem::Fn(*def_id, args));
|
||||||
|
}
|
||||||
let callee_ty = self.monomorphize(callee_ty);
|
let callee_ty = self.monomorphize(callee_ty);
|
||||||
self.check_fn_args_move_size(callee_ty, args, *fn_span, location);
|
self.check_fn_args_move_size(callee_ty, args, *fn_span, location);
|
||||||
visit_fn_use(self.tcx, callee_ty, true, source, &mut self.used_items)
|
visit_fn_use(self.tcx, callee_ty, true, source, &mut self.used_items)
|
||||||
}
|
}
|
||||||
mir::TerminatorKind::Drop { ref place, .. } => {
|
mir::TerminatorKind::Drop { ref place, .. } => {
|
||||||
let ty = place.ty(self.body, self.tcx).ty;
|
let ty = place.ty(self.body, self.tcx).ty;
|
||||||
|
// *Before* monomorphizing, record that we already handled this mention.
|
||||||
|
self.used_mentioned_items.insert(MentionedItem::Drop(ty));
|
||||||
let ty = self.monomorphize(ty);
|
let ty = self.monomorphize(ty);
|
||||||
visit_drop_use(self.tcx, ty, true, source, self.used_items);
|
visit_drop_use(self.tcx, ty, true, source, self.used_items);
|
||||||
}
|
}
|
||||||
@ -1639,10 +1648,22 @@ fn collect_items_of_instance<'tcx>(
|
|||||||
mode: CollectionMode,
|
mode: CollectionMode,
|
||||||
) {
|
) {
|
||||||
let body = tcx.instance_mir(instance.def);
|
let body = tcx.instance_mir(instance.def);
|
||||||
|
// Naively, in "used" collection mode, all functions get added to *both* `used_items` and
|
||||||
|
// `mentioned_items`. Mentioned items processing will then notice that they have already been
|
||||||
|
// visited, but at that point each mentioned item has been monomorphized, added to the
|
||||||
|
// `mentioned_items` worklist, and checked in the global set of visited items. To removes that
|
||||||
|
// overhead, we have a special optimization that avoids adding items to `mentioned_items` when
|
||||||
|
// they are already added in `used_items`. We could just scan `used_items`, but that's a linear
|
||||||
|
// scan and not very efficient. Furthermore we can only do that *after* monomorphizing the
|
||||||
|
// mentioned item. So instead we collect all pre-monomorphized `MentionedItem` that were already
|
||||||
|
// added to `used_items` in a hash set, which can efficiently query in the
|
||||||
|
// `body.mentioned_items` loop below.
|
||||||
|
let mut used_mentioned_items = FxHashSet::<MentionedItem<'tcx>>::default();
|
||||||
let mut collector = MirUsedCollector {
|
let mut collector = MirUsedCollector {
|
||||||
tcx,
|
tcx,
|
||||||
body,
|
body,
|
||||||
used_items,
|
used_items,
|
||||||
|
used_mentioned_items: &mut used_mentioned_items,
|
||||||
instance,
|
instance,
|
||||||
move_size_spans: vec![],
|
move_size_spans: vec![],
|
||||||
visiting_call_terminator: false,
|
visiting_call_terminator: false,
|
||||||
@ -1662,12 +1683,15 @@ fn collect_items_of_instance<'tcx>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always gather mentioned items.
|
// Always gather mentioned items. We try to avoid processing items that we have already added to
|
||||||
|
// `used_items` above.
|
||||||
for item in &body.mentioned_items {
|
for item in &body.mentioned_items {
|
||||||
|
if !collector.used_mentioned_items.contains(&item.node) {
|
||||||
let item_mono = collector.monomorphize(item.node);
|
let item_mono = collector.monomorphize(item.node);
|
||||||
visit_mentioned_item(tcx, &item_mono, item.span, mentioned_items);
|
visit_mentioned_item(tcx, &item_mono, item.span, mentioned_items);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// `item` must be already monomorphized
|
/// `item` must be already monomorphized
|
||||||
fn visit_mentioned_item<'tcx>(
|
fn visit_mentioned_item<'tcx>(
|
||||||
|
Loading…
Reference in New Issue
Block a user