]> git.proxmox.com Git - rustc.git/blame - src/doc/rustc-dev-guide/src/hir.md
New upstream version 1.52.0~beta.3+dfsg1
[rustc.git] / src / doc / rustc-dev-guide / src / hir.md
CommitLineData
a1dfa0c6
XL
1# The HIR
2
6a06907d
XL
3<!-- toc -->
4
a1dfa0c6
XL
5The HIR – "High-Level Intermediate Representation" – is the primary IR used
6in most of rustc. It is a compiler-friendly representation of the abstract
7syntax tree (AST) that is generated after parsing, macro expansion, and name
8resolution (see [Lowering](./lowering.html) for how the HIR is created).
9Many parts of HIR resemble Rust surface syntax quite closely, with
10the exception that some of Rust's expression forms have been desugared away.
11For example, `for` loops are converted into a `loop` and do not appear in
12the HIR. This makes HIR more amenable to analysis than a normal AST.
13
14This chapter covers the main concepts of the HIR.
15
16You can view the HIR representation of your code by passing the
6a06907d 17`-Z unpretty=hir-tree` flag to rustc:
a1dfa0c6
XL
18
19```bash
6a06907d 20cargo rustc -- -Z unpretty=hir-tree
a1dfa0c6
XL
21```
22
6a06907d 23## Out-of-band storage and the `Crate` type
a1dfa0c6
XL
24
25The top-level data-structure in the HIR is the [`Crate`], which stores
26the contents of the crate currently being compiled (we only ever
27construct HIR for the current crate). Whereas in the AST the crate
28data structure basically just contains the root module, the HIR
29`Crate` structure contains a number of maps and other things that
30serve to organize the content of the crate for easier access.
31
dfeec247 32[`Crate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/struct.Crate.html
a1dfa0c6
XL
33
34For example, the contents of individual items (e.g. modules,
35functions, traits, impls, etc) in the HIR are not immediately
36accessible in the parents. So, for example, if there is a module item
37`foo` containing a function `bar()`:
38
39```rust
40mod foo {
41 fn bar() { }
42}
43```
44
45then in the HIR the representation of module `foo` (the [`Mod`]
46struct) would only have the **`ItemId`** `I` of `bar()`. To get the
47details of the function `bar()`, we would lookup `I` in the
48`items` map.
49
dfeec247 50[`Mod`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/struct.Mod.html
a1dfa0c6
XL
51
52One nice result from this representation is that one can iterate
53over all items in the crate by iterating over the key-value pairs
54in these maps (without the need to trawl through the whole HIR).
55There are similar maps for things like trait items and impl items,
56as well as "bodies" (explained below).
57
58The other reason to set up the representation this way is for better
59integration with incremental compilation. This way, if you gain access
dfeec247 60to an [`&rustc_hir::Item`] (e.g. for the mod `foo`), you do not immediately
a1dfa0c6
XL
61gain access to the contents of the function `bar()`. Instead, you only
62gain access to the **id** for `bar()`, and you must invoke some
63function to lookup the contents of `bar()` given its id; this gives
64the compiler a chance to observe that you accessed the data for
65`bar()`, and then record the dependency.
66
dfeec247 67[`&rustc_hir::Item`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/struct.Item.html
a1dfa0c6
XL
68
69<a name="hir-id"></a>
70
6a06907d
XL
71## Identifiers in the HIR
72
73There are a bunch of different identifiers to refer to other nodes or definitions
74in the HIR. In short:
75- A [`DefId`] refers to a *definition* in any crate.
76- A [`LocalDefId`] refers to a *definition* in the currently compiled crate.
77- A [`HirId`] refers to *any node* in the HIR.
78
79For more detailed information, check out the [chapter on identifiers][ids].
a1dfa0c6 80
dfeec247 81[`DefId`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/def_id/struct.DefId.html
6a06907d 82[`LocalDefId`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/def_id/struct.LocalDefId.html
dfeec247 83[`HirId`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir_id/struct.HirId.html
6a06907d 84[ids]: ./identifiers.md#in-the-hir
dfeec247 85
6a06907d 86## The HIR Map
a1dfa0c6
XL
87
88Most of the time when you are working with the HIR, you will do so via
6a06907d 89the **HIR Map**, accessible in the tcx via [`tcx.hir()`] (and defined in
a1dfa0c6
XL
90the [`hir::map`] module). The [HIR map] contains a [number of methods] to
91convert between IDs of various kinds and to lookup data associated
6a06907d 92with a HIR node.
a1dfa0c6 93
6a06907d 94[`tcx.hir()`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html#method.hir
ba9703b0
XL
95[`hir::map`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/index.html
96[HIR map]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/struct.Map.html
97[number of methods]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/struct.Map.html#methods
a1dfa0c6
XL
98
99For example, if you have a [`DefId`], and you would like to convert it
100to a [`NodeId`], you can use
6a06907d 101[`tcx.hir().as_local_node_id(def_id)`][as_local_node_id]. This returns
a1dfa0c6
XL
102an `Option<NodeId>` – this will be `None` if the def-id refers to
103something outside of the current crate (since then it has no HIR
104node), but otherwise returns `Some(n)` where `n` is the node-id of the
105definition.
106
6a06907d 107[`NodeId`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/node_id/struct.NodeId.html
ba9703b0 108[as_local_node_id]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/struct.Map.html#method.as_local_node_id
a1dfa0c6 109
6a06907d 110Similarly, you can use [`tcx.hir().find(n)`][find] to lookup the node for a
a1dfa0c6
XL
111[`NodeId`]. This returns a `Option<Node<'tcx>>`, where [`Node`] is an enum
112defined in the map; by matching on this you can find out what sort of
113node the node-id referred to and also get a pointer to the data
114itself. Often, you know what sort of node `n` is – e.g. if you know
115that `n` must be some HIR expression, you can do
6a06907d 116[`tcx.hir().expect_expr(n)`][expect_expr], which will extract and return the
a1dfa0c6
XL
117[`&hir::Expr`][Expr], panicking if `n` is not in fact an expression.
118
ba9703b0 119[find]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/struct.Map.html#method.find
dfeec247 120[`Node`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/enum.Node.html
ba9703b0 121[expect_expr]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/struct.Map.html#method.expect_expr
dfeec247 122[Expr]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/struct.Expr.html
a1dfa0c6
XL
123
124Finally, you can use the HIR map to find the parents of nodes, via
6a06907d 125calls like [`tcx.hir().get_parent_node(n)`][get_parent_node].
a1dfa0c6 126
ba9703b0 127[get_parent_node]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/struct.Map.html#method.get_parent_node
a1dfa0c6 128
6a06907d 129## HIR Bodies
a1dfa0c6 130
dfeec247 131A [`rustc_hir::Body`] represents some kind of executable code, such as the body
a1dfa0c6
XL
132of a function/closure or the definition of a constant. Bodies are
133associated with an **owner**, which is typically some kind of item
134(e.g. an `fn()` or `const`), but could also be a closure expression
135(e.g. `|x, y| x + y`). You can use the HIR map to find the body
136associated with a given def-id ([`maybe_body_owned_by`]) or to find
137the owner of a body ([`body_owner_def_id`]).
138
dfeec247 139[`rustc_hir::Body`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/struct.Body.html
ba9703b0
XL
140[`maybe_body_owned_by`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/struct.Map.html#method.maybe_body_owned_by
141[`body_owner_def_id`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/struct.Map.html#method.body_owner_def_id