2024-11-02 19:33:00 -07:00
|
|
|
use rustc_abi::ExternAbi;
|
2024-02-24 15:22:42 -05:00
|
|
|
use rustc_ast::visit::{VisitorResult, walk_list};
|
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;
|
2023-10-18 08:47:17 +00:00
|
|
|
use rustc_data_structures::sync::{DynSend, DynSync, par_for_each_in, try_par_for_each_in};
|
2020-01-05 02:37:57 +01:00
|
|
|
use rustc_hir::def::{DefKind, Res};
|
2023-04-26 20:53:51 +02:00
|
|
|
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId, LocalModDefId};
|
2023-11-21 23:40:23 +03:00
|
|
|
use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
|
2023-11-10 10:11:24 +08:00
|
|
|
use rustc_hir::intravisit::Visitor;
|
2020-01-05 02:37:57 +01:00
|
|
|
use rustc_hir::*;
|
2024-10-17 01:14:01 +02:00
|
|
|
use rustc_hir_pretty as pprust_hir;
|
2021-06-08 18:36:30 +02:00
|
|
|
use rustc_span::def_id::StableCrateId;
|
2024-12-21 20:37:24 +00:00
|
|
|
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw, sym, with_metavar_spans};
|
2024-07-29 08:13:50 +10:00
|
|
|
|
2025-02-11 13:58:38 +11:00
|
|
|
use crate::hir::{ModuleItems, nested_filter};
|
2023-05-16 21:03:28 +02:00
|
|
|
use crate::middle::debugger_visualizer::DebuggerVisualizerFile;
|
2023-03-13 22:22:59 +00:00
|
|
|
use crate::query::LocalCrate;
|
2023-02-22 19:51:17 +04:00
|
|
|
use crate::ty::TyCtxt;
|
2015-07-31 00:04:06 -07:00
|
|
|
|
2023-12-01 05:28:34 -08:00
|
|
|
// FIXME: the structure was necessary in the past but now it
|
|
|
|
// only serves as "namespace" for HIR-related methods, and can be
|
|
|
|
// removed if all the methods are reasonably renamed and moved to tcx
|
|
|
|
// (https://github.com/rust-lang/rust/pull/118256#issuecomment-1826442834).
|
2025-04-02 07:04:24 +11:00
|
|
|
#[allow(unused)] // FIXME: temporary
|
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`.
|
2025-02-21 07:54:35 +11:00
|
|
|
/// Constructed using `tcx.hir_parent_iter(hir_id)`.
|
2025-02-21 07:54:46 +11:00
|
|
|
struct ParentHirIterator<'tcx> {
|
2019-09-25 17:05:30 -07:00
|
|
|
current_id: HirId,
|
2025-02-21 07:54:46 +11:00
|
|
|
tcx: TyCtxt<'tcx>,
|
2024-07-06 11:49:52 +00:00
|
|
|
// Cache the current value of `hir_owner_nodes` to avoid repeatedly calling the same query for
|
|
|
|
// the same owner, which will uselessly record many times the same query dependency.
|
2025-02-21 07:54:46 +11:00
|
|
|
current_owner_nodes: Option<&'tcx OwnerNodes<'tcx>>,
|
2024-07-06 11:49:52 +00:00
|
|
|
}
|
|
|
|
|
2025-02-21 07:54:46 +11:00
|
|
|
impl<'tcx> ParentHirIterator<'tcx> {
|
|
|
|
fn new(tcx: TyCtxt<'tcx>, current_id: HirId) -> ParentHirIterator<'tcx> {
|
|
|
|
ParentHirIterator { current_id, tcx, current_owner_nodes: None }
|
2024-07-06 11:49:52 +00:00
|
|
|
}
|
2019-09-25 17:05:30 -07:00
|
|
|
}
|
|
|
|
|
2025-02-21 07:54:46 +11:00
|
|
|
impl<'tcx> Iterator for ParentHirIterator<'tcx> {
|
2022-09-15 18:39:53 +02:00
|
|
|
type Item = HirId;
|
2019-09-25 17:05:30 -07:00
|
|
|
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
|
|
if self.current_id == CRATE_HIR_ID {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
|
2024-07-06 11:49:52 +00:00
|
|
|
let HirId { owner, local_id } = self.current_id;
|
2019-09-25 17:05:30 -07:00
|
|
|
|
2024-07-06 11:49:52 +00:00
|
|
|
let parent_id = if local_id == ItemLocalId::ZERO {
|
|
|
|
// We go from an owner to its parent, so clear the cache.
|
|
|
|
self.current_owner_nodes = None;
|
2025-02-21 07:54:46 +11:00
|
|
|
self.tcx.hir_owner_parent(owner)
|
2024-07-06 11:49:52 +00:00
|
|
|
} else {
|
|
|
|
let owner_nodes =
|
2025-02-21 07:54:46 +11:00
|
|
|
self.current_owner_nodes.get_or_insert_with(|| self.tcx.hir_owner_nodes(owner));
|
2024-07-06 11:49:52 +00:00
|
|
|
let parent_local_id = owner_nodes.nodes[local_id].parent;
|
|
|
|
// HIR indexing should have checked that.
|
|
|
|
debug_assert_ne!(parent_local_id, local_id);
|
|
|
|
HirId { owner, local_id: parent_local_id }
|
|
|
|
};
|
|
|
|
|
|
|
|
debug_assert_ne!(parent_id, self.current_id);
|
2023-04-09 22:35:49 +02:00
|
|
|
|
|
|
|
self.current_id = parent_id;
|
2024-09-09 12:22:00 +02:00
|
|
|
Some(parent_id)
|
2021-03-03 21:50:45 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// An iterator that walks up the ancestor tree of a given `HirId`.
|
2025-02-21 07:54:35 +11:00
|
|
|
/// Constructed using `tcx.hir_parent_owner_iter(hir_id)`.
|
2025-02-21 07:54:46 +11:00
|
|
|
pub struct ParentOwnerIterator<'tcx> {
|
2021-03-03 21:50:45 +01:00
|
|
|
current_id: HirId,
|
2025-02-21 07:54:46 +11:00
|
|
|
tcx: TyCtxt<'tcx>,
|
2021-03-03 21:50:45 +01:00
|
|
|
}
|
|
|
|
|
2025-02-21 07:54:46 +11:00
|
|
|
impl<'tcx> Iterator for ParentOwnerIterator<'tcx> {
|
|
|
|
type Item = (OwnerId, OwnerNode<'tcx>);
|
2021-03-03 21:50:45 +01:00
|
|
|
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
|
|
if self.current_id.local_id.index() != 0 {
|
2024-04-03 17:49:59 +03:00
|
|
|
self.current_id.local_id = ItemLocalId::ZERO;
|
2025-02-21 07:54:46 +11:00
|
|
|
let node = self.tcx.hir_owner_node(self.current_id.owner);
|
2024-01-25 19:34:49 +03:00
|
|
|
return Some((self.current_id.owner, node));
|
2021-03-03 21:50:45 +01:00
|
|
|
}
|
|
|
|
if self.current_id == CRATE_HIR_ID {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
|
2025-02-21 07:54:46 +11:00
|
|
|
let parent_id = self.tcx.hir_def_key(self.current_id.owner.def_id).parent;
|
2024-02-25 01:11:09 +03:00
|
|
|
let parent_id = parent_id.map_or(CRATE_OWNER_ID, |local_def_index| {
|
|
|
|
let def_id = LocalDefId { local_def_index };
|
2025-02-21 07:54:46 +11:00
|
|
|
self.tcx.local_def_id_to_hir_id(def_id).owner
|
2024-02-25 01:11:09 +03:00
|
|
|
});
|
|
|
|
self.current_id = HirId::make_owner(parent_id.def_id);
|
2021-03-03 21:50:45 +01:00
|
|
|
|
2025-02-21 07:54:46 +11:00
|
|
|
let node = self.tcx.hir_owner_node(self.current_id.owner);
|
2024-09-09 12:22:00 +02:00
|
|
|
Some((self.current_id.owner, node))
|
2019-09-25 17:05:30 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-01 05:28:34 -08:00
|
|
|
impl<'tcx> TyCtxt<'tcx> {
|
2024-01-15 22:31:02 +00:00
|
|
|
#[inline]
|
2024-01-25 19:34:49 +03:00
|
|
|
fn expect_hir_owner_nodes(self, def_id: LocalDefId) -> &'tcx OwnerNodes<'tcx> {
|
|
|
|
self.opt_hir_owner_nodes(def_id)
|
|
|
|
.unwrap_or_else(|| span_bug!(self.def_span(def_id), "{def_id:?} is not an owner"))
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn hir_owner_nodes(self, owner_id: OwnerId) -> &'tcx OwnerNodes<'tcx> {
|
|
|
|
self.expect_hir_owner_nodes(owner_id.def_id)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn opt_hir_owner_node(self, def_id: LocalDefId) -> Option<OwnerNode<'tcx>> {
|
|
|
|
self.opt_hir_owner_nodes(def_id).map(|nodes| nodes.node())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2024-01-25 20:47:03 +03:00
|
|
|
pub fn expect_hir_owner_node(self, def_id: LocalDefId) -> OwnerNode<'tcx> {
|
2024-01-25 19:34:49 +03:00
|
|
|
self.expect_hir_owner_nodes(def_id).node()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2024-01-25 20:47:03 +03:00
|
|
|
pub fn hir_owner_node(self, owner_id: OwnerId) -> OwnerNode<'tcx> {
|
2024-01-25 19:34:49 +03:00
|
|
|
self.hir_owner_nodes(owner_id).node()
|
2024-01-15 22:31:02 +00:00
|
|
|
}
|
|
|
|
|
2024-01-21 21:13:15 +03:00
|
|
|
/// Retrieves the `hir::Node` corresponding to `id`.
|
2023-12-01 05:28:34 -08:00
|
|
|
pub fn hir_node(self, id: HirId) -> Node<'tcx> {
|
2024-01-21 21:13:15 +03:00
|
|
|
self.hir_owner_nodes(id.owner).nodes[id.local_id].node
|
2023-12-01 05:28:34 -08:00
|
|
|
}
|
|
|
|
|
2024-02-11 19:08:30 +03:00
|
|
|
/// Retrieves the `hir::Node` corresponding to `id`.
|
2023-12-01 05:28:34 -08:00
|
|
|
#[inline]
|
|
|
|
pub fn hir_node_by_def_id(self, id: LocalDefId) -> Node<'tcx> {
|
2024-02-11 19:08:30 +03:00
|
|
|
self.hir_node(self.local_def_id_to_hir_id(id))
|
2023-12-01 05:28:34 -08:00
|
|
|
}
|
2024-02-09 23:58:36 +03:00
|
|
|
|
|
|
|
/// Returns `HirId` of the parent HIR node of node with this `hir_id`.
|
|
|
|
/// Returns the same `hir_id` if and only if `hir_id == CRATE_HIR_ID`.
|
|
|
|
///
|
2025-02-21 07:54:35 +11:00
|
|
|
/// If calling repeatedly and iterating over parents, prefer [`TyCtxt::hir_parent_iter`].
|
2024-02-09 23:58:36 +03:00
|
|
|
pub fn parent_hir_id(self, hir_id: HirId) -> HirId {
|
|
|
|
let HirId { owner, local_id } = hir_id;
|
2024-04-03 17:49:59 +03:00
|
|
|
if local_id == ItemLocalId::ZERO {
|
2024-02-09 23:58:36 +03:00
|
|
|
self.hir_owner_parent(owner)
|
|
|
|
} else {
|
|
|
|
let parent_local_id = self.hir_owner_nodes(owner).nodes[local_id].parent;
|
|
|
|
// HIR indexing should have checked that.
|
|
|
|
debug_assert_ne!(parent_local_id, local_id);
|
|
|
|
HirId { owner, local_id: parent_local_id }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns parent HIR node of node with this `hir_id`.
|
|
|
|
/// Returns HIR node of the same `hir_id` if and only if `hir_id == CRATE_HIR_ID`.
|
|
|
|
pub fn parent_hir_node(self, hir_id: HirId) -> Node<'tcx> {
|
|
|
|
self.hir_node(self.parent_hir_id(hir_id))
|
|
|
|
}
|
2023-12-01 05:28:34 -08:00
|
|
|
|
2022-07-30 22:44:49 +02:00
|
|
|
#[inline]
|
2025-02-03 10:45:49 +11:00
|
|
|
pub fn hir_root_module(self) -> &'tcx Mod<'tcx> {
|
|
|
|
match self.hir_owner_node(CRATE_OWNER_ID) {
|
2024-01-25 19:34:49 +03:00
|
|
|
OwnerNode::Crate(item) => item,
|
2021-09-13 20:43:43 +02:00
|
|
|
_ => bug!(),
|
2021-09-12 01:11:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-30 22:44:49 +02:00
|
|
|
#[inline]
|
2025-02-20 18:58:46 +00:00
|
|
|
pub fn hir_free_items(self) -> impl Iterator<Item = ItemId> {
|
2025-02-03 10:45:49 +11:00
|
|
|
self.hir_crate_items(()).free_items.iter().copied()
|
2022-04-03 15:50:33 -04:00
|
|
|
}
|
|
|
|
|
2022-07-30 22:44:49 +02:00
|
|
|
#[inline]
|
2025-02-20 18:58:46 +00:00
|
|
|
pub fn hir_module_free_items(self, module: LocalModDefId) -> impl Iterator<Item = ItemId> {
|
2025-02-03 10:45:49 +11:00
|
|
|
self.hir_module_items(module).free_items()
|
2022-05-07 14:45:30 -04:00
|
|
|
}
|
|
|
|
|
2025-02-03 10:45:49 +11:00
|
|
|
pub fn hir_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.
|
2025-02-03 10:45:49 +11:00
|
|
|
self.definitions_untracked().def_key(def_id)
|
2015-09-17 14:29:59 -04:00
|
|
|
}
|
|
|
|
|
2025-02-03 10:45:49 +11:00
|
|
|
pub fn hir_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.
|
2025-02-03 10:45:49 +11:00
|
|
|
self.definitions_untracked().def_path(def_id)
|
2015-09-17 14:29:59 -04:00
|
|
|
}
|
|
|
|
|
2021-05-20 20:17:45 +02:00
|
|
|
#[inline]
|
2025-02-03 10:45:49 +11:00
|
|
|
pub fn hir_def_path_hash(self, def_id: LocalDefId) -> DefPathHash {
|
2021-05-20 20:17:45 +02:00
|
|
|
// Accessing the DefPathHash is ok, it is incr. comp. stable.
|
2025-02-03 10:45:49 +11:00
|
|
|
self.definitions_untracked().def_path_hash(def_id)
|
2021-05-20 20:17:45 +02:00
|
|
|
}
|
|
|
|
|
2025-02-03 10:45:49 +11:00
|
|
|
pub fn hir_get_if_local(self, id: DefId) -> Option<Node<'tcx>> {
|
|
|
|
id.as_local().map(|id| self.hir_node_by_def_id(id))
|
2021-03-03 21:50:45 +01:00
|
|
|
}
|
|
|
|
|
2025-02-03 10:45:49 +11:00
|
|
|
pub fn hir_get_generics(self, id: LocalDefId) -> Option<&'tcx Generics<'tcx>> {
|
|
|
|
self.opt_hir_owner_node(id)?.generics()
|
2020-03-16 19:17:40 +01:00
|
|
|
}
|
|
|
|
|
2025-02-03 10:45:49 +11:00
|
|
|
pub fn hir_item(self, id: ItemId) -> &'tcx Item<'tcx> {
|
|
|
|
self.hir_owner_node(id.owner_id).expect_item()
|
2020-01-07 15:51:38 +01:00
|
|
|
}
|
|
|
|
|
2025-02-03 10:45:49 +11:00
|
|
|
pub fn hir_trait_item(self, id: TraitItemId) -> &'tcx TraitItem<'tcx> {
|
|
|
|
self.hir_owner_node(id.owner_id).expect_trait_item()
|
2016-12-04 04:21:06 +02:00
|
|
|
}
|
|
|
|
|
2025-02-03 10:45:49 +11:00
|
|
|
pub fn hir_impl_item(self, id: ImplItemId) -> &'tcx ImplItem<'tcx> {
|
|
|
|
self.hir_owner_node(id.owner_id).expect_impl_item()
|
2016-11-02 18:25:31 -04:00
|
|
|
}
|
|
|
|
|
2025-02-03 10:45:49 +11:00
|
|
|
pub fn hir_foreign_item(self, id: ForeignItemId) -> &'tcx ForeignItem<'tcx> {
|
|
|
|
self.hir_owner_node(id.owner_id).expect_foreign_item()
|
2020-11-11 21:57:54 +01:00
|
|
|
}
|
|
|
|
|
2025-02-03 10:45:49 +11:00
|
|
|
pub fn hir_body(self, id: BodyId) -> &'tcx Body<'tcx> {
|
|
|
|
self.hir_owner_nodes(id.hir_id.owner).bodies[&id.hir_id.local_id]
|
2016-12-21 12:32:59 +02:00
|
|
|
}
|
|
|
|
|
2022-10-12 14:16:31 +00:00
|
|
|
#[track_caller]
|
2025-02-17 14:17:57 +11:00
|
|
|
pub fn hir_fn_decl_by_hir_id(self, hir_id: HirId) -> Option<&'tcx FnDecl<'tcx>> {
|
|
|
|
self.hir_node(hir_id).fn_decl()
|
2019-02-04 11:09:32 +01:00
|
|
|
}
|
|
|
|
|
2022-10-12 14:16:31 +00:00
|
|
|
#[track_caller]
|
2025-02-17 14:17:57 +11:00
|
|
|
pub fn hir_fn_sig_by_hir_id(self, hir_id: HirId) -> Option<&'tcx FnSig<'tcx>> {
|
|
|
|
self.hir_node(hir_id).fn_sig()
|
2019-11-06 11:43:33 -08:00
|
|
|
}
|
|
|
|
|
2022-10-12 14:16:31 +00:00
|
|
|
#[track_caller]
|
2025-02-17 14:17:57 +11:00
|
|
|
pub fn hir_enclosing_body_owner(self, hir_id: HirId) -> LocalDefId {
|
2025-02-21 07:54:35 +11:00
|
|
|
for (_, node) in self.hir_parent_iter(hir_id) {
|
2024-03-05 09:42:25 +00:00
|
|
|
if let Some((def_id, _)) = node.associated_body() {
|
2022-11-05 15:33:58 +00:00
|
|
|
return def_id;
|
2020-05-20 14:57:16 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-17 14:17:57 +11:00
|
|
|
bug!("no `hir_enclosing_body_owner` for hir_id `{}`", hir_id);
|
2020-05-20 14:57:16 +02:00
|
|
|
}
|
|
|
|
|
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`.
|
2025-02-17 14:17:57 +11:00
|
|
|
pub fn hir_body_owner(self, BodyId { hir_id }: BodyId) -> HirId {
|
|
|
|
let parent = self.parent_hir_id(hir_id);
|
|
|
|
assert_eq!(self.hir_node(parent).body_id().unwrap().hir_id, hir_id, "{hir_id:?}");
|
2019-06-14 12:28:47 +02:00
|
|
|
parent
|
2016-12-20 23:05:21 +02:00
|
|
|
}
|
|
|
|
|
2025-02-17 14:17:57 +11:00
|
|
|
pub fn hir_body_owner_def_id(self, BodyId { hir_id }: BodyId) -> LocalDefId {
|
|
|
|
self.parent_hir_node(hir_id).associated_body().unwrap().0
|
2016-12-20 23:05:21 +02:00
|
|
|
}
|
|
|
|
|
2022-07-15 23:13:04 -04:00
|
|
|
/// Given a `LocalDefId`, returns the `BodyId` associated with it,
|
2017-04-24 22:03:47 +03:00
|
|
|
/// if the node is a body owner, otherwise returns `None`.
|
2025-02-17 14:17:57 +11:00
|
|
|
pub fn hir_maybe_body_owned_by(self, id: LocalDefId) -> Option<&'tcx Body<'tcx>> {
|
|
|
|
Some(self.hir_body(self.hir_node_by_def_id(id).body_id()?))
|
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.
|
2022-10-12 14:16:31 +00:00
|
|
|
#[track_caller]
|
2025-02-17 14:17:57 +11:00
|
|
|
pub fn hir_body_owned_by(self, id: LocalDefId) -> &'tcx Body<'tcx> {
|
|
|
|
self.hir_maybe_body_owned_by(id).unwrap_or_else(|| {
|
|
|
|
let hir_id = self.local_def_id_to_hir_id(id);
|
2019-06-14 18:58:55 +02:00
|
|
|
span_bug!(
|
2025-04-02 07:04:24 +11:00
|
|
|
self.hir_span(hir_id),
|
2019-06-14 18:58:55 +02:00
|
|
|
"body_owned_by: {} has no associated body",
|
2025-02-21 18:51:45 +11:00
|
|
|
self.hir_id_to_string(hir_id)
|
2019-06-16 17:30:02 +02:00
|
|
|
);
|
2017-04-24 22:03:47 +03:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
Use `Option<Ident>` for lowered param names.
Parameter patterns are lowered to an `Ident` by
`lower_fn_params_to_names`, which is used when lowering bare function
types, trait methods, and foreign functions. Currently, there are two
exceptional cases where the lowered param can become an empty `Ident`.
- If the incoming pattern is an empty `Ident`. This occurs if the
parameter is anonymous, e.g. in a bare function type.
- If the incoming pattern is neither an ident nor an underscore. Any
such parameter will have triggered a compile error (hence the
`span_delayed_bug`), but lowering still occurs.
This commit replaces these empty `Ident` results with `None`, which
eliminates a number of `kw::Empty` uses, and makes it impossible to fail
to check for these exceptional cases.
Note: the `FIXME` comment in `is_unwrap_or_empty_symbol` is removed. It
actually should have been removed in #138482, the precursor to this PR.
That PR changed the lowering of wild patterns to `_` symbols instead of
empty symbols, which made the mentioned underscore check load-bearing.
2025-03-14 09:03:23 +11:00
|
|
|
pub fn hir_body_param_names(self, id: BodyId) -> impl Iterator<Item = Option<Ident>> {
|
2025-03-14 08:40:43 +11:00
|
|
|
self.hir_body(id).params.iter().map(|param| match param.pat.kind {
|
Use `Option<Ident>` for lowered param names.
Parameter patterns are lowered to an `Ident` by
`lower_fn_params_to_names`, which is used when lowering bare function
types, trait methods, and foreign functions. Currently, there are two
exceptional cases where the lowered param can become an empty `Ident`.
- If the incoming pattern is an empty `Ident`. This occurs if the
parameter is anonymous, e.g. in a bare function type.
- If the incoming pattern is neither an ident nor an underscore. Any
such parameter will have triggered a compile error (hence the
`span_delayed_bug`), but lowering still occurs.
This commit replaces these empty `Ident` results with `None`, which
eliminates a number of `kw::Empty` uses, and makes it impossible to fail
to check for these exceptional cases.
Note: the `FIXME` comment in `is_unwrap_or_empty_symbol` is removed. It
actually should have been removed in #138482, the precursor to this PR.
That PR changed the lowering of wild patterns to `_` symbols instead of
empty symbols, which made the mentioned underscore check load-bearing.
2025-03-14 09:03:23 +11:00
|
|
|
PatKind::Binding(_, _, ident, _) => Some(ident),
|
|
|
|
PatKind::Wild => Some(Ident::new(kw::Underscore, param.pat.span)),
|
|
|
|
_ => None,
|
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.
|
2025-02-17 14:17:57 +11:00
|
|
|
pub fn hir_body_owner_kind(self, def_id: impl Into<DefId>) -> BodyOwnerKind {
|
2023-12-10 13:06:18 +00:00
|
|
|
let def_id = def_id.into();
|
2025-02-17 14:17:57 +11:00
|
|
|
match self.def_kind(def_id) {
|
2023-09-18 15:30:07 +00:00
|
|
|
DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => {
|
|
|
|
BodyOwnerKind::Const { inline: false }
|
2022-03-29 17:11:12 +02:00
|
|
|
}
|
2023-09-18 15:30:07 +00:00
|
|
|
DefKind::InlineConst => BodyOwnerKind::Const { inline: true },
|
2022-03-29 17:11:12 +02:00
|
|
|
DefKind::Ctor(..) | DefKind::Fn | DefKind::AssocFn => BodyOwnerKind::Fn,
|
2024-08-01 13:05:17 -04:00
|
|
|
DefKind::Closure | DefKind::SyntheticCoroutineBody => BodyOwnerKind::Closure,
|
2024-05-07 14:43:23 +02:00
|
|
|
DefKind::Static { safety: _, mutability, nested: false } => {
|
|
|
|
BodyOwnerKind::Static(mutability)
|
|
|
|
}
|
2025-02-17 16:09:46 +00:00
|
|
|
DefKind::GlobalAsm => BodyOwnerKind::GlobalAsm,
|
2022-03-29 17:11:12 +02:00
|
|
|
dk => bug!("{:?} is not a body node: {:?}", def_id, dk),
|
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
|
2021-12-12 12:34:46 +08:00
|
|
|
/// value of `Some` does not always suggest that the owner of the body is `const`,
|
|
|
|
/// just that it has to be checked as if it were.
|
2025-02-17 14:17:57 +11:00
|
|
|
pub fn hir_body_const_context(self, def_id: impl Into<DefId>) -> Option<ConstContext> {
|
2023-12-10 13:06:18 +00:00
|
|
|
let def_id = def_id.into();
|
2025-02-17 14:17:57 +11:00
|
|
|
let ccx = match self.hir_body_owner_kind(def_id) {
|
2023-09-18 15:30:07 +00:00
|
|
|
BodyOwnerKind::Const { inline } => ConstContext::Const { inline },
|
2024-03-11 17:33:57 +00:00
|
|
|
BodyOwnerKind::Static(mutability) => ConstContext::Static(mutability),
|
2020-05-07 10:22:35 -07:00
|
|
|
|
2025-02-17 14:17:57 +11:00
|
|
|
BodyOwnerKind::Fn if self.is_constructor(def_id) => return None,
|
|
|
|
BodyOwnerKind::Fn | BodyOwnerKind::Closure if self.is_const_fn(def_id) => {
|
2021-07-10 11:16:03 +08:00
|
|
|
ConstContext::ConstFn
|
|
|
|
}
|
2025-02-17 14:17:57 +11:00
|
|
|
BodyOwnerKind::Fn if self.is_const_default_method(def_id) => ConstContext::ConstFn,
|
2025-02-17 16:09:46 +00:00
|
|
|
BodyOwnerKind::Fn | BodyOwnerKind::Closure | BodyOwnerKind::GlobalAsm => return None,
|
2020-05-07 10:22:35 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
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
|
2024-06-03 09:11:58 +00:00
|
|
|
/// themselves, you can do `self.hir().krate().body_ids.iter()`.
|
2022-07-30 22:44:49 +02:00
|
|
|
#[inline]
|
2025-02-20 18:58:46 +00:00
|
|
|
pub fn hir_body_owners(self) -> impl Iterator<Item = LocalDefId> {
|
2025-02-17 14:17:57 +11:00
|
|
|
self.hir_crate_items(()).body_owners.iter().copied()
|
2021-09-12 11:33:16 +02:00
|
|
|
}
|
|
|
|
|
2022-07-30 22:44:49 +02:00
|
|
|
#[inline]
|
2025-02-17 14:17:57 +11:00
|
|
|
pub fn par_hir_body_owners(self, f: impl Fn(LocalDefId) + DynSend + DynSync) {
|
|
|
|
par_for_each_in(&self.hir_crate_items(()).body_owners[..], |&def_id| f(def_id));
|
2021-09-12 11:33:16 +02:00
|
|
|
}
|
|
|
|
|
2025-02-17 14:17:57 +11:00
|
|
|
pub fn hir_ty_param_owner(self, def_id: LocalDefId) -> LocalDefId {
|
|
|
|
let def_kind = self.def_kind(def_id);
|
2022-04-07 22:24:07 +02:00
|
|
|
match def_kind {
|
|
|
|
DefKind::Trait | DefKind::TraitAlias => def_id,
|
2022-05-24 12:51:59 +02:00
|
|
|
DefKind::LifetimeParam | DefKind::TyParam | DefKind::ConstParam => {
|
2025-02-17 14:17:57 +11:00
|
|
|
self.local_parent(def_id)
|
2022-05-24 12:51:59 +02:00
|
|
|
}
|
2022-04-07 22:24:07 +02:00
|
|
|
_ => bug!("ty_param_owner: {:?} is a {:?} not a type parameter", def_id, def_kind),
|
2017-02-11 19:26:13 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-17 14:17:57 +11:00
|
|
|
pub fn hir_ty_param_name(self, def_id: LocalDefId) -> Symbol {
|
|
|
|
let def_kind = self.def_kind(def_id);
|
2022-04-08 23:06:20 +02:00
|
|
|
match def_kind {
|
|
|
|
DefKind::Trait | DefKind::TraitAlias => kw::SelfUpper,
|
2022-05-24 12:51:59 +02:00
|
|
|
DefKind::LifetimeParam | DefKind::TyParam | DefKind::ConstParam => {
|
2025-02-17 14:17:57 +11:00
|
|
|
self.item_name(def_id.to_def_id())
|
2022-05-24 12:51:59 +02:00
|
|
|
}
|
2022-04-08 23:06:20 +02:00
|
|
|
_ => bug!("ty_param_name: {:?} is a {:?} not a type parameter", def_id, def_kind),
|
2017-02-11 19:26:13 +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.
|
2025-02-17 14:17:57 +11:00
|
|
|
pub fn hir_krate_attrs(self) -> &'tcx [Attribute] {
|
2025-02-21 18:33:05 +11:00
|
|
|
self.hir_attrs(CRATE_HIR_ID)
|
2016-03-16 05:53:45 -04:00
|
|
|
}
|
|
|
|
|
2025-02-17 14:17:57 +11:00
|
|
|
pub fn hir_rustc_coherence_is_core(self) -> bool {
|
|
|
|
self.hir_krate_attrs().iter().any(|attr| attr.has_name(sym::rustc_coherence_is_core))
|
2022-03-15 16:30:30 +01:00
|
|
|
}
|
|
|
|
|
2025-02-17 14:17:57 +11:00
|
|
|
pub fn hir_get_module(self, module: LocalModDefId) -> (&'tcx Mod<'tcx>, Span, HirId) {
|
2023-04-26 20:53:51 +02:00
|
|
|
let hir_id = HirId::make_owner(module.to_local_def_id());
|
2025-02-17 14:17:57 +11:00
|
|
|
match self.hir_owner_node(hir_id.owner) {
|
Move `hir::Item::ident` into `hir::ItemKind`.
`hir::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Macro`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
Trait`, TraitAalis`.
- It's always empty for these item kinds: `ForeignMod`, `GlobalAsm`,
`Impl`.
- For `Use`, it is non-empty for `UseKind::Single` and empty for
`UseKind::{Glob,ListStem}`.
All of this is quite non-obvious; the only documentation is a single
comment saying "The name might be a dummy name in case of anonymous
items". Some sites that handle items check for an empty ident, some
don't. This is a very C-like way of doing things, but this is Rust, we
have sum types, we can do this properly and never forget to check for
the exceptional case and never YOLO possibly empty identifiers (or
possibly dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- A similar transformation makes sense for `ast::Item`, but this is
already a big change. That can be done later.
- Lots of assertions are added to item lowering to ensure that
identifiers are empty/non-empty as expected. These will be removable
when `ast::Item` is done later.
- `ItemKind::Use` doesn't get an `Ident`, but `UseKind::Single` does.
- `lower_use_tree` is significantly simpler. No more confusing `&mut
Ident` to deal with.
- `ItemKind::ident` is a new method, it returns an `Option<Ident>`. It's
used with `unwrap` in a few places; sometimes it's hard to tell
exactly which item kinds might occur. None of these unwraps fail on
the test suite. It's conceivable that some might fail on alternative
input. We can deal with those if/when they happen.
- In `trait_path` the `find_map`/`if let` is replaced with a loop, and
things end up much clearer that way.
- `named_span` no longer checks for an empty name; instead the call site
now checks for a missing identifier if necessary.
- `maybe_inline_local` doesn't need the `glob` argument, it can be
computed in-function from the `renamed` argument.
- `arbitrary_source_item_ordering::check_mod` had a big `if` statement
that was just getting the ident from the item kinds that had one. It
could be mostly replaced by a single call to the new `ItemKind::ident`
method.
- `ItemKind` grows from 56 to 64 bytes, but `Item` stays the same size,
and that's what matters, because `ItemKind` only occurs within `Item`.
2025-03-06 19:07:36 +11:00
|
|
|
OwnerNode::Item(&Item { span, kind: ItemKind::Mod(_, m), .. }) => (m, span, hir_id),
|
2024-01-25 19:34:49 +03:00
|
|
|
OwnerNode::Crate(item) => (item, item.spans.inner_span, hir_id),
|
2023-07-25 22:00:13 +02:00
|
|
|
node => panic!("not a module: {node:?}"),
|
2018-06-08 19:14:03 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-03 15:28:57 +02:00
|
|
|
/// Walks the contents of the local crate. See also `visit_all_item_likes_in_crate`.
|
2025-02-17 14:17:57 +11:00
|
|
|
pub fn hir_walk_toplevel_module<V>(self, visitor: &mut V) -> V::Result
|
2024-02-18 03:12:44 -05:00
|
|
|
where
|
2025-02-17 14:17:57 +11:00
|
|
|
V: Visitor<'tcx>,
|
2024-02-18 03:12:44 -05:00
|
|
|
{
|
2025-02-17 14:17:57 +11:00
|
|
|
let (top_mod, span, hir_id) = self.hir_get_module(LocalModDefId::CRATE_DEF_ID);
|
2024-02-18 03:12:44 -05:00
|
|
|
visitor.visit_mod(top_mod, span, hir_id)
|
2021-08-26 18:42:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Walks the attributes in a crate.
|
2025-02-17 14:17:57 +11:00
|
|
|
pub fn hir_walk_attributes<V>(self, visitor: &mut V) -> V::Result
|
2024-02-18 03:12:44 -05:00
|
|
|
where
|
2025-02-17 14:17:57 +11:00
|
|
|
V: Visitor<'tcx>,
|
2024-02-18 03:12:44 -05:00
|
|
|
{
|
2025-02-17 14:17:57 +11:00
|
|
|
let krate = self.hir_crate(());
|
2022-06-16 07:54:03 +10:00
|
|
|
for info in krate.owners.iter() {
|
2021-09-22 19:28:20 +02:00
|
|
|
if let MaybeOwner::Owner(info) = info {
|
2022-06-16 07:54:03 +10:00
|
|
|
for attrs in info.attrs.map.values() {
|
2024-02-18 03:12:44 -05:00
|
|
|
walk_list!(visitor, visit_attribute, *attrs);
|
2021-07-16 14:42:26 +02:00
|
|
|
}
|
2021-08-26 18:42:08 +02:00
|
|
|
}
|
|
|
|
}
|
2024-02-18 03:12:44 -05:00
|
|
|
V::Result::output()
|
2021-08-26 18:42:08 +02:00
|
|
|
}
|
|
|
|
|
2022-07-03 15:28:57 +02:00
|
|
|
/// Visits all item-likes in the crate in some deterministic (but unspecified) order. If you
|
|
|
|
/// need to process every item-like, and don't care about visiting nested items in a particular
|
2022-11-16 20:34:16 +00:00
|
|
|
/// order then this method is the best choice. If you do care about this nesting, you should
|
2025-02-17 14:17:57 +11:00
|
|
|
/// use the `tcx.hir_walk_toplevel_module`.
|
2022-07-03 15:28:57 +02:00
|
|
|
///
|
2022-11-16 20:34:16 +00:00
|
|
|
/// Note that this function will access HIR for all the item-likes in the crate. If you only
|
2022-07-03 15:28:57 +02:00
|
|
|
/// need to access some of them, it is usually better to manually loop on the iterators
|
|
|
|
/// provided by `tcx.hir_crate_items(())`.
|
2021-09-12 01:11:22 +02:00
|
|
|
///
|
2022-05-07 16:35:38 -04:00
|
|
|
/// Please see the notes in `intravisit.rs` for more information.
|
2025-02-17 14:17:57 +11:00
|
|
|
pub fn hir_visit_all_item_likes_in_crate<V>(self, visitor: &mut V) -> V::Result
|
2021-09-12 01:11:22 +02:00
|
|
|
where
|
2025-02-17 14:17:57 +11:00
|
|
|
V: Visitor<'tcx>,
|
2021-09-12 01:11:22 +02:00
|
|
|
{
|
2025-02-17 14:17:57 +11:00
|
|
|
let krate = self.hir_crate_items(());
|
|
|
|
walk_list!(visitor, visit_item, krate.free_items().map(|id| self.hir_item(id)));
|
2025-02-03 10:45:49 +11:00
|
|
|
walk_list!(
|
|
|
|
visitor,
|
|
|
|
visit_trait_item,
|
2025-02-17 14:17:57 +11:00
|
|
|
krate.trait_items().map(|id| self.hir_trait_item(id))
|
2025-02-03 10:45:49 +11:00
|
|
|
);
|
2025-02-17 14:17:57 +11:00
|
|
|
walk_list!(visitor, visit_impl_item, krate.impl_items().map(|id| self.hir_impl_item(id)));
|
2024-02-18 03:12:44 -05:00
|
|
|
walk_list!(
|
|
|
|
visitor,
|
|
|
|
visit_foreign_item,
|
2025-02-17 14:17:57 +11:00
|
|
|
krate.foreign_items().map(|id| self.hir_foreign_item(id))
|
2024-02-18 03:12:44 -05:00
|
|
|
);
|
|
|
|
V::Result::output()
|
2021-09-12 01:11:22 +02:00
|
|
|
}
|
|
|
|
|
2022-07-03 15:28:57 +02:00
|
|
|
/// This method is the equivalent of `visit_all_item_likes_in_crate` but restricted to
|
|
|
|
/// item-likes in a single module.
|
2025-02-17 14:17:57 +11:00
|
|
|
pub fn hir_visit_item_likes_in_module<V>(
|
|
|
|
self,
|
|
|
|
module: LocalModDefId,
|
|
|
|
visitor: &mut V,
|
|
|
|
) -> V::Result
|
2018-06-06 22:13:52 +02:00
|
|
|
where
|
2025-02-17 14:17:57 +11:00
|
|
|
V: Visitor<'tcx>,
|
2018-06-06 22:13:52 +02:00
|
|
|
{
|
2025-02-17 14:17:57 +11:00
|
|
|
let module = self.hir_module_items(module);
|
|
|
|
walk_list!(visitor, visit_item, module.free_items().map(|id| self.hir_item(id)));
|
2025-02-03 10:45:49 +11:00
|
|
|
walk_list!(
|
|
|
|
visitor,
|
|
|
|
visit_trait_item,
|
2025-02-17 14:17:57 +11:00
|
|
|
module.trait_items().map(|id| self.hir_trait_item(id))
|
2025-02-03 10:45:49 +11:00
|
|
|
);
|
2025-02-17 14:17:57 +11:00
|
|
|
walk_list!(visitor, visit_impl_item, module.impl_items().map(|id| self.hir_impl_item(id)));
|
2024-02-18 03:12:44 -05:00
|
|
|
walk_list!(
|
|
|
|
visitor,
|
|
|
|
visit_foreign_item,
|
2025-02-17 14:17:57 +11:00
|
|
|
module.foreign_items().map(|id| self.hir_foreign_item(id))
|
2024-02-18 03:12:44 -05:00
|
|
|
);
|
|
|
|
V::Result::output()
|
2018-06-06 22:13:52 +02:00
|
|
|
}
|
|
|
|
|
2025-02-17 14:17:57 +11:00
|
|
|
pub fn hir_for_each_module(self, mut f: impl FnMut(LocalModDefId)) {
|
|
|
|
let crate_items = self.hir_crate_items(());
|
2022-04-03 15:50:33 -04:00
|
|
|
for module in crate_items.submodules.iter() {
|
2023-04-26 20:53:51 +02:00
|
|
|
f(LocalModDefId::new_unchecked(module.def_id))
|
2021-07-18 18:12:17 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-08 17:24:03 +02:00
|
|
|
#[inline]
|
2025-02-17 14:17:57 +11:00
|
|
|
pub fn par_hir_for_each_module(self, f: impl Fn(LocalModDefId) + DynSend + DynSync) {
|
|
|
|
let crate_items = self.hir_crate_items(());
|
2023-04-26 20:53:51 +02:00
|
|
|
par_for_each_in(&crate_items.submodules[..], |module| {
|
|
|
|
f(LocalModDefId::new_unchecked(module.def_id))
|
|
|
|
})
|
2021-07-18 18:12:17 +02:00
|
|
|
}
|
|
|
|
|
2023-10-18 08:47:17 +00:00
|
|
|
#[inline]
|
2025-02-17 14:17:57 +11:00
|
|
|
pub fn try_par_hir_for_each_module(
|
2023-10-18 08:47:17 +00:00
|
|
|
self,
|
|
|
|
f: impl Fn(LocalModDefId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync,
|
|
|
|
) -> Result<(), ErrorGuaranteed> {
|
2025-02-17 14:17:57 +11:00
|
|
|
let crate_items = self.hir_crate_items(());
|
2023-10-18 08:47:17 +00:00
|
|
|
try_par_for_each_in(&crate_items.submodules[..], |module| {
|
|
|
|
f(LocalModDefId::new_unchecked(module.def_id))
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-02-25 05:30:11 +01:00
|
|
|
/// Returns an iterator for the nodes in the ancestor tree of the `current_id`
|
2023-01-03 07:31:04 +00:00
|
|
|
/// until the crate root is reached. Prefer this over your own loop using `parent_id`.
|
2022-07-30 22:44:49 +02:00
|
|
|
#[inline]
|
2025-02-20 18:58:46 +00:00
|
|
|
pub fn hir_parent_id_iter(self, current_id: HirId) -> impl Iterator<Item = HirId> {
|
2025-02-21 07:54:35 +11:00
|
|
|
ParentHirIterator::new(self, current_id)
|
2020-02-25 05:30:11 +01:00
|
|
|
}
|
|
|
|
|
2022-09-15 18:39:53 +02:00
|
|
|
/// Returns an iterator for the nodes in the ancestor tree of the `current_id`
|
2023-01-03 07:31:04 +00:00
|
|
|
/// until the crate root is reached. Prefer this over your own loop using `parent_id`.
|
2022-09-15 18:39:53 +02:00
|
|
|
#[inline]
|
2025-02-21 07:54:35 +11:00
|
|
|
pub fn hir_parent_iter(self, current_id: HirId) -> impl Iterator<Item = (HirId, Node<'tcx>)> {
|
|
|
|
self.hir_parent_id_iter(current_id).map(move |id| (id, self.hir_node(id)))
|
2022-09-15 18:39:53 +02:00
|
|
|
}
|
|
|
|
|
2021-03-03 21:50:45 +01:00
|
|
|
/// Returns an iterator for the nodes in the ancestor tree of the `current_id`
|
2023-01-03 07:31:04 +00:00
|
|
|
/// until the crate root is reached. Prefer this over your own loop using `parent_id`.
|
2022-07-30 22:44:49 +02:00
|
|
|
#[inline]
|
2025-02-21 07:54:35 +11:00
|
|
|
pub fn hir_parent_owner_iter(self, current_id: HirId) -> ParentOwnerIterator<'tcx> {
|
|
|
|
ParentOwnerIterator { current_id, tcx: self }
|
2021-03-03 21:50:45 +01:00
|
|
|
}
|
|
|
|
|
2021-01-24 10:32:24 +03:00
|
|
|
/// Checks if the node is left-hand side of an assignment.
|
2025-02-21 07:54:35 +11:00
|
|
|
pub fn hir_is_lhs(self, id: HirId) -> bool {
|
|
|
|
match self.parent_hir_node(id) {
|
2024-02-09 23:58:36 +03:00
|
|
|
Node::Expr(expr) => match expr.kind {
|
2021-01-24 10:32:24 +03:00
|
|
|
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.
|
2025-02-21 07:54:35 +11:00
|
|
|
pub fn hir_is_inside_const_context(self, hir_id: HirId) -> bool {
|
|
|
|
self.hir_body_const_context(self.hir_enclosing_body_owner(hir_id)).is_some()
|
2019-04-29 17:14:31 -07:00
|
|
|
}
|
|
|
|
|
2024-04-11 13:14:08 -04:00
|
|
|
/// Retrieves the `HirId` for `id`'s enclosing function *if* the `id` block or return is
|
|
|
|
/// in the "tail" position of the function, in other words if it's likely to correspond
|
|
|
|
/// to the return type of the function.
|
2017-06-27 13:34:56 -07:00
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// fn foo(x: usize) -> bool {
|
|
|
|
/// if x == 1 {
|
2024-04-11 13:14:08 -04:00
|
|
|
/// true // If `get_fn_id_for_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
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
/// ```
|
|
|
|
///
|
2022-04-15 15:04:34 -07:00
|
|
|
/// ```compile_fail,E0308
|
2017-06-27 13:34:56 -07:00
|
|
|
/// fn foo(x: usize) -> bool {
|
|
|
|
/// loop {
|
2024-04-11 13:14:08 -04:00
|
|
|
/// true // If `get_fn_id_for_return_block` gets passed the `id` corresponding
|
2017-06-27 13:34:56 -07:00
|
|
|
/// } // to this, it will return `None`.
|
|
|
|
/// false
|
|
|
|
/// }
|
|
|
|
/// ```
|
2025-02-21 07:54:35 +11:00
|
|
|
pub fn hir_get_fn_id_for_return_block(self, id: HirId) -> Option<HirId> {
|
|
|
|
let enclosing_body_owner = self.local_def_id_to_hir_id(self.hir_enclosing_body_owner(id));
|
2024-08-16 20:53:02 +01:00
|
|
|
|
|
|
|
// Return `None` if the `id` expression is not the returned value of the enclosing body
|
2025-02-21 07:54:35 +11:00
|
|
|
let mut iter = [id].into_iter().chain(self.hir_parent_id_iter(id)).peekable();
|
2024-08-16 20:53:02 +01:00
|
|
|
while let Some(cur_id) = iter.next() {
|
|
|
|
if enclosing_body_owner == cur_id {
|
|
|
|
break;
|
|
|
|
}
|
2023-08-30 07:40:08 +05:30
|
|
|
|
2024-08-16 20:53:02 +01:00
|
|
|
// A return statement is always the value returned from the enclosing body regardless of
|
|
|
|
// what the parent expressions are.
|
2025-02-21 07:54:35 +11:00
|
|
|
if let Node::Expr(Expr { kind: ExprKind::Ret(_), .. }) = self.hir_node(cur_id) {
|
2024-08-16 20:53:02 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2025-02-21 07:54:35 +11:00
|
|
|
// If the current expression's value doesnt get used as the parent expressions value
|
|
|
|
// then return `None`
|
2024-08-16 20:53:02 +01:00
|
|
|
if let Some(&parent_id) = iter.peek() {
|
2025-02-21 07:54:35 +11:00
|
|
|
match self.hir_node(parent_id) {
|
|
|
|
// The current node is not the tail expression of the block expression parent
|
|
|
|
// expr.
|
2024-08-16 20:53:02 +01:00
|
|
|
Node::Block(Block { expr: Some(e), .. }) if cur_id != e.hir_id => return None,
|
2024-04-11 13:40:16 -04:00
|
|
|
Node::Block(Block { expr: Some(e), .. })
|
|
|
|
if matches!(e.kind, ExprKind::If(_, _, None)) =>
|
|
|
|
{
|
|
|
|
return None;
|
|
|
|
}
|
2024-08-16 20:53:02 +01:00
|
|
|
|
2025-02-21 07:54:35 +11:00
|
|
|
// The current expression's value does not pass up through these parent
|
|
|
|
// expressions.
|
2024-08-16 20:53:02 +01:00
|
|
|
Node::Block(Block { expr: None, .. })
|
|
|
|
| Node::Expr(Expr { kind: ExprKind::Loop(..), .. })
|
|
|
|
| Node::LetStmt(..) => return None,
|
|
|
|
|
2019-09-25 23:01:01 -07:00
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
2019-09-25 17:05:30 -07:00
|
|
|
}
|
2024-08-16 20:53:02 +01:00
|
|
|
|
|
|
|
Some(enclosing_body_owner)
|
2017-06-24 00:57:39 -07:00
|
|
|
}
|
|
|
|
|
2022-09-20 14:11:23 +09:00
|
|
|
/// Retrieves the `OwnerId` 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.
|
2025-02-21 07:54:35 +11:00
|
|
|
pub fn hir_get_parent_item(self, hir_id: HirId) -> OwnerId {
|
2024-09-23 09:36:17 +00:00
|
|
|
if hir_id.local_id != ItemLocalId::ZERO {
|
|
|
|
// If this is a child of a HIR owner, return the owner.
|
2024-09-20 16:12:44 +02:00
|
|
|
hir_id.owner
|
2025-02-21 07:54:35 +11:00
|
|
|
} else if let Some((def_id, _node)) = self.hir_parent_owner_iter(hir_id).next() {
|
2021-10-21 19:41:47 +02:00
|
|
|
def_id
|
2021-03-27 13:56:22 +01:00
|
|
|
} else {
|
2022-09-20 14:11:23 +09:00
|
|
|
CRATE_OWNER_ID
|
2015-07-01 08:58:48 +12:00
|
|
|
}
|
2015-06-16 21:56:33 +12: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.
|
2025-02-21 07:54:35 +11:00
|
|
|
pub fn hir_get_if_cause(self, hir_id: HirId) -> Option<&'tcx Expr<'tcx>> {
|
|
|
|
for (_, node) in self.hir_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(_)
|
2024-03-14 11:53:38 +01:00
|
|
|
| Node::Stmt(Stmt { kind: StmtKind::Let(_), .. }) => 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.
|
2025-02-21 07:54:35 +11:00
|
|
|
pub fn hir_get_enclosing_scope(self, hir_id: HirId) -> Option<HirId> {
|
|
|
|
for (hir_id, node) in self.hir_parent_iter(hir_id) {
|
2020-03-24 06:17:44 +01:00
|
|
|
if let Node::Item(Item {
|
|
|
|
kind:
|
2025-01-04 11:30:31 +01:00
|
|
|
ItemKind::Fn { .. }
|
2020-05-10 11:57:58 +01:00
|
|
|
| ItemKind::Const(..)
|
|
|
|
| ItemKind::Static(..)
|
2019-09-25 17:05:30 -07: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.
|
2025-02-21 07:54:35 +11:00
|
|
|
pub fn hir_get_defining_scope(self, id: HirId) -> HirId {
|
2019-02-28 22:43:53 +00:00
|
|
|
let mut scope = id;
|
|
|
|
loop {
|
2025-02-21 07:54:35 +11:00
|
|
|
scope = self.hir_get_enclosing_scope(scope).unwrap_or(CRATE_HIR_ID);
|
|
|
|
if scope == CRATE_HIR_ID || !matches!(self.hir_node(scope), Node::Block(_)) {
|
2021-01-10 14:38:14 +01:00
|
|
|
return scope;
|
2019-02-28 22:43:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2025-02-21 18:51:45 +11:00
|
|
|
|
|
|
|
/// Get a representation of this `id` for debugging purposes.
|
|
|
|
/// NOTE: Do NOT use this in diagnostics!
|
|
|
|
pub fn hir_id_to_string(self, id: HirId) -> String {
|
|
|
|
let path_str = |def_id: LocalDefId| self.def_path_str(def_id);
|
|
|
|
|
2025-04-02 07:04:24 +11:00
|
|
|
let span_str =
|
|
|
|
|| self.sess.source_map().span_to_snippet(self.hir_span(id)).unwrap_or_default();
|
2025-02-21 18:51:45 +11:00
|
|
|
let node_str = |prefix| format!("{id} ({prefix} `{}`)", span_str());
|
|
|
|
|
|
|
|
match self.hir_node(id) {
|
|
|
|
Node::Item(item) => {
|
|
|
|
let item_str = match item.kind {
|
|
|
|
ItemKind::ExternCrate(..) => "extern crate",
|
|
|
|
ItemKind::Use(..) => "use",
|
|
|
|
ItemKind::Static(..) => "static",
|
|
|
|
ItemKind::Const(..) => "const",
|
|
|
|
ItemKind::Fn { .. } => "fn",
|
|
|
|
ItemKind::Macro(..) => "macro",
|
|
|
|
ItemKind::Mod(..) => "mod",
|
|
|
|
ItemKind::ForeignMod { .. } => "foreign mod",
|
|
|
|
ItemKind::GlobalAsm { .. } => "global asm",
|
|
|
|
ItemKind::TyAlias(..) => "ty",
|
|
|
|
ItemKind::Enum(..) => "enum",
|
|
|
|
ItemKind::Struct(..) => "struct",
|
|
|
|
ItemKind::Union(..) => "union",
|
|
|
|
ItemKind::Trait(..) => "trait",
|
|
|
|
ItemKind::TraitAlias(..) => "trait alias",
|
|
|
|
ItemKind::Impl { .. } => "impl",
|
|
|
|
};
|
|
|
|
format!("{id} ({item_str} {})", path_str(item.owner_id.def_id))
|
|
|
|
}
|
|
|
|
Node::ForeignItem(item) => {
|
|
|
|
format!("{id} (foreign item {})", path_str(item.owner_id.def_id))
|
|
|
|
}
|
|
|
|
Node::ImplItem(ii) => {
|
|
|
|
let kind = match ii.kind {
|
|
|
|
ImplItemKind::Const(..) => "associated constant",
|
|
|
|
ImplItemKind::Fn(fn_sig, _) => match fn_sig.decl.implicit_self {
|
|
|
|
ImplicitSelfKind::None => "associated function",
|
|
|
|
_ => "method",
|
|
|
|
},
|
|
|
|
ImplItemKind::Type(_) => "associated type",
|
|
|
|
};
|
|
|
|
format!("{id} ({kind} `{}` in {})", ii.ident, path_str(ii.owner_id.def_id))
|
|
|
|
}
|
|
|
|
Node::TraitItem(ti) => {
|
|
|
|
let kind = match ti.kind {
|
|
|
|
TraitItemKind::Const(..) => "associated constant",
|
|
|
|
TraitItemKind::Fn(fn_sig, _) => match fn_sig.decl.implicit_self {
|
|
|
|
ImplicitSelfKind::None => "associated function",
|
|
|
|
_ => "trait method",
|
|
|
|
},
|
|
|
|
TraitItemKind::Type(..) => "associated type",
|
|
|
|
};
|
|
|
|
|
|
|
|
format!("{id} ({kind} `{}` in {})", ti.ident, path_str(ti.owner_id.def_id))
|
|
|
|
}
|
|
|
|
Node::Variant(variant) => {
|
|
|
|
format!("{id} (variant `{}` in {})", variant.ident, path_str(variant.def_id))
|
|
|
|
}
|
|
|
|
Node::Field(field) => {
|
|
|
|
format!("{id} (field `{}` in {})", field.ident, path_str(field.def_id))
|
|
|
|
}
|
|
|
|
Node::AnonConst(_) => node_str("const"),
|
|
|
|
Node::ConstBlock(_) => node_str("const"),
|
|
|
|
Node::ConstArg(_) => node_str("const"),
|
|
|
|
Node::Expr(_) => node_str("expr"),
|
|
|
|
Node::ExprField(_) => node_str("expr field"),
|
|
|
|
Node::Stmt(_) => node_str("stmt"),
|
|
|
|
Node::PathSegment(_) => node_str("path segment"),
|
|
|
|
Node::Ty(_) => node_str("type"),
|
|
|
|
Node::AssocItemConstraint(_) => node_str("assoc item constraint"),
|
|
|
|
Node::TraitRef(_) => node_str("trait ref"),
|
|
|
|
Node::OpaqueTy(_) => node_str("opaque type"),
|
|
|
|
Node::Pat(_) => node_str("pat"),
|
|
|
|
Node::TyPat(_) => node_str("pat ty"),
|
|
|
|
Node::PatField(_) => node_str("pattern field"),
|
|
|
|
Node::PatExpr(_) => node_str("pattern literal"),
|
|
|
|
Node::Param(_) => node_str("param"),
|
|
|
|
Node::Arm(_) => node_str("arm"),
|
|
|
|
Node::Block(_) => node_str("block"),
|
|
|
|
Node::Infer(_) => node_str("infer"),
|
|
|
|
Node::LetStmt(_) => node_str("local"),
|
|
|
|
Node::Ctor(ctor) => format!(
|
|
|
|
"{id} (ctor {})",
|
|
|
|
ctor.ctor_def_id().map_or("<missing path>".into(), |def_id| path_str(def_id)),
|
|
|
|
),
|
|
|
|
Node::Lifetime(_) => node_str("lifetime"),
|
|
|
|
Node::GenericParam(param) => {
|
|
|
|
format!("{id} (generic_param {})", path_str(param.def_id))
|
|
|
|
}
|
|
|
|
Node::Crate(..) => String::from("(root_crate)"),
|
|
|
|
Node::WherePredicate(_) => node_str("where predicate"),
|
|
|
|
Node::Synthetic => unreachable!(),
|
|
|
|
Node::Err(_) => node_str("error"),
|
|
|
|
Node::PreciseCapturingNonLifetimeArg(_param) => node_str("parameter"),
|
|
|
|
}
|
|
|
|
}
|
2019-02-28 22:43:53 +00:00
|
|
|
|
2025-02-21 18:33:05 +11:00
|
|
|
pub fn hir_get_foreign_abi(self, hir_id: HirId) -> ExternAbi {
|
|
|
|
let parent = self.hir_get_parent_item(hir_id);
|
2024-01-25 19:34:49 +03:00
|
|
|
if let OwnerNode::Item(Item { kind: ItemKind::ForeignMod { abi, .. }, .. }) =
|
2025-02-21 18:33:05 +11:00
|
|
|
self.hir_owner_node(parent)
|
2024-01-15 22:31:02 +00:00
|
|
|
{
|
|
|
|
return *abi;
|
2014-02-14 07:07:09 +02:00
|
|
|
}
|
2021-10-21 19:41:47 +02:00
|
|
|
bug!(
|
|
|
|
"expected foreign mod or inlined parent, found {}",
|
2025-02-21 18:33:05 +11:00
|
|
|
self.hir_id_to_string(HirId::make_owner(parent.def_id))
|
2021-10-21 19:41:47 +02:00
|
|
|
)
|
2019-02-04 11:09:32 +01:00
|
|
|
}
|
|
|
|
|
2025-02-21 18:33:05 +11:00
|
|
|
pub fn hir_expect_item(self, id: LocalDefId) -> &'tcx Item<'tcx> {
|
|
|
|
match self.expect_hir_owner_node(id) {
|
2024-01-25 19:34:49 +03:00
|
|
|
OwnerNode::Item(item) => item,
|
2025-02-21 18:33:05 +11:00
|
|
|
_ => bug!("expected item, found {}", self.hir_id_to_string(HirId::make_owner(id))),
|
2019-03-07 15:46:41 +01:00
|
|
|
}
|
2019-02-03 09:14:31 +01:00
|
|
|
}
|
|
|
|
|
2025-02-21 18:33:05 +11:00
|
|
|
pub fn hir_expect_impl_item(self, id: LocalDefId) -> &'tcx ImplItem<'tcx> {
|
|
|
|
match self.expect_hir_owner_node(id) {
|
2024-01-25 19:34:49 +03:00
|
|
|
OwnerNode::ImplItem(item) => item,
|
2025-02-21 18:33:05 +11:00
|
|
|
_ => bug!("expected impl item, found {}", self.hir_id_to_string(HirId::make_owner(id))),
|
2016-08-10 01:43:12 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-21 18:33:05 +11:00
|
|
|
pub fn hir_expect_trait_item(self, id: LocalDefId) -> &'tcx TraitItem<'tcx> {
|
|
|
|
match self.expect_hir_owner_node(id) {
|
2024-01-25 19:34:49 +03:00
|
|
|
OwnerNode::TraitItem(item) => item,
|
2021-10-20 22:38:10 +02:00
|
|
|
_ => {
|
2025-02-21 18:33:05 +11:00
|
|
|
bug!("expected trait item, found {}", self.hir_id_to_string(HirId::make_owner(id)))
|
2021-10-20 22:38:10 +02:00
|
|
|
}
|
2014-02-14 07:07:09 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-21 18:33:05 +11:00
|
|
|
pub fn hir_get_fn_output(self, def_id: LocalDefId) -> Option<&'tcx FnRetTy<'tcx>> {
|
|
|
|
Some(&self.opt_hir_owner_node(def_id)?.fn_decl()?.output)
|
|
|
|
}
|
|
|
|
|
2024-08-09 20:43:30 -07:00
|
|
|
#[track_caller]
|
2025-02-21 18:33:05 +11:00
|
|
|
pub fn hir_expect_opaque_ty(self, id: LocalDefId) -> &'tcx OpaqueTy<'tcx> {
|
|
|
|
match self.hir_node_by_def_id(id) {
|
2024-08-09 20:43:30 -07:00
|
|
|
Node::OpaqueTy(opaq) => opaq,
|
|
|
|
_ => {
|
|
|
|
bug!(
|
|
|
|
"expected opaque type definition, found {}",
|
2025-02-21 18:33:05 +11:00
|
|
|
self.hir_id_to_string(self.local_def_id_to_hir_id(id))
|
2024-08-09 20:43:30 -07:00
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-21 18:33:05 +11:00
|
|
|
pub fn hir_expect_expr(self, id: HirId) -> &'tcx Expr<'tcx> {
|
|
|
|
match self.hir_node(id) {
|
2024-01-21 21:13:15 +03:00
|
|
|
Node::Expr(expr) => expr,
|
2025-02-21 18:33:05 +11:00
|
|
|
_ => bug!("expected expr, found {}", self.hir_id_to_string(id)),
|
2019-03-09 08:57:35 +01:00
|
|
|
}
|
2019-02-04 11:09:32 +01:00
|
|
|
}
|
|
|
|
|
2025-02-21 18:33:05 +11:00
|
|
|
pub fn hir_opt_delegation_sig_id(self, def_id: LocalDefId) -> Option<DefId> {
|
|
|
|
self.opt_hir_owner_node(def_id)?.fn_decl()?.opt_delegation_sig_id()
|
2024-05-30 22:00:44 +03:00
|
|
|
}
|
|
|
|
|
2022-04-19 21:25:26 +02:00
|
|
|
#[inline]
|
2025-02-21 18:33:05 +11:00
|
|
|
fn hir_opt_ident(self, id: HirId) -> Option<Ident> {
|
|
|
|
match self.hir_node(id) {
|
2022-06-28 13:15:30 -05:00
|
|
|
Node::Pat(&Pat { kind: PatKind::Binding(_, _, ident, _), .. }) => Some(ident),
|
2022-04-08 18:53:16 +02:00
|
|
|
// A `Ctor` doesn't have an identifier itself, but its parent
|
2024-01-21 21:13:15 +03:00
|
|
|
// struct/variant does. Compare with `hir::Map::span`.
|
2025-02-21 18:33:05 +11:00
|
|
|
Node::Ctor(..) => match self.parent_hir_node(id) {
|
Move `hir::Item::ident` into `hir::ItemKind`.
`hir::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Macro`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
Trait`, TraitAalis`.
- It's always empty for these item kinds: `ForeignMod`, `GlobalAsm`,
`Impl`.
- For `Use`, it is non-empty for `UseKind::Single` and empty for
`UseKind::{Glob,ListStem}`.
All of this is quite non-obvious; the only documentation is a single
comment saying "The name might be a dummy name in case of anonymous
items". Some sites that handle items check for an empty ident, some
don't. This is a very C-like way of doing things, but this is Rust, we
have sum types, we can do this properly and never forget to check for
the exceptional case and never YOLO possibly empty identifiers (or
possibly dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- A similar transformation makes sense for `ast::Item`, but this is
already a big change. That can be done later.
- Lots of assertions are added to item lowering to ensure that
identifiers are empty/non-empty as expected. These will be removable
when `ast::Item` is done later.
- `ItemKind::Use` doesn't get an `Ident`, but `UseKind::Single` does.
- `lower_use_tree` is significantly simpler. No more confusing `&mut
Ident` to deal with.
- `ItemKind::ident` is a new method, it returns an `Option<Ident>`. It's
used with `unwrap` in a few places; sometimes it's hard to tell
exactly which item kinds might occur. None of these unwraps fail on
the test suite. It's conceivable that some might fail on alternative
input. We can deal with those if/when they happen.
- In `trait_path` the `find_map`/`if let` is replaced with a loop, and
things end up much clearer that way.
- `named_span` no longer checks for an empty name; instead the call site
now checks for a missing identifier if necessary.
- `maybe_inline_local` doesn't need the `glob` argument, it can be
computed in-function from the `renamed` argument.
- `arbitrary_source_item_ordering::check_mod` had a big `if` statement
that was just getting the ident from the item kinds that had one. It
could be mostly replaced by a single call to the new `ItemKind::ident`
method.
- `ItemKind` grows from 56 to 64 bytes, but `Item` stays the same size,
and that's what matters, because `ItemKind` only occurs within `Item`.
2025-03-06 19:07:36 +11:00
|
|
|
Node::Item(item) => Some(item.kind.ident().unwrap()),
|
2022-04-08 18:53:16 +02:00
|
|
|
Node::Variant(variant) => Some(variant.ident),
|
|
|
|
_ => unreachable!(),
|
|
|
|
},
|
|
|
|
node => node.ident(),
|
2022-04-19 21:25:26 +02:00
|
|
|
}
|
2022-04-08 18:53:16 +02:00
|
|
|
}
|
|
|
|
|
2022-04-19 21:25:26 +02:00
|
|
|
#[inline]
|
2025-02-21 18:33:05 +11:00
|
|
|
pub(super) fn hir_opt_ident_span(self, id: HirId) -> Option<Span> {
|
|
|
|
self.hir_opt_ident(id).map(|ident| ident.span)
|
2022-04-19 21:25:26 +02:00
|
|
|
}
|
|
|
|
|
2022-10-25 17:59:18 +00:00
|
|
|
#[inline]
|
2025-02-21 18:33:05 +11:00
|
|
|
pub fn hir_ident(self, id: HirId) -> Ident {
|
|
|
|
self.hir_opt_ident(id).unwrap()
|
2022-10-25 17:59:18 +00:00
|
|
|
}
|
|
|
|
|
2022-04-19 21:25:26 +02:00
|
|
|
#[inline]
|
2025-02-21 18:33:05 +11:00
|
|
|
pub fn hir_opt_name(self, id: HirId) -> Option<Symbol> {
|
|
|
|
self.hir_opt_ident(id).map(|ident| ident.name)
|
2019-12-13 15:27:55 -08:00
|
|
|
}
|
|
|
|
|
2025-02-21 18:33:05 +11:00
|
|
|
pub fn hir_name(self, id: HirId) -> Symbol {
|
|
|
|
self.hir_opt_name(id).unwrap_or_else(|| bug!("no name for {}", self.hir_id_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.
|
2025-02-21 18:33:05 +11:00
|
|
|
pub fn hir_attrs(self, id: HirId) -> &'tcx [Attribute] {
|
|
|
|
self.hir_attr_map(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.
|
2022-02-13 16:27:59 +01:00
|
|
|
/// This is used by `tcx.def_span`.
|
2025-04-02 07:04:24 +11:00
|
|
|
pub fn hir_span(self, hir_id: HirId) -> Span {
|
2022-02-13 16:27:59 +01:00
|
|
|
fn until_within(outer: Span, end: Span) -> Span {
|
|
|
|
if let Some(end) = end.find_ancestor_inside(outer) {
|
|
|
|
outer.with_hi(end.hi())
|
|
|
|
} else {
|
|
|
|
outer
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn named_span(item_span: Span, ident: Ident, generics: Option<&Generics<'_>>) -> Span {
|
Move `hir::Item::ident` into `hir::ItemKind`.
`hir::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Macro`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
Trait`, TraitAalis`.
- It's always empty for these item kinds: `ForeignMod`, `GlobalAsm`,
`Impl`.
- For `Use`, it is non-empty for `UseKind::Single` and empty for
`UseKind::{Glob,ListStem}`.
All of this is quite non-obvious; the only documentation is a single
comment saying "The name might be a dummy name in case of anonymous
items". Some sites that handle items check for an empty ident, some
don't. This is a very C-like way of doing things, but this is Rust, we
have sum types, we can do this properly and never forget to check for
the exceptional case and never YOLO possibly empty identifiers (or
possibly dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- A similar transformation makes sense for `ast::Item`, but this is
already a big change. That can be done later.
- Lots of assertions are added to item lowering to ensure that
identifiers are empty/non-empty as expected. These will be removable
when `ast::Item` is done later.
- `ItemKind::Use` doesn't get an `Ident`, but `UseKind::Single` does.
- `lower_use_tree` is significantly simpler. No more confusing `&mut
Ident` to deal with.
- `ItemKind::ident` is a new method, it returns an `Option<Ident>`. It's
used with `unwrap` in a few places; sometimes it's hard to tell
exactly which item kinds might occur. None of these unwraps fail on
the test suite. It's conceivable that some might fail on alternative
input. We can deal with those if/when they happen.
- In `trait_path` the `find_map`/`if let` is replaced with a loop, and
things end up much clearer that way.
- `named_span` no longer checks for an empty name; instead the call site
now checks for a missing identifier if necessary.
- `maybe_inline_local` doesn't need the `glob` argument, it can be
computed in-function from the `renamed` argument.
- `arbitrary_source_item_ordering::check_mod` had a big `if` statement
that was just getting the ident from the item kinds that had one. It
could be mostly replaced by a single call to the new `ItemKind::ident`
method.
- `ItemKind` grows from 56 to 64 bytes, but `Item` stays the same size,
and that's what matters, because `ItemKind` only occurs within `Item`.
2025-03-06 19:07:36 +11:00
|
|
|
let mut span = until_within(item_span, ident.span);
|
|
|
|
if let Some(g) = generics
|
|
|
|
&& !g.span.is_dummy()
|
|
|
|
&& let Some(g_span) = g.span.find_ancestor_inside(item_span)
|
|
|
|
{
|
|
|
|
span = span.to(g_span);
|
2022-02-13 16:27:59 +01:00
|
|
|
}
|
Move `hir::Item::ident` into `hir::ItemKind`.
`hir::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Macro`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
Trait`, TraitAalis`.
- It's always empty for these item kinds: `ForeignMod`, `GlobalAsm`,
`Impl`.
- For `Use`, it is non-empty for `UseKind::Single` and empty for
`UseKind::{Glob,ListStem}`.
All of this is quite non-obvious; the only documentation is a single
comment saying "The name might be a dummy name in case of anonymous
items". Some sites that handle items check for an empty ident, some
don't. This is a very C-like way of doing things, but this is Rust, we
have sum types, we can do this properly and never forget to check for
the exceptional case and never YOLO possibly empty identifiers (or
possibly dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- A similar transformation makes sense for `ast::Item`, but this is
already a big change. That can be done later.
- Lots of assertions are added to item lowering to ensure that
identifiers are empty/non-empty as expected. These will be removable
when `ast::Item` is done later.
- `ItemKind::Use` doesn't get an `Ident`, but `UseKind::Single` does.
- `lower_use_tree` is significantly simpler. No more confusing `&mut
Ident` to deal with.
- `ItemKind::ident` is a new method, it returns an `Option<Ident>`. It's
used with `unwrap` in a few places; sometimes it's hard to tell
exactly which item kinds might occur. None of these unwraps fail on
the test suite. It's conceivable that some might fail on alternative
input. We can deal with those if/when they happen.
- In `trait_path` the `find_map`/`if let` is replaced with a loop, and
things end up much clearer that way.
- `named_span` no longer checks for an empty name; instead the call site
now checks for a missing identifier if necessary.
- `maybe_inline_local` doesn't need the `glob` argument, it can be
computed in-function from the `renamed` argument.
- `arbitrary_source_item_ordering::check_mod` had a big `if` statement
that was just getting the ident from the item kinds that had one. It
could be mostly replaced by a single call to the new `ItemKind::ident`
method.
- `ItemKind` grows from 56 to 64 bytes, but `Item` stays the same size,
and that's what matters, because `ItemKind` only occurs within `Item`.
2025-03-06 19:07:36 +11:00
|
|
|
span
|
2022-02-13 16:27:59 +01:00
|
|
|
}
|
|
|
|
|
2025-04-02 07:04:24 +11:00
|
|
|
let span = match self.hir_node(hir_id) {
|
2022-02-13 16:27:59 +01:00
|
|
|
// Function-like.
|
2025-01-04 11:30:31 +01:00
|
|
|
Node::Item(Item { kind: ItemKind::Fn { sig, .. }, span: outer_span, .. })
|
2022-10-01 11:25:25 +02:00
|
|
|
| Node::TraitItem(TraitItem {
|
|
|
|
kind: TraitItemKind::Fn(sig, ..),
|
|
|
|
span: outer_span,
|
|
|
|
..
|
|
|
|
})
|
|
|
|
| Node::ImplItem(ImplItem {
|
|
|
|
kind: ImplItemKind::Fn(sig, ..), span: outer_span, ..
|
2024-08-07 13:01:34 -04:00
|
|
|
})
|
|
|
|
| Node::ForeignItem(ForeignItem {
|
|
|
|
kind: ForeignItemKind::Fn(sig, ..),
|
|
|
|
span: outer_span,
|
|
|
|
..
|
2022-10-01 11:25:25 +02:00
|
|
|
}) => {
|
|
|
|
// Ensure that the returned span has the item's SyntaxContext, and not the
|
|
|
|
// SyntaxContext of the visibility.
|
|
|
|
sig.span.find_ancestor_in_same_ctxt(*outer_span).unwrap_or(*outer_span)
|
|
|
|
}
|
2023-10-06 20:35:52 +00:00
|
|
|
// Impls, including their where clauses.
|
|
|
|
Node::Item(Item {
|
|
|
|
kind: ItemKind::Impl(Impl { generics, .. }),
|
|
|
|
span: outer_span,
|
|
|
|
..
|
|
|
|
}) => until_within(*outer_span, generics.where_clause_span),
|
2022-02-13 16:27:59 +01:00
|
|
|
// Constants and Statics.
|
|
|
|
Node::Item(Item {
|
Move `hir::Item::ident` into `hir::ItemKind`.
`hir::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Macro`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
Trait`, TraitAalis`.
- It's always empty for these item kinds: `ForeignMod`, `GlobalAsm`,
`Impl`.
- For `Use`, it is non-empty for `UseKind::Single` and empty for
`UseKind::{Glob,ListStem}`.
All of this is quite non-obvious; the only documentation is a single
comment saying "The name might be a dummy name in case of anonymous
items". Some sites that handle items check for an empty ident, some
don't. This is a very C-like way of doing things, but this is Rust, we
have sum types, we can do this properly and never forget to check for
the exceptional case and never YOLO possibly empty identifiers (or
possibly dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- A similar transformation makes sense for `ast::Item`, but this is
already a big change. That can be done later.
- Lots of assertions are added to item lowering to ensure that
identifiers are empty/non-empty as expected. These will be removable
when `ast::Item` is done later.
- `ItemKind::Use` doesn't get an `Ident`, but `UseKind::Single` does.
- `lower_use_tree` is significantly simpler. No more confusing `&mut
Ident` to deal with.
- `ItemKind::ident` is a new method, it returns an `Option<Ident>`. It's
used with `unwrap` in a few places; sometimes it's hard to tell
exactly which item kinds might occur. None of these unwraps fail on
the test suite. It's conceivable that some might fail on alternative
input. We can deal with those if/when they happen.
- In `trait_path` the `find_map`/`if let` is replaced with a loop, and
things end up much clearer that way.
- `named_span` no longer checks for an empty name; instead the call site
now checks for a missing identifier if necessary.
- `maybe_inline_local` doesn't need the `glob` argument, it can be
computed in-function from the `renamed` argument.
- `arbitrary_source_item_ordering::check_mod` had a big `if` statement
that was just getting the ident from the item kinds that had one. It
could be mostly replaced by a single call to the new `ItemKind::ident`
method.
- `ItemKind` grows from 56 to 64 bytes, but `Item` stays the same size,
and that's what matters, because `ItemKind` only occurs within `Item`.
2025-03-06 19:07:36 +11:00
|
|
|
kind: ItemKind::Const(_, ty, ..) | ItemKind::Static(_, ty, ..),
|
2022-02-13 16:27:59 +01:00
|
|
|
span: outer_span,
|
|
|
|
..
|
|
|
|
})
|
|
|
|
| Node::TraitItem(TraitItem {
|
|
|
|
kind: TraitItemKind::Const(ty, ..),
|
|
|
|
span: outer_span,
|
|
|
|
..
|
|
|
|
})
|
|
|
|
| Node::ImplItem(ImplItem {
|
|
|
|
kind: ImplItemKind::Const(ty, ..),
|
|
|
|
span: outer_span,
|
|
|
|
..
|
|
|
|
})
|
|
|
|
| Node::ForeignItem(ForeignItem {
|
|
|
|
kind: ForeignItemKind::Static(ty, ..),
|
|
|
|
span: outer_span,
|
|
|
|
..
|
|
|
|
}) => until_within(*outer_span, ty.span),
|
|
|
|
// With generics and bounds.
|
|
|
|
Node::Item(Item {
|
Move `hir::Item::ident` into `hir::ItemKind`.
`hir::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Macro`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
Trait`, TraitAalis`.
- It's always empty for these item kinds: `ForeignMod`, `GlobalAsm`,
`Impl`.
- For `Use`, it is non-empty for `UseKind::Single` and empty for
`UseKind::{Glob,ListStem}`.
All of this is quite non-obvious; the only documentation is a single
comment saying "The name might be a dummy name in case of anonymous
items". Some sites that handle items check for an empty ident, some
don't. This is a very C-like way of doing things, but this is Rust, we
have sum types, we can do this properly and never forget to check for
the exceptional case and never YOLO possibly empty identifiers (or
possibly dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- A similar transformation makes sense for `ast::Item`, but this is
already a big change. That can be done later.
- Lots of assertions are added to item lowering to ensure that
identifiers are empty/non-empty as expected. These will be removable
when `ast::Item` is done later.
- `ItemKind::Use` doesn't get an `Ident`, but `UseKind::Single` does.
- `lower_use_tree` is significantly simpler. No more confusing `&mut
Ident` to deal with.
- `ItemKind::ident` is a new method, it returns an `Option<Ident>`. It's
used with `unwrap` in a few places; sometimes it's hard to tell
exactly which item kinds might occur. None of these unwraps fail on
the test suite. It's conceivable that some might fail on alternative
input. We can deal with those if/when they happen.
- In `trait_path` the `find_map`/`if let` is replaced with a loop, and
things end up much clearer that way.
- `named_span` no longer checks for an empty name; instead the call site
now checks for a missing identifier if necessary.
- `maybe_inline_local` doesn't need the `glob` argument, it can be
computed in-function from the `renamed` argument.
- `arbitrary_source_item_ordering::check_mod` had a big `if` statement
that was just getting the ident from the item kinds that had one. It
could be mostly replaced by a single call to the new `ItemKind::ident`
method.
- `ItemKind` grows from 56 to 64 bytes, but `Item` stays the same size,
and that's what matters, because `ItemKind` only occurs within `Item`.
2025-03-06 19:07:36 +11:00
|
|
|
kind: ItemKind::Trait(_, _, _, generics, bounds, _),
|
2022-02-13 16:27:59 +01:00
|
|
|
span: outer_span,
|
|
|
|
..
|
|
|
|
})
|
|
|
|
| Node::TraitItem(TraitItem {
|
|
|
|
kind: TraitItemKind::Type(bounds, _),
|
|
|
|
generics,
|
|
|
|
span: outer_span,
|
|
|
|
..
|
|
|
|
}) => {
|
|
|
|
let end = if let Some(b) = bounds.last() { b.span() } else { generics.span };
|
|
|
|
until_within(*outer_span, end)
|
|
|
|
}
|
|
|
|
// Other cases.
|
2020-12-23 10:32:00 +01:00
|
|
|
Node::Item(item) => match &item.kind {
|
2022-10-01 11:25:25 +02:00
|
|
|
ItemKind::Use(path, _) => {
|
|
|
|
// Ensure that the returned span has the item's SyntaxContext, and not the
|
|
|
|
// SyntaxContext of the path.
|
|
|
|
path.span.find_ancestor_in_same_ctxt(item.span).unwrap_or(item.span)
|
|
|
|
}
|
Move `hir::Item::ident` into `hir::ItemKind`.
`hir::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Macro`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
Trait`, TraitAalis`.
- It's always empty for these item kinds: `ForeignMod`, `GlobalAsm`,
`Impl`.
- For `Use`, it is non-empty for `UseKind::Single` and empty for
`UseKind::{Glob,ListStem}`.
All of this is quite non-obvious; the only documentation is a single
comment saying "The name might be a dummy name in case of anonymous
items". Some sites that handle items check for an empty ident, some
don't. This is a very C-like way of doing things, but this is Rust, we
have sum types, we can do this properly and never forget to check for
the exceptional case and never YOLO possibly empty identifiers (or
possibly dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- A similar transformation makes sense for `ast::Item`, but this is
already a big change. That can be done later.
- Lots of assertions are added to item lowering to ensure that
identifiers are empty/non-empty as expected. These will be removable
when `ast::Item` is done later.
- `ItemKind::Use` doesn't get an `Ident`, but `UseKind::Single` does.
- `lower_use_tree` is significantly simpler. No more confusing `&mut
Ident` to deal with.
- `ItemKind::ident` is a new method, it returns an `Option<Ident>`. It's
used with `unwrap` in a few places; sometimes it's hard to tell
exactly which item kinds might occur. None of these unwraps fail on
the test suite. It's conceivable that some might fail on alternative
input. We can deal with those if/when they happen.
- In `trait_path` the `find_map`/`if let` is replaced with a loop, and
things end up much clearer that way.
- `named_span` no longer checks for an empty name; instead the call site
now checks for a missing identifier if necessary.
- `maybe_inline_local` doesn't need the `glob` argument, it can be
computed in-function from the `renamed` argument.
- `arbitrary_source_item_ordering::check_mod` had a big `if` statement
that was just getting the ident from the item kinds that had one. It
could be mostly replaced by a single call to the new `ItemKind::ident`
method.
- `ItemKind` grows from 56 to 64 bytes, but `Item` stays the same size,
and that's what matters, because `ItemKind` only occurs within `Item`.
2025-03-06 19:07:36 +11:00
|
|
|
_ => {
|
|
|
|
if let Some(ident) = item.kind.ident() {
|
|
|
|
named_span(item.span, ident, item.kind.generics())
|
|
|
|
} else {
|
|
|
|
item.span
|
|
|
|
}
|
|
|
|
}
|
2020-08-12 17:02:14 -04:00
|
|
|
},
|
2022-07-04 18:13:16 +09:00
|
|
|
Node::Variant(variant) => named_span(variant.span, variant.ident, None),
|
2022-02-13 16:27:59 +01:00
|
|
|
Node::ImplItem(item) => named_span(item.span, item.ident, Some(item.generics)),
|
2024-08-07 13:01:34 -04:00
|
|
|
Node::ForeignItem(item) => named_span(item.span, item.ident, None),
|
2025-04-02 07:04:24 +11:00
|
|
|
Node::Ctor(_) => return self.hir_span(self.parent_hir_id(hir_id)),
|
2022-10-01 11:25:25 +02:00
|
|
|
Node::Expr(Expr {
|
|
|
|
kind: ExprKind::Closure(Closure { fn_decl_span, .. }),
|
|
|
|
span,
|
|
|
|
..
|
|
|
|
}) => {
|
|
|
|
// Ensure that the returned span has the item's SyntaxContext.
|
2022-11-09 20:39:28 +05:30
|
|
|
fn_decl_span.find_ancestor_inside(*span).unwrap_or(*span)
|
2022-07-11 23:39:53 +04:00
|
|
|
}
|
2025-04-02 07:04:24 +11:00
|
|
|
_ => self.hir_span_with_body(hir_id),
|
2022-02-13 16:27:59 +01:00
|
|
|
};
|
2025-04-02 07:04:24 +11:00
|
|
|
debug_assert_eq!(span.ctxt(), self.hir_span_with_body(hir_id).ctxt());
|
2024-01-21 21:13:15 +03:00
|
|
|
span
|
2022-02-13 16:27:59 +01:00
|
|
|
}
|
|
|
|
|
2025-04-02 07:04:24 +11:00
|
|
|
/// Like `hir_span()`, but includes the body of items
|
2022-02-13 16:27:59 +01:00
|
|
|
/// (instead of just the item header)
|
2025-04-02 07:04:24 +11:00
|
|
|
pub fn hir_span_with_body(self, hir_id: HirId) -> Span {
|
|
|
|
match self.hir_node(hir_id) {
|
2022-02-13 16:27:59 +01:00
|
|
|
Node::Param(param) => param.span,
|
|
|
|
Node::Item(item) => item.span,
|
|
|
|
Node::ForeignItem(foreign_item) => foreign_item.span,
|
|
|
|
Node::TraitItem(trait_item) => trait_item.span,
|
|
|
|
Node::ImplItem(impl_item) => impl_item.span,
|
2020-12-23 10:32:00 +01:00
|
|
|
Node::Variant(variant) => variant.span,
|
|
|
|
Node::Field(field) => field.span,
|
2024-04-29 09:48:19 +00:00
|
|
|
Node::AnonConst(constant) => constant.span,
|
2025-04-02 07:04:24 +11:00
|
|
|
Node::ConstBlock(constant) => self.hir_body(constant.body).value.span,
|
2024-07-16 19:07:36 -07:00
|
|
|
Node::ConstArg(const_arg) => const_arg.span(),
|
2020-12-23 10:32:00 +01:00
|
|
|
Node::Expr(expr) => expr.span,
|
2022-05-03 13:23:03 -07:00
|
|
|
Node::ExprField(field) => field.span,
|
2020-12-23 10:32:00 +01:00
|
|
|
Node::Stmt(stmt) => stmt.span,
|
2022-02-14 13:25:26 +01:00
|
|
|
Node::PathSegment(seg) => {
|
|
|
|
let ident_span = seg.ident.span;
|
|
|
|
ident_span
|
|
|
|
.with_hi(seg.args.map_or_else(|| ident_span.hi(), |args| args.span_ext.hi()))
|
|
|
|
}
|
2020-12-23 10:32:00 +01:00
|
|
|
Node::Ty(ty) => ty.span,
|
2024-05-27 23:53:46 +02:00
|
|
|
Node::AssocItemConstraint(constraint) => constraint.span,
|
2020-12-23 10:32:00 +01:00
|
|
|
Node::TraitRef(tr) => tr.path.span,
|
2024-08-09 20:43:30 -07:00
|
|
|
Node::OpaqueTy(op) => op.span,
|
2020-12-23 10:32:00 +01:00
|
|
|
Node::Pat(pat) => pat.span,
|
2025-01-07 10:24:16 +00:00
|
|
|
Node::TyPat(pat) => pat.span,
|
2022-05-03 11:52:53 -07:00
|
|
|
Node::PatField(field) => field.span,
|
2024-12-11 16:50:45 +00:00
|
|
|
Node::PatExpr(lit) => lit.span,
|
2020-12-23 10:32:00 +01:00
|
|
|
Node::Arm(arm) => arm.span,
|
|
|
|
Node::Block(block) => block.span,
|
2025-04-02 07:04:24 +11:00
|
|
|
Node::Ctor(..) => self.hir_span_with_body(self.parent_hir_id(hir_id)),
|
2022-11-05 22:41:07 +00:00
|
|
|
Node::Lifetime(lifetime) => lifetime.ident.span,
|
2020-12-23 10:32:00 +01:00
|
|
|
Node::GenericParam(param) => param.span,
|
2021-04-24 21:41:57 +00:00
|
|
|
Node::Infer(i) => i.span,
|
2024-03-22 18:06:20 +01:00
|
|
|
Node::LetStmt(local) => local.span,
|
2022-03-18 17:13:38 -04:00
|
|
|
Node::Crate(item) => item.spans.inner_span,
|
2024-11-25 16:38:35 +08:00
|
|
|
Node::WherePredicate(pred) => pred.span,
|
2024-04-04 14:46:26 -04:00
|
|
|
Node::PreciseCapturingNonLifetimeArg(param) => param.ident.span,
|
2024-03-19 08:37:53 +00:00
|
|
|
Node::Synthetic => unreachable!(),
|
2024-04-26 13:09:04 +00:00
|
|
|
Node::Err(span) => span,
|
2020-08-12 17:02:14 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-04-02 07:04:24 +11:00
|
|
|
pub fn hir_span_if_local(self, id: DefId) -> Option<Span> {
|
|
|
|
id.is_local().then(|| self.def_span(id))
|
2015-09-04 13:52:28 -04:00
|
|
|
}
|
|
|
|
|
2025-04-02 07:04:24 +11:00
|
|
|
pub fn hir_res_span(self, res: Res) -> Option<Span> {
|
2019-09-28 02:30:48 +02:00
|
|
|
match res {
|
|
|
|
Res::Err => None,
|
2025-04-02 07:04:24 +11:00
|
|
|
Res::Local(id) => Some(self.hir_span(id)),
|
|
|
|
res => self.hir_span_if_local(res.opt_def_id()?),
|
2019-09-28 02:30:48 +02: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
|
2025-04-02 07:04:24 +11:00
|
|
|
pub fn hir_opt_const_param_default_param_def_id(self, anon_const: HirId) -> Option<LocalDefId> {
|
|
|
|
let const_arg = self.parent_hir_id(anon_const);
|
|
|
|
match self.parent_hir_node(const_arg) {
|
2021-07-13 17:23:26 +01:00
|
|
|
Node::GenericParam(GenericParam {
|
2022-11-06 18:26:36 +00:00
|
|
|
def_id: param_id,
|
2021-07-13 17:23:26 +01:00
|
|
|
kind: GenericParamKind::Const { .. },
|
|
|
|
..
|
|
|
|
}) => Some(*param_id),
|
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
2023-07-13 18:55:45 +08:00
|
|
|
|
2025-04-02 07:04:24 +11:00
|
|
|
pub fn hir_maybe_get_struct_pattern_shorthand_field(self, expr: &Expr<'_>) -> Option<Symbol> {
|
2023-07-13 18:55:45 +08:00
|
|
|
let local = match expr {
|
|
|
|
Expr {
|
|
|
|
kind:
|
|
|
|
ExprKind::Path(QPath::Resolved(
|
|
|
|
None,
|
|
|
|
Path {
|
|
|
|
res: def::Res::Local(_), segments: [PathSegment { ident, .. }], ..
|
|
|
|
},
|
|
|
|
)),
|
|
|
|
..
|
|
|
|
} => Some(ident),
|
|
|
|
_ => None,
|
|
|
|
}?;
|
|
|
|
|
2025-04-02 07:04:24 +11:00
|
|
|
match self.parent_hir_node(expr.hir_id) {
|
2023-07-13 18:55:45 +08:00
|
|
|
Node::ExprField(field) => {
|
|
|
|
if field.ident.name == local.name && field.is_shorthand {
|
|
|
|
return Some(local.name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
|
|
|
|
None
|
|
|
|
}
|
2014-01-17 23:23:09 +11:00
|
|
|
}
|
2013-02-04 14:02:01 -08:00
|
|
|
|
2025-02-03 14:42:01 +11:00
|
|
|
impl<'tcx> intravisit::HirTyCtxt<'tcx> for TyCtxt<'tcx> {
|
|
|
|
fn hir_node(&self, hir_id: HirId) -> Node<'tcx> {
|
|
|
|
(*self).hir_node(hir_id)
|
2020-03-24 02:44:41 +01:00
|
|
|
}
|
|
|
|
|
2025-02-03 14:42:01 +11:00
|
|
|
fn hir_body(&self, id: BodyId) -> &'tcx Body<'tcx> {
|
|
|
|
(*self).hir_body(id)
|
2020-01-07 17:25:33 +01:00
|
|
|
}
|
|
|
|
|
2025-02-03 14:42:01 +11:00
|
|
|
fn hir_item(&self, id: ItemId) -> &'tcx Item<'tcx> {
|
|
|
|
(*self).hir_item(id)
|
2020-01-07 17:25:33 +01:00
|
|
|
}
|
|
|
|
|
2025-02-03 14:42:01 +11:00
|
|
|
fn hir_trait_item(&self, id: TraitItemId) -> &'tcx TraitItem<'tcx> {
|
|
|
|
(*self).hir_trait_item(id)
|
2020-01-07 17:25:33 +01:00
|
|
|
}
|
|
|
|
|
2025-02-03 14:42:01 +11:00
|
|
|
fn hir_impl_item(&self, id: ImplItemId) -> &'tcx ImplItem<'tcx> {
|
|
|
|
(*self).hir_impl_item(id)
|
2020-01-07 17:25:33 +01:00
|
|
|
}
|
2020-11-11 21:57:54 +01:00
|
|
|
|
2025-02-03 14:42:01 +11:00
|
|
|
fn hir_foreign_item(&self, id: ForeignItemId) -> &'tcx ForeignItem<'tcx> {
|
|
|
|
(*self).hir_foreign_item(id)
|
2020-11-11 21:57:54 +01:00
|
|
|
}
|
2020-01-07 17:25:33 +01:00
|
|
|
}
|
|
|
|
|
2024-04-14 10:26:59 -04:00
|
|
|
impl<'tcx> pprust_hir::PpAnn for TyCtxt<'tcx> {
|
|
|
|
fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) {
|
2025-02-03 14:42:01 +11:00
|
|
|
pprust_hir::PpAnn::nested(&(self as &dyn intravisit::HirTyCtxt<'_>), state, nested)
|
2024-04-14 10:26:59 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-13 22:22:59 +00:00
|
|
|
pub(super) fn crate_hash(tcx: TyCtxt<'_>, _: LocalCrate) -> Svh {
|
2021-09-19 22:07:12 +02:00
|
|
|
let krate = tcx.hir_crate(());
|
2023-03-03 17:02:11 +11:00
|
|
|
let hir_body_hash = krate.opt_hir_hash.expect("HIR hash missing while computing crate hash");
|
2021-02-28 18:58:50 +01:00
|
|
|
|
2024-06-06 09:45:50 +00:00
|
|
|
let upstream_crates = upstream_crates(tcx);
|
2021-02-28 18:58:50 +01:00
|
|
|
|
2022-05-30 18:49:17 +02:00
|
|
|
let resolutions = tcx.resolutions(());
|
|
|
|
|
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)
|
2023-12-19 22:34:26 +01:00
|
|
|
.map(|source_file| source_file.stable_id)
|
2021-02-28 18:58:50 +01:00
|
|
|
.collect();
|
|
|
|
|
|
|
|
source_file_names.sort_unstable();
|
|
|
|
|
2023-05-16 18:50:05 +02:00
|
|
|
// We have to take care of debugger visualizers explicitly. The HIR (and
|
|
|
|
// thus `hir_body_hash`) contains the #[debugger_visualizer] attributes but
|
|
|
|
// these attributes only store the file path to the visualizer file, not
|
|
|
|
// their content. Yet that content is exported into crate metadata, so any
|
|
|
|
// changes to it need to be reflected in the crate hash.
|
2023-05-16 13:37:46 +02:00
|
|
|
let debugger_visualizers: Vec<_> = tcx
|
|
|
|
.debugger_visualizers(LOCAL_CRATE)
|
|
|
|
.iter()
|
|
|
|
// We ignore the path to the visualizer file since it's not going to be
|
|
|
|
// encoded in crate metadata and we already hash the full contents of
|
|
|
|
// the file.
|
|
|
|
.map(DebuggerVisualizerFile::path_erased)
|
|
|
|
.collect();
|
|
|
|
|
2021-07-12 22:19:25 +02:00
|
|
|
let crate_hash: Fingerprint = tcx.with_stable_hashing_context(|mut hcx| {
|
|
|
|
let mut stable_hasher = StableHasher::new();
|
|
|
|
hir_body_hash.hash_stable(&mut hcx, &mut stable_hasher);
|
|
|
|
upstream_crates.hash_stable(&mut hcx, &mut stable_hasher);
|
|
|
|
source_file_names.hash_stable(&mut hcx, &mut stable_hasher);
|
2023-05-16 13:37:46 +02:00
|
|
|
debugger_visualizers.hash_stable(&mut hcx, &mut stable_hasher);
|
2023-09-07 20:13:57 +00:00
|
|
|
if tcx.sess.opts.incremental.is_some() {
|
2023-08-31 09:16:33 +02:00
|
|
|
let definitions = tcx.untracked().definitions.freeze();
|
2025-03-19 14:18:15 +00:00
|
|
|
let mut owner_spans: Vec<_> = tcx
|
|
|
|
.hir_crate_items(())
|
|
|
|
.definitions()
|
|
|
|
.map(|def_id| {
|
2021-07-12 22:19:25 +02:00
|
|
|
let def_path_hash = definitions.def_path_hash(def_id);
|
2022-12-07 14:31:50 +00:00
|
|
|
let span = tcx.source_span(def_id);
|
2021-07-12 22:19:25 +02:00
|
|
|
debug_assert_eq!(span.parent(), None);
|
2025-03-19 14:18:15 +00:00
|
|
|
(def_path_hash, span)
|
2021-07-12 22:19:25 +02:00
|
|
|
})
|
|
|
|
.collect();
|
|
|
|
owner_spans.sort_unstable_by_key(|bn| bn.0);
|
|
|
|
owner_spans.hash_stable(&mut hcx, &mut stable_hasher);
|
|
|
|
}
|
|
|
|
tcx.sess.opts.dep_tracking_hash(true).hash_stable(&mut hcx, &mut stable_hasher);
|
2023-08-08 20:08:24 +08:00
|
|
|
tcx.stable_crate_id(LOCAL_CRATE).hash_stable(&mut hcx, &mut stable_hasher);
|
2021-07-12 22:19:25 +02:00
|
|
|
// Hash visibility information since it does not appear in HIR.
|
2023-12-05 23:16:08 +03:00
|
|
|
// FIXME: Figure out how to remove `visibilities_for_hashing` by hashing visibilities on
|
|
|
|
// the fly in the resolver, storing only their accumulated hash in `ResolverGlobalCtxt`,
|
|
|
|
// and combining it with other hashes here.
|
|
|
|
resolutions.visibilities_for_hashing.hash_stable(&mut hcx, &mut stable_hasher);
|
2024-12-18 19:51:59 +00:00
|
|
|
with_metavar_spans(|mspans| {
|
2024-12-21 20:37:24 +00:00
|
|
|
mspans.freeze_and_get_read_spans().hash_stable(&mut hcx, &mut stable_hasher);
|
2024-12-18 19:51:59 +00:00
|
|
|
});
|
2021-07-12 22:19:25 +02:00
|
|
|
stable_hasher.finish()
|
|
|
|
});
|
2021-02-28 18:58:50 +01:00
|
|
|
|
2023-04-15 13:53:50 -04:00
|
|
|
Svh::new(crate_hash)
|
2021-02-28 18:58:50 +01:00
|
|
|
}
|
|
|
|
|
2024-06-06 09:45:50 +00:00
|
|
|
fn upstream_crates(tcx: TyCtxt<'_>) -> Vec<(StableCrateId, Svh)> {
|
2021-07-12 21:20:16 +02:00
|
|
|
let mut upstream_crates: Vec<_> = tcx
|
2024-06-06 09:45:50 +00:00
|
|
|
.crates(())
|
2021-02-28 18:58:50 +01:00
|
|
|
.iter()
|
|
|
|
.map(|&cnum| {
|
2021-07-14 00:48:51 +02:00
|
|
|
let stable_crate_id = tcx.stable_crate_id(cnum);
|
2021-07-12 21:20:16 +02:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2023-04-26 20:53:51 +02:00
|
|
|
pub(super) fn hir_module_items(tcx: TyCtxt<'_>, module_id: LocalModDefId) -> ModuleItems {
|
2022-07-06 19:13:49 -04:00
|
|
|
let mut collector = ItemCollector::new(tcx, false);
|
2021-07-18 18:12:17 +02:00
|
|
|
|
2025-02-17 14:17:57 +11:00
|
|
|
let (hir_mod, span, hir_id) = tcx.hir_get_module(module_id);
|
2021-07-18 18:12:17 +02:00
|
|
|
collector.visit_mod(hir_mod, span, hir_id);
|
|
|
|
|
2022-07-06 19:13:49 -04:00
|
|
|
let ItemCollector {
|
2022-06-15 22:29:59 -04:00
|
|
|
submodules,
|
|
|
|
items,
|
|
|
|
trait_items,
|
|
|
|
impl_items,
|
|
|
|
foreign_items,
|
|
|
|
body_owners,
|
2024-08-09 20:43:30 -07:00
|
|
|
opaques,
|
2025-01-10 01:27:01 +00:00
|
|
|
nested_bodies,
|
2022-06-15 22:29:59 -04:00
|
|
|
..
|
|
|
|
} = collector;
|
2024-09-09 12:22:00 +02:00
|
|
|
ModuleItems {
|
2021-09-07 20:07:33 +02:00
|
|
|
submodules: submodules.into_boxed_slice(),
|
2024-03-20 23:52:26 +01:00
|
|
|
free_items: items.into_boxed_slice(),
|
2021-09-07 20:07:33 +02:00
|
|
|
trait_items: trait_items.into_boxed_slice(),
|
|
|
|
impl_items: impl_items.into_boxed_slice(),
|
|
|
|
foreign_items: foreign_items.into_boxed_slice(),
|
2022-06-15 22:29:59 -04:00
|
|
|
body_owners: body_owners.into_boxed_slice(),
|
2024-08-09 20:43:30 -07:00
|
|
|
opaques: opaques.into_boxed_slice(),
|
2025-01-10 01:27:01 +00:00
|
|
|
nested_bodies: nested_bodies.into_boxed_slice(),
|
2024-09-09 12:22:00 +02:00
|
|
|
}
|
2021-07-18 18:12:17 +02:00
|
|
|
}
|
2022-04-03 15:50:33 -04:00
|
|
|
|
|
|
|
pub(crate) fn hir_crate_items(tcx: TyCtxt<'_>, _: ()) -> ModuleItems {
|
2022-07-06 19:13:49 -04:00
|
|
|
let mut collector = ItemCollector::new(tcx, true);
|
2022-04-03 15:50:33 -04:00
|
|
|
|
2022-07-13 13:25:53 -04:00
|
|
|
// A "crate collector" and "module collector" start at a
|
|
|
|
// module item (the former starts at the crate root) but only
|
|
|
|
// the former needs to collect it. ItemCollector does not do this for us.
|
2022-09-20 14:11:23 +09:00
|
|
|
collector.submodules.push(CRATE_OWNER_ID);
|
2025-02-17 14:17:57 +11:00
|
|
|
tcx.hir_walk_toplevel_module(&mut collector);
|
2022-04-03 15:50:33 -04:00
|
|
|
|
2022-07-06 19:13:49 -04:00
|
|
|
let ItemCollector {
|
2022-06-15 22:29:59 -04:00
|
|
|
submodules,
|
|
|
|
items,
|
|
|
|
trait_items,
|
|
|
|
impl_items,
|
|
|
|
foreign_items,
|
|
|
|
body_owners,
|
2024-08-09 20:43:30 -07:00
|
|
|
opaques,
|
2025-01-10 01:27:01 +00:00
|
|
|
nested_bodies,
|
2022-06-15 22:29:59 -04:00
|
|
|
..
|
|
|
|
} = collector;
|
2022-04-03 15:50:33 -04:00
|
|
|
|
2024-09-09 12:22:00 +02:00
|
|
|
ModuleItems {
|
2022-04-03 15:50:33 -04:00
|
|
|
submodules: submodules.into_boxed_slice(),
|
2024-03-20 23:52:26 +01:00
|
|
|
free_items: items.into_boxed_slice(),
|
2022-04-03 15:50:33 -04:00
|
|
|
trait_items: trait_items.into_boxed_slice(),
|
|
|
|
impl_items: impl_items.into_boxed_slice(),
|
|
|
|
foreign_items: foreign_items.into_boxed_slice(),
|
2022-06-15 22:29:59 -04:00
|
|
|
body_owners: body_owners.into_boxed_slice(),
|
2024-08-09 20:43:30 -07:00
|
|
|
opaques: opaques.into_boxed_slice(),
|
2025-01-10 01:27:01 +00:00
|
|
|
nested_bodies: nested_bodies.into_boxed_slice(),
|
2024-09-09 12:22:00 +02:00
|
|
|
}
|
2022-07-06 19:13:49 -04:00
|
|
|
}
|
2022-04-03 15:50:33 -04:00
|
|
|
|
2022-07-06 19:13:49 -04:00
|
|
|
struct ItemCollector<'tcx> {
|
|
|
|
// When true, it collects all items in the create,
|
|
|
|
// otherwise it collects items in some module.
|
|
|
|
crate_collector: bool,
|
|
|
|
tcx: TyCtxt<'tcx>,
|
2022-09-20 14:11:23 +09:00
|
|
|
submodules: Vec<OwnerId>,
|
2022-07-06 19:13:49 -04:00
|
|
|
items: Vec<ItemId>,
|
|
|
|
trait_items: Vec<TraitItemId>,
|
|
|
|
impl_items: Vec<ImplItemId>,
|
|
|
|
foreign_items: Vec<ForeignItemId>,
|
|
|
|
body_owners: Vec<LocalDefId>,
|
2024-08-09 20:43:30 -07:00
|
|
|
opaques: Vec<LocalDefId>,
|
2025-01-10 01:27:01 +00:00
|
|
|
nested_bodies: Vec<LocalDefId>,
|
2022-07-06 19:13:49 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'tcx> ItemCollector<'tcx> {
|
|
|
|
fn new(tcx: TyCtxt<'tcx>, crate_collector: bool) -> ItemCollector<'tcx> {
|
|
|
|
ItemCollector {
|
|
|
|
crate_collector,
|
|
|
|
tcx,
|
|
|
|
submodules: Vec::default(),
|
|
|
|
items: Vec::default(),
|
|
|
|
trait_items: Vec::default(),
|
|
|
|
impl_items: Vec::default(),
|
|
|
|
foreign_items: Vec::default(),
|
|
|
|
body_owners: Vec::default(),
|
2024-08-09 20:43:30 -07:00
|
|
|
opaques: Vec::default(),
|
2025-01-10 01:27:01 +00:00
|
|
|
nested_bodies: Vec::default(),
|
2022-07-06 19:13:49 -04:00
|
|
|
}
|
2022-04-03 15:50:33 -04:00
|
|
|
}
|
2022-07-06 19:13:49 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'hir> Visitor<'hir> for ItemCollector<'hir> {
|
|
|
|
type NestedFilter = nested_filter::All;
|
2022-04-03 15:50:33 -04:00
|
|
|
|
2025-02-03 14:42:01 +11:00
|
|
|
fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
|
|
|
|
self.tcx
|
2022-07-06 19:13:49 -04:00
|
|
|
}
|
2022-04-03 15:50:33 -04:00
|
|
|
|
2022-07-06 19:13:49 -04:00
|
|
|
fn visit_item(&mut self, item: &'hir Item<'hir>) {
|
2024-03-05 09:42:25 +00:00
|
|
|
if Node::Item(item).associated_body().is_some() {
|
2022-10-27 14:02:18 +11:00
|
|
|
self.body_owners.push(item.owner_id.def_id);
|
2022-04-03 15:50:33 -04:00
|
|
|
}
|
|
|
|
|
2022-07-06 19:13:49 -04:00
|
|
|
self.items.push(item.item_id());
|
2022-06-15 22:29:59 -04:00
|
|
|
|
2022-07-13 13:25:53 -04:00
|
|
|
// Items that are modules are handled here instead of in visit_mod.
|
Move `hir::Item::ident` into `hir::ItemKind`.
`hir::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Macro`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
Trait`, TraitAalis`.
- It's always empty for these item kinds: `ForeignMod`, `GlobalAsm`,
`Impl`.
- For `Use`, it is non-empty for `UseKind::Single` and empty for
`UseKind::{Glob,ListStem}`.
All of this is quite non-obvious; the only documentation is a single
comment saying "The name might be a dummy name in case of anonymous
items". Some sites that handle items check for an empty ident, some
don't. This is a very C-like way of doing things, but this is Rust, we
have sum types, we can do this properly and never forget to check for
the exceptional case and never YOLO possibly empty identifiers (or
possibly dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- A similar transformation makes sense for `ast::Item`, but this is
already a big change. That can be done later.
- Lots of assertions are added to item lowering to ensure that
identifiers are empty/non-empty as expected. These will be removable
when `ast::Item` is done later.
- `ItemKind::Use` doesn't get an `Ident`, but `UseKind::Single` does.
- `lower_use_tree` is significantly simpler. No more confusing `&mut
Ident` to deal with.
- `ItemKind::ident` is a new method, it returns an `Option<Ident>`. It's
used with `unwrap` in a few places; sometimes it's hard to tell
exactly which item kinds might occur. None of these unwraps fail on
the test suite. It's conceivable that some might fail on alternative
input. We can deal with those if/when they happen.
- In `trait_path` the `find_map`/`if let` is replaced with a loop, and
things end up much clearer that way.
- `named_span` no longer checks for an empty name; instead the call site
now checks for a missing identifier if necessary.
- `maybe_inline_local` doesn't need the `glob` argument, it can be
computed in-function from the `renamed` argument.
- `arbitrary_source_item_ordering::check_mod` had a big `if` statement
that was just getting the ident from the item kinds that had one. It
could be mostly replaced by a single call to the new `ItemKind::ident`
method.
- `ItemKind` grows from 56 to 64 bytes, but `Item` stays the same size,
and that's what matters, because `ItemKind` only occurs within `Item`.
2025-03-06 19:07:36 +11:00
|
|
|
if let ItemKind::Mod(_, module) = &item.kind {
|
2022-10-27 14:02:18 +11:00
|
|
|
self.submodules.push(item.owner_id);
|
2022-07-13 13:25:53 -04:00
|
|
|
// A module collector does not recurse inside nested modules.
|
|
|
|
if self.crate_collector {
|
2025-03-07 17:02:33 +11:00
|
|
|
intravisit::walk_mod(self, module);
|
2022-07-13 13:25:53 -04:00
|
|
|
}
|
2022-07-06 19:13:49 -04:00
|
|
|
} else {
|
2022-04-03 15:50:33 -04:00
|
|
|
intravisit::walk_item(self, item)
|
|
|
|
}
|
2022-07-06 19:13:49 -04:00
|
|
|
}
|
2022-04-03 15:50:33 -04:00
|
|
|
|
2022-07-06 19:13:49 -04:00
|
|
|
fn visit_foreign_item(&mut self, item: &'hir ForeignItem<'hir>) {
|
|
|
|
self.foreign_items.push(item.foreign_item_id());
|
|
|
|
intravisit::walk_foreign_item(self, item)
|
|
|
|
}
|
2022-04-03 15:50:33 -04:00
|
|
|
|
2022-07-06 19:13:49 -04:00
|
|
|
fn visit_anon_const(&mut self, c: &'hir AnonConst) {
|
2022-11-06 19:17:57 +00:00
|
|
|
self.body_owners.push(c.def_id);
|
2022-07-06 19:13:49 -04:00
|
|
|
intravisit::walk_anon_const(self, c)
|
|
|
|
}
|
2022-04-03 15:50:33 -04:00
|
|
|
|
2024-06-03 09:11:58 +00:00
|
|
|
fn visit_inline_const(&mut self, c: &'hir ConstBlock) {
|
|
|
|
self.body_owners.push(c.def_id);
|
2025-01-10 01:27:01 +00:00
|
|
|
self.nested_bodies.push(c.def_id);
|
2024-06-03 09:11:58 +00:00
|
|
|
intravisit::walk_inline_const(self, c)
|
|
|
|
}
|
|
|
|
|
2024-08-09 20:43:30 -07:00
|
|
|
fn visit_opaque_ty(&mut self, o: &'hir OpaqueTy<'hir>) {
|
|
|
|
self.opaques.push(o.def_id);
|
|
|
|
intravisit::walk_opaque_ty(self, o)
|
|
|
|
}
|
|
|
|
|
2022-07-06 19:13:49 -04:00
|
|
|
fn visit_expr(&mut self, ex: &'hir Expr<'hir>) {
|
2022-11-06 13:29:21 +00:00
|
|
|
if let ExprKind::Closure(closure) = ex.kind {
|
|
|
|
self.body_owners.push(closure.def_id);
|
2025-01-10 01:27:01 +00:00
|
|
|
self.nested_bodies.push(closure.def_id);
|
2022-04-03 15:50:33 -04:00
|
|
|
}
|
2022-07-06 19:13:49 -04:00
|
|
|
intravisit::walk_expr(self, ex)
|
|
|
|
}
|
2022-04-03 15:50:33 -04:00
|
|
|
|
2022-07-06 19:13:49 -04:00
|
|
|
fn visit_trait_item(&mut self, item: &'hir TraitItem<'hir>) {
|
2024-03-05 09:42:25 +00:00
|
|
|
if Node::TraitItem(item).associated_body().is_some() {
|
2022-10-27 14:02:18 +11:00
|
|
|
self.body_owners.push(item.owner_id.def_id);
|
2022-04-03 15:50:33 -04:00
|
|
|
}
|
|
|
|
|
2022-07-06 19:13:49 -04:00
|
|
|
self.trait_items.push(item.trait_item_id());
|
|
|
|
intravisit::walk_trait_item(self, item)
|
|
|
|
}
|
2022-06-15 22:29:59 -04:00
|
|
|
|
2022-07-06 19:13:49 -04:00
|
|
|
fn visit_impl_item(&mut self, item: &'hir ImplItem<'hir>) {
|
2024-03-05 09:42:25 +00:00
|
|
|
if Node::ImplItem(item).associated_body().is_some() {
|
2022-10-27 14:02:18 +11:00
|
|
|
self.body_owners.push(item.owner_id.def_id);
|
2022-04-03 15:50:33 -04:00
|
|
|
}
|
2022-07-06 19:13:49 -04:00
|
|
|
|
|
|
|
self.impl_items.push(item.impl_item_id());
|
|
|
|
intravisit::walk_impl_item(self, item)
|
2022-04-03 15:50:33 -04:00
|
|
|
}
|
|
|
|
}
|