//! another function. It suffices to just take a reference in order to introduce
//! an edge. Consider the following example:
//!
-//! ```rust
+//! ```
+//! # use core::fmt::Display;
//! fn print_val<T: Display>(x: T) {
//! println!("{}", x);
//! }
//!
-//! fn call_fn(f: &Fn(i32), x: i32) {
+//! fn call_fn(f: &dyn Fn(i32), x: i32) {
//! f(x);
//! }
//!
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::sync::{par_iter, MTLock, MTRef, ParallelIterator};
use rustc_hir as hir;
+use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
-use rustc_hir::itemlikevisit::ItemLikeVisitor;
use rustc_hir::lang_items::LangItem;
use rustc_index::bit_set::GrowableBitSet;
use rustc_middle::mir::interpret::{AllocId, ConstValue};
debug!("collect_roots: entry_fn = {:?}", entry_fn);
- let mut visitor = RootCollector { tcx, mode, entry_fn, output: &mut roots };
+ let mut collector = RootCollector { tcx, mode, entry_fn, output: &mut roots };
+
+ let crate_items = tcx.hir_crate_items(());
- tcx.hir().visit_all_item_likes(&mut visitor);
+ for id in crate_items.items() {
+ collector.process_item(id);
+ }
- visitor.push_extra_entry_roots();
+ for id in crate_items.impl_items() {
+ collector.process_impl_item(id);
+ }
+
+ collector.push_extra_entry_roots();
}
// We can only codegen items that are instantiable - items all of
entry_fn: Option<(DefId, EntryFnType)>,
}
-impl<'v> ItemLikeVisitor<'v> for RootCollector<'_, 'v> {
- fn visit_item(&mut self, item: &'v hir::Item<'v>) {
- match item.kind {
- hir::ItemKind::ExternCrate(..)
- | hir::ItemKind::Use(..)
- | hir::ItemKind::Macro(..)
- | hir::ItemKind::ForeignMod { .. }
- | hir::ItemKind::TyAlias(..)
- | hir::ItemKind::Trait(..)
- | hir::ItemKind::TraitAlias(..)
- | hir::ItemKind::OpaqueTy(..)
- | hir::ItemKind::Mod(..) => {
- // Nothing to do, just keep recursing.
- }
-
- hir::ItemKind::Impl { .. } => {
- if self.mode == MonoItemCollectionMode::Eager {
- create_mono_items_for_default_impls(self.tcx, item, self.output);
- }
- }
-
- hir::ItemKind::Enum(_, ref generics)
- | hir::ItemKind::Struct(_, ref generics)
- | hir::ItemKind::Union(_, ref generics) => {
- if generics.params.is_empty() {
- if self.mode == MonoItemCollectionMode::Eager {
- debug!(
- "RootCollector: ADT drop-glue for {}",
- self.tcx.def_path_str(item.def_id.to_def_id())
- );
-
- let ty = Instance::new(item.def_id.to_def_id(), InternalSubsts::empty())
- .ty(self.tcx, ty::ParamEnv::reveal_all());
- visit_drop_use(self.tcx, ty, true, DUMMY_SP, self.output);
+impl<'v> RootCollector<'_, 'v> {
+ fn process_item(&mut self, id: hir::ItemId) {
+ match self.tcx.hir().def_kind(id.def_id) {
+ DefKind::Enum | DefKind::Struct | DefKind::Union => {
+ let item = self.tcx.hir().item(id);
+ match item.kind {
+ hir::ItemKind::Enum(_, ref generics)
+ | hir::ItemKind::Struct(_, ref generics)
+ | hir::ItemKind::Union(_, ref generics) => {
+ if generics.params.is_empty() {
+ if self.mode == MonoItemCollectionMode::Eager {
+ debug!(
+ "RootCollector: ADT drop-glue for {}",
+ self.tcx.def_path_str(item.def_id.to_def_id())
+ );
+
+ let ty =
+ Instance::new(item.def_id.to_def_id(), InternalSubsts::empty())
+ .ty(self.tcx, ty::ParamEnv::reveal_all());
+ visit_drop_use(self.tcx, ty, true, DUMMY_SP, self.output);
+ }
+ }
}
+ _ => bug!(),
}
}
- hir::ItemKind::GlobalAsm(..) => {
+ DefKind::GlobalAsm => {
debug!(
"RootCollector: ItemKind::GlobalAsm({})",
- self.tcx.def_path_str(item.def_id.to_def_id())
+ self.tcx.def_path_str(id.def_id.to_def_id())
);
- self.output.push(dummy_spanned(MonoItem::GlobalAsm(item.item_id())));
+ self.output.push(dummy_spanned(MonoItem::GlobalAsm(id)));
}
- hir::ItemKind::Static(..) => {
+ DefKind::Static(..) => {
debug!(
"RootCollector: ItemKind::Static({})",
- self.tcx.def_path_str(item.def_id.to_def_id())
+ self.tcx.def_path_str(id.def_id.to_def_id())
);
- self.output.push(dummy_spanned(MonoItem::Static(item.def_id.to_def_id())));
+ self.output.push(dummy_spanned(MonoItem::Static(id.def_id.to_def_id())));
}
- hir::ItemKind::Const(..) => {
+ DefKind::Const => {
// const items only generate mono items if they are
// actually used somewhere. Just declaring them is insufficient.
// but even just declaring them must collect the items they refer to
- if let Ok(val) = self.tcx.const_eval_poly(item.def_id.to_def_id()) {
+ if let Ok(val) = self.tcx.const_eval_poly(id.def_id.to_def_id()) {
collect_const_value(self.tcx, val, &mut self.output);
}
}
- hir::ItemKind::Fn(..) => {
- self.push_if_root(item.def_id);
+ DefKind::Impl => {
+ if self.mode == MonoItemCollectionMode::Eager {
+ let item = self.tcx.hir().item(id);
+ create_mono_items_for_default_impls(self.tcx, item, self.output);
+ }
+ }
+ DefKind::Fn => {
+ self.push_if_root(id.def_id);
}
+ _ => {}
}
}
- fn visit_trait_item(&mut self, _: &'v hir::TraitItem<'v>) {
- // Even if there's a default body with no explicit generics,
- // it's still generic over some `Self: Trait`, so not a root.
- }
-
- fn visit_impl_item(&mut self, ii: &'v hir::ImplItem<'v>) {
- if let hir::ImplItemKind::Fn(hir::FnSig { .. }, _) = ii.kind {
- self.push_if_root(ii.def_id);
+ fn process_impl_item(&mut self, id: hir::ImplItemId) {
+ if matches!(self.tcx.hir().def_kind(id.def_id), DefKind::AssocFn) {
+ self.push_if_root(id.def_id);
}
}
- fn visit_foreign_item(&mut self, _foreign_item: &'v hir::ForeignItem<'v>) {}
-}
-
-impl<'v> RootCollector<'_, 'v> {
fn is_root(&self, def_id: LocalDefId) -> bool {
!item_requires_monomorphization(self.tcx, def_id)
&& match self.mode {