@@ -20,13 +20,15 @@ You can view the HIR representation of your code by passing the
20
20
21
21
### Out-of-band storage and the ` Crate ` type
22
22
23
- The top-level data-structure in the HIR is the ` Crate ` , which stores
23
+ The top-level data-structure in the HIR is the [ ` Crate ` ] , which stores
24
24
the contents of the crate currently being compiled (we only ever
25
25
construct HIR for the current crate). Whereas in the AST the crate
26
26
data structure basically just contains the root module, the HIR
27
27
` Crate ` structure contains a number of maps and other things that
28
28
serve to organize the content of the crate for easier access.
29
29
30
+ [ `Crate` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc/hir/struct.Crate.html
31
+
30
32
For example, the contents of individual items (e.g. modules,
31
33
functions, traits, impls, etc) in the HIR are not immediately
32
34
accessible in the parents. So, for example, if there is a module item
@@ -38,11 +40,13 @@ mod foo {
38
40
}
39
41
```
40
42
41
- then in the HIR the representation of module ` foo ` (the ` Mod `
42
- stuct ) would only have the ** ` ItemId ` ** ` I ` of ` bar() ` . To get the
43
+ then in the HIR the representation of module ` foo ` (the [ ` Mod ` ]
44
+ struct ) would only have the ** ` ItemId ` ** ` I ` of ` bar() ` . To get the
43
45
details of the function ` bar() ` , we would lookup ` I ` in the
44
46
` items ` map.
45
47
48
+ [ `Mod` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc/hir/struct.Mod.html
49
+
46
50
One nice result from this representation is that one can iterate
47
51
over all items in the crate by iterating over the key-value pairs
48
52
in these maps (without the need to trawl through the whole HIR).
@@ -51,12 +55,14 @@ as well as "bodies" (explained below).
51
55
52
56
The other reason to set up the representation this way is for better
53
57
integration with incremental compilation. This way, if you gain access
54
- to an ` &hir::Item ` (e.g. for the mod ` foo ` ), you do not immediately
58
+ to an [ ` &hir::Item ` ] (e.g. for the mod ` foo ` ), you do not immediately
55
59
gain access to the contents of the function ` bar() ` . Instead, you only
56
60
gain access to the ** id** for ` bar() ` , and you must invoke some
57
- function to lookup the contents of ` bar() ` given its id; this gives the
58
- compiler a chance to observe that you accessed the data for ` bar() ` ,
59
- and then record the dependency.
61
+ function to lookup the contents of ` bar() ` given its id; this gives
62
+ the compiler a chance to observe that you accessed the data for
63
+ ` bar() ` , and then record the dependency.
64
+
65
+ [ `&hir::Item` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc/hir/struct.Item.html
60
66
61
67
<a name =" hir-id " ></a >
62
68
@@ -67,63 +73,86 @@ carry around references into the HIR, but rather to carry around
67
73
* identifier numbers* (or just "ids"). Right now, you will find four
68
74
sorts of identifiers in active use:
69
75
70
- - ` DefId ` , which primarily names "definitions" or top-level items.
71
- - You can think of a ` DefId ` as being shorthand for a very explicit
76
+ - [ ` DefId ` ] , which primarily names "definitions" or top-level items.
77
+ - You can think of a [ ` DefId ` ] as being shorthand for a very explicit
72
78
and complete path, like ` std::collections::HashMap ` . However,
73
79
these paths are able to name things that are not nameable in
74
80
normal Rust (e.g. impls), and they also include extra information
75
81
about the crate (such as its version number, as two versions of
76
82
the same crate can co-exist).
77
- - A ` DefId ` really consists of two parts, a ` CrateNum ` (which
83
+ - A [ ` DefId ` ] really consists of two parts, a ` CrateNum ` (which
78
84
identifies the crate) and a ` DefIndex ` (which indixes into a list
79
85
of items that is maintained per crate).
80
- - ` HirId ` , which combines the index of a particular item with an
86
+ - [ ` HirId ` ] , which combines the index of a particular item with an
81
87
offset within that item.
82
- - the key point of a ` HirId ` is that it is * relative* to some item
83
- (which is named via a ` DefId ` ).
84
- - ` BodyId ` , this is an absolute identifier that refers to a specific
88
+ - the key point of a [ ` HirId ` ] is that it is * relative* to some item
89
+ (which is named via a [ ` DefId ` ] ).
90
+ - [ ` BodyId ` ] , this is an absolute identifier that refers to a specific
85
91
body (definition of a function or constant) in the crate. It is currently
86
- effectively a "newtype'd" ` NodeId ` .
87
- - ` NodeId ` , which is an absolute id that identifies a single node in the HIR
92
+ effectively a "newtype'd" [ ` NodeId ` ] .
93
+ - [ ` NodeId ` ] , which is an absolute id that identifies a single node in the HIR
88
94
tree.
89
95
- While these are still in common use, ** they are being slowly phased out** .
90
96
- Since they are absolute within the crate, adding a new node anywhere in the
91
- tree causes the ` NodeId ` s of all subsequent code in the crate to change.
97
+ tree causes the [ ` NodeId ` ] s of all subsequent code in the crate to change.
92
98
This is terrible for incremental compilation, as you can perhaps imagine.
93
99
100
+ [ `DefId` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc/hir/def_id/struct.DefId.html
101
+ [ `HirId` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc/hir/struct.HirId.html
102
+ [ `BodyId` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc/hir/struct.BodyId.html
103
+ [ `NodeId` ] : https://doc.rust-lang.org/nightly/nightly-rustc/syntax/ast/struct.NodeId.html
104
+
94
105
### The HIR Map
95
106
96
107
Most of the time when you are working with the HIR, you will do so via
97
- the ** HIR Map** , accessible in the tcx via ` tcx.hir ` (and defined in
98
- the ` hir::map ` module). The HIR map contains a number of methods to
108
+ the ** HIR Map** , accessible in the tcx via [ ` tcx.hir ` ] (and defined in
109
+ the [ ` hir::map ` ] module). The [ HIR map] contains a [ number of methods] to
99
110
convert between IDs of various kinds and to lookup data associated
100
111
with an HIR node.
101
112
102
- For example, if you have a ` DefId ` , and you would like to convert it
103
- to a ` NodeId ` , you can use ` tcx.hir.as_local_node_id(def_id) ` . This
113
+ [ `tcx.hir` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/context/struct.GlobalCtxt.html#structfield.hir
114
+ [ `hir::map` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc/hir/map/index.html
115
+ [ HIR map ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc/hir/map/struct.Map.html
116
+ [ number of methods ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc/hir/map/struct.Map.html#methods
117
+
118
+ For example, if you have a [ ` DefId ` ] , and you would like to convert it
119
+ to a [ ` NodeId ` ] , you can use [ ` tcx.hir.as_local_node_id(def_id) ` ] [ as_local_node_id ] . This
104
120
returns an ` Option<NodeId> ` – this will be ` None ` if the def-id
105
121
refers to something outside of the current crate (since then it has no
106
122
HIR node), but otherwise returns ` Some(n) ` where ` n ` is the node-id of
107
123
the definition.
108
124
109
- Similarly, you can use ` tcx.hir.find(n) ` to lookup the node for a
110
- ` NodeId ` . This returns a ` Option<Node<'tcx>> ` , where ` Node ` is an enum
125
+ [ as_local_node_id ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc/hir/map/struct.Map.html#method.as_local_node_id
126
+
127
+ Similarly, you can use [ ` tcx.hir.find(n) ` ] [ find ] to lookup the node for a
128
+ [ ` NodeId ` ] . This returns a ` Option<Node<'tcx>> ` , where [ ` Node ` ] is an enum
111
129
defined in the map; by matching on this you can find out what sort of
112
130
node the node-id referred to and also get a pointer to the data
113
131
itself. Often, you know what sort of node ` n ` is – e.g. if you know
114
132
that ` n ` must be some HIR expression, you can do
115
- ` tcx.hir.expect_expr(n) ` , which will extract and return the
116
- ` &hir::Expr ` , panicking if ` n ` is not in fact an expression.
133
+ [ ` tcx.hir.expect_expr(n) ` ] [ expect_expr ] , which will extract and return the
134
+ [ ` &hir::Expr ` ] [ Expr ] , panicking if ` n ` is not in fact an expression.
135
+
136
+ [ find ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc/hir/map/struct.Map.html#method.find
137
+ [ `Node` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc/hir/enum.Node.html
138
+ [ expect_expr ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc/hir/map/struct.Map.html#method.expect_expr
139
+ [ Expr ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc/hir/struct.Expr.html
117
140
118
141
Finally, you can use the HIR map to find the parents of nodes, via
119
- calls like ` tcx.hir.get_parent_node(n) ` .
142
+ calls like [ ` tcx.hir.get_parent_node(n) ` ] [ get_parent_node ] .
143
+
144
+ [ get_parent_node ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc/hir/map/struct.Map.html#method.get_parent_node
120
145
121
146
### HIR Bodies
122
147
123
- A ** body ** represents some kind of executable code, such as the body
148
+ A [ ` hir::Body ` ] represents some kind of executable code, such as the body
124
149
of a function/closure or the definition of a constant. Bodies are
125
150
associated with an ** owner** , which is typically some kind of item
126
151
(e.g. an ` fn() ` or ` const ` ), but could also be a closure expression
127
152
(e.g. ` |x, y| x + y ` ). You can use the HIR map to find the body
128
- associated with a given def-id (` maybe_body_owned_by() ` ) or to find
129
- the owner of a body (` body_owner_def_id() ` ).
153
+ associated with a given def-id ([ ` maybe_body_owned_by ` ] ) or to find
154
+ the owner of a body ([ ` body_owner_def_id ` ] ).
155
+
156
+ [ `hir::Body` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc/hir/struct.Body.html
157
+ [ `maybe_body_owned_by` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc/hir/map/struct.Map.html#method.maybe_body_owned_by
158
+ [ `body_owner_def_id` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc/hir/map/struct.Map.html#method.body_owner_def_id
0 commit comments