Auto merge of #95655 - kckeiks:create-hir-crate-items-query, r=cjgillot
Refactor HIR item-like traversal (part 1) Issue #95004 - Create hir_crate_items query which traverses tcx.hir_crate(()).owners to return a hir::ModuleItems - use tcx.hir_crate_items in tcx.hir().items() to return an iterator of hir::ItemId - use tcx.hir_crate_items to introduce a tcx.hir().par_items(impl Fn(hir::ItemId)) to traverse all items in parallel; Signed-off-by: Miguel Guarniz <mi9uel9@gmail.com> cc `@cjgillot`
This commit is contained in:
commit
edba282770
18 changed files with 435 additions and 422 deletions
|
@ -7,6 +7,7 @@
|
||||||
use crate::hir;
|
use crate::hir;
|
||||||
use crate::{Item, ItemKind, TraitItem, TraitItemKind};
|
use crate::{Item, ItemKind, TraitItem, TraitItemKind};
|
||||||
|
|
||||||
|
use crate::def::DefKind;
|
||||||
use std::fmt::{self, Display};
|
use std::fmt::{self, Display};
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||||
|
@ -130,6 +131,30 @@ impl Target {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: For now, should only be used with def_kinds from ItemIds
|
||||||
|
pub fn from_def_kind(def_kind: DefKind) -> Target {
|
||||||
|
match def_kind {
|
||||||
|
DefKind::ExternCrate => Target::ExternCrate,
|
||||||
|
DefKind::Use => Target::Use,
|
||||||
|
DefKind::Static(..) => Target::Static,
|
||||||
|
DefKind::Const => Target::Const,
|
||||||
|
DefKind::Fn => Target::Fn,
|
||||||
|
DefKind::Macro(..) => Target::MacroDef,
|
||||||
|
DefKind::Mod => Target::Mod,
|
||||||
|
DefKind::ForeignMod => Target::ForeignMod,
|
||||||
|
DefKind::GlobalAsm => Target::GlobalAsm,
|
||||||
|
DefKind::TyAlias => Target::TyAlias,
|
||||||
|
DefKind::OpaqueTy => Target::OpaqueTy,
|
||||||
|
DefKind::Enum => Target::Enum,
|
||||||
|
DefKind::Struct => Target::Struct,
|
||||||
|
DefKind::Union => Target::Union,
|
||||||
|
DefKind::Trait => Target::Trait,
|
||||||
|
DefKind::TraitAlias => Target::TraitAlias,
|
||||||
|
DefKind::Impl => Target::Impl,
|
||||||
|
_ => panic!("impossible case reached"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn from_trait_item(trait_item: &TraitItem<'_>) -> Target {
|
pub fn from_trait_item(trait_item: &TraitItem<'_>) -> Target {
|
||||||
match trait_item.kind {
|
match trait_item.kind {
|
||||||
TraitItemKind::Const(..) => Target::AssocConst,
|
TraitItemKind::Const(..) => Target::AssocConst,
|
||||||
|
|
|
@ -24,7 +24,6 @@ use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def_id::LocalDefId;
|
use rustc_hir::def_id::LocalDefId;
|
||||||
use rustc_hir::intravisit;
|
use rustc_hir::intravisit;
|
||||||
use rustc_hir::itemlikevisit::ItemLikeVisitor;
|
|
||||||
use rustc_hir::Node as HirNode;
|
use rustc_hir::Node as HirNode;
|
||||||
use rustc_hir::{ImplItemKind, ItemKind as HirItem, TraitItemKind};
|
use rustc_hir::{ImplItemKind, ItemKind as HirItem, TraitItemKind};
|
||||||
use rustc_middle::dep_graph::{label_strs, DepNode, DepNodeExt};
|
use rustc_middle::dep_graph::{label_strs, DepNode, DepNodeExt};
|
||||||
|
@ -147,7 +146,24 @@ pub fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) {
|
||||||
|
|
||||||
tcx.dep_graph.with_ignore(|| {
|
tcx.dep_graph.with_ignore(|| {
|
||||||
let mut dirty_clean_visitor = DirtyCleanVisitor { tcx, checked_attrs: Default::default() };
|
let mut dirty_clean_visitor = DirtyCleanVisitor { tcx, checked_attrs: Default::default() };
|
||||||
tcx.hir().visit_all_item_likes(&mut dirty_clean_visitor);
|
|
||||||
|
let crate_items = tcx.hir_crate_items(());
|
||||||
|
|
||||||
|
for id in crate_items.items() {
|
||||||
|
dirty_clean_visitor.check_item(id.def_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
for id in crate_items.trait_items() {
|
||||||
|
dirty_clean_visitor.check_item(id.def_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
for id in crate_items.impl_items() {
|
||||||
|
dirty_clean_visitor.check_item(id.def_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
for id in crate_items.foreign_items() {
|
||||||
|
dirty_clean_visitor.check_item(id.def_id);
|
||||||
|
}
|
||||||
|
|
||||||
let mut all_attrs = FindAllAttrs { tcx, found_attrs: vec![] };
|
let mut all_attrs = FindAllAttrs { tcx, found_attrs: vec![] };
|
||||||
tcx.hir().walk_attributes(&mut all_attrs);
|
tcx.hir().walk_attributes(&mut all_attrs);
|
||||||
|
@ -365,7 +381,8 @@ impl<'tcx> DirtyCleanVisitor<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_item(&mut self, item_id: LocalDefId, item_span: Span) {
|
fn check_item(&mut self, item_id: LocalDefId) {
|
||||||
|
let item_span = self.tcx.def_span(item_id.to_def_id());
|
||||||
let def_path_hash = self.tcx.def_path_hash(item_id.to_def_id());
|
let def_path_hash = self.tcx.def_path_hash(item_id.to_def_id());
|
||||||
for attr in self.tcx.get_attrs(item_id.to_def_id()).iter() {
|
for attr in self.tcx.get_attrs(item_id.to_def_id()).iter() {
|
||||||
let Some(assertion) = self.assertion_maybe(item_id, attr) else {
|
let Some(assertion) = self.assertion_maybe(item_id, attr) else {
|
||||||
|
@ -388,24 +405,6 @@ impl<'tcx> DirtyCleanVisitor<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> ItemLikeVisitor<'tcx> for DirtyCleanVisitor<'tcx> {
|
|
||||||
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
|
|
||||||
self.check_item(item.def_id, item.span);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_trait_item(&mut self, item: &hir::TraitItem<'_>) {
|
|
||||||
self.check_item(item.def_id, item.span);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_impl_item(&mut self, item: &hir::ImplItem<'_>) {
|
|
||||||
self.check_item(item.def_id, item.span);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_foreign_item(&mut self, item: &hir::ForeignItem<'_>) {
|
|
||||||
self.check_item(item.def_id, item.span);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Given a `#[rustc_clean]` attribute, scan for a `cfg="foo"` attribute and check whether we have
|
/// Given a `#[rustc_clean]` attribute, scan for a `cfg="foo"` attribute and check whether we have
|
||||||
/// a cfg flag called `foo`.
|
/// a cfg flag called `foo`.
|
||||||
fn check_config(tcx: TyCtxt<'_>, attr: &Attribute) -> bool {
|
fn check_config(tcx: TyCtxt<'_>, attr: &Attribute) -> bool {
|
||||||
|
|
|
@ -1,35 +1,25 @@
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def_id::LocalDefId;
|
use rustc_hir::def_id::LocalDefId;
|
||||||
use rustc_hir::itemlikevisit::ItemLikeVisitor;
|
|
||||||
use rustc_middle::ty::query::Providers;
|
use rustc_middle::ty::query::Providers;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
|
|
||||||
fn proc_macro_decls_static(tcx: TyCtxt<'_>, (): ()) -> Option<LocalDefId> {
|
fn proc_macro_decls_static(tcx: TyCtxt<'_>, (): ()) -> Option<LocalDefId> {
|
||||||
let mut finder = Finder { tcx, decls: None };
|
let mut finder = Finder { tcx, decls: None };
|
||||||
tcx.hir().visit_all_item_likes(&mut finder);
|
|
||||||
|
|
||||||
finder.decls.map(|id| tcx.hir().local_def_id(id))
|
for id in tcx.hir().items() {
|
||||||
|
let attrs = finder.tcx.hir().attrs(id.hir_id());
|
||||||
|
if finder.tcx.sess.contains_name(attrs, sym::rustc_proc_macro_decls) {
|
||||||
|
finder.decls = Some(id.def_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
finder.decls
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Finder<'tcx> {
|
struct Finder<'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
decls: Option<hir::HirId>,
|
decls: Option<hir::def_id::LocalDefId>,
|
||||||
}
|
|
||||||
|
|
||||||
impl<'v> ItemLikeVisitor<'v> for Finder<'_> {
|
|
||||||
fn visit_item(&mut self, item: &hir::Item<'_>) {
|
|
||||||
let attrs = self.tcx.hir().attrs(item.hir_id());
|
|
||||||
if self.tcx.sess.contains_name(attrs, sym::rustc_proc_macro_decls) {
|
|
||||||
self.decls = Some(item.hir_id());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
|
|
||||||
|
|
||||||
fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
|
|
||||||
|
|
||||||
fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn provide(providers: &mut Providers) {
|
pub(crate) fn provide(providers: &mut Providers) {
|
||||||
|
|
|
@ -1,29 +1,19 @@
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::itemlikevisit::ItemLikeVisitor;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_session::cstore::ForeignModule;
|
use rustc_session::cstore::ForeignModule;
|
||||||
|
|
||||||
crate fn collect(tcx: TyCtxt<'_>) -> Vec<ForeignModule> {
|
crate fn collect(tcx: TyCtxt<'_>) -> Vec<ForeignModule> {
|
||||||
let mut collector = Collector { modules: Vec::new() };
|
let mut modules = Vec::new();
|
||||||
tcx.hir().visit_all_item_likes(&mut collector);
|
for id in tcx.hir().items() {
|
||||||
collector.modules
|
if !matches!(tcx.hir().def_kind(id.def_id), DefKind::ForeignMod) {
|
||||||
}
|
continue;
|
||||||
|
}
|
||||||
struct Collector {
|
let item = tcx.hir().item(id);
|
||||||
modules: Vec<ForeignModule>,
|
if let hir::ItemKind::ForeignMod { items, .. } = item.kind {
|
||||||
}
|
let foreign_items = items.iter().map(|it| it.id.def_id.to_def_id()).collect();
|
||||||
|
modules.push(ForeignModule { foreign_items, def_id: id.def_id.to_def_id() });
|
||||||
impl<'tcx> ItemLikeVisitor<'tcx> for Collector {
|
}
|
||||||
fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) {
|
|
||||||
let hir::ItemKind::ForeignMod { items, .. } = it.kind else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
let foreign_items = items.iter().map(|it| it.id.def_id.to_def_id()).collect();
|
|
||||||
self.modules.push(ForeignModule { foreign_items, def_id: it.def_id.to_def_id() });
|
|
||||||
}
|
}
|
||||||
|
modules
|
||||||
fn visit_trait_item(&mut self, _it: &'tcx hir::TraitItem<'tcx>) {}
|
|
||||||
fn visit_impl_item(&mut self, _it: &'tcx hir::ImplItem<'tcx>) {}
|
|
||||||
fn visit_foreign_item(&mut self, _it: &'tcx hir::ForeignItem<'tcx>) {}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ use rustc_attr as attr;
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_errors::struct_span_err;
|
use rustc_errors::struct_span_err;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::itemlikevisit::ItemLikeVisitor;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_middle::ty::{List, ParamEnv, ParamEnvAnd, Ty, TyCtxt};
|
use rustc_middle::ty::{List, ParamEnv, ParamEnvAnd, Ty, TyCtxt};
|
||||||
use rustc_session::cstore::{DllCallingConvention, DllImport, NativeLib};
|
use rustc_session::cstore::{DllCallingConvention, DllImport, NativeLib};
|
||||||
use rustc_session::parse::feature_err;
|
use rustc_session::parse::feature_err;
|
||||||
|
@ -15,7 +15,9 @@ use rustc_target::spec::abi::Abi;
|
||||||
|
|
||||||
crate fn collect(tcx: TyCtxt<'_>) -> Vec<NativeLib> {
|
crate fn collect(tcx: TyCtxt<'_>) -> Vec<NativeLib> {
|
||||||
let mut collector = Collector { tcx, libs: Vec::new() };
|
let mut collector = Collector { tcx, libs: Vec::new() };
|
||||||
tcx.hir().visit_all_item_likes(&mut collector);
|
for id in tcx.hir().items() {
|
||||||
|
collector.process_item(id);
|
||||||
|
}
|
||||||
collector.process_command_line();
|
collector.process_command_line();
|
||||||
collector.libs
|
collector.libs
|
||||||
}
|
}
|
||||||
|
@ -32,8 +34,13 @@ struct Collector<'tcx> {
|
||||||
libs: Vec<NativeLib>,
|
libs: Vec<NativeLib>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> ItemLikeVisitor<'tcx> for Collector<'tcx> {
|
impl<'tcx> Collector<'tcx> {
|
||||||
fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) {
|
fn process_item(&mut self, id: rustc_hir::ItemId) {
|
||||||
|
if !matches!(self.tcx.hir().def_kind(id.def_id), DefKind::ForeignMod) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let it = self.tcx.hir().item(id);
|
||||||
let hir::ItemKind::ForeignMod { abi, items: foreign_mod_items } = it.kind else {
|
let hir::ItemKind::ForeignMod { abi, items: foreign_mod_items } = it.kind else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
@ -252,12 +259,6 @@ impl<'tcx> ItemLikeVisitor<'tcx> for Collector<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_trait_item(&mut self, _it: &'tcx hir::TraitItem<'tcx>) {}
|
|
||||||
fn visit_impl_item(&mut self, _it: &'tcx hir::ImplItem<'tcx>) {}
|
|
||||||
fn visit_foreign_item(&mut self, _it: &'tcx hir::ForeignItem<'tcx>) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Collector<'_> {
|
|
||||||
fn register_native_lib(&mut self, span: Option<Span>, lib: NativeLib) {
|
fn register_native_lib(&mut self, span: Option<Span>, lib: NativeLib) {
|
||||||
if lib.name.as_ref().map_or(false, |&s| s == kw::Empty) {
|
if lib.name.as_ref().map_or(false, |&s| s == kw::Empty) {
|
||||||
match span {
|
match span {
|
||||||
|
|
|
@ -1787,10 +1787,27 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||||
debug!("EncodeContext::encode_traits_and_impls()");
|
debug!("EncodeContext::encode_traits_and_impls()");
|
||||||
empty_proc_macro!(self);
|
empty_proc_macro!(self);
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
let mut visitor = ImplsVisitor { tcx, impls: FxHashMap::default() };
|
let mut fx_hash_map: FxHashMap<DefId, Vec<(DefIndex, Option<SimplifiedType>)>> =
|
||||||
tcx.hir().visit_all_item_likes(&mut visitor);
|
FxHashMap::default();
|
||||||
|
|
||||||
let mut all_impls: Vec<_> = visitor.impls.into_iter().collect();
|
for id in tcx.hir().items() {
|
||||||
|
if matches!(tcx.hir().def_kind(id.def_id), DefKind::Impl) {
|
||||||
|
if let Some(trait_ref) = tcx.impl_trait_ref(id.def_id.to_def_id()) {
|
||||||
|
let simplified_self_ty = fast_reject::simplify_type(
|
||||||
|
self.tcx,
|
||||||
|
trait_ref.self_ty(),
|
||||||
|
TreatParams::AsPlaceholders,
|
||||||
|
);
|
||||||
|
|
||||||
|
fx_hash_map
|
||||||
|
.entry(trait_ref.def_id)
|
||||||
|
.or_default()
|
||||||
|
.push((id.def_id.local_def_index, simplified_self_ty));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut all_impls: Vec<_> = fx_hash_map.into_iter().collect();
|
||||||
|
|
||||||
// Bring everything into deterministic order for hashing
|
// Bring everything into deterministic order for hashing
|
||||||
all_impls.sort_by_cached_key(|&(trait_def_id, _)| tcx.def_path_hash(trait_def_id));
|
all_impls.sort_by_cached_key(|&(trait_def_id, _)| tcx.def_path_hash(trait_def_id));
|
||||||
|
@ -2053,41 +2070,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ImplsVisitor<'tcx> {
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
impls: FxHashMap<DefId, Vec<(DefIndex, Option<SimplifiedType>)>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplsVisitor<'tcx> {
|
|
||||||
fn visit_item(&mut self, item: &hir::Item<'_>) {
|
|
||||||
match item.kind {
|
|
||||||
hir::ItemKind::Impl(..) => {
|
|
||||||
if let Some(trait_ref) = self.tcx.impl_trait_ref(item.def_id.to_def_id()) {
|
|
||||||
let simplified_self_ty = fast_reject::simplify_type(
|
|
||||||
self.tcx,
|
|
||||||
trait_ref.self_ty(),
|
|
||||||
TreatParams::AsPlaceholders,
|
|
||||||
);
|
|
||||||
|
|
||||||
self.impls
|
|
||||||
.entry(trait_ref.def_id)
|
|
||||||
.or_default()
|
|
||||||
.push((item.def_id.local_def_index, simplified_self_ty));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_trait_item(&mut self, _trait_item: &'v hir::TraitItem<'v>) {}
|
|
||||||
|
|
||||||
fn visit_impl_item(&mut self, _impl_item: &'v hir::ImplItem<'v>) {
|
|
||||||
// handled in `visit_item` above
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_foreign_item(&mut self, _foreign_item: &'v hir::ForeignItem<'v>) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Used to prefetch queries which will be needed later by metadata encoding.
|
/// Used to prefetch queries which will be needed later by metadata encoding.
|
||||||
/// Only a subset of the queries are actually prefetched to keep this code smaller.
|
/// Only a subset of the queries are actually prefetched to keep this code smaller.
|
||||||
fn prefetch_mir(tcx: TyCtxt<'_>) {
|
fn prefetch_mir(tcx: TyCtxt<'_>) {
|
||||||
|
|
|
@ -18,7 +18,6 @@ use rustc_span::source_map::Spanned;
|
||||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
use std::collections::VecDeque;
|
|
||||||
|
|
||||||
fn fn_decl<'hir>(node: Node<'hir>) -> Option<&'hir FnDecl<'hir>> {
|
fn fn_decl<'hir>(node: Node<'hir>) -> Option<&'hir FnDecl<'hir>> {
|
||||||
match node {
|
match node {
|
||||||
|
@ -159,12 +158,12 @@ impl<'hir> Map<'hir> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn items(self) -> impl Iterator<Item = &'hir Item<'hir>> + 'hir {
|
pub fn items(self) -> impl Iterator<Item = ItemId> + 'hir {
|
||||||
let krate = self.krate();
|
self.tcx.hir_crate_items(()).items.iter().copied()
|
||||||
krate.owners.iter().filter_map(|owner| match owner.as_owner()?.node() {
|
}
|
||||||
OwnerNode::Item(item) => Some(item),
|
|
||||||
_ => None,
|
pub fn par_for_each_item(self, f: impl Fn(ItemId) + Sync + Send) {
|
||||||
})
|
par_for_each_in(&self.tcx.hir_crate_items(()).items[..], |id| f(*id));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn def_key(self, def_id: LocalDefId) -> DefKey {
|
pub fn def_key(self, def_id: LocalDefId) -> DefKey {
|
||||||
|
@ -675,13 +674,9 @@ impl<'hir> Map<'hir> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn for_each_module(self, f: impl Fn(LocalDefId)) {
|
pub fn for_each_module(self, f: impl Fn(LocalDefId)) {
|
||||||
let mut queue = VecDeque::new();
|
let crate_items = self.tcx.hir_crate_items(());
|
||||||
queue.push_back(CRATE_DEF_ID);
|
for module in crate_items.submodules.iter() {
|
||||||
|
f(*module)
|
||||||
while let Some(id) = queue.pop_front() {
|
|
||||||
f(id);
|
|
||||||
let items = self.tcx.hir_module_items(id);
|
|
||||||
queue.extend(items.submodules.iter().copied())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1308,3 +1303,69 @@ pub(super) fn hir_module_items(tcx: TyCtxt<'_>, module_id: LocalDefId) -> Module
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn hir_crate_items(tcx: TyCtxt<'_>, _: ()) -> ModuleItems {
|
||||||
|
let mut collector = CrateCollector {
|
||||||
|
tcx,
|
||||||
|
submodules: Vec::default(),
|
||||||
|
items: Vec::default(),
|
||||||
|
trait_items: Vec::default(),
|
||||||
|
impl_items: Vec::default(),
|
||||||
|
foreign_items: Vec::default(),
|
||||||
|
};
|
||||||
|
|
||||||
|
tcx.hir().walk_toplevel_module(&mut collector);
|
||||||
|
|
||||||
|
let CrateCollector { submodules, items, trait_items, impl_items, foreign_items, .. } =
|
||||||
|
collector;
|
||||||
|
|
||||||
|
return ModuleItems {
|
||||||
|
submodules: submodules.into_boxed_slice(),
|
||||||
|
items: items.into_boxed_slice(),
|
||||||
|
trait_items: trait_items.into_boxed_slice(),
|
||||||
|
impl_items: impl_items.into_boxed_slice(),
|
||||||
|
foreign_items: foreign_items.into_boxed_slice(),
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CrateCollector<'tcx> {
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
submodules: Vec<LocalDefId>,
|
||||||
|
items: Vec<ItemId>,
|
||||||
|
trait_items: Vec<TraitItemId>,
|
||||||
|
impl_items: Vec<ImplItemId>,
|
||||||
|
foreign_items: Vec<ForeignItemId>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'hir> Visitor<'hir> for CrateCollector<'hir> {
|
||||||
|
type NestedFilter = nested_filter::All;
|
||||||
|
|
||||||
|
fn nested_visit_map(&mut self) -> Self::Map {
|
||||||
|
self.tcx.hir()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_item(&mut self, item: &'hir Item<'hir>) {
|
||||||
|
self.items.push(item.item_id());
|
||||||
|
intravisit::walk_item(self, item)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_mod(&mut self, m: &'hir Mod<'hir>, _s: Span, n: HirId) {
|
||||||
|
self.submodules.push(n.owner);
|
||||||
|
intravisit::walk_mod(self, m, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_foreign_item(&mut self, item: &'hir ForeignItem<'hir>) {
|
||||||
|
self.foreign_items.push(item.foreign_item_id());
|
||||||
|
intravisit::walk_foreign_item(self, item)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_trait_item(&mut self, item: &'hir TraitItem<'hir>) {
|
||||||
|
self.trait_items.push(item.trait_item_id());
|
||||||
|
intravisit::walk_trait_item(self, item)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_impl_item(&mut self, item: &'hir ImplItem<'hir>) {
|
||||||
|
self.impl_items.push(item.impl_item_id());
|
||||||
|
intravisit::walk_impl_item(self, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -45,6 +45,24 @@ pub struct ModuleItems {
|
||||||
foreign_items: Box<[ForeignItemId]>,
|
foreign_items: Box<[ForeignItemId]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ModuleItems {
|
||||||
|
pub fn items(&self) -> impl Iterator<Item = ItemId> + '_ {
|
||||||
|
self.items.iter().copied()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn trait_items(&self) -> impl Iterator<Item = TraitItemId> + '_ {
|
||||||
|
self.trait_items.iter().copied()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn impl_items(&self) -> impl Iterator<Item = ImplItemId> + '_ {
|
||||||
|
self.impl_items.iter().copied()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn foreign_items(&self) -> impl Iterator<Item = ForeignItemId> + '_ {
|
||||||
|
self.foreign_items.iter().copied()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> TyCtxt<'tcx> {
|
impl<'tcx> TyCtxt<'tcx> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn hir(self) -> map::Map<'tcx> {
|
pub fn hir(self) -> map::Map<'tcx> {
|
||||||
|
@ -68,6 +86,7 @@ pub fn provide(providers: &mut Providers) {
|
||||||
hir.get_module_parent_node(hir.local_def_id_to_hir_id(id))
|
hir.get_module_parent_node(hir.local_def_id_to_hir_id(id))
|
||||||
};
|
};
|
||||||
providers.hir_crate = |tcx, ()| tcx.untracked_crate;
|
providers.hir_crate = |tcx, ()| tcx.untracked_crate;
|
||||||
|
providers.hir_crate_items = map::hir_crate_items;
|
||||||
providers.crate_hash = map::crate_hash;
|
providers.crate_hash = map::crate_hash;
|
||||||
providers.hir_module_items = map::hir_module_items;
|
providers.hir_module_items = map::hir_module_items;
|
||||||
providers.hir_owner = |tcx, id| {
|
providers.hir_owner = |tcx, id| {
|
||||||
|
|
|
@ -45,6 +45,13 @@ rustc_queries! {
|
||||||
desc { "get the crate HIR" }
|
desc { "get the crate HIR" }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// All items in the crate.
|
||||||
|
query hir_crate_items(_: ()) -> rustc_middle::hir::ModuleItems {
|
||||||
|
storage(ArenaCacheSelector<'tcx>)
|
||||||
|
eval_always
|
||||||
|
desc { "get HIR crate items" }
|
||||||
|
}
|
||||||
|
|
||||||
/// The items in a module.
|
/// The items in a module.
|
||||||
///
|
///
|
||||||
/// This can be conveniently accessed by `tcx.hir().visit_item_likes_in_module`.
|
/// This can be conveniently accessed by `tcx.hir().visit_item_likes_in_module`.
|
||||||
|
|
|
@ -8,7 +8,6 @@ use rustc_hir as hir;
|
||||||
use rustc_hir::def::{self, CtorKind, DefKind, Namespace};
|
use rustc_hir::def::{self, CtorKind, DefKind, Namespace};
|
||||||
use rustc_hir::def_id::{DefId, DefIdSet, CRATE_DEF_INDEX, LOCAL_CRATE};
|
use rustc_hir::def_id::{DefId, DefIdSet, CRATE_DEF_INDEX, LOCAL_CRATE};
|
||||||
use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData};
|
use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData};
|
||||||
use rustc_hir::ItemKind;
|
|
||||||
use rustc_session::config::TrimmedDefPaths;
|
use rustc_session::config::TrimmedDefPaths;
|
||||||
use rustc_session::cstore::{ExternCrate, ExternCrateSource};
|
use rustc_session::cstore::{ExternCrate, ExternCrateSource};
|
||||||
use rustc_span::symbol::{kw, Ident, Symbol};
|
use rustc_span::symbol::{kw, Ident, Symbol};
|
||||||
|
@ -2678,8 +2677,13 @@ define_print_and_forward_display! {
|
||||||
fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, Namespace, DefId)) {
|
fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, Namespace, DefId)) {
|
||||||
// Iterate all local crate items no matter where they are defined.
|
// Iterate all local crate items no matter where they are defined.
|
||||||
let hir = tcx.hir();
|
let hir = tcx.hir();
|
||||||
for item in hir.items() {
|
for id in hir.items() {
|
||||||
if item.ident.name.as_str().is_empty() || matches!(item.kind, ItemKind::Use(_, _)) {
|
if matches!(hir.def_kind(id.def_id), DefKind::Use) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let item = hir.item(id);
|
||||||
|
if item.ident.name == kw::Empty {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -181,8 +181,8 @@
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_data_structures::sync::{par_iter, MTLock, MTRef, ParallelIterator};
|
use rustc_data_structures::sync::{par_iter, MTLock, MTRef, ParallelIterator};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
|
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
|
||||||
use rustc_hir::itemlikevisit::ItemLikeVisitor;
|
|
||||||
use rustc_hir::lang_items::LangItem;
|
use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_index::bit_set::GrowableBitSet;
|
use rustc_index::bit_set::GrowableBitSet;
|
||||||
use rustc_middle::mir::interpret::{AllocId, ConstValue};
|
use rustc_middle::mir::interpret::{AllocId, ConstValue};
|
||||||
|
@ -327,11 +327,19 @@ fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionMode) -> Vec<MonoItem<
|
||||||
|
|
||||||
debug!("collect_roots: entry_fn = {:?}", entry_fn);
|
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 };
|
||||||
|
|
||||||
tcx.hir().visit_all_item_likes(&mut visitor);
|
let crate_items = tcx.hir_crate_items(());
|
||||||
|
|
||||||
visitor.push_extra_entry_roots();
|
for id in crate_items.items() {
|
||||||
|
collector.process_item(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
// We can only codegen items that are instantiable - items all of
|
||||||
|
@ -1159,87 +1167,74 @@ struct RootCollector<'a, 'tcx> {
|
||||||
entry_fn: Option<(DefId, EntryFnType)>,
|
entry_fn: Option<(DefId, EntryFnType)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'v> ItemLikeVisitor<'v> for RootCollector<'_, 'v> {
|
impl<'v> RootCollector<'_, 'v> {
|
||||||
fn visit_item(&mut self, item: &'v hir::Item<'v>) {
|
fn process_item(&mut self, id: hir::ItemId) {
|
||||||
match item.kind {
|
match self.tcx.hir().def_kind(id.def_id) {
|
||||||
hir::ItemKind::ExternCrate(..)
|
DefKind::Enum | DefKind::Struct | DefKind::Union => {
|
||||||
| hir::ItemKind::Use(..)
|
let item = self.tcx.hir().item(id);
|
||||||
| hir::ItemKind::Macro(..)
|
match item.kind {
|
||||||
| hir::ItemKind::ForeignMod { .. }
|
hir::ItemKind::Enum(_, ref generics)
|
||||||
| hir::ItemKind::TyAlias(..)
|
| hir::ItemKind::Struct(_, ref generics)
|
||||||
| hir::ItemKind::Trait(..)
|
| hir::ItemKind::Union(_, ref generics) => {
|
||||||
| hir::ItemKind::TraitAlias(..)
|
if generics.params.is_empty() {
|
||||||
| hir::ItemKind::OpaqueTy(..)
|
if self.mode == MonoItemCollectionMode::Eager {
|
||||||
| hir::ItemKind::Mod(..) => {
|
debug!(
|
||||||
// Nothing to do, just keep recursing.
|
"RootCollector: ADT drop-glue for {}",
|
||||||
}
|
self.tcx.def_path_str(item.def_id.to_def_id())
|
||||||
|
);
|
||||||
|
|
||||||
hir::ItemKind::Impl { .. } => {
|
let ty =
|
||||||
if self.mode == MonoItemCollectionMode::Eager {
|
Instance::new(item.def_id.to_def_id(), InternalSubsts::empty())
|
||||||
create_mono_items_for_default_impls(self.tcx, item, self.output);
|
.ty(self.tcx, ty::ParamEnv::reveal_all());
|
||||||
}
|
visit_drop_use(self.tcx, ty, true, DUMMY_SP, 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);
|
|
||||||
}
|
}
|
||||||
|
_ => bug!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::ItemKind::GlobalAsm(..) => {
|
DefKind::GlobalAsm => {
|
||||||
debug!(
|
debug!(
|
||||||
"RootCollector: ItemKind::GlobalAsm({})",
|
"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!(
|
debug!(
|
||||||
"RootCollector: ItemKind::Static({})",
|
"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
|
// const items only generate mono items if they are
|
||||||
// actually used somewhere. Just declaring them is insufficient.
|
// actually used somewhere. Just declaring them is insufficient.
|
||||||
|
|
||||||
// but even just declaring them must collect the items they refer to
|
// 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);
|
collect_const_value(self.tcx, val, &mut self.output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::ItemKind::Fn(..) => {
|
DefKind::Impl => {
|
||||||
self.push_if_root(item.def_id);
|
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>) {
|
fn process_impl_item(&mut self, id: hir::ImplItemId) {
|
||||||
// Even if there's a default body with no explicit generics,
|
if matches!(self.tcx.hir().def_kind(id.def_id), DefKind::AssocFn) {
|
||||||
// it's still generic over some `Self: Trait`, so not a root.
|
self.push_if_root(id.def_id);
|
||||||
}
|
|
||||||
|
|
||||||
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 visit_foreign_item(&mut self, _foreign_item: &'v hir::ForeignItem<'v>) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'v> RootCollector<'_, 'v> {
|
|
||||||
fn is_root(&self, def_id: LocalDefId) -> bool {
|
fn is_root(&self, def_id: LocalDefId) -> bool {
|
||||||
!item_requires_monomorphization(self.tcx, def_id)
|
!item_requires_monomorphization(self.tcx, def_id)
|
||||||
&& match self.mode {
|
&& match self.mode {
|
||||||
|
|
|
@ -12,8 +12,8 @@ use crate::weak_lang_items;
|
||||||
|
|
||||||
use rustc_errors::{pluralize, struct_span_err};
|
use rustc_errors::{pluralize, struct_span_err};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_hir::itemlikevisit::ItemLikeVisitor;
|
|
||||||
use rustc_hir::lang_items::{extract, GenericRequirement, ITEM_REFS};
|
use rustc_hir::lang_items::{extract, GenericRequirement, ITEM_REFS};
|
||||||
use rustc_hir::{HirId, LangItem, LanguageItems, Target};
|
use rustc_hir::{HirId, LangItem, LanguageItems, Target};
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
|
@ -27,28 +27,6 @@ struct LanguageItemCollector<'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'v, 'tcx> ItemLikeVisitor<'v> for LanguageItemCollector<'tcx> {
|
|
||||||
fn visit_item(&mut self, item: &hir::Item<'_>) {
|
|
||||||
self.check_for_lang(Target::from_item(item), item.hir_id());
|
|
||||||
|
|
||||||
if let hir::ItemKind::Enum(def, ..) = &item.kind {
|
|
||||||
for variant in def.variants {
|
|
||||||
self.check_for_lang(Target::Variant, variant.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_trait_item(&mut self, trait_item: &hir::TraitItem<'_>) {
|
|
||||||
self.check_for_lang(Target::from_trait_item(trait_item), trait_item.hir_id())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) {
|
|
||||||
self.check_for_lang(target_from_impl_item(self.tcx, impl_item), impl_item.hir_id())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_foreign_item(&mut self, _: &hir::ForeignItem<'_>) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> LanguageItemCollector<'tcx> {
|
impl<'tcx> LanguageItemCollector<'tcx> {
|
||||||
fn new(tcx: TyCtxt<'tcx>) -> LanguageItemCollector<'tcx> {
|
fn new(tcx: TyCtxt<'tcx>) -> LanguageItemCollector<'tcx> {
|
||||||
LanguageItemCollector { tcx, items: LanguageItems::new() }
|
LanguageItemCollector { tcx, items: LanguageItems::new() }
|
||||||
|
@ -259,7 +237,32 @@ fn get_lang_items(tcx: TyCtxt<'_>, (): ()) -> LanguageItems {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect lang items in this crate.
|
// Collect lang items in this crate.
|
||||||
tcx.hir().visit_all_item_likes(&mut collector);
|
let crate_items = tcx.hir_crate_items(());
|
||||||
|
|
||||||
|
for id in crate_items.items() {
|
||||||
|
collector.check_for_lang(Target::from_def_kind(tcx.hir().def_kind(id.def_id)), id.hir_id());
|
||||||
|
|
||||||
|
if matches!(tcx.hir().def_kind(id.def_id), DefKind::Enum) {
|
||||||
|
let item = tcx.hir().item(id);
|
||||||
|
if let hir::ItemKind::Enum(def, ..) = &item.kind {
|
||||||
|
for variant in def.variants {
|
||||||
|
collector.check_for_lang(Target::Variant, variant.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: avoid calling trait_item() when possible
|
||||||
|
for id in crate_items.trait_items() {
|
||||||
|
let item = tcx.hir().trait_item(id);
|
||||||
|
collector.check_for_lang(Target::from_trait_item(item), item.hir_id())
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: avoid calling impl_item() when possible
|
||||||
|
for id in crate_items.impl_items() {
|
||||||
|
let item = tcx.hir().impl_item(id);
|
||||||
|
collector.check_for_lang(target_from_impl_item(tcx, item), item.hir_id())
|
||||||
|
}
|
||||||
|
|
||||||
// Extract out the found lang items.
|
// Extract out the found lang items.
|
||||||
let LanguageItemCollector { mut items, .. } = collector;
|
let LanguageItemCollector { mut items, .. } = collector;
|
||||||
|
|
|
@ -2,20 +2,11 @@
|
||||||
|
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_errors::struct_span_err;
|
use rustc_errors::struct_span_err;
|
||||||
use rustc_hir as hir;
|
|
||||||
use rustc_hir::intravisit::{self, Visitor};
|
|
||||||
use rustc_hir::lang_items::{self, LangItem};
|
use rustc_hir::lang_items::{self, LangItem};
|
||||||
use rustc_hir::weak_lang_items::WEAK_ITEMS_REFS;
|
use rustc_hir::weak_lang_items::WEAK_ITEMS_REFS;
|
||||||
use rustc_middle::middle::lang_items::required;
|
use rustc_middle::middle::lang_items::required;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_session::config::CrateType;
|
use rustc_session::config::CrateType;
|
||||||
use rustc_span::symbol::Symbol;
|
|
||||||
use rustc_span::Span;
|
|
||||||
|
|
||||||
struct Context<'a, 'tcx> {
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
items: &'a mut lang_items::LanguageItems,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Checks the crate for usage of weak lang items, returning a vector of all the
|
/// Checks the crate for usage of weak lang items, returning a vector of all the
|
||||||
/// language items required by this crate, but not defined yet.
|
/// language items required by this crate, but not defined yet.
|
||||||
|
@ -30,10 +21,28 @@ pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>, items: &mut lang_items::LanguageItem
|
||||||
items.missing.push(LangItem::EhCatchTypeinfo);
|
items.missing.push(LangItem::EhCatchTypeinfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
let crate_items = tcx.hir_crate_items(());
|
||||||
let mut cx = Context { tcx, items };
|
for id in crate_items.foreign_items() {
|
||||||
tcx.hir().visit_all_item_likes(&mut cx.as_deep_visitor());
|
let attrs = tcx.hir().attrs(id.hir_id());
|
||||||
|
if let Some((lang_item, _)) = lang_items::extract(attrs) {
|
||||||
|
if let Some(&item) = WEAK_ITEMS_REFS.get(&lang_item) {
|
||||||
|
if items.require(item).is_err() {
|
||||||
|
items.missing.push(item);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let span = tcx.def_span(id.def_id);
|
||||||
|
struct_span_err!(
|
||||||
|
tcx.sess,
|
||||||
|
span,
|
||||||
|
E0264,
|
||||||
|
"unknown external lang item: `{}`",
|
||||||
|
lang_item
|
||||||
|
)
|
||||||
|
.emit();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
verify(tcx, items);
|
verify(tcx, items);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,26 +89,3 @@ fn verify<'tcx>(tcx: TyCtxt<'tcx>, items: &lang_items::LanguageItems) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> Context<'a, 'tcx> {
|
|
||||||
fn register(&mut self, name: Symbol, span: Span) {
|
|
||||||
if let Some(&item) = WEAK_ITEMS_REFS.get(&name) {
|
|
||||||
if self.items.require(item).is_err() {
|
|
||||||
self.items.missing.push(item);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
struct_span_err!(self.tcx.sess, span, E0264, "unknown external lang item: `{}`", name)
|
|
||||||
.emit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> {
|
|
||||||
fn visit_foreign_item(&mut self, i: &hir::ForeignItem<'_>) {
|
|
||||||
let attrs = self.tcx.hir().attrs(i.hir_id());
|
|
||||||
if let Some((lang_item, _)) = lang_items::extract(attrs) {
|
|
||||||
self.register(lang_item, i.span);
|
|
||||||
}
|
|
||||||
intravisit::walk_foreign_item(self, i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
//! def-path. This is used for unit testing the code that generates
|
//! def-path. This is used for unit testing the code that generates
|
||||||
//! paths etc in all kinds of annoying scenarios.
|
//! paths etc in all kinds of annoying scenarios.
|
||||||
|
|
||||||
use rustc_hir as hir;
|
|
||||||
use rustc_hir::def_id::LocalDefId;
|
use rustc_hir::def_id::LocalDefId;
|
||||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||||
use rustc_middle::ty::{subst::InternalSubsts, Instance, TyCtxt};
|
use rustc_middle::ty::{subst::InternalSubsts, Instance, TyCtxt};
|
||||||
|
@ -22,8 +21,24 @@ pub fn report_symbol_names(tcx: TyCtxt<'_>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
tcx.dep_graph.with_ignore(|| {
|
tcx.dep_graph.with_ignore(|| {
|
||||||
let mut visitor = SymbolNamesTest { tcx };
|
let mut symbol_names = SymbolNamesTest { tcx };
|
||||||
tcx.hir().visit_all_item_likes(&mut visitor);
|
let crate_items = tcx.hir_crate_items(());
|
||||||
|
|
||||||
|
for id in crate_items.items() {
|
||||||
|
symbol_names.process_attrs(id.def_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
for id in crate_items.trait_items() {
|
||||||
|
symbol_names.process_attrs(id.def_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
for id in crate_items.impl_items() {
|
||||||
|
symbol_names.process_attrs(id.def_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
for id in crate_items.foreign_items() {
|
||||||
|
symbol_names.process_attrs(id.def_id);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,21 +73,3 @@ impl SymbolNamesTest<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> hir::itemlikevisit::ItemLikeVisitor<'tcx> for SymbolNamesTest<'tcx> {
|
|
||||||
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
|
|
||||||
self.process_attrs(item.def_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
|
|
||||||
self.process_attrs(trait_item.def_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
|
|
||||||
self.process_attrs(impl_item.def_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_foreign_item(&mut self, foreign_item: &'tcx hir::ForeignItem<'tcx>) {
|
|
||||||
self.process_attrs(foreign_item.def_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,72 +1,58 @@
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
use rustc_hir::itemlikevisit::ItemLikeVisitor;
|
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_session::lint;
|
use rustc_session::lint;
|
||||||
use rustc_span::{Span, Symbol};
|
use rustc_span::{Span, Symbol};
|
||||||
|
|
||||||
pub fn check_crate(tcx: TyCtxt<'_>) {
|
pub fn check_crate(tcx: TyCtxt<'_>) {
|
||||||
let mut used_trait_imports = FxHashSet::default();
|
let mut used_trait_imports: FxHashSet<LocalDefId> = FxHashSet::default();
|
||||||
|
|
||||||
for item_def_id in tcx.hir().body_owners() {
|
for item_def_id in tcx.hir().body_owners() {
|
||||||
let imports = tcx.used_trait_imports(item_def_id);
|
let imports = tcx.used_trait_imports(item_def_id);
|
||||||
debug!("GatherVisitor: item_def_id={:?} with imports {:#?}", item_def_id, imports);
|
debug!("GatherVisitor: item_def_id={:?} with imports {:#?}", item_def_id, imports);
|
||||||
used_trait_imports.extend(imports.iter());
|
used_trait_imports.extend(imports.iter());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut visitor = CheckVisitor { tcx, used_trait_imports };
|
for id in tcx.hir().items() {
|
||||||
tcx.hir().visit_all_item_likes(&mut visitor);
|
if matches!(tcx.hir().def_kind(id.def_id), DefKind::Use) {
|
||||||
|
let item = tcx.hir().item(id);
|
||||||
|
if item.vis.node.is_pub() || item.span.is_dummy() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if let hir::ItemKind::Use(path, _) = item.kind {
|
||||||
|
check_import(tcx, &mut used_trait_imports, item.item_id(), path.span);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unused_crates_lint(tcx);
|
unused_crates_lint(tcx);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> ItemLikeVisitor<'_> for CheckVisitor<'tcx> {
|
fn check_import<'tcx>(
|
||||||
fn visit_item(&mut self, item: &hir::Item<'_>) {
|
|
||||||
if item.vis.node.is_pub() || item.span.is_dummy() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if let hir::ItemKind::Use(path, _) = item.kind {
|
|
||||||
self.check_import(item.item_id(), path.span);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
|
|
||||||
|
|
||||||
fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
|
|
||||||
|
|
||||||
fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct CheckVisitor<'tcx> {
|
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
used_trait_imports: FxHashSet<LocalDefId>,
|
used_trait_imports: &mut FxHashSet<LocalDefId>,
|
||||||
}
|
item_id: hir::ItemId,
|
||||||
|
span: Span,
|
||||||
impl<'tcx> CheckVisitor<'tcx> {
|
) {
|
||||||
fn check_import(&self, item_id: hir::ItemId, span: Span) {
|
if !tcx.maybe_unused_trait_import(item_id.def_id) {
|
||||||
if !self.tcx.maybe_unused_trait_import(item_id.def_id) {
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.used_trait_imports.contains(&item_id.def_id) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.tcx.struct_span_lint_hir(
|
|
||||||
lint::builtin::UNUSED_IMPORTS,
|
|
||||||
item_id.hir_id(),
|
|
||||||
span,
|
|
||||||
|lint| {
|
|
||||||
let msg = if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
|
|
||||||
format!("unused import: `{}`", snippet)
|
|
||||||
} else {
|
|
||||||
"unused import".to_owned()
|
|
||||||
};
|
|
||||||
lint.build(&msg).emit();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if used_trait_imports.contains(&item_id.def_id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tcx.struct_span_lint_hir(lint::builtin::UNUSED_IMPORTS, item_id.hir_id(), span, |lint| {
|
||||||
|
let msg = if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(span) {
|
||||||
|
format!("unused import: `{}`", snippet)
|
||||||
|
} else {
|
||||||
|
"unused import".to_owned()
|
||||||
|
};
|
||||||
|
lint.build(&msg).emit();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unused_crates_lint(tcx: TyCtxt<'_>) {
|
fn unused_crates_lint(tcx: TyCtxt<'_>) {
|
||||||
|
@ -110,9 +96,20 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) {
|
||||||
|
|
||||||
// Collect all the extern crates (in a reliable order).
|
// Collect all the extern crates (in a reliable order).
|
||||||
let mut crates_to_lint = vec![];
|
let mut crates_to_lint = vec![];
|
||||||
tcx.hir().visit_all_item_likes(&mut CollectExternCrateVisitor {
|
|
||||||
crates_to_lint: &mut crates_to_lint,
|
for id in tcx.hir().items() {
|
||||||
});
|
if matches!(tcx.hir().def_kind(id.def_id), DefKind::ExternCrate) {
|
||||||
|
let item = tcx.hir().item(id);
|
||||||
|
if let hir::ItemKind::ExternCrate(orig_name) = item.kind {
|
||||||
|
crates_to_lint.push(ExternCrateToLint {
|
||||||
|
def_id: item.def_id.to_def_id(),
|
||||||
|
span: item.span,
|
||||||
|
orig_name,
|
||||||
|
warn_if_unused: !item.ident.as_str().starts_with('_'),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let extern_prelude = &tcx.resolutions(()).extern_prelude;
|
let extern_prelude = &tcx.resolutions(()).extern_prelude;
|
||||||
|
|
||||||
|
@ -193,10 +190,6 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CollectExternCrateVisitor<'a> {
|
|
||||||
crates_to_lint: &'a mut Vec<ExternCrateToLint>,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ExternCrateToLint {
|
struct ExternCrateToLint {
|
||||||
/// `DefId` of the extern crate
|
/// `DefId` of the extern crate
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
|
@ -213,22 +206,3 @@ struct ExternCrateToLint {
|
||||||
/// about it going unused (but we should still emit idiom lints).
|
/// about it going unused (but we should still emit idiom lints).
|
||||||
warn_if_unused: bool,
|
warn_if_unused: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'v> ItemLikeVisitor<'v> for CollectExternCrateVisitor<'a> {
|
|
||||||
fn visit_item(&mut self, item: &hir::Item<'_>) {
|
|
||||||
if let hir::ItemKind::ExternCrate(orig_name) = item.kind {
|
|
||||||
self.crates_to_lint.push(ExternCrateToLint {
|
|
||||||
def_id: item.def_id.to_def_id(),
|
|
||||||
span: item.span,
|
|
||||||
orig_name,
|
|
||||||
warn_if_unused: !item.ident.as_str().starts_with('_'),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
|
|
||||||
|
|
||||||
fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
|
|
||||||
|
|
||||||
fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_hir as hir;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_hir::itemlikevisit::ItemLikeVisitor;
|
|
||||||
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst};
|
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst};
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
@ -29,81 +28,57 @@ pub fn infer_predicates<'tcx>(
|
||||||
while predicates_added {
|
while predicates_added {
|
||||||
predicates_added = false;
|
predicates_added = false;
|
||||||
|
|
||||||
let mut visitor = InferVisitor {
|
|
||||||
tcx,
|
|
||||||
global_inferred_outlives: &mut global_inferred_outlives,
|
|
||||||
predicates_added: &mut predicates_added,
|
|
||||||
explicit_map,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Visit all the crates and infer predicates
|
// Visit all the crates and infer predicates
|
||||||
tcx.hir().visit_all_item_likes(&mut visitor);
|
for id in tcx.hir().items() {
|
||||||
}
|
let item_did = id.def_id;
|
||||||
|
|
||||||
global_inferred_outlives
|
debug!("InferVisitor::visit_item(item={:?})", item_did);
|
||||||
}
|
|
||||||
|
|
||||||
pub struct InferVisitor<'cx, 'tcx> {
|
let mut item_required_predicates = RequiredPredicates::default();
|
||||||
tcx: TyCtxt<'tcx>,
|
match tcx.hir().def_kind(item_did) {
|
||||||
global_inferred_outlives: &'cx mut FxHashMap<DefId, RequiredPredicates<'tcx>>,
|
DefKind::Union | DefKind::Enum | DefKind::Struct => {
|
||||||
predicates_added: &'cx mut bool,
|
let adt_def = tcx.adt_def(item_did.to_def_id());
|
||||||
explicit_map: &'cx mut ExplicitPredicatesMap<'tcx>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'cx, 'tcx> ItemLikeVisitor<'tcx> for InferVisitor<'cx, 'tcx> {
|
// Iterate over all fields in item_did
|
||||||
fn visit_item(&mut self, item: &hir::Item<'_>) {
|
for field_def in adt_def.all_fields() {
|
||||||
let item_did = item.def_id;
|
// Calculating the predicate requirements necessary
|
||||||
|
// for item_did.
|
||||||
debug!("InferVisitor::visit_item(item={:?})", item_did);
|
//
|
||||||
|
// For field of type &'a T (reference) or Adt
|
||||||
let mut item_required_predicates = RequiredPredicates::default();
|
// (struct/enum/union) there will be outlive
|
||||||
match item.kind {
|
// requirements for adt_def.
|
||||||
hir::ItemKind::Union(..) | hir::ItemKind::Enum(..) | hir::ItemKind::Struct(..) => {
|
let field_ty = tcx.type_of(field_def.did);
|
||||||
let adt_def = self.tcx.adt_def(item_did.to_def_id());
|
let field_span = tcx.def_span(field_def.did);
|
||||||
|
insert_required_predicates_to_be_wf(
|
||||||
// Iterate over all fields in item_did
|
tcx,
|
||||||
for field_def in adt_def.all_fields() {
|
field_ty,
|
||||||
// Calculating the predicate requirements necessary
|
field_span,
|
||||||
// for item_did.
|
&mut global_inferred_outlives,
|
||||||
//
|
&mut item_required_predicates,
|
||||||
// For field of type &'a T (reference) or Adt
|
explicit_map,
|
||||||
// (struct/enum/union) there will be outlive
|
);
|
||||||
// requirements for adt_def.
|
}
|
||||||
let field_ty = self.tcx.type_of(field_def.did);
|
|
||||||
let field_span = self.tcx.def_span(field_def.did);
|
|
||||||
insert_required_predicates_to_be_wf(
|
|
||||||
self.tcx,
|
|
||||||
field_ty,
|
|
||||||
field_span,
|
|
||||||
self.global_inferred_outlives,
|
|
||||||
&mut item_required_predicates,
|
|
||||||
&mut self.explicit_map,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// If new predicates were added (`local_predicate_map` has more
|
||||||
|
// predicates than the `global_inferred_outlives`), the new predicates
|
||||||
|
// might result in implied predicates for their parent types.
|
||||||
|
// Therefore mark `predicates_added` as true and which will ensure
|
||||||
|
// we walk the crates again and re-calculate predicates for all
|
||||||
|
// items.
|
||||||
|
let item_predicates_len: usize =
|
||||||
|
global_inferred_outlives.get(&item_did.to_def_id()).map_or(0, |p| p.len());
|
||||||
|
if item_required_predicates.len() > item_predicates_len {
|
||||||
|
predicates_added = true;
|
||||||
|
global_inferred_outlives.insert(item_did.to_def_id(), item_required_predicates);
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// If new predicates were added (`local_predicate_map` has more
|
|
||||||
// predicates than the `global_inferred_outlives`), the new predicates
|
|
||||||
// might result in implied predicates for their parent types.
|
|
||||||
// Therefore mark `predicates_added` as true and which will ensure
|
|
||||||
// we walk the crates again and re-calculate predicates for all
|
|
||||||
// items.
|
|
||||||
let item_predicates_len: usize =
|
|
||||||
self.global_inferred_outlives.get(&item_did.to_def_id()).map_or(0, |p| p.len());
|
|
||||||
if item_required_predicates.len() > item_predicates_len {
|
|
||||||
*self.predicates_added = true;
|
|
||||||
self.global_inferred_outlives.insert(item_did.to_def_id(), item_required_predicates);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_trait_item(&mut self, _trait_item: &'tcx hir::TraitItem<'tcx>) {}
|
global_inferred_outlives
|
||||||
|
|
||||||
fn visit_impl_item(&mut self, _impl_item: &'tcx hir::ImplItem<'tcx>) {}
|
|
||||||
|
|
||||||
fn visit_foreign_item(&mut self, _foreign_item: &'tcx hir::ForeignItem<'tcx>) {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert_required_predicates_to_be_wf<'tcx>(
|
fn insert_required_predicates_to_be_wf<'tcx>(
|
||||||
|
|
|
@ -50,7 +50,12 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod {
|
||||||
fn check_crate_post(&mut self, cx: &LateContext<'tcx>) {
|
fn check_crate_post(&mut self, cx: &LateContext<'tcx>) {
|
||||||
let mut map = FxHashMap::<Res, ExistingName>::default();
|
let mut map = FxHashMap::<Res, ExistingName>::default();
|
||||||
|
|
||||||
for item in cx.tcx.hir().items() {
|
for id in cx.tcx.hir().items() {
|
||||||
|
if !matches!(cx.tcx.hir().def_kind(id.def_id), DefKind::Impl) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let item = cx.tcx.hir().item(id);
|
||||||
if let ItemKind::Impl(Impl {
|
if let ItemKind::Impl(Impl {
|
||||||
items,
|
items,
|
||||||
of_trait,
|
of_trait,
|
||||||
|
|
|
@ -11,6 +11,19 @@ note: existing `foo` defined here
|
||||||
LL | fn foo() {}
|
LL | fn foo() {}
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: method's name is the same as an existing method in a trait
|
||||||
|
--> $DIR/same_name_method.rs:34:13
|
||||||
|
|
|
||||||
|
LL | fn clone() {}
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
note: existing `clone` defined here
|
||||||
|
--> $DIR/same_name_method.rs:30:18
|
||||||
|
|
|
||||||
|
LL | #[derive(Clone)]
|
||||||
|
| ^^^^^
|
||||||
|
= note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: method's name is the same as an existing method in a trait
|
error: method's name is the same as an existing method in a trait
|
||||||
--> $DIR/same_name_method.rs:44:13
|
--> $DIR/same_name_method.rs:44:13
|
||||||
|
|
|
|
||||||
|
@ -47,18 +60,5 @@ note: existing `foo` defined here
|
||||||
LL | impl T1 for S {}
|
LL | impl T1 for S {}
|
||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: method's name is the same as an existing method in a trait
|
|
||||||
--> $DIR/same_name_method.rs:34:13
|
|
||||||
|
|
|
||||||
LL | fn clone() {}
|
|
||||||
| ^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
note: existing `clone` defined here
|
|
||||||
--> $DIR/same_name_method.rs:30:18
|
|
||||||
|
|
|
||||||
LL | #[derive(Clone)]
|
|
||||||
| ^^^^^
|
|
||||||
= note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
||||||
|
|
||||||
error: aborting due to 5 previous errors
|
error: aborting due to 5 previous errors
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue