2021-07-16 14:42:26 +02:00
|
|
|
use crate::hir::{IndexedHir, ModuleItems, Owner};
|
2020-02-07 13:13:35 +01:00
|
|
|
use crate::ty::TyCtxt;
|
2020-04-27 23:26:11 +05:30
|
|
|
use rustc_ast as ast;
|
2021-02-28 18:58:50 +01:00
|
|
|
use rustc_data_structures::fingerprint::Fingerprint;
|
|
|
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
2018-08-03 12:22:22 -06:00
|
|
|
use rustc_data_structures::svh::Svh;
|
2021-09-12 01:11:22 +02:00
|
|
|
use rustc_data_structures::sync::{par_for_each_in, Send, Sync};
|
2020-01-05 02:37:57 +01:00
|
|
|
use rustc_hir::def::{DefKind, Res};
|
2021-07-14 19:53:57 +02:00
|
|
|
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
|
2021-05-20 20:17:45 +02:00
|
|
|
use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
|
2021-08-26 18:42:08 +02:00
|
|
|
use rustc_hir::intravisit::{self, Visitor};
|
2020-01-05 02:37:57 +01:00
|
|
|
use rustc_hir::itemlikevisit::ItemLikeVisitor;
|
|
|
|
use rustc_hir::*;
|
2021-03-03 21:50:45 +01:00
|
|
|
use rustc_index::vec::Idx;
|
2021-06-08 18:36:30 +02:00
|
|
|
use rustc_span::def_id::StableCrateId;
|
2019-12-31 20:15:40 +03:00
|
|
|
use rustc_span::hygiene::MacroKind;
|
2020-01-01 19:25:28 +01:00
|
|
|
use rustc_span::source_map::Spanned;
|
2021-07-10 11:16:03 +08:00
|
|
|
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
2020-01-07 14:38:27 +01:00
|
|
|
use rustc_span::Span;
|
2019-12-22 17:42:04 -05:00
|
|
|
use rustc_target::spec::abi::Abi;
|
2021-09-07 20:07:33 +02:00
|
|
|
use std::collections::VecDeque;
|
2015-07-31 00:04:06 -07:00
|
|
|
|
2014-07-02 17:50:18 +02:00
|
|
|
pub mod blocks;
|
2015-09-10 15:53:08 -04:00
|
|
|
mod collector;
|
2014-07-02 17:50:18 +02:00
|
|
|
|
2020-02-07 15:34:39 +01:00
|
|
|
fn fn_decl<'hir>(node: Node<'hir>) -> Option<&'hir FnDecl<'hir>> {
|
|
|
|
match node {
|
2020-03-24 06:17:44 +01:00
|
|
|
Node::Item(Item { kind: ItemKind::Fn(sig, _, _), .. })
|
|
|
|
| Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(sig, _), .. })
|
|
|
|
| Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(sig, _), .. }) => Some(&sig.decl),
|
Support HIR wf checking for function signatures
During function type-checking, we normalize any associated types in
the function signature (argument types + return type), and then
create WF obligations for each of the normalized types. The HIR wf code
does not currently support this case, so any errors that we get have
imprecise spans.
This commit extends `ObligationCauseCode::WellFormed` to support
recording a function parameter, allowing us to get the corresponding
HIR type if an error occurs. Function typechecking is modified to
pass this information during signature normalization and WF checking.
The resulting code is fairly verbose, due to the fact that we can
no longer normalize the entire signature with a single function call.
As part of the refactoring, we now perform HIR-based WF checking
for several other 'typed items' (statics, consts, and inherent impls).
As a result, WF and projection errors in a function signature now
have a precise span, which points directly at the responsible type.
If a function signature is constructed via a macro, this will allow
the error message to point at the code 'most responsible' for the error
(e.g. a user-supplied macro argument).
2021-07-18 11:33:49 -05:00
|
|
|
Node::Expr(Expr { kind: ExprKind::Closure(_, fn_decl, ..), .. })
|
|
|
|
| Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_decl, ..), .. }) => {
|
|
|
|
Some(fn_decl)
|
|
|
|
}
|
2020-02-07 15:34:39 +01:00
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
2019-11-06 11:43:33 -08:00
|
|
|
|
2020-11-30 23:58:08 -08:00
|
|
|
pub fn fn_sig<'hir>(node: Node<'hir>) -> Option<&'hir FnSig<'hir>> {
|
2020-02-07 15:34:39 +01:00
|
|
|
match &node {
|
2020-03-24 06:17:44 +01:00
|
|
|
Node::Item(Item { kind: ItemKind::Fn(sig, _, _), .. })
|
|
|
|
| Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(sig, _), .. })
|
|
|
|
| Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(sig, _), .. }) => Some(sig),
|
2020-02-07 15:34:39 +01:00
|
|
|
_ => None,
|
2019-11-06 11:43:33 -08:00
|
|
|
}
|
2020-02-07 15:34:39 +01:00
|
|
|
}
|
2019-11-06 11:43:33 -08:00
|
|
|
|
2020-06-22 15:54:28 -07:00
|
|
|
pub fn associated_body<'hir>(node: Node<'hir>) -> Option<BodyId> {
|
2020-02-07 16:10:50 +01:00
|
|
|
match node {
|
2020-03-24 06:17:44 +01:00
|
|
|
Node::Item(Item {
|
|
|
|
kind: ItemKind::Const(_, body) | ItemKind::Static(.., body) | ItemKind::Fn(.., body),
|
|
|
|
..
|
|
|
|
})
|
|
|
|
| Node::TraitItem(TraitItem {
|
|
|
|
kind:
|
|
|
|
TraitItemKind::Const(_, Some(body)) | TraitItemKind::Fn(_, TraitFn::Provided(body)),
|
|
|
|
..
|
|
|
|
})
|
|
|
|
| Node::ImplItem(ImplItem {
|
|
|
|
kind: ImplItemKind::Const(_, body) | ImplItemKind::Fn(_, body),
|
|
|
|
..
|
|
|
|
})
|
|
|
|
| Node::Expr(Expr { kind: ExprKind::Closure(.., body, _, _), .. }) => Some(*body),
|
2018-05-17 21:28:50 +03:00
|
|
|
|
2020-02-07 16:10:50 +01:00
|
|
|
Node::AnonConst(constant) => Some(constant.body),
|
2016-12-20 23:05:21 +02:00
|
|
|
|
2020-02-07 16:10:50 +01:00
|
|
|
_ => None,
|
2017-02-20 21:18:16 -05:00
|
|
|
}
|
2020-02-07 16:10:50 +01:00
|
|
|
}
|
2017-02-20 21:18:16 -05:00
|
|
|
|
2020-02-07 16:10:50 +01:00
|
|
|
fn is_body_owner<'hir>(node: Node<'hir>, hir_id: HirId) -> bool {
|
|
|
|
match associated_body(node) {
|
|
|
|
Some(b) => b.hir_id == hir_id,
|
|
|
|
None => false,
|
2016-12-20 23:05:21 +02:00
|
|
|
}
|
2013-08-31 17:13:57 +10:00
|
|
|
}
|
|
|
|
|
2020-02-09 15:32:00 +01:00
|
|
|
#[derive(Copy, Clone)]
|
2017-01-26 03:21:50 +02:00
|
|
|
pub struct Map<'hir> {
|
2020-02-07 13:13:35 +01:00
|
|
|
pub(super) tcx: TyCtxt<'hir>,
|
2014-01-17 23:23:09 +11:00
|
|
|
}
|
|
|
|
|
2020-02-25 05:30:11 +01:00
|
|
|
/// An iterator that walks up the ancestor tree of a given `HirId`.
|
|
|
|
/// Constructed using `tcx.hir().parent_iter(hir_id)`.
|
2021-09-18 15:48:07 -05:00
|
|
|
pub struct ParentHirIterator<'hir> {
|
2019-09-25 17:05:30 -07:00
|
|
|
current_id: HirId,
|
2021-09-18 15:48:07 -05:00
|
|
|
map: Map<'hir>,
|
2019-09-25 17:05:30 -07:00
|
|
|
}
|
|
|
|
|
2021-09-18 15:48:07 -05:00
|
|
|
impl<'hir> Iterator for ParentHirIterator<'hir> {
|
2019-11-29 14:08:03 +01:00
|
|
|
type Item = (HirId, Node<'hir>);
|
2019-09-25 17:05:30 -07:00
|
|
|
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
|
|
if self.current_id == CRATE_HIR_ID {
|
|
|
|
return None;
|
|
|
|
}
|
2019-12-22 17:42:04 -05:00
|
|
|
loop {
|
|
|
|
// There are nodes that do not have entries, so we need to skip them.
|
2019-09-25 17:05:30 -07:00
|
|
|
let parent_id = self.map.get_parent_node(self.current_id);
|
|
|
|
|
|
|
|
if parent_id == self.current_id {
|
|
|
|
self.current_id = CRATE_HIR_ID;
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
|
|
|
|
self.current_id = parent_id;
|
2021-03-03 21:50:45 +01:00
|
|
|
if let Some(node) = self.map.find(parent_id) {
|
|
|
|
return Some((parent_id, node));
|
|
|
|
}
|
|
|
|
// If this `HirId` doesn't have an entry, skip it and look for its `parent_id`.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// An iterator that walks up the ancestor tree of a given `HirId`.
|
|
|
|
/// Constructed using `tcx.hir().parent_owner_iter(hir_id)`.
|
2021-09-18 15:48:07 -05:00
|
|
|
pub struct ParentOwnerIterator<'hir> {
|
2021-03-03 21:50:45 +01:00
|
|
|
current_id: HirId,
|
2021-09-18 15:48:07 -05:00
|
|
|
map: Map<'hir>,
|
2021-03-03 21:50:45 +01:00
|
|
|
}
|
|
|
|
|
2021-09-18 15:48:07 -05:00
|
|
|
impl<'hir> Iterator for ParentOwnerIterator<'hir> {
|
2021-03-27 13:56:22 +01:00
|
|
|
type Item = (HirId, OwnerNode<'hir>);
|
2021-03-03 21:50:45 +01:00
|
|
|
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
|
|
if self.current_id.local_id.index() != 0 {
|
|
|
|
self.current_id.local_id = ItemLocalId::new(0);
|
2021-03-27 13:56:22 +01:00
|
|
|
if let Some(node) = self.map.tcx.hir_owner(self.current_id.owner) {
|
|
|
|
return Some((self.current_id, node.node));
|
2021-03-03 21:50:45 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if self.current_id == CRATE_HIR_ID {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
loop {
|
|
|
|
// There are nodes that do not have entries, so we need to skip them.
|
|
|
|
let parent_id = self.map.def_key(self.current_id.owner).parent;
|
|
|
|
|
|
|
|
let parent_id = parent_id.map_or(CRATE_HIR_ID.owner, |local_def_index| {
|
|
|
|
let def_id = LocalDefId { local_def_index };
|
|
|
|
self.map.local_def_id_to_hir_id(def_id).owner
|
|
|
|
});
|
|
|
|
self.current_id = HirId::make_owner(parent_id);
|
|
|
|
|
|
|
|
// If this `HirId` doesn't have an entry, skip it and look for its `parent_id`.
|
2021-03-27 13:56:22 +01:00
|
|
|
if let Some(node) = self.map.tcx.hir_owner(self.current_id.owner) {
|
|
|
|
return Some((self.current_id, node.node));
|
2019-09-25 17:05:30 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-26 03:21:50 +02:00
|
|
|
impl<'hir> Map<'hir> {
|
2020-02-09 15:32:00 +01:00
|
|
|
pub fn krate(&self) -> &'hir Crate<'hir> {
|
2021-05-11 11:42:01 +02:00
|
|
|
self.tcx.hir_crate(())
|
2020-02-06 13:41:37 +01:00
|
|
|
}
|
|
|
|
|
2021-09-12 01:11:22 +02:00
|
|
|
pub fn root_module(&self) -> &'hir Mod<'hir> {
|
|
|
|
match self.tcx.hir_owner(CRATE_DEF_ID).map(|o| o.node) {
|
|
|
|
Some(OwnerNode::Crate(item)) => item,
|
2021-09-13 20:43:43 +02:00
|
|
|
_ => bug!(),
|
2021-09-12 01:11:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-12 11:58:27 +02:00
|
|
|
pub fn items(&self) -> impl Iterator<Item = &'hir Item<'hir>> + 'hir {
|
2021-09-12 01:11:22 +02:00
|
|
|
let krate = self.krate();
|
2021-07-16 14:42:26 +02:00
|
|
|
krate.owners.iter().filter_map(|owner| match owner.as_ref()?.node {
|
|
|
|
OwnerNode::Item(item) => Some(item),
|
2021-09-12 01:11:22 +02:00
|
|
|
_ => None,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-11-03 20:48:08 +02:00
|
|
|
pub fn def_key(&self, def_id: LocalDefId) -> DefKey {
|
2021-05-20 20:17:45 +02:00
|
|
|
// Accessing the DefKey is ok, since it is part of DefPathHash.
|
2021-04-04 14:40:35 +02:00
|
|
|
self.tcx.untracked_resolutions.definitions.def_key(def_id)
|
2015-09-17 14:29:59 -04:00
|
|
|
}
|
|
|
|
|
2019-04-27 22:39:17 +02:00
|
|
|
pub fn def_path_from_hir_id(&self, id: HirId) -> Option<DefPath> {
|
2020-04-08 12:33:38 +01:00
|
|
|
self.opt_local_def_id(id).map(|def_id| self.def_path(def_id))
|
2015-09-17 14:29:59 -04:00
|
|
|
}
|
|
|
|
|
2019-11-03 20:48:08 +02:00
|
|
|
pub fn def_path(&self, def_id: LocalDefId) -> DefPath {
|
2021-05-20 20:17:45 +02:00
|
|
|
// Accessing the DefPath is ok, since it is part of DefPathHash.
|
2021-04-04 14:40:35 +02:00
|
|
|
self.tcx.untracked_resolutions.definitions.def_path(def_id)
|
2015-09-17 14:29:59 -04:00
|
|
|
}
|
|
|
|
|
2021-05-20 20:17:45 +02:00
|
|
|
#[inline]
|
|
|
|
pub fn def_path_hash(self, def_id: LocalDefId) -> DefPathHash {
|
|
|
|
// Accessing the DefPathHash is ok, it is incr. comp. stable.
|
|
|
|
self.tcx.untracked_resolutions.definitions.def_path_hash(def_id)
|
|
|
|
}
|
|
|
|
|
2019-02-03 09:14:31 +01:00
|
|
|
#[inline]
|
2020-04-09 09:43:00 +01:00
|
|
|
pub fn local_def_id(&self, hir_id: HirId) -> LocalDefId {
|
|
|
|
self.opt_local_def_id(hir_id).unwrap_or_else(|| {
|
|
|
|
bug!(
|
|
|
|
"local_def_id: no entry for `{:?}`, which has a map of `{:?}`",
|
|
|
|
hir_id,
|
2021-03-03 21:50:45 +01:00
|
|
|
self.find(hir_id)
|
2020-04-09 09:43:00 +01:00
|
|
|
)
|
|
|
|
})
|
2019-02-03 09:14:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2020-04-08 12:33:38 +01:00
|
|
|
pub fn opt_local_def_id(&self, hir_id: HirId) -> Option<LocalDefId> {
|
2021-05-20 20:17:45 +02:00
|
|
|
// FIXME(#85914) is this access safe for incr. comp.?
|
2021-04-04 14:40:35 +02:00
|
|
|
self.tcx.untracked_resolutions.definitions.opt_hir_id_to_local_def_id(hir_id)
|
2015-09-02 16:11:32 -04:00
|
|
|
}
|
|
|
|
|
2017-11-16 14:04:01 +01:00
|
|
|
#[inline]
|
|
|
|
pub fn local_def_id_to_hir_id(&self, def_id: LocalDefId) -> HirId {
|
2021-05-20 20:17:45 +02:00
|
|
|
// FIXME(#85914) is this access safe for incr. comp.?
|
2021-04-04 14:40:35 +02:00
|
|
|
self.tcx.untracked_resolutions.definitions.local_def_id_to_hir_id(def_id)
|
2017-11-16 14:04:01 +01:00
|
|
|
}
|
|
|
|
|
2020-11-28 22:07:00 +01:00
|
|
|
pub fn iter_local_def_id(&self) -> impl Iterator<Item = LocalDefId> + '_ {
|
2021-05-20 20:17:45 +02:00
|
|
|
// Create a dependency to the crate to be sure we reexcute this when the amount of
|
|
|
|
// definitions change.
|
|
|
|
self.tcx.ensure().hir_crate(());
|
2021-04-04 14:40:35 +02:00
|
|
|
self.tcx.untracked_resolutions.definitions.iter_local_def_id()
|
2020-11-28 22:07:00 +01:00
|
|
|
}
|
|
|
|
|
2021-01-16 14:35:16 +01:00
|
|
|
pub fn opt_def_kind(&self, local_def_id: LocalDefId) -> Option<DefKind> {
|
2020-03-16 10:01:03 -05:00
|
|
|
let hir_id = self.local_def_id_to_hir_id(local_def_id);
|
2021-01-16 14:35:16 +01:00
|
|
|
let def_kind = match self.find(hir_id)? {
|
2019-12-22 17:42:04 -05:00
|
|
|
Node::Item(item) => match item.kind {
|
|
|
|
ItemKind::Static(..) => DefKind::Static,
|
|
|
|
ItemKind::Const(..) => DefKind::Const,
|
|
|
|
ItemKind::Fn(..) => DefKind::Fn,
|
2021-07-30 23:50:57 -07:00
|
|
|
ItemKind::Macro(..) => DefKind::Macro(MacroKind::Bang),
|
2019-12-22 17:42:04 -05:00
|
|
|
ItemKind::Mod(..) => DefKind::Mod,
|
|
|
|
ItemKind::OpaqueTy(..) => DefKind::OpaqueTy,
|
|
|
|
ItemKind::TyAlias(..) => DefKind::TyAlias,
|
|
|
|
ItemKind::Enum(..) => DefKind::Enum,
|
|
|
|
ItemKind::Struct(..) => DefKind::Struct,
|
|
|
|
ItemKind::Union(..) => DefKind::Union,
|
|
|
|
ItemKind::Trait(..) => DefKind::Trait,
|
|
|
|
ItemKind::TraitAlias(..) => DefKind::TraitAlias,
|
2020-03-16 10:01:03 -05:00
|
|
|
ItemKind::ExternCrate(_) => DefKind::ExternCrate,
|
|
|
|
ItemKind::Use(..) => DefKind::Use,
|
2020-11-11 22:40:09 +01:00
|
|
|
ItemKind::ForeignMod { .. } => DefKind::ForeignMod,
|
2020-03-16 10:01:03 -05:00
|
|
|
ItemKind::GlobalAsm(..) => DefKind::GlobalAsm,
|
|
|
|
ItemKind::Impl { .. } => DefKind::Impl,
|
2019-12-22 17:42:04 -05:00
|
|
|
},
|
|
|
|
Node::ForeignItem(item) => match item.kind {
|
|
|
|
ForeignItemKind::Fn(..) => DefKind::Fn,
|
|
|
|
ForeignItemKind::Static(..) => DefKind::Static,
|
|
|
|
ForeignItemKind::Type => DefKind::ForeignTy,
|
|
|
|
},
|
|
|
|
Node::TraitItem(item) => match item.kind {
|
|
|
|
TraitItemKind::Const(..) => DefKind::AssocConst,
|
2020-03-03 12:46:22 -06:00
|
|
|
TraitItemKind::Fn(..) => DefKind::AssocFn,
|
2019-12-22 17:42:04 -05:00
|
|
|
TraitItemKind::Type(..) => DefKind::AssocTy,
|
|
|
|
},
|
|
|
|
Node::ImplItem(item) => match item.kind {
|
|
|
|
ImplItemKind::Const(..) => DefKind::AssocConst,
|
2020-03-05 09:57:34 -06:00
|
|
|
ImplItemKind::Fn(..) => DefKind::AssocFn,
|
2019-12-22 17:42:04 -05:00
|
|
|
ImplItemKind::TyAlias(..) => DefKind::AssocTy,
|
|
|
|
},
|
2019-04-20 18:26:26 +03:00
|
|
|
Node::Variant(_) => DefKind::Variant,
|
2019-03-24 18:21:59 +01:00
|
|
|
Node::Ctor(variant_data) => {
|
2019-04-20 18:26:26 +03:00
|
|
|
// FIXME(eddyb) is this even possible, if we have a `Node::Ctor`?
|
2020-04-17 21:55:17 +03:00
|
|
|
assert_ne!(variant_data.ctor_hir_id(), None);
|
2020-03-01 22:04:42 +01:00
|
|
|
|
2019-06-24 09:58:49 +02:00
|
|
|
let ctor_of = match self.find(self.get_parent_node(hir_id)) {
|
2019-03-24 18:54:56 +01:00
|
|
|
Some(Node::Item(..)) => def::CtorOf::Struct,
|
|
|
|
Some(Node::Variant(..)) => def::CtorOf::Variant,
|
2019-03-24 18:21:59 +01:00
|
|
|
_ => unreachable!(),
|
|
|
|
};
|
2019-04-20 18:26:26 +03:00
|
|
|
DefKind::Ctor(ctor_of, def::CtorKind::from_hir(variant_data))
|
2019-02-03 14:09:56 +01:00
|
|
|
}
|
2020-03-16 10:01:03 -05:00
|
|
|
Node::AnonConst(_) => DefKind::AnonConst,
|
|
|
|
Node::Field(_) => DefKind::Field,
|
|
|
|
Node::Expr(expr) => match expr.kind {
|
2020-04-17 16:55:08 +03:00
|
|
|
ExprKind::Closure(.., None) => DefKind::Closure,
|
|
|
|
ExprKind::Closure(.., Some(_)) => DefKind::Generator,
|
2020-03-16 10:01:03 -05:00
|
|
|
_ => bug!("def_kind: unsupported node: {}", self.node_to_string(hir_id)),
|
|
|
|
},
|
|
|
|
Node::GenericParam(param) => match param.kind {
|
|
|
|
GenericParamKind::Lifetime { .. } => DefKind::LifetimeParam,
|
|
|
|
GenericParamKind::Type { .. } => DefKind::TyParam,
|
|
|
|
GenericParamKind::Const { .. } => DefKind::ConstParam,
|
|
|
|
},
|
2021-01-18 19:15:53 +01:00
|
|
|
Node::Crate(_) => DefKind::Mod,
|
2020-03-16 10:01:03 -05:00
|
|
|
Node::Stmt(_)
|
2019-12-22 17:42:04 -05:00
|
|
|
| Node::PathSegment(_)
|
|
|
|
| Node::Ty(_)
|
2021-04-26 18:19:23 +00:00
|
|
|
| Node::Infer(_)
|
2019-12-22 17:42:04 -05:00
|
|
|
| Node::TraitRef(_)
|
|
|
|
| Node::Pat(_)
|
|
|
|
| Node::Binding(_)
|
|
|
|
| Node::Local(_)
|
|
|
|
| Node::Param(_)
|
|
|
|
| Node::Arm(_)
|
|
|
|
| Node::Lifetime(_)
|
|
|
|
| Node::Visibility(_)
|
2021-01-18 19:15:53 +01:00
|
|
|
| Node::Block(_) => return None,
|
2021-01-16 14:35:16 +01:00
|
|
|
};
|
|
|
|
Some(def_kind)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn def_kind(&self, local_def_id: LocalDefId) -> DefKind {
|
|
|
|
self.opt_def_kind(local_def_id)
|
|
|
|
.unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", local_def_id))
|
2019-02-04 11:09:32 +01:00
|
|
|
}
|
|
|
|
|
2021-03-03 21:50:45 +01:00
|
|
|
pub fn find_parent_node(&self, id: HirId) -> Option<HirId> {
|
2020-03-10 13:44:53 -07:00
|
|
|
if id.local_id == ItemLocalId::from_u32(0) {
|
2021-03-06 11:25:41 +01:00
|
|
|
Some(self.tcx.hir_owner_parent(id.owner))
|
2020-02-07 16:43:36 +01:00
|
|
|
} else {
|
2021-03-03 21:50:45 +01:00
|
|
|
let owner = self.tcx.hir_owner_nodes(id.owner)?;
|
|
|
|
let node = owner.nodes[id.local_id].as_ref()?;
|
|
|
|
let hir_id = HirId { owner: id.owner, local_id: node.parent };
|
|
|
|
Some(hir_id)
|
2020-02-07 16:43:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-03 21:50:45 +01:00
|
|
|
pub fn get_parent_node(&self, hir_id: HirId) -> HirId {
|
2021-02-28 20:23:10 +01:00
|
|
|
self.find_parent_node(hir_id).unwrap()
|
2021-03-03 21:50:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Retrieves the `Node` corresponding to `id`, returning `None` if cannot be found.
|
|
|
|
pub fn find(&self, id: HirId) -> Option<Node<'hir>> {
|
|
|
|
if id.local_id == ItemLocalId::from_u32(0) {
|
|
|
|
let owner = self.tcx.hir_owner(id.owner)?;
|
2021-03-27 13:21:26 +01:00
|
|
|
Some(owner.node.into())
|
2021-03-03 21:50:45 +01:00
|
|
|
} else {
|
|
|
|
let owner = self.tcx.hir_owner_nodes(id.owner)?;
|
|
|
|
let node = owner.nodes[id.local_id].as_ref()?;
|
|
|
|
Some(node.node)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Retrieves the `Node` corresponding to `id`, panicking if it cannot be found.
|
|
|
|
pub fn get(&self, id: HirId) -> Node<'hir> {
|
|
|
|
self.find(id).unwrap_or_else(|| bug!("couldn't find hir id {} in the HIR map", id))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_if_local(&self, id: DefId) -> Option<Node<'hir>> {
|
|
|
|
id.as_local().and_then(|id| self.find(self.local_def_id_to_hir_id(id)))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_generics(&self, id: DefId) -> Option<&'hir Generics<'hir>> {
|
2021-03-27 13:56:22 +01:00
|
|
|
let id = id.as_local()?;
|
|
|
|
let node = self.tcx.hir_owner(id)?;
|
|
|
|
match node.node {
|
|
|
|
OwnerNode::ImplItem(impl_item) => Some(&impl_item.generics),
|
|
|
|
OwnerNode::TraitItem(trait_item) => Some(&trait_item.generics),
|
|
|
|
OwnerNode::Item(Item {
|
2021-03-03 21:50:45 +01:00
|
|
|
kind:
|
|
|
|
ItemKind::Fn(_, generics, _)
|
|
|
|
| ItemKind::TyAlias(_, generics)
|
|
|
|
| ItemKind::Enum(_, generics)
|
|
|
|
| ItemKind::Struct(_, generics)
|
|
|
|
| ItemKind::Union(_, generics)
|
|
|
|
| ItemKind::Trait(_, _, generics, ..)
|
|
|
|
| ItemKind::TraitAlias(generics, _)
|
|
|
|
| ItemKind::Impl(Impl { generics, .. }),
|
|
|
|
..
|
|
|
|
}) => Some(generics),
|
|
|
|
_ => None,
|
2021-03-27 13:56:22 +01:00
|
|
|
}
|
2020-03-16 19:17:40 +01:00
|
|
|
}
|
|
|
|
|
2021-01-30 12:06:04 +01:00
|
|
|
pub fn item(&self, id: ItemId) -> &'hir Item<'hir> {
|
2021-03-27 13:56:22 +01:00
|
|
|
self.tcx.hir_owner(id.def_id).unwrap().node.expect_item()
|
2020-01-07 15:51:38 +01:00
|
|
|
}
|
|
|
|
|
2019-11-28 21:47:10 +01:00
|
|
|
pub fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir> {
|
2021-03-27 13:56:22 +01:00
|
|
|
self.tcx.hir_owner(id.def_id).unwrap().node.expect_trait_item()
|
2016-12-04 04:21:06 +02:00
|
|
|
}
|
|
|
|
|
2019-11-28 22:16:44 +01:00
|
|
|
pub fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir> {
|
2021-03-27 13:56:22 +01:00
|
|
|
self.tcx.hir_owner(id.def_id).unwrap().node.expect_impl_item()
|
2016-11-02 18:25:31 -04:00
|
|
|
}
|
|
|
|
|
2020-11-11 21:57:54 +01:00
|
|
|
pub fn foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir> {
|
2021-03-27 13:56:22 +01:00
|
|
|
self.tcx.hir_owner(id.def_id).unwrap().node.expect_foreign_item()
|
2020-11-11 21:57:54 +01:00
|
|
|
}
|
|
|
|
|
2019-11-29 11:09:23 +01:00
|
|
|
pub fn body(&self, id: BodyId) -> &'hir Body<'hir> {
|
2021-09-17 19:41:05 +02:00
|
|
|
self.tcx.hir_owner_nodes(id.hir_id.owner).unwrap().bodies[id.hir_id.local_id].unwrap()
|
2016-12-21 12:32:59 +02:00
|
|
|
}
|
|
|
|
|
2019-11-30 17:46:46 +01:00
|
|
|
pub fn fn_decl_by_hir_id(&self, hir_id: HirId) -> Option<&'hir FnDecl<'hir>> {
|
2020-02-07 15:34:39 +01:00
|
|
|
if let Some(node) = self.find(hir_id) {
|
|
|
|
fn_decl(node)
|
2019-03-09 08:57:35 +01:00
|
|
|
} else {
|
2020-02-07 15:34:39 +01:00
|
|
|
bug!("no node for hir_id `{}`", hir_id)
|
2019-03-09 08:57:35 +01:00
|
|
|
}
|
2019-02-04 11:09:32 +01:00
|
|
|
}
|
|
|
|
|
2019-11-30 15:20:35 +01:00
|
|
|
pub fn fn_sig_by_hir_id(&self, hir_id: HirId) -> Option<&'hir FnSig<'hir>> {
|
2020-02-07 15:34:39 +01:00
|
|
|
if let Some(node) = self.find(hir_id) {
|
|
|
|
fn_sig(node)
|
2019-11-06 11:43:33 -08:00
|
|
|
} else {
|
2020-02-07 15:34:39 +01:00
|
|
|
bug!("no node for hir_id `{}`", hir_id)
|
2019-11-06 11:43:33 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-20 14:57:16 +02:00
|
|
|
pub fn enclosing_body_owner(&self, hir_id: HirId) -> HirId {
|
|
|
|
for (parent, _) in self.parent_iter(hir_id) {
|
|
|
|
if let Some(body) = self.maybe_body_owned_by(parent) {
|
|
|
|
return self.body_owner(body);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bug!("no `enclosing_body_owner` for hir_id `{}`", hir_id);
|
|
|
|
}
|
|
|
|
|
2019-06-16 17:30:53 +02:00
|
|
|
/// Returns the `HirId` that corresponds to the definition of
|
2018-11-27 02:59:49 +00:00
|
|
|
/// which this is the body of, i.e., a `fn`, `const` or `static`
|
2018-05-17 21:28:50 +03:00
|
|
|
/// item (possibly associated), a closure, or a `hir::AnonConst`.
|
2019-06-14 12:28:47 +02:00
|
|
|
pub fn body_owner(&self, BodyId { hir_id }: BodyId) -> HirId {
|
2019-06-24 09:46:38 +02:00
|
|
|
let parent = self.get_parent_node(hir_id);
|
2020-02-07 16:10:50 +01:00
|
|
|
assert!(self.find(parent).map_or(false, |n| is_body_owner(n, hir_id)));
|
2019-06-14 12:28:47 +02:00
|
|
|
parent
|
2016-12-20 23:05:21 +02:00
|
|
|
}
|
|
|
|
|
2020-04-08 14:53:06 +01:00
|
|
|
pub fn body_owner_def_id(&self, id: BodyId) -> LocalDefId {
|
2020-04-09 09:43:00 +01:00
|
|
|
self.local_def_id(self.body_owner(id))
|
2016-12-20 23:05:21 +02:00
|
|
|
}
|
|
|
|
|
2019-06-14 12:28:47 +02:00
|
|
|
/// Given a `HirId`, returns the `BodyId` associated with it,
|
2017-04-24 22:03:47 +03:00
|
|
|
/// if the node is a body owner, otherwise returns `None`.
|
2019-06-14 18:58:55 +02:00
|
|
|
pub fn maybe_body_owned_by(&self, hir_id: HirId) -> Option<BodyId> {
|
2020-05-14 23:07:46 +08:00
|
|
|
self.find(hir_id).map(associated_body).flatten()
|
2017-04-04 12:06:35 -04:00
|
|
|
}
|
|
|
|
|
2017-04-24 22:03:47 +03:00
|
|
|
/// Given a body owner's id, returns the `BodyId` associated with it.
|
2019-03-04 09:00:30 +01:00
|
|
|
pub fn body_owned_by(&self, id: HirId) -> BodyId {
|
2019-06-14 18:58:55 +02:00
|
|
|
self.maybe_body_owned_by(id).unwrap_or_else(|| {
|
2019-12-22 17:42:04 -05:00
|
|
|
span_bug!(
|
|
|
|
self.span(id),
|
|
|
|
"body_owned_by: {} has no associated body",
|
|
|
|
self.node_to_string(id)
|
|
|
|
);
|
2017-04-24 22:03:47 +03:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-06-11 13:42:22 -04:00
|
|
|
pub fn body_param_names(&self, id: BodyId) -> impl Iterator<Item = Ident> + 'hir {
|
|
|
|
self.body(id).params.iter().map(|arg| match arg.pat.kind {
|
|
|
|
PatKind::Binding(_, _, ident, _) => ident,
|
2020-12-29 20:28:08 -05:00
|
|
|
_ => Ident::new(kw::Empty, rustc_span::DUMMY_SP),
|
2020-06-11 13:42:22 -04:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-05-07 10:22:35 -07:00
|
|
|
/// Returns the `BodyOwnerKind` of this `LocalDefId`.
|
|
|
|
///
|
|
|
|
/// Panics if `LocalDefId` does not have an associated body.
|
2019-06-14 18:58:55 +02:00
|
|
|
pub fn body_owner_kind(&self, id: HirId) -> BodyOwnerKind {
|
2019-06-20 10:39:19 +02:00
|
|
|
match self.get(id) {
|
2019-12-22 17:42:04 -05:00
|
|
|
Node::Item(&Item { kind: ItemKind::Const(..), .. })
|
|
|
|
| Node::TraitItem(&TraitItem { kind: TraitItemKind::Const(..), .. })
|
|
|
|
| Node::ImplItem(&ImplItem { kind: ImplItemKind::Const(..), .. })
|
|
|
|
| Node::AnonConst(_) => BodyOwnerKind::Const,
|
|
|
|
Node::Ctor(..)
|
|
|
|
| Node::Item(&Item { kind: ItemKind::Fn(..), .. })
|
2020-03-03 12:46:22 -06:00
|
|
|
| Node::TraitItem(&TraitItem { kind: TraitItemKind::Fn(..), .. })
|
2020-03-05 09:57:34 -06:00
|
|
|
| Node::ImplItem(&ImplItem { kind: ImplItemKind::Fn(..), .. }) => BodyOwnerKind::Fn,
|
2019-12-22 17:42:04 -05:00
|
|
|
Node::Item(&Item { kind: ItemKind::Static(_, m, _), .. }) => BodyOwnerKind::Static(m),
|
|
|
|
Node::Expr(&Expr { kind: ExprKind::Closure(..), .. }) => BodyOwnerKind::Closure,
|
2018-12-07 18:25:55 +01:00
|
|
|
node => bug!("{:#?} is not a body node", node),
|
2017-11-10 19:20:35 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-07 10:22:35 -07:00
|
|
|
/// Returns the `ConstContext` of the body associated with this `LocalDefId`.
|
|
|
|
///
|
|
|
|
/// Panics if `LocalDefId` does not have an associated body.
|
2021-07-10 11:16:03 +08:00
|
|
|
///
|
|
|
|
/// This should only be used for determining the context of a body, a return
|
|
|
|
/// value of `Some` does not always suggest that the owner of the body is `const`.
|
2020-05-07 10:22:35 -07:00
|
|
|
pub fn body_const_context(&self, did: LocalDefId) -> Option<ConstContext> {
|
|
|
|
let hir_id = self.local_def_id_to_hir_id(did);
|
|
|
|
let ccx = match self.body_owner_kind(hir_id) {
|
|
|
|
BodyOwnerKind::Const => ConstContext::Const,
|
|
|
|
BodyOwnerKind::Static(mt) => ConstContext::Static(mt),
|
|
|
|
|
|
|
|
BodyOwnerKind::Fn if self.tcx.is_constructor(did.to_def_id()) => return None,
|
|
|
|
BodyOwnerKind::Fn if self.tcx.is_const_fn_raw(did.to_def_id()) => ConstContext::ConstFn,
|
2021-07-10 11:16:03 +08:00
|
|
|
BodyOwnerKind::Fn
|
|
|
|
if self.tcx.has_attr(did.to_def_id(), sym::default_method_body_is_const) =>
|
|
|
|
{
|
|
|
|
ConstContext::ConstFn
|
|
|
|
}
|
2020-05-07 10:22:35 -07:00
|
|
|
BodyOwnerKind::Fn | BodyOwnerKind::Closure => return None,
|
|
|
|
};
|
|
|
|
|
|
|
|
Some(ccx)
|
|
|
|
}
|
|
|
|
|
2021-09-12 11:33:16 +02:00
|
|
|
/// Returns an iterator of the `DefId`s for all body-owners in this
|
|
|
|
/// crate. If you would prefer to iterate over the bodies
|
|
|
|
/// themselves, you can do `self.hir().krate().body_ids.iter()`.
|
|
|
|
pub fn body_owners(self) -> impl Iterator<Item = LocalDefId> + 'hir {
|
2021-07-16 14:42:26 +02:00
|
|
|
self.krate()
|
|
|
|
.owners
|
|
|
|
.iter_enumerated()
|
|
|
|
.flat_map(move |(owner, owner_info)| {
|
|
|
|
let bodies = &owner_info.as_ref()?.bodies;
|
2021-09-17 19:41:05 +02:00
|
|
|
Some(bodies.iter_enumerated().filter_map(move |(local_id, body)| {
|
|
|
|
if body.is_none() {
|
|
|
|
return None;
|
|
|
|
}
|
2021-07-16 14:42:26 +02:00
|
|
|
let hir_id = HirId { owner, local_id };
|
|
|
|
let body_id = BodyId { hir_id };
|
2021-09-17 19:41:05 +02:00
|
|
|
Some(self.body_owner_def_id(body_id))
|
2021-07-16 14:42:26 +02:00
|
|
|
}))
|
|
|
|
})
|
|
|
|
.flatten()
|
2021-09-12 11:33:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn par_body_owners<F: Fn(LocalDefId) + Sync + Send>(self, f: F) {
|
2021-07-16 14:42:26 +02:00
|
|
|
use rustc_data_structures::sync::{par_iter, ParallelIterator};
|
|
|
|
#[cfg(parallel_compiler)]
|
|
|
|
use rustc_rayon::iter::IndexedParallelIterator;
|
|
|
|
|
|
|
|
par_iter(&self.krate().owners.raw).enumerate().for_each(|(owner, owner_info)| {
|
|
|
|
let owner = LocalDefId::new(owner);
|
|
|
|
if let Some(owner_info) = owner_info {
|
2021-09-17 19:41:05 +02:00
|
|
|
par_iter(&owner_info.bodies.raw).enumerate().for_each(|(local_id, body)| {
|
|
|
|
if body.is_some() {
|
|
|
|
let local_id = ItemLocalId::new(local_id);
|
|
|
|
let hir_id = HirId { owner, local_id };
|
|
|
|
let body_id = BodyId { hir_id };
|
|
|
|
f(self.body_owner_def_id(body_id))
|
|
|
|
}
|
2021-07-16 14:42:26 +02:00
|
|
|
})
|
|
|
|
}
|
|
|
|
});
|
2021-09-12 11:33:16 +02:00
|
|
|
}
|
|
|
|
|
2019-03-04 09:00:30 +01:00
|
|
|
pub fn ty_param_owner(&self, id: HirId) -> HirId {
|
2019-06-20 10:39:19 +02:00
|
|
|
match self.get(id) {
|
2020-04-16 17:38:52 -07:00
|
|
|
Node::Item(&Item { kind: ItemKind::Trait(..) | ItemKind::TraitAlias(..), .. }) => id,
|
2019-06-24 09:46:38 +02:00
|
|
|
Node::GenericParam(_) => self.get_parent_node(id),
|
2019-12-22 17:42:04 -05:00
|
|
|
_ => bug!("ty_param_owner: {} not a type parameter", self.node_to_string(id)),
|
2017-02-11 19:26:13 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-19 13:00:18 +02:00
|
|
|
pub fn ty_param_name(&self, id: HirId) -> Symbol {
|
2019-06-20 10:39:19 +02:00
|
|
|
match self.get(id) {
|
2020-04-16 17:38:52 -07:00
|
|
|
Node::Item(&Item { kind: ItemKind::Trait(..) | ItemKind::TraitAlias(..), .. }) => {
|
|
|
|
kw::SelfUpper
|
|
|
|
}
|
2018-08-25 15:56:16 +01:00
|
|
|
Node::GenericParam(param) => param.name.ident().name,
|
2019-06-16 17:30:02 +02:00
|
|
|
_ => bug!("ty_param_name: {} not a type parameter", self.node_to_string(id)),
|
2017-02-11 19:26:13 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-01 11:12:49 +01:00
|
|
|
pub fn trait_impls(&self, trait_did: DefId) -> &'hir [LocalDefId] {
|
2021-05-11 11:42:01 +02:00
|
|
|
self.tcx.all_local_trait_impls(()).get(&trait_did).map_or(&[], |xs| &xs[..])
|
2017-02-19 14:46:29 +02:00
|
|
|
}
|
|
|
|
|
2019-02-08 14:53:55 +01:00
|
|
|
/// Gets the attributes on the crate. This is preferable to
|
2016-03-16 05:53:45 -04:00
|
|
|
/// invoking `krate.attrs` because it registers a tighter
|
|
|
|
/// dep-graph access.
|
2017-01-26 03:21:50 +02:00
|
|
|
pub fn krate_attrs(&self) -> &'hir [ast::Attribute] {
|
2020-11-24 18:12:42 +01:00
|
|
|
self.attrs(CRATE_HIR_ID)
|
2016-03-16 05:53:45 -04:00
|
|
|
}
|
|
|
|
|
2020-04-12 13:45:41 +01:00
|
|
|
pub fn get_module(&self, module: LocalDefId) -> (&'hir Mod<'hir>, Span, HirId) {
|
2021-03-27 13:56:22 +01:00
|
|
|
let hir_id = HirId::make_owner(module);
|
|
|
|
match self.tcx.hir_owner(module).map(|o| o.node) {
|
|
|
|
Some(OwnerNode::Item(&Item { span, kind: ItemKind::Mod(ref m), .. })) => {
|
|
|
|
(m, span, hir_id)
|
|
|
|
}
|
|
|
|
Some(OwnerNode::Crate(item)) => (item, item.inner, hir_id),
|
2019-08-21 16:11:01 -07:00
|
|
|
node => panic!("not a module: {:?}", node),
|
2018-06-08 19:14:03 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-26 18:42:08 +02:00
|
|
|
/// Walks the contents of a crate. See also `Crate::visit_all_items`.
|
2021-09-02 19:22:24 +02:00
|
|
|
pub fn walk_toplevel_module(self, visitor: &mut impl Visitor<'hir>) {
|
2021-08-26 18:42:08 +02:00
|
|
|
let (top_mod, span, hir_id) = self.get_module(CRATE_DEF_ID);
|
|
|
|
visitor.visit_mod(top_mod, span, hir_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Walks the attributes in a crate.
|
|
|
|
pub fn walk_attributes(self, visitor: &mut impl Visitor<'hir>) {
|
|
|
|
let krate = self.krate();
|
2021-07-16 14:42:26 +02:00
|
|
|
for (owner, info) in krate.owners.iter_enumerated() {
|
|
|
|
if let Some(info) = info {
|
|
|
|
for (&local_id, attrs) in info.attrs.iter() {
|
|
|
|
let id = HirId { owner, local_id };
|
|
|
|
for a in *attrs {
|
|
|
|
visitor.visit_attribute(id, a)
|
|
|
|
}
|
|
|
|
}
|
2021-08-26 18:42:08 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-12 01:11:22 +02:00
|
|
|
/// Visits all items in the crate in some deterministic (but
|
|
|
|
/// unspecified) order. If you just need to process every item,
|
|
|
|
/// but don't care about nesting, this method is the best choice.
|
|
|
|
///
|
|
|
|
/// If you do care about nesting -- usually because your algorithm
|
|
|
|
/// follows lexical scoping rules -- then you want a different
|
|
|
|
/// approach. You should override `visit_nested_item` in your
|
|
|
|
/// visitor and then call `intravisit::walk_crate` instead.
|
|
|
|
pub fn visit_all_item_likes<V>(&self, visitor: &mut V)
|
|
|
|
where
|
|
|
|
V: itemlikevisit::ItemLikeVisitor<'hir>,
|
|
|
|
{
|
|
|
|
let krate = self.krate();
|
|
|
|
for owner in krate.owners.iter().filter_map(Option::as_ref) {
|
2021-07-16 14:42:26 +02:00
|
|
|
match owner.node {
|
2021-09-12 01:11:22 +02:00
|
|
|
OwnerNode::Item(item) => visitor.visit_item(item),
|
|
|
|
OwnerNode::ForeignItem(item) => visitor.visit_foreign_item(item),
|
|
|
|
OwnerNode::ImplItem(item) => visitor.visit_impl_item(item),
|
|
|
|
OwnerNode::TraitItem(item) => visitor.visit_trait_item(item),
|
|
|
|
OwnerNode::Crate(_) => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A parallel version of `visit_all_item_likes`.
|
|
|
|
pub fn par_visit_all_item_likes<V>(&self, visitor: &V)
|
|
|
|
where
|
|
|
|
V: itemlikevisit::ParItemLikeVisitor<'hir> + Sync + Send,
|
|
|
|
{
|
|
|
|
let krate = self.krate();
|
2021-07-16 14:42:26 +02:00
|
|
|
par_for_each_in(&krate.owners.raw, |owner| match owner.as_ref().map(|o| o.node) {
|
2021-09-12 01:11:22 +02:00
|
|
|
Some(OwnerNode::Item(item)) => visitor.visit_item(item),
|
|
|
|
Some(OwnerNode::ForeignItem(item)) => visitor.visit_foreign_item(item),
|
|
|
|
Some(OwnerNode::ImplItem(item)) => visitor.visit_impl_item(item),
|
|
|
|
Some(OwnerNode::TraitItem(item)) => visitor.visit_trait_item(item),
|
|
|
|
Some(OwnerNode::Crate(_)) | None => {}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-06-27 13:09:54 +02:00
|
|
|
pub fn visit_item_likes_in_module<V>(&self, module: LocalDefId, visitor: &mut V)
|
2019-12-22 17:42:04 -05:00
|
|
|
where
|
|
|
|
V: ItemLikeVisitor<'hir>,
|
2018-06-06 22:13:52 +02:00
|
|
|
{
|
2020-06-27 13:09:54 +02:00
|
|
|
let module = self.tcx.hir_module_items(module);
|
2018-06-06 22:13:52 +02:00
|
|
|
|
2021-09-07 20:07:33 +02:00
|
|
|
for id in module.items.iter() {
|
2021-01-30 12:06:04 +01:00
|
|
|
visitor.visit_item(self.item(*id));
|
2018-06-06 22:13:52 +02:00
|
|
|
}
|
|
|
|
|
2021-09-07 20:07:33 +02:00
|
|
|
for id in module.trait_items.iter() {
|
2021-01-30 12:06:04 +01:00
|
|
|
visitor.visit_trait_item(self.trait_item(*id));
|
2018-06-06 22:13:52 +02:00
|
|
|
}
|
|
|
|
|
2021-09-07 20:07:33 +02:00
|
|
|
for id in module.impl_items.iter() {
|
2021-01-30 12:06:04 +01:00
|
|
|
visitor.visit_impl_item(self.impl_item(*id));
|
2018-06-06 22:13:52 +02:00
|
|
|
}
|
2020-11-11 21:57:54 +01:00
|
|
|
|
2021-09-07 20:07:33 +02:00
|
|
|
for id in module.foreign_items.iter() {
|
2021-01-30 12:06:04 +01:00
|
|
|
visitor.visit_foreign_item(self.foreign_item(*id));
|
2020-11-11 21:57:54 +01:00
|
|
|
}
|
2018-06-06 22:13:52 +02:00
|
|
|
}
|
|
|
|
|
2021-07-18 18:12:17 +02:00
|
|
|
pub fn for_each_module(&self, f: impl Fn(LocalDefId)) {
|
2021-09-07 20:07:33 +02:00
|
|
|
let mut queue = VecDeque::new();
|
|
|
|
queue.push_back(CRATE_DEF_ID);
|
2021-07-18 18:12:17 +02:00
|
|
|
|
2021-09-07 20:07:33 +02:00
|
|
|
while let Some(id) = queue.pop_front() {
|
2021-07-18 18:12:17 +02:00
|
|
|
f(id);
|
|
|
|
let items = self.tcx.hir_module_items(id);
|
|
|
|
queue.extend(items.submodules.iter().copied())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-08 17:24:03 +02:00
|
|
|
#[cfg(not(parallel_compiler))]
|
|
|
|
#[inline]
|
|
|
|
pub fn par_for_each_module(&self, f: impl Fn(LocalDefId)) {
|
|
|
|
self.for_each_module(f)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(parallel_compiler)]
|
|
|
|
pub fn par_for_each_module(&self, f: impl Fn(LocalDefId) + Sync) {
|
|
|
|
use rustc_data_structures::sync::{par_iter, ParallelIterator};
|
2021-07-18 18:12:17 +02:00
|
|
|
par_iter_submodules(self.tcx, CRATE_DEF_ID, &f);
|
|
|
|
|
|
|
|
fn par_iter_submodules<F>(tcx: TyCtxt<'_>, module: LocalDefId, f: &F)
|
|
|
|
where
|
2021-09-08 17:24:03 +02:00
|
|
|
F: Fn(LocalDefId) + Sync,
|
2021-07-18 18:12:17 +02:00
|
|
|
{
|
|
|
|
(*f)(module);
|
|
|
|
let items = tcx.hir_module_items(module);
|
2021-09-07 20:07:33 +02:00
|
|
|
par_iter(&items.submodules[..]).for_each(|&sm| par_iter_submodules(tcx, sm, f));
|
2021-07-18 18:12:17 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-25 05:30:11 +01:00
|
|
|
/// Returns an iterator for the nodes in the ancestor tree of the `current_id`
|
|
|
|
/// until the crate root is reached. Prefer this over your own loop using `get_parent_node`.
|
2021-09-18 15:48:07 -05:00
|
|
|
pub fn parent_iter(self, current_id: HirId) -> ParentHirIterator<'hir> {
|
2020-02-25 05:30:11 +01:00
|
|
|
ParentHirIterator { current_id, map: self }
|
|
|
|
}
|
|
|
|
|
2021-03-03 21:50:45 +01:00
|
|
|
/// Returns an iterator for the nodes in the ancestor tree of the `current_id`
|
|
|
|
/// until the crate root is reached. Prefer this over your own loop using `get_parent_node`.
|
2021-09-18 15:48:07 -05:00
|
|
|
pub fn parent_owner_iter(self, current_id: HirId) -> ParentOwnerIterator<'hir> {
|
2021-03-03 21:50:45 +01:00
|
|
|
ParentOwnerIterator { current_id, map: self }
|
|
|
|
}
|
|
|
|
|
2021-01-24 10:32:24 +03:00
|
|
|
/// Checks if the node is left-hand side of an assignment.
|
|
|
|
pub fn is_lhs(&self, id: HirId) -> bool {
|
|
|
|
match self.find(self.get_parent_node(id)) {
|
|
|
|
Some(Node::Expr(expr)) => match expr.kind {
|
|
|
|
ExprKind::Assign(lhs, _rhs, _span) => lhs.hir_id == id,
|
|
|
|
_ => false,
|
|
|
|
},
|
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-13 11:24:08 -07:00
|
|
|
/// Whether the expression pointed at by `hir_id` belongs to a `const` evaluation context.
|
|
|
|
/// Used exclusively for diagnostics, to avoid suggestion function calls.
|
2020-05-20 20:10:04 +02:00
|
|
|
pub fn is_inside_const_context(&self, hir_id: HirId) -> bool {
|
2020-05-20 14:57:16 +02:00
|
|
|
self.body_const_context(self.local_def_id(self.enclosing_body_owner(hir_id))).is_some()
|
2019-04-29 17:14:31 -07:00
|
|
|
}
|
|
|
|
|
2019-06-16 17:44:19 +02:00
|
|
|
/// Retrieves the `HirId` for `id`'s enclosing method, unless there's a
|
2017-08-01 19:13:47 -07:00
|
|
|
/// `while` or `loop` before reaching it, as block tail returns are not
|
2017-06-27 13:34:56 -07:00
|
|
|
/// available in them.
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// fn foo(x: usize) -> bool {
|
|
|
|
/// if x == 1 {
|
2019-09-06 03:57:44 +01:00
|
|
|
/// true // If `get_return_block` gets passed the `id` corresponding
|
2019-06-16 17:44:19 +02:00
|
|
|
/// } else { // to this, it will return `foo`'s `HirId`.
|
2017-06-27 13:34:56 -07:00
|
|
|
/// false
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// fn foo(x: usize) -> bool {
|
|
|
|
/// loop {
|
2019-09-06 03:57:44 +01:00
|
|
|
/// true // If `get_return_block` gets passed the `id` corresponding
|
2017-06-27 13:34:56 -07:00
|
|
|
/// } // to this, it will return `None`.
|
|
|
|
/// false
|
|
|
|
/// }
|
|
|
|
/// ```
|
2019-02-24 09:33:17 +01:00
|
|
|
pub fn get_return_block(&self, id: HirId) -> Option<HirId> {
|
2020-02-25 05:30:11 +01:00
|
|
|
let mut iter = self.parent_iter(id).peekable();
|
2019-09-25 23:01:01 -07:00
|
|
|
let mut ignore_tail = false;
|
2021-03-03 21:50:45 +01:00
|
|
|
if let Some(node) = self.find(id) {
|
|
|
|
if let Node::Expr(Expr { kind: ExprKind::Ret(_), .. }) = node {
|
2019-09-25 23:01:01 -07:00
|
|
|
// When dealing with `return` statements, we don't care about climbing only tail
|
|
|
|
// expressions.
|
|
|
|
ignore_tail = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while let Some((hir_id, node)) = iter.next() {
|
|
|
|
if let (Some((_, next_node)), false) = (iter.peek(), ignore_tail) {
|
|
|
|
match next_node {
|
|
|
|
Node::Block(Block { expr: None, .. }) => return None,
|
2020-03-24 06:17:44 +01:00
|
|
|
// The current node is not the tail expression of its parent.
|
|
|
|
Node::Block(Block { expr: Some(e), .. }) if hir_id != e.hir_id => return None,
|
2019-09-25 23:01:01 -07:00
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
2019-09-25 17:05:30 -07:00
|
|
|
match node {
|
2019-12-22 17:42:04 -05:00
|
|
|
Node::Item(_)
|
|
|
|
| Node::ForeignItem(_)
|
|
|
|
| Node::TraitItem(_)
|
|
|
|
| Node::Expr(Expr { kind: ExprKind::Closure(..), .. })
|
|
|
|
| Node::ImplItem(_) => return Some(hir_id),
|
2020-03-24 06:17:44 +01:00
|
|
|
// Ignore `return`s on the first iteration
|
|
|
|
Node::Expr(Expr { kind: ExprKind::Loop(..) | ExprKind::Ret(..), .. })
|
|
|
|
| Node::Local(_) => {
|
|
|
|
return None;
|
2017-06-24 00:57:39 -07:00
|
|
|
}
|
2019-09-25 17:05:30 -07:00
|
|
|
_ => {}
|
2017-06-24 00:57:39 -07:00
|
|
|
}
|
2019-09-25 17:05:30 -07:00
|
|
|
}
|
|
|
|
None
|
2017-06-24 00:57:39 -07:00
|
|
|
}
|
|
|
|
|
2019-06-14 12:28:47 +02:00
|
|
|
/// Retrieves the `HirId` for `id`'s parent item, or `id` itself if no
|
2015-07-01 08:58:48 +12:00
|
|
|
/// parent item is in this map. The "parent item" is the closest parent node
|
2018-06-13 09:11:23 +02:00
|
|
|
/// in the HIR which is recorded by the map and is an item, either an item
|
2015-07-01 08:58:48 +12:00
|
|
|
/// in a module, trait, or impl.
|
2019-03-09 08:57:35 +01:00
|
|
|
pub fn get_parent_item(&self, hir_id: HirId) -> HirId {
|
2021-03-27 13:56:22 +01:00
|
|
|
if let Some((hir_id, _node)) = self.parent_owner_iter(hir_id).next() {
|
|
|
|
hir_id
|
|
|
|
} else {
|
|
|
|
CRATE_HIR_ID
|
2015-07-01 08:58:48 +12:00
|
|
|
}
|
2015-06-16 21:56:33 +12:00
|
|
|
}
|
|
|
|
|
2019-03-09 08:57:35 +01:00
|
|
|
/// Returns the `HirId` of `id`'s nearest module parent, or `id` itself if no
|
2018-09-19 09:28:49 -05:00
|
|
|
/// module parent is in this map.
|
2020-02-22 19:53:10 +01:00
|
|
|
pub(super) fn get_module_parent_node(&self, hir_id: HirId) -> HirId {
|
2021-03-03 21:50:45 +01:00
|
|
|
for (hir_id, node) in self.parent_owner_iter(hir_id) {
|
2021-03-27 13:56:22 +01:00
|
|
|
if let OwnerNode::Item(&Item { kind: ItemKind::Mod(_), .. }) = node {
|
2019-09-25 17:05:30 -07:00
|
|
|
return hir_id;
|
|
|
|
}
|
2018-09-19 09:28:49 -05:00
|
|
|
}
|
2019-09-25 17:05:30 -07:00
|
|
|
CRATE_HIR_ID
|
2016-02-25 01:55:54 +00:00
|
|
|
}
|
|
|
|
|
2021-01-01 15:38:11 -03:00
|
|
|
/// When on an if expression, a match arm tail expression or a match arm, give back
|
|
|
|
/// the enclosing `if` or `match` expression.
|
2019-09-27 18:35:34 -07:00
|
|
|
///
|
2021-01-01 15:38:11 -03:00
|
|
|
/// Used by error reporting when there's a type error in an if or match arm caused by the
|
2019-09-27 18:35:34 -07:00
|
|
|
/// expression needing to be unit.
|
2021-01-01 15:38:11 -03:00
|
|
|
pub fn get_if_cause(&self, hir_id: HirId) -> Option<&'hir Expr<'hir>> {
|
2020-02-25 05:30:11 +01:00
|
|
|
for (_, node) in self.parent_iter(hir_id) {
|
2019-09-26 17:16:34 -07:00
|
|
|
match node {
|
2020-03-24 06:17:44 +01:00
|
|
|
Node::Item(_)
|
|
|
|
| Node::ForeignItem(_)
|
|
|
|
| Node::TraitItem(_)
|
|
|
|
| Node::ImplItem(_)
|
|
|
|
| Node::Stmt(Stmt { kind: StmtKind::Local(_), .. }) => break,
|
2021-01-01 15:38:11 -03:00
|
|
|
Node::Expr(expr @ Expr { kind: ExprKind::If(..) | ExprKind::Match(..), .. }) => {
|
|
|
|
return Some(expr);
|
|
|
|
}
|
2019-09-26 17:16:34 -07:00
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
|
|
|
|
2019-02-28 22:43:53 +00:00
|
|
|
/// Returns the nearest enclosing scope. A scope is roughly an item or block.
|
2019-05-04 16:09:28 +01:00
|
|
|
pub fn get_enclosing_scope(&self, hir_id: HirId) -> Option<HirId> {
|
2020-02-25 05:30:11 +01:00
|
|
|
for (hir_id, node) in self.parent_iter(hir_id) {
|
2020-03-24 06:17:44 +01:00
|
|
|
if let Node::Item(Item {
|
|
|
|
kind:
|
2019-12-22 17:42:04 -05:00
|
|
|
ItemKind::Fn(..)
|
2020-05-10 11:57:58 +01:00
|
|
|
| ItemKind::Const(..)
|
|
|
|
| ItemKind::Static(..)
|
2019-12-22 17:42:04 -05:00
|
|
|
| ItemKind::Mod(..)
|
|
|
|
| ItemKind::Enum(..)
|
|
|
|
| ItemKind::Struct(..)
|
|
|
|
| ItemKind::Union(..)
|
|
|
|
| ItemKind::Trait(..)
|
2020-03-24 06:17:44 +01:00
|
|
|
| ItemKind::Impl { .. },
|
|
|
|
..
|
|
|
|
})
|
|
|
|
| Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(..), .. })
|
|
|
|
| Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(..), .. })
|
|
|
|
| Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(..), .. })
|
|
|
|
| Node::Block(_) = node
|
|
|
|
{
|
2019-09-25 17:05:30 -07:00
|
|
|
return Some(hir_id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None
|
2015-06-16 22:20:30 +12:00
|
|
|
}
|
|
|
|
|
2019-08-01 00:41:54 +01:00
|
|
|
/// Returns the defining scope for an opaque type definition.
|
2019-09-26 14:38:01 -07:00
|
|
|
pub fn get_defining_scope(&self, id: HirId) -> HirId {
|
2019-02-28 22:43:53 +00:00
|
|
|
let mut scope = id;
|
|
|
|
loop {
|
2019-09-25 17:05:30 -07:00
|
|
|
scope = self.get_enclosing_scope(scope).unwrap_or(CRATE_HIR_ID);
|
2021-01-10 14:38:14 +01:00
|
|
|
if scope == CRATE_HIR_ID || !matches!(self.get(scope), Node::Block(_)) {
|
|
|
|
return scope;
|
2019-02-28 22:43:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-08 15:42:53 +01:00
|
|
|
pub fn get_parent_did(&self, id: HirId) -> LocalDefId {
|
2020-04-09 09:43:00 +01:00
|
|
|
self.local_def_id(self.get_parent_item(id))
|
2019-02-04 11:09:32 +01:00
|
|
|
}
|
|
|
|
|
2019-06-14 18:58:55 +02:00
|
|
|
pub fn get_foreign_abi(&self, hir_id: HirId) -> Abi {
|
2019-03-09 08:23:35 +01:00
|
|
|
let parent = self.get_parent_item(hir_id);
|
2021-03-27 13:56:22 +01:00
|
|
|
if let Some(node) = self.tcx.hir_owner(self.local_def_id(parent)) {
|
|
|
|
if let OwnerNode::Item(Item { kind: ItemKind::ForeignMod { abi, .. }, .. }) = node.node
|
|
|
|
{
|
2020-11-11 22:40:09 +01:00
|
|
|
return *abi;
|
2014-05-18 02:38:13 +03:00
|
|
|
}
|
2014-02-14 07:07:09 +02:00
|
|
|
}
|
2019-06-16 17:30:02 +02:00
|
|
|
bug!("expected foreign mod or inlined parent, found {}", self.node_to_string(parent))
|
2019-02-04 11:09:32 +01:00
|
|
|
}
|
|
|
|
|
2019-11-28 19:28:50 +01:00
|
|
|
pub fn expect_item(&self, id: HirId) -> &'hir Item<'hir> {
|
2021-03-27 13:56:22 +01:00
|
|
|
match self.tcx.hir_owner(id.expect_owner()) {
|
2021-09-19 22:17:50 +02:00
|
|
|
Some(Owner { node: OwnerNode::Item(item), .. }) => item,
|
2019-12-22 17:42:04 -05:00
|
|
|
_ => bug!("expected item, found {}", self.node_to_string(id)),
|
2019-03-07 15:46:41 +01:00
|
|
|
}
|
2019-02-03 09:14:31 +01:00
|
|
|
}
|
|
|
|
|
2019-11-28 22:16:44 +01:00
|
|
|
pub fn expect_impl_item(&self, id: HirId) -> &'hir ImplItem<'hir> {
|
2021-03-27 13:56:22 +01:00
|
|
|
match self.tcx.hir_owner(id.expect_owner()) {
|
2021-09-19 22:17:50 +02:00
|
|
|
Some(Owner { node: OwnerNode::ImplItem(item), .. }) => item,
|
2019-12-22 17:42:04 -05:00
|
|
|
_ => bug!("expected impl item, found {}", self.node_to_string(id)),
|
2016-08-10 01:43:12 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-28 21:47:10 +01:00
|
|
|
pub fn expect_trait_item(&self, id: HirId) -> &'hir TraitItem<'hir> {
|
2021-03-27 13:56:22 +01:00
|
|
|
match self.tcx.hir_owner(id.expect_owner()) {
|
2021-09-19 22:17:50 +02:00
|
|
|
Some(Owner { node: OwnerNode::TraitItem(item), .. }) => item,
|
2019-12-22 17:42:04 -05:00
|
|
|
_ => bug!("expected trait item, found {}", self.node_to_string(id)),
|
2014-04-03 13:38:45 +13:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-29 09:26:18 +01:00
|
|
|
pub fn expect_variant(&self, id: HirId) -> &'hir Variant<'hir> {
|
2019-06-24 09:58:49 +02:00
|
|
|
match self.find(id) {
|
2018-08-25 15:56:16 +01:00
|
|
|
Some(Node::Variant(variant)) => variant,
|
2019-06-16 17:30:02 +02:00
|
|
|
_ => bug!("expected variant, found {}", self.node_to_string(id)),
|
2014-04-08 21:00:20 +12:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-28 20:18:29 +01:00
|
|
|
pub fn expect_foreign_item(&self, id: HirId) -> &'hir ForeignItem<'hir> {
|
2021-03-27 13:56:22 +01:00
|
|
|
match self.tcx.hir_owner(id.expect_owner()) {
|
2021-09-19 22:17:50 +02:00
|
|
|
Some(Owner { node: OwnerNode::ForeignItem(item), .. }) => item,
|
2019-12-22 17:42:04 -05:00
|
|
|
_ => bug!("expected foreign item, found {}", self.node_to_string(id)),
|
2014-02-14 07:07:09 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-29 13:43:03 +01:00
|
|
|
pub fn expect_expr(&self, id: HirId) -> &'hir Expr<'hir> {
|
2019-12-22 17:42:04 -05:00
|
|
|
match self.find(id) {
|
2019-03-09 08:57:35 +01:00
|
|
|
Some(Node::Expr(expr)) => expr,
|
2019-12-22 17:42:04 -05:00
|
|
|
_ => bug!("expected expr, found {}", self.node_to_string(id)),
|
2019-03-09 08:57:35 +01:00
|
|
|
}
|
2019-02-04 11:09:32 +01:00
|
|
|
}
|
|
|
|
|
2020-04-19 13:00:18 +02:00
|
|
|
pub fn opt_name(&self, id: HirId) -> Option<Symbol> {
|
2019-12-13 15:27:55 -08:00
|
|
|
Some(match self.get(id) {
|
2018-12-01 02:47:08 +00:00
|
|
|
Node::Item(i) => i.ident.name,
|
|
|
|
Node::ForeignItem(fi) => fi.ident.name,
|
2018-08-25 15:56:16 +01:00
|
|
|
Node::ImplItem(ii) => ii.ident.name,
|
|
|
|
Node::TraitItem(ti) => ti.ident.name,
|
2019-08-13 21:40:21 -03:00
|
|
|
Node::Variant(v) => v.ident.name,
|
2018-08-25 15:56:16 +01:00
|
|
|
Node::Field(f) => f.ident.name,
|
|
|
|
Node::Lifetime(lt) => lt.name.ident().name,
|
|
|
|
Node::GenericParam(param) => param.name.ident().name,
|
2019-09-26 16:18:31 +01:00
|
|
|
Node::Binding(&Pat { kind: PatKind::Binding(_, _, l, _), .. }) => l.name,
|
2019-06-19 15:44:51 +02:00
|
|
|
Node::Ctor(..) => self.name(self.get_parent_item(id)),
|
2019-12-13 15:27:55 -08:00
|
|
|
_ => return None,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-04-19 13:00:18 +02:00
|
|
|
pub fn name(&self, id: HirId) -> Symbol {
|
2019-12-13 15:27:55 -08:00
|
|
|
match self.opt_name(id) {
|
|
|
|
Some(name) => name,
|
|
|
|
None => bug!("no name for {}", self.node_to_string(id)),
|
2014-02-14 07:07:09 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-28 22:43:53 +00:00
|
|
|
/// Given a node ID, gets a list of attributes associated with the AST
|
|
|
|
/// corresponding to the node-ID.
|
2019-06-14 18:58:55 +02:00
|
|
|
pub fn attrs(&self, id: HirId) -> &'hir [ast::Attribute] {
|
2021-01-24 17:14:17 +01:00
|
|
|
self.tcx.hir_attrs(id.owner).get(id.local_id)
|
2014-02-14 07:07:09 +02:00
|
|
|
}
|
|
|
|
|
2020-08-12 17:02:14 -04:00
|
|
|
/// Gets the span of the definition of the specified HIR node.
|
|
|
|
/// This is used by `tcx.get_span`
|
2019-06-14 18:58:55 +02:00
|
|
|
pub fn span(&self, hir_id: HirId) -> Span {
|
2020-12-23 10:32:00 +01:00
|
|
|
self.opt_span(hir_id)
|
|
|
|
.unwrap_or_else(|| bug!("hir::map::Map::span: id not in map: {:?}", hir_id))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn opt_span(&self, hir_id: HirId) -> Option<Span> {
|
2021-03-03 21:50:45 +01:00
|
|
|
let span = match self.find(hir_id)? {
|
2020-12-23 10:32:00 +01:00
|
|
|
Node::Param(param) => param.span,
|
|
|
|
Node::Item(item) => match &item.kind {
|
2020-08-12 17:02:14 -04:00
|
|
|
ItemKind::Fn(sig, _, _) => sig.span,
|
|
|
|
_ => item.span,
|
|
|
|
},
|
2020-12-23 10:32:00 +01:00
|
|
|
Node::ForeignItem(foreign_item) => foreign_item.span,
|
|
|
|
Node::TraitItem(trait_item) => match &trait_item.kind {
|
2020-08-12 17:02:14 -04:00
|
|
|
TraitItemKind::Fn(sig, _) => sig.span,
|
|
|
|
_ => trait_item.span,
|
|
|
|
},
|
2020-12-23 10:32:00 +01:00
|
|
|
Node::ImplItem(impl_item) => match &impl_item.kind {
|
2020-08-12 17:02:14 -04:00
|
|
|
ImplItemKind::Fn(sig, _) => sig.span,
|
|
|
|
_ => impl_item.span,
|
|
|
|
},
|
2020-12-23 10:32:00 +01:00
|
|
|
Node::Variant(variant) => variant.span,
|
|
|
|
Node::Field(field) => field.span,
|
|
|
|
Node::AnonConst(constant) => self.body(constant.body).value.span,
|
|
|
|
Node::Expr(expr) => expr.span,
|
|
|
|
Node::Stmt(stmt) => stmt.span,
|
|
|
|
Node::PathSegment(seg) => seg.ident.span,
|
|
|
|
Node::Ty(ty) => ty.span,
|
|
|
|
Node::TraitRef(tr) => tr.path.span,
|
|
|
|
Node::Binding(pat) => pat.span,
|
|
|
|
Node::Pat(pat) => pat.span,
|
|
|
|
Node::Arm(arm) => arm.span,
|
|
|
|
Node::Block(block) => block.span,
|
|
|
|
Node::Ctor(..) => match self.find(self.get_parent_node(hir_id))? {
|
|
|
|
Node::Item(item) => item.span,
|
|
|
|
Node::Variant(variant) => variant.span,
|
2019-03-24 18:21:59 +01:00
|
|
|
_ => unreachable!(),
|
2019-12-22 17:42:04 -05:00
|
|
|
},
|
2020-12-23 10:32:00 +01:00
|
|
|
Node::Lifetime(lifetime) => lifetime.span,
|
|
|
|
Node::GenericParam(param) => param.span,
|
|
|
|
Node::Visibility(&Spanned {
|
2019-12-22 17:42:04 -05:00
|
|
|
node: VisibilityKind::Restricted { ref path, .. },
|
|
|
|
..
|
2020-12-23 10:32:00 +01:00
|
|
|
}) => path.span,
|
2021-04-24 21:41:57 +00:00
|
|
|
Node::Infer(i) => i.span,
|
2020-12-23 10:32:00 +01:00
|
|
|
Node::Visibility(v) => bug!("unexpected Visibility {:?}", v),
|
|
|
|
Node::Local(local) => local.span,
|
2021-03-30 20:31:06 +02:00
|
|
|
Node::Crate(item) => item.inner,
|
2020-12-23 10:32:00 +01:00
|
|
|
};
|
|
|
|
Some(span)
|
2014-02-14 07:07:09 +02:00
|
|
|
}
|
|
|
|
|
2020-08-12 17:02:14 -04:00
|
|
|
/// Like `hir.span()`, but includes the body of function items
|
|
|
|
/// (instead of just the function header)
|
|
|
|
pub fn span_with_body(&self, hir_id: HirId) -> Span {
|
2021-03-03 21:50:45 +01:00
|
|
|
match self.find(hir_id) {
|
2020-08-12 17:02:14 -04:00
|
|
|
Some(Node::TraitItem(item)) => item.span,
|
|
|
|
Some(Node::ImplItem(impl_item)) => impl_item.span,
|
|
|
|
Some(Node::Item(item)) => item.span,
|
|
|
|
Some(_) => self.span(hir_id),
|
|
|
|
_ => bug!("hir::map::Map::span_with_body: id not in map: {:?}", hir_id),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-04 13:52:28 -04:00
|
|
|
pub fn span_if_local(&self, id: DefId) -> Option<Span> {
|
2020-12-23 10:32:00 +01:00
|
|
|
id.as_local().and_then(|id| self.opt_span(self.local_def_id_to_hir_id(id)))
|
2015-09-04 13:52:28 -04:00
|
|
|
}
|
|
|
|
|
2019-09-28 02:30:48 +02:00
|
|
|
pub fn res_span(&self, res: Res) -> Option<Span> {
|
|
|
|
match res {
|
|
|
|
Res::Err => None,
|
|
|
|
Res::Local(id) => Some(self.span(id)),
|
|
|
|
res => self.span_if_local(res.opt_def_id()?),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-24 02:44:41 +01:00
|
|
|
/// Get a representation of this `id` for debugging purposes.
|
|
|
|
/// NOTE: Do NOT use this in diagnostics!
|
2019-06-16 17:30:02 +02:00
|
|
|
pub fn node_to_string(&self, id: HirId) -> String {
|
2020-03-24 02:44:41 +01:00
|
|
|
hir_id_to_string(self, id)
|
2019-02-03 09:14:31 +01:00
|
|
|
}
|
2021-07-13 17:23:26 +01:00
|
|
|
|
|
|
|
/// Returns the HirId of `N` in `struct Foo<const N: usize = { ... }>` when
|
|
|
|
/// called with the HirId for the `{ ... }` anon const
|
|
|
|
pub fn opt_const_param_default_param_hir_id(&self, anon_const: HirId) -> Option<HirId> {
|
|
|
|
match self.get(self.get_parent_node(anon_const)) {
|
|
|
|
Node::GenericParam(GenericParam {
|
|
|
|
hir_id: param_id,
|
|
|
|
kind: GenericParamKind::Const { .. },
|
|
|
|
..
|
|
|
|
}) => Some(*param_id),
|
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
2014-01-17 23:23:09 +11:00
|
|
|
}
|
2013-02-04 14:02:01 -08:00
|
|
|
|
2020-01-07 17:25:33 +01:00
|
|
|
impl<'hir> intravisit::Map<'hir> for Map<'hir> {
|
2020-03-24 02:44:41 +01:00
|
|
|
fn find(&self, hir_id: HirId) -> Option<Node<'hir>> {
|
|
|
|
self.find(hir_id)
|
|
|
|
}
|
|
|
|
|
2020-01-07 17:25:33 +01:00
|
|
|
fn body(&self, id: BodyId) -> &'hir Body<'hir> {
|
|
|
|
self.body(id)
|
|
|
|
}
|
|
|
|
|
2021-01-30 12:06:04 +01:00
|
|
|
fn item(&self, id: ItemId) -> &'hir Item<'hir> {
|
2020-01-07 17:25:33 +01:00
|
|
|
self.item(id)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir> {
|
|
|
|
self.trait_item(id)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir> {
|
|
|
|
self.impl_item(id)
|
|
|
|
}
|
2020-11-11 21:57:54 +01:00
|
|
|
|
|
|
|
fn foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir> {
|
|
|
|
self.foreign_item(id)
|
|
|
|
}
|
2020-01-07 17:25:33 +01:00
|
|
|
}
|
|
|
|
|
2021-02-28 20:23:10 +01:00
|
|
|
pub(super) fn index_hir<'tcx>(
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
owner: LocalDefId,
|
|
|
|
) -> Option<&'tcx IndexedHir<'tcx>> {
|
|
|
|
let map = collector::collect(
|
2021-04-04 14:40:35 +02:00
|
|
|
tcx.sess,
|
|
|
|
tcx.untracked_crate,
|
|
|
|
&tcx.untracked_resolutions.definitions,
|
2021-02-28 20:23:10 +01:00
|
|
|
owner,
|
|
|
|
)?;
|
2014-01-17 23:23:09 +11:00
|
|
|
|
2021-02-28 20:23:10 +01:00
|
|
|
Some(&*tcx.arena.alloc(map))
|
2021-02-28 18:58:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
|
2021-02-28 20:23:10 +01:00
|
|
|
debug_assert_eq!(crate_num, LOCAL_CRATE);
|
2021-02-28 18:58:50 +01:00
|
|
|
let mut hir_body_nodes: Vec<_> = tcx
|
2021-02-28 20:23:10 +01:00
|
|
|
.untracked_resolutions
|
|
|
|
.definitions
|
|
|
|
.def_path_table()
|
|
|
|
.all_def_path_hashes_and_def_ids()
|
|
|
|
.filter_map(|(def_path_hash, local_def_index)| {
|
|
|
|
let def_id = LocalDefId { local_def_index };
|
|
|
|
let hash = tcx.index_hir(def_id).as_ref()?.nodes.hash;
|
2021-05-02 12:16:59 +02:00
|
|
|
Some((def_path_hash, hash, def_id))
|
2021-02-28 18:58:50 +01:00
|
|
|
})
|
|
|
|
.collect();
|
|
|
|
hir_body_nodes.sort_unstable_by_key(|bn| bn.0);
|
|
|
|
|
2021-07-12 21:20:16 +02:00
|
|
|
let upstream_crates = upstream_crates(tcx);
|
2021-02-28 18:58:50 +01:00
|
|
|
|
|
|
|
// We hash the final, remapped names of all local source files so we
|
|
|
|
// don't have to include the path prefix remapping commandline args.
|
|
|
|
// If we included the full mapping in the SVH, we could only have
|
|
|
|
// reproducible builds by compiling from the same directory. So we just
|
|
|
|
// hash the result of the mapping instead of the mapping itself.
|
|
|
|
let mut source_file_names: Vec<_> = tcx
|
|
|
|
.sess
|
|
|
|
.source_map()
|
|
|
|
.files()
|
|
|
|
.iter()
|
|
|
|
.filter(|source_file| source_file.cnum == LOCAL_CRATE)
|
|
|
|
.map(|source_file| source_file.name_hash)
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
source_file_names.sort_unstable();
|
|
|
|
|
2021-02-28 20:23:10 +01:00
|
|
|
let mut hcx = tcx.create_stable_hashing_context();
|
2021-02-28 18:58:50 +01:00
|
|
|
let mut stable_hasher = StableHasher::new();
|
2021-05-02 12:16:59 +02:00
|
|
|
for (def_path_hash, fingerprint, def_id) in hir_body_nodes.iter() {
|
|
|
|
def_path_hash.0.hash_stable(&mut hcx, &mut stable_hasher);
|
|
|
|
fingerprint.hash_stable(&mut hcx, &mut stable_hasher);
|
2021-07-16 14:42:26 +02:00
|
|
|
tcx.untracked_crate.owners[*def_id]
|
|
|
|
.as_ref()
|
|
|
|
.unwrap()
|
|
|
|
.attrs
|
2021-05-02 12:16:59 +02:00
|
|
|
.hash_stable(&mut hcx, &mut stable_hasher);
|
|
|
|
if tcx.sess.opts.debugging_opts.incremental_relative_spans {
|
|
|
|
let span = tcx.untracked_resolutions.definitions.def_span(*def_id);
|
|
|
|
debug_assert_eq!(span.parent(), None);
|
|
|
|
span.hash_stable(&mut hcx, &mut stable_hasher);
|
|
|
|
}
|
|
|
|
}
|
2021-02-28 18:58:50 +01:00
|
|
|
upstream_crates.hash_stable(&mut hcx, &mut stable_hasher);
|
|
|
|
source_file_names.hash_stable(&mut hcx, &mut stable_hasher);
|
|
|
|
tcx.sess.opts.dep_tracking_hash(true).hash_stable(&mut hcx, &mut stable_hasher);
|
2021-06-08 18:36:30 +02:00
|
|
|
tcx.sess.local_stable_crate_id().hash_stable(&mut hcx, &mut stable_hasher);
|
2021-02-28 18:58:50 +01:00
|
|
|
|
|
|
|
let crate_hash: Fingerprint = stable_hasher.finish();
|
|
|
|
Svh::new(crate_hash.to_smaller_hash())
|
|
|
|
}
|
|
|
|
|
2021-07-12 21:20:16 +02:00
|
|
|
fn upstream_crates(tcx: TyCtxt<'_>) -> Vec<(StableCrateId, Svh)> {
|
|
|
|
let mut upstream_crates: Vec<_> = tcx
|
|
|
|
.crates(())
|
2021-02-28 18:58:50 +01:00
|
|
|
.iter()
|
|
|
|
.map(|&cnum| {
|
2021-07-12 21:20:16 +02:00
|
|
|
let stable_crate_id = tcx.resolutions(()).cstore.stable_crate_id(cnum);
|
|
|
|
let hash = tcx.crate_hash(cnum);
|
2021-06-08 18:36:30 +02:00
|
|
|
(stable_crate_id, hash)
|
2021-02-28 18:58:50 +01:00
|
|
|
})
|
|
|
|
.collect();
|
2021-06-08 18:36:30 +02:00
|
|
|
upstream_crates.sort_unstable_by_key(|&(stable_crate_id, _)| stable_crate_id);
|
2021-02-28 18:58:50 +01:00
|
|
|
upstream_crates
|
2011-06-19 22:41:21 +02:00
|
|
|
}
|
|
|
|
|
2020-03-24 02:44:41 +01:00
|
|
|
fn hir_id_to_string(map: &Map<'_>, id: HirId) -> String {
|
2019-04-27 22:39:17 +02:00
|
|
|
let id_str = format!(" (hir_id={})", id);
|
2014-09-19 15:38:53 +02:00
|
|
|
|
2016-04-06 13:51:55 +03:00
|
|
|
let path_str = || {
|
2019-09-06 03:57:44 +01:00
|
|
|
// This functionality is used for debugging, try to use `TyCtxt` to get
|
|
|
|
// the user-friendly path, otherwise fall back to stringifying `DefPath`.
|
2019-02-05 11:20:45 -06:00
|
|
|
crate::ty::tls::with_opt(|tcx| {
|
2016-04-06 13:51:55 +03:00
|
|
|
if let Some(tcx) = tcx {
|
2019-06-27 11:28:14 +02:00
|
|
|
let def_id = map.local_def_id(id);
|
2020-04-09 09:43:00 +01:00
|
|
|
tcx.def_path_str(def_id.to_def_id())
|
2019-04-27 22:39:17 +02:00
|
|
|
} else if let Some(path) = map.def_path_from_hir_id(id) {
|
2020-08-31 22:57:48 +01:00
|
|
|
path.data.into_iter().map(|elem| elem.to_string()).collect::<Vec<_>>().join("::")
|
2016-04-06 13:51:55 +03:00
|
|
|
} else {
|
|
|
|
String::from("<missing path>")
|
|
|
|
}
|
|
|
|
})
|
|
|
|
};
|
|
|
|
|
2020-03-24 02:44:41 +01:00
|
|
|
let span_str = || map.tcx.sess.source_map().span_to_snippet(map.span(id)).unwrap_or_default();
|
|
|
|
let node_str = |prefix| format!("{} {}{}", prefix, span_str(), id_str);
|
|
|
|
|
2019-06-24 09:58:49 +02:00
|
|
|
match map.find(id) {
|
2018-08-25 15:56:16 +01:00
|
|
|
Some(Node::Item(item)) => {
|
2019-09-26 17:51:36 +01:00
|
|
|
let item_str = match item.kind {
|
2018-07-11 23:36:06 +08:00
|
|
|
ItemKind::ExternCrate(..) => "extern crate",
|
|
|
|
ItemKind::Use(..) => "use",
|
|
|
|
ItemKind::Static(..) => "static",
|
|
|
|
ItemKind::Const(..) => "const",
|
|
|
|
ItemKind::Fn(..) => "fn",
|
2021-07-30 23:50:57 -07:00
|
|
|
ItemKind::Macro(..) => "macro",
|
2018-07-11 23:36:06 +08:00
|
|
|
ItemKind::Mod(..) => "mod",
|
2020-11-11 22:40:09 +01:00
|
|
|
ItemKind::ForeignMod { .. } => "foreign mod",
|
2018-07-11 23:36:06 +08:00
|
|
|
ItemKind::GlobalAsm(..) => "global asm",
|
2019-08-02 11:02:08 +01:00
|
|
|
ItemKind::TyAlias(..) => "ty",
|
2019-08-01 00:41:54 +01:00
|
|
|
ItemKind::OpaqueTy(..) => "opaque type",
|
2018-07-11 23:36:06 +08:00
|
|
|
ItemKind::Enum(..) => "enum",
|
|
|
|
ItemKind::Struct(..) => "struct",
|
|
|
|
ItemKind::Union(..) => "union",
|
|
|
|
ItemKind::Trait(..) => "trait",
|
|
|
|
ItemKind::TraitAlias(..) => "trait alias",
|
2020-01-17 16:14:29 -08:00
|
|
|
ItemKind::Impl { .. } => "impl",
|
2014-02-14 07:07:09 +02:00
|
|
|
};
|
2016-04-06 13:51:55 +03:00
|
|
|
format!("{} {}{}", item_str, path_str(), id_str)
|
2014-02-14 07:07:09 +02:00
|
|
|
}
|
2019-12-22 17:42:04 -05:00
|
|
|
Some(Node::ForeignItem(_)) => format!("foreign item {}{}", path_str(), id_str),
|
|
|
|
Some(Node::ImplItem(ii)) => match ii.kind {
|
|
|
|
ImplItemKind::Const(..) => {
|
|
|
|
format!("assoc const {} in {}{}", ii.ident, path_str(), id_str)
|
2014-08-04 13:56:56 -07:00
|
|
|
}
|
2020-03-05 09:57:34 -06:00
|
|
|
ImplItemKind::Fn(..) => format!("method {} in {}{}", ii.ident, path_str(), id_str),
|
2019-12-22 17:42:04 -05:00
|
|
|
ImplItemKind::TyAlias(_) => {
|
|
|
|
format!("assoc type {} in {}{}", ii.ident, path_str(), id_str)
|
|
|
|
}
|
|
|
|
},
|
2018-08-25 15:56:16 +01:00
|
|
|
Some(Node::TraitItem(ti)) => {
|
2019-09-26 17:07:54 +01:00
|
|
|
let kind = match ti.kind {
|
2016-12-04 04:21:06 +02:00
|
|
|
TraitItemKind::Const(..) => "assoc constant",
|
2020-03-03 12:46:22 -06:00
|
|
|
TraitItemKind::Fn(..) => "trait method",
|
2016-12-04 04:21:06 +02:00
|
|
|
TraitItemKind::Type(..) => "assoc type",
|
2015-03-10 12:28:44 +02:00
|
|
|
};
|
|
|
|
|
2018-06-10 22:24:24 +03:00
|
|
|
format!("{} {} in {}{}", kind, ti.ident, path_str(), id_str)
|
2014-02-14 07:07:09 +02:00
|
|
|
}
|
2018-08-25 15:56:16 +01:00
|
|
|
Some(Node::Variant(ref variant)) => {
|
2019-12-22 17:42:04 -05:00
|
|
|
format!("variant {} in {}{}", variant.ident, path_str(), id_str)
|
2014-02-14 07:07:09 +02:00
|
|
|
}
|
2018-08-25 15:56:16 +01:00
|
|
|
Some(Node::Field(ref field)) => {
|
2019-12-22 17:42:04 -05:00
|
|
|
format!("field {} in {}{}", field.ident, path_str(), id_str)
|
2014-02-14 07:07:09 +02:00
|
|
|
}
|
2020-03-24 02:44:41 +01:00
|
|
|
Some(Node::AnonConst(_)) => node_str("const"),
|
|
|
|
Some(Node::Expr(_)) => node_str("expr"),
|
|
|
|
Some(Node::Stmt(_)) => node_str("stmt"),
|
|
|
|
Some(Node::PathSegment(_)) => node_str("path segment"),
|
|
|
|
Some(Node::Ty(_)) => node_str("type"),
|
|
|
|
Some(Node::TraitRef(_)) => node_str("trait ref"),
|
|
|
|
Some(Node::Binding(_)) => node_str("local"),
|
|
|
|
Some(Node::Pat(_)) => node_str("pat"),
|
|
|
|
Some(Node::Param(_)) => node_str("param"),
|
|
|
|
Some(Node::Arm(_)) => node_str("arm"),
|
|
|
|
Some(Node::Block(_)) => node_str("block"),
|
2021-04-24 21:41:57 +00:00
|
|
|
Some(Node::Infer(_)) => node_str("infer"),
|
2020-03-24 02:44:41 +01:00
|
|
|
Some(Node::Local(_)) => node_str("local"),
|
2019-12-22 17:42:04 -05:00
|
|
|
Some(Node::Ctor(..)) => format!("ctor {}{}", path_str(), id_str),
|
2020-03-24 02:44:41 +01:00
|
|
|
Some(Node::Lifetime(_)) => node_str("lifetime"),
|
2019-12-22 17:42:04 -05:00
|
|
|
Some(Node::GenericParam(ref param)) => format!("generic_param {:?}{}", param, id_str),
|
|
|
|
Some(Node::Visibility(ref vis)) => format!("visibility {:?}{}", vis, id_str),
|
2020-02-07 16:43:36 +01:00
|
|
|
Some(Node::Crate(..)) => String::from("root_crate"),
|
2018-08-25 15:48:42 +01:00
|
|
|
None => format!("unknown node{}", id_str),
|
2013-10-29 06:03:32 -04:00
|
|
|
}
|
|
|
|
}
|
2021-07-18 18:12:17 +02:00
|
|
|
|
|
|
|
pub(super) fn hir_module_items(tcx: TyCtxt<'_>, module_id: LocalDefId) -> ModuleItems {
|
|
|
|
let mut collector = ModuleCollector {
|
|
|
|
tcx,
|
2021-09-07 20:07:33 +02:00
|
|
|
submodules: Vec::default(),
|
|
|
|
items: Vec::default(),
|
|
|
|
trait_items: Vec::default(),
|
|
|
|
impl_items: Vec::default(),
|
|
|
|
foreign_items: Vec::default(),
|
2021-07-18 18:12:17 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
let (hir_mod, span, hir_id) = tcx.hir().get_module(module_id);
|
|
|
|
collector.visit_mod(hir_mod, span, hir_id);
|
|
|
|
|
|
|
|
let ModuleCollector { submodules, items, trait_items, impl_items, foreign_items, .. } =
|
|
|
|
collector;
|
2021-09-07 20:07:33 +02:00
|
|
|
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(),
|
|
|
|
};
|
2021-07-18 18:12:17 +02:00
|
|
|
|
|
|
|
struct ModuleCollector<'tcx> {
|
|
|
|
tcx: TyCtxt<'tcx>,
|
2021-09-07 20:07:33 +02:00
|
|
|
submodules: Vec<LocalDefId>,
|
|
|
|
items: Vec<ItemId>,
|
|
|
|
trait_items: Vec<TraitItemId>,
|
|
|
|
impl_items: Vec<ImplItemId>,
|
|
|
|
foreign_items: Vec<ForeignItemId>,
|
2021-07-18 18:12:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'hir> Visitor<'hir> for ModuleCollector<'hir> {
|
|
|
|
type Map = Map<'hir>;
|
|
|
|
|
|
|
|
fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
|
|
|
|
intravisit::NestedVisitorMap::All(self.tcx.hir())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_item(&mut self, item: &'hir Item<'hir>) {
|
2021-09-07 20:07:33 +02:00
|
|
|
self.items.push(item.item_id());
|
2021-07-18 18:12:17 +02:00
|
|
|
if let ItemKind::Mod(..) = item.kind {
|
|
|
|
// If this declares another module, do not recurse inside it.
|
2021-09-07 20:07:33 +02:00
|
|
|
self.submodules.push(item.def_id);
|
2021-07-18 18:12:17 +02:00
|
|
|
} else {
|
|
|
|
intravisit::walk_item(self, item)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_trait_item(&mut self, item: &'hir TraitItem<'hir>) {
|
2021-09-07 20:07:33 +02:00
|
|
|
self.trait_items.push(item.trait_item_id());
|
2021-07-18 18:12:17 +02:00
|
|
|
intravisit::walk_trait_item(self, item)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_impl_item(&mut self, item: &'hir ImplItem<'hir>) {
|
2021-09-07 20:07:33 +02:00
|
|
|
self.impl_items.push(item.impl_item_id());
|
2021-07-18 18:12:17 +02:00
|
|
|
intravisit::walk_impl_item(self, item)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_foreign_item(&mut self, item: &'hir ForeignItem<'hir>) {
|
2021-09-07 20:07:33 +02:00
|
|
|
self.foreign_items.push(item.foreign_item_id());
|
2021-07-18 18:12:17 +02:00
|
|
|
intravisit::walk_foreign_item(self, item)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|