]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_middle/src/hir/mod.rs
Remove rustfmt tests from top-level .gitattributes
[rust.git] / compiler / rustc_middle / src / hir / mod.rs
1 //! HIR datatypes. See the [rustc dev guide] for more info.
2 //!
3 //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html
4
5 pub mod exports;
6 pub mod map;
7 pub mod place;
8
9 use crate::ich::StableHashingContext;
10 use crate::ty::query::Providers;
11 use crate::ty::TyCtxt;
12 use rustc_ast::Attribute;
13 use rustc_data_structures::fingerprint::Fingerprint;
14 use rustc_data_structures::fx::FxHashMap;
15 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
16 use rustc_hir::def_id::LocalDefId;
17 use rustc_hir::*;
18 use rustc_index::vec::{Idx, IndexVec};
19 use rustc_span::DUMMY_SP;
20 use std::collections::BTreeMap;
21
22 /// Result of HIR indexing.
23 #[derive(Debug)]
24 pub struct IndexedHir<'hir> {
25     /// Contents of the HIR owned by each definition. None for definitions that are not HIR owners.
26     // The `mut` comes from construction time, and is harmless since we only ever hand out
27     // immutable refs to IndexedHir.
28     map: IndexVec<LocalDefId, Option<&'hir mut OwnerNodes<'hir>>>,
29     /// Map from each owner to its parent's HirId inside another owner.
30     // This map is separate from `map` to eventually allow for per-owner indexing.
31     parenting: FxHashMap<LocalDefId, HirId>,
32 }
33
34 /// Top-level HIR node for current owner. This only contains the node for which
35 /// `HirId::local_id == 0`, and excludes bodies.
36 #[derive(Copy, Clone, Debug)]
37 pub struct Owner<'tcx> {
38     node: Node<'tcx>,
39 }
40
41 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Owner<'tcx> {
42     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
43         let Owner { node } = self;
44         hcx.while_hashing_hir_bodies(false, |hcx| node.hash_stable(hcx, hasher));
45     }
46 }
47
48 /// HIR node coupled with its parent's id in the same HIR owner.
49 ///
50 /// The parent is trash when the node is a HIR owner.
51 #[derive(Clone, Debug)]
52 pub struct ParentedNode<'tcx> {
53     parent: ItemLocalId,
54     node: Node<'tcx>,
55 }
56
57 #[derive(Debug)]
58 pub struct OwnerNodes<'tcx> {
59     /// Pre-computed hash of the full HIR.
60     hash: Fingerprint,
61     /// Full HIR for the current owner.
62     // The zeroth node's parent is trash, but is never accessed.
63     nodes: IndexVec<ItemLocalId, Option<ParentedNode<'tcx>>>,
64     /// Content of local bodies.
65     bodies: FxHashMap<ItemLocalId, &'tcx Body<'tcx>>,
66 }
67
68 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for OwnerNodes<'tcx> {
69     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
70         // We ignore the `nodes` and `bodies` fields since these refer to information included in
71         // `hash` which is hashed in the collector and used for the crate hash.
72         let OwnerNodes { hash, nodes: _, bodies: _ } = *self;
73         hash.hash_stable(hcx, hasher);
74     }
75 }
76
77 /// Attributes owner by a HIR owner. It is build as a slice inside the attributes map, restricted
78 /// to the nodes whose `HirId::owner` is `prefix`.
79 #[derive(Copy, Clone)]
80 pub struct AttributeMap<'tcx> {
81     map: &'tcx BTreeMap<HirId, &'tcx [Attribute]>,
82     prefix: LocalDefId,
83 }
84
85 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for AttributeMap<'tcx> {
86     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
87         let range = self.range();
88
89         range.clone().count().hash_stable(hcx, hasher);
90         for (key, value) in range {
91             key.hash_stable(hcx, hasher);
92             value.hash_stable(hcx, hasher);
93         }
94     }
95 }
96
97 impl<'tcx> std::fmt::Debug for AttributeMap<'tcx> {
98     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
99         f.debug_struct("AttributeMap")
100             .field("prefix", &self.prefix)
101             .field("range", &&self.range().collect::<Vec<_>>()[..])
102             .finish()
103     }
104 }
105
106 impl<'tcx> AttributeMap<'tcx> {
107     fn get(&self, id: ItemLocalId) -> &'tcx [Attribute] {
108         self.map.get(&HirId { owner: self.prefix, local_id: id }).copied().unwrap_or(&[])
109     }
110
111     fn range(&self) -> std::collections::btree_map::Range<'_, rustc_hir::HirId, &[Attribute]> {
112         let local_zero = ItemLocalId::from_u32(0);
113         let range = HirId { owner: self.prefix, local_id: local_zero }..HirId {
114             owner: LocalDefId { local_def_index: self.prefix.local_def_index + 1 },
115             local_id: local_zero,
116         };
117         self.map.range(range)
118     }
119 }
120
121 impl<'tcx> TyCtxt<'tcx> {
122     #[inline(always)]
123     pub fn hir(self) -> map::Map<'tcx> {
124         map::Map { tcx: self }
125     }
126
127     pub fn parent_module(self, id: HirId) -> LocalDefId {
128         self.parent_module_from_def_id(id.owner)
129     }
130 }
131
132 pub fn provide(providers: &mut Providers) {
133     providers.parent_module_from_def_id = |tcx, id| {
134         let hir = tcx.hir();
135         hir.local_def_id(hir.get_module_parent_node(hir.local_def_id_to_hir_id(id)))
136     };
137     providers.hir_crate = |tcx, ()| tcx.untracked_crate;
138     providers.index_hir = map::index_hir;
139     providers.crate_hash = map::crate_hash;
140     providers.hir_module_items = |tcx, id| &tcx.untracked_crate.modules[&id];
141     providers.hir_owner = |tcx, id| {
142         let owner = tcx.index_hir(()).map[id].as_ref()?;
143         let node = owner.nodes[ItemLocalId::new(0)].as_ref()?.node;
144         Some(Owner { node })
145     };
146     providers.hir_owner_nodes = |tcx, id| tcx.index_hir(()).map[id].as_deref();
147     providers.hir_owner_parent = |tcx, id| {
148         let index = tcx.index_hir(());
149         index.parenting.get(&id).copied().unwrap_or(CRATE_HIR_ID)
150     };
151     providers.hir_attrs = |tcx, id| AttributeMap { map: &tcx.untracked_crate.attrs, prefix: id };
152     providers.def_span = |tcx, def_id| tcx.hir().span_if_local(def_id).unwrap_or(DUMMY_SP);
153     providers.fn_arg_names = |tcx, id| {
154         let hir = tcx.hir();
155         let hir_id = hir.local_def_id_to_hir_id(id.expect_local());
156         if let Some(body_id) = hir.maybe_body_owned_by(hir_id) {
157             tcx.arena.alloc_from_iter(hir.body_param_names(body_id))
158         } else if let Node::TraitItem(&TraitItem {
159             kind: TraitItemKind::Fn(_, TraitFn::Required(idents)),
160             ..
161         }) = hir.get(hir_id)
162         {
163             tcx.arena.alloc_slice(idents)
164         } else {
165             span_bug!(hir.span(hir_id), "fn_arg_names: unexpected item {:?}", id);
166         }
167     };
168     providers.opt_def_kind = |tcx, def_id| tcx.hir().opt_def_kind(def_id.expect_local());
169     providers.all_local_trait_impls = |tcx, ()| &tcx.hir_crate(()).trait_impls;
170 }