hir: Introduce TyCtxt::parent_hir_{id,node}
Remove the FIXME and keep `CRATE_HIR_ID` being its own parent. This scheme turned out to be more practical than having an `Option` on closer inspection. Also make `hir_owner_parent` more readable.
This commit is contained in:
parent
68125c72d3
commit
e46e3e7107
2 changed files with 34 additions and 28 deletions
|
@ -175,6 +175,28 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
self.opt_hir_node_by_def_id(id)
|
self.opt_hir_node_by_def_id(id)
|
||||||
.unwrap_or_else(|| bug!("couldn't find HIR node for def id {id:?}"))
|
.unwrap_or_else(|| bug!("couldn't find HIR node for def id {id:?}"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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`.
|
||||||
|
///
|
||||||
|
/// If calling repeatedly and iterating over parents, prefer [`Map::parent_iter`].
|
||||||
|
pub fn parent_hir_id(self, hir_id: HirId) -> HirId {
|
||||||
|
let HirId { owner, local_id } = hir_id;
|
||||||
|
if local_id == ItemLocalId::from_u32(0) {
|
||||||
|
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))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'hir> Map<'hir> {
|
impl<'hir> Map<'hir> {
|
||||||
|
@ -217,37 +239,20 @@ impl<'hir> Map<'hir> {
|
||||||
self.tcx.definitions_untracked().def_path_hash(def_id)
|
self.tcx.definitions_untracked().def_path_hash(def_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Finds the id of the parent node to this one.
|
|
||||||
///
|
|
||||||
/// If calling repeatedly and iterating over parents, prefer [`Map::parent_iter`].
|
|
||||||
pub fn opt_parent_id(self, id: HirId) -> Option<HirId> {
|
pub fn opt_parent_id(self, id: HirId) -> Option<HirId> {
|
||||||
if id.local_id == ItemLocalId::from_u32(0) {
|
Some(self.tcx.parent_hir_id(id))
|
||||||
// FIXME: This function never returns `None` right now, and the parent chain end is
|
|
||||||
// determined by checking for `parent(id) == id`. This function should return `None`
|
|
||||||
// for the crate root instead.
|
|
||||||
Some(self.tcx.hir_owner_parent(id.owner))
|
|
||||||
} else {
|
|
||||||
let owner = self.tcx.hir_owner_nodes(id.owner);
|
|
||||||
let node = &owner.nodes[id.local_id];
|
|
||||||
let hir_id = HirId { owner: id.owner, local_id: node.parent };
|
|
||||||
// HIR indexing should have checked that.
|
|
||||||
debug_assert_ne!(id.local_id, node.parent);
|
|
||||||
Some(hir_id)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
|
||||||
pub fn parent_id(self, hir_id: HirId) -> HirId {
|
pub fn parent_id(self, hir_id: HirId) -> HirId {
|
||||||
self.opt_parent_id(hir_id)
|
self.tcx.parent_hir_id(hir_id)
|
||||||
.unwrap_or_else(|| bug!("No parent for node {}", self.node_to_string(hir_id)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_parent(self, hir_id: HirId) -> Node<'hir> {
|
pub fn get_parent(self, hir_id: HirId) -> Node<'hir> {
|
||||||
self.tcx.hir_node(self.parent_id(hir_id))
|
self.tcx.parent_hir_node(hir_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_parent(self, hir_id: HirId) -> Option<Node<'hir>> {
|
pub fn find_parent(self, hir_id: HirId) -> Option<Node<'hir>> {
|
||||||
Some(self.tcx.hir_node(self.opt_parent_id(hir_id)?))
|
Some(self.tcx.parent_hir_node(hir_id))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_if_local(self, id: DefId) -> Option<Node<'hir>> {
|
pub fn get_if_local(self, id: DefId) -> Option<Node<'hir>> {
|
||||||
|
|
|
@ -136,13 +136,14 @@ pub fn provide(providers: &mut Providers) {
|
||||||
};
|
};
|
||||||
providers.opt_hir_owner_nodes =
|
providers.opt_hir_owner_nodes =
|
||||||
|tcx, id| tcx.hir_crate(()).owners.get(id)?.as_owner().map(|i| &i.nodes);
|
|tcx, id| tcx.hir_crate(()).owners.get(id)?.as_owner().map(|i| &i.nodes);
|
||||||
providers.hir_owner_parent = |tcx, id| {
|
providers.hir_owner_parent = |tcx, owner_id| {
|
||||||
// Accessing the local_parent is ok since its value is hashed as part of `id`'s DefPathHash.
|
tcx.opt_local_parent(owner_id.def_id).map_or(CRATE_HIR_ID, |parent_def_id| {
|
||||||
tcx.opt_local_parent(id.def_id).map_or(CRATE_HIR_ID, |parent| {
|
let parent_owner_id = tcx.local_def_id_to_hir_id(parent_def_id).owner;
|
||||||
let mut parent_hir_id = tcx.local_def_id_to_hir_id(parent);
|
HirId {
|
||||||
parent_hir_id.local_id =
|
owner: parent_owner_id,
|
||||||
tcx.hir_crate(()).owners[parent_hir_id.owner.def_id].unwrap().parenting[&id.def_id];
|
local_id: tcx.hir_crate(()).owners[parent_owner_id.def_id].unwrap().parenting
|
||||||
parent_hir_id
|
[&owner_id.def_id],
|
||||||
|
}
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
providers.hir_attrs = |tcx, id| {
|
providers.hir_attrs = |tcx, id| {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue