1 //! HIR datatypes. See the [rustc dev guide] for more info.
3 //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html
9 use crate::query
::Providers
;
10 use crate::ty
::{EarlyBinder, ImplSubject, TyCtxt}
;
11 use rustc_data_structures
::stable_hasher
::{HashStable, StableHasher}
;
12 use rustc_data_structures
::sync
::{try_par_for_each_in, DynSend, DynSync}
;
13 use rustc_hir
::def
::DefKind
;
14 use rustc_hir
::def_id
::{DefId, LocalDefId, LocalModDefId}
;
16 use rustc_query_system
::ich
::StableHashingContext
;
17 use rustc_span
::{ErrorGuaranteed, ExpnId, DUMMY_SP}
;
19 /// Top-level HIR node for current owner. This only contains the node for which
20 /// `HirId::local_id == 0`, and excludes bodies.
22 /// This struct exists to encapsulate all access to the hir_owner query in this module, and to
23 /// implement HashStable without hashing bodies.
24 #[derive(Copy, Clone, Debug)]
25 pub struct Owner
<'tcx
> {
26 node
: OwnerNode
<'tcx
>,
29 impl<'a
, 'tcx
> HashStable
<StableHashingContext
<'a
>> for Owner
<'tcx
> {
31 fn hash_stable(&self, hcx
: &mut StableHashingContext
<'a
>, hasher
: &mut StableHasher
) {
32 // Perform a shallow hash instead using the deep hash saved in `OwnerNodes`. This lets us
33 // differentiate queries that depend on the full HIR tree from those that only depend on
34 // the item signature.
35 hcx
.without_hir_bodies(|hcx
| self.node
.hash_stable(hcx
, hasher
));
39 /// Gather the LocalDefId for each item-like within a module, including items contained within
40 /// bodies. The Ids are in visitor order. This is used to partition a pass between modules.
41 #[derive(Debug, HashStable, Encodable, Decodable)]
42 pub struct ModuleItems
{
43 submodules
: Box
<[OwnerId
]>,
45 trait_items
: Box
<[TraitItemId
]>,
46 impl_items
: Box
<[ImplItemId
]>,
47 foreign_items
: Box
<[ForeignItemId
]>,
48 body_owners
: Box
<[LocalDefId
]>,
52 pub fn items(&self) -> impl Iterator
<Item
= ItemId
> + '_
{
53 self.items
.iter().copied()
56 pub fn trait_items(&self) -> impl Iterator
<Item
= TraitItemId
> + '_
{
57 self.trait_items
.iter().copied()
60 pub fn impl_items(&self) -> impl Iterator
<Item
= ImplItemId
> + '_
{
61 self.impl_items
.iter().copied()
64 pub fn foreign_items(&self) -> impl Iterator
<Item
= ForeignItemId
> + '_
{
65 self.foreign_items
.iter().copied()
68 pub fn owners(&self) -> impl Iterator
<Item
= OwnerId
> + '_
{
71 .map(|id
| id
.owner_id
)
72 .chain(self.trait_items
.iter().map(|id
| id
.owner_id
))
73 .chain(self.impl_items
.iter().map(|id
| id
.owner_id
))
74 .chain(self.foreign_items
.iter().map(|id
| id
.owner_id
))
77 pub fn definitions(&self) -> impl Iterator
<Item
= LocalDefId
> + '_
{
78 self.owners().map(|id
| id
.def_id
)
83 f
: impl Fn(ItemId
) -> Result
<(), ErrorGuaranteed
> + DynSend
+ DynSync
,
84 ) -> Result
<(), ErrorGuaranteed
> {
85 try_par_for_each_in(&self.items
[..], |&id
| f(id
))
88 pub fn par_trait_items(
90 f
: impl Fn(TraitItemId
) -> Result
<(), ErrorGuaranteed
> + DynSend
+ DynSync
,
91 ) -> Result
<(), ErrorGuaranteed
> {
92 try_par_for_each_in(&self.trait_items
[..], |&id
| f(id
))
95 pub fn par_impl_items(
97 f
: impl Fn(ImplItemId
) -> Result
<(), ErrorGuaranteed
> + DynSend
+ DynSync
,
98 ) -> Result
<(), ErrorGuaranteed
> {
99 try_par_for_each_in(&self.impl_items
[..], |&id
| f(id
))
102 pub fn par_foreign_items(
104 f
: impl Fn(ForeignItemId
) -> Result
<(), ErrorGuaranteed
> + DynSend
+ DynSync
,
105 ) -> Result
<(), ErrorGuaranteed
> {
106 try_par_for_each_in(&self.foreign_items
[..], |&id
| f(id
))
110 impl<'tcx
> TyCtxt
<'tcx
> {
112 pub fn hir(self) -> map
::Map
<'tcx
> {
113 map
::Map { tcx: self }
116 pub fn parent_module(self, id
: HirId
) -> LocalModDefId
{
117 if !id
.is_owner() && self.def_kind(id
.owner
) == DefKind
::Mod
{
118 LocalModDefId
::new_unchecked(id
.owner
.def_id
)
120 self.parent_module_from_def_id(id
.owner
.def_id
)
124 pub fn parent_module_from_def_id(self, mut id
: LocalDefId
) -> LocalModDefId
{
125 while let Some(parent
) = self.opt_local_parent(id
) {
127 if self.def_kind(id
) == DefKind
::Mod
{
131 LocalModDefId
::new_unchecked(id
)
134 pub fn impl_subject(self, def_id
: DefId
) -> EarlyBinder
<ImplSubject
<'tcx
>> {
135 match self.impl_trait_ref(def_id
) {
136 Some(t
) => t
.map_bound(ImplSubject
::Trait
),
137 None
=> self.type_of(def_id
).map_bound(ImplSubject
::Inherent
),
141 /// Returns `true` if this is a foreign item (i.e., linked via `extern { ... }`).
142 pub fn is_foreign_item(self, def_id
: impl Into
<DefId
>) -> bool
{
143 self.opt_parent(def_id
.into())
144 .is_some_and(|parent
| matches
!(self.def_kind(parent
), DefKind
::ForeignMod
))
148 pub fn provide(providers
: &mut Providers
) {
149 providers
.hir_crate_items
= map
::hir_crate_items
;
150 providers
.crate_hash
= map
::crate_hash
;
151 providers
.hir_module_items
= map
::hir_module_items
;
152 providers
.hir_owner
= |tcx
, id
| {
153 let owner
= tcx
.hir_crate(()).owners
.get(id
.def_id
)?
.as_owner()?
;
154 let node
= owner
.node();
157 providers
.opt_local_def_id_to_hir_id
= |tcx
, id
| {
158 let owner
= tcx
.hir_crate(()).owners
[id
].map(|_
| ());
160 MaybeOwner
::Owner(_
) => HirId
::make_owner(id
),
161 MaybeOwner
::Phantom
=> bug
!("No HirId for {:?}", id
),
162 MaybeOwner
::NonOwner(hir_id
) => hir_id
,
165 providers
.hir_owner_nodes
= |tcx
, id
| tcx
.hir_crate(()).owners
[id
.def_id
].map(|i
| &i
.nodes
);
166 providers
.hir_owner_parent
= |tcx
, id
| {
167 // Accessing the local_parent is ok since its value is hashed as part of `id`'s DefPathHash.
168 tcx
.opt_local_parent(id
.def_id
).map_or(CRATE_HIR_ID
, |parent
| {
169 let mut parent_hir_id
= tcx
.hir().local_def_id_to_hir_id(parent
);
170 parent_hir_id
.local_id
=
171 tcx
.hir_crate(()).owners
[parent_hir_id
.owner
.def_id
].unwrap().parenting
[&id
.def_id
];
175 providers
.hir_attrs
= |tcx
, id
| {
176 tcx
.hir_crate(()).owners
[id
.def_id
].as_owner().map_or(AttributeMap
::EMPTY
, |o
| &o
.attrs
)
178 providers
.def_span
= |tcx
, def_id
| {
179 let hir_id
= tcx
.hir().local_def_id_to_hir_id(def_id
);
180 tcx
.hir().opt_span(hir_id
).unwrap_or(DUMMY_SP
)
182 providers
.def_ident_span
= |tcx
, def_id
| {
183 let hir_id
= tcx
.hir().local_def_id_to_hir_id(def_id
);
184 tcx
.hir().opt_ident_span(hir_id
)
186 providers
.fn_arg_names
= |tcx
, def_id
| {
188 let hir_id
= hir
.local_def_id_to_hir_id(def_id
);
189 if let Some(body_id
) = hir
.maybe_body_owned_by(def_id
) {
190 tcx
.arena
.alloc_from_iter(hir
.body_param_names(body_id
))
191 } else if let Node
::TraitItem(&TraitItem
{
192 kind
: TraitItemKind
::Fn(_
, TraitFn
::Required(idents
)),
195 | Node
::ForeignItem(&ForeignItem
{
196 kind
: ForeignItemKind
::Fn(_
, idents
, _
),
202 span_bug
!(hir
.span(hir_id
), "fn_arg_names: unexpected item {:?}", def_id
);
205 providers
.opt_def_kind
= |tcx
, def_id
| tcx
.hir().opt_def_kind(def_id
);
206 providers
.all_local_trait_impls
= |tcx
, ()| &tcx
.resolutions(()).trait_impls
;
207 providers
.expn_that_defined
=
208 |tcx
, id
| tcx
.resolutions(()).expn_that_defined
.get(&id
).copied().unwrap_or(ExpnId
::root());
209 providers
.in_scope_traits_map
= |tcx
, id
| {
210 tcx
.hir_crate(()).owners
[id
.def_id
].as_owner().map(|owner_info
| &owner_info
.trait_map
)