4
4
5
5
The THIR ("Typed High-Level Intermediate Representation"), previously called HAIR for
6
6
"High-Level Abstract IR", is another IR used by rustc that is generated after
7
- [ type checking] . It is (as of <!-- date: 2021-03 --> March 2021) only used for
8
- [ MIR construction] and [ exhaustiveness checking] , but
9
- [ it may also soon be used for unsafety checking] [ thir-unsafeck ] as a replacement
10
- for the current MIR unsafety checker.
7
+ [ type checking] . It is (as of <!-- date: 2021-08 --> August 2021) only used for
8
+ [ MIR construction] and [ exhaustiveness checking] . There is also
9
+ [ an experimental unsafety checker] [ thir-unsafeck ] that operates on the THIR as a replacement for
10
+ the current MIR unsafety checker, and can be used instead of the MIR unsafety checker by passing
11
+ the ` -Z thir-unsafeck ` flag to ` rustc ` .
11
12
12
13
[ type checking ] : ./type-checking.md
13
14
[ MIR construction ] : ./mir/construction.md
@@ -19,8 +20,10 @@ the types have been filled in, which is possible after type checking has complet
19
20
But it has some other interesting features that distinguish it from the HIR:
20
21
21
22
- Like the MIR, the THIR only represents bodies, i.e. "executable code"; this includes
22
- function bodies, but also ` const ` initializers, for example. Consequently, the THIR
23
- has no representation for items like ` struct ` s or ` trait ` s.
23
+ function bodies, but also ` const ` initializers, for example. Specifically, everything with a
24
+ ` DefId ` can (and does) have a THIR body created. Consequently, the THIR
25
+ has no representation for items like ` struct ` s or ` trait ` s. References to those items are
26
+ represented as ` HirId ` s in the THIR.
24
27
25
28
- Each body of THIR is only stored temporarily and is dropped as soon as it's no longer
26
29
needed, as opposed to being stored until the end of the compilation process (which
@@ -31,6 +34,11 @@ But it has some other interesting features that distinguish it from the HIR:
31
34
are made explicit, and method calls and overloaded operators are converted into
32
35
plain function calls. Destruction scopes are also made explicit.
33
36
37
+ - Statements, expressions, and match arms are stored separately. Statements in the ` stmts ` array
38
+ reference expressions by their index in the ` exprs ` array. Expressions reference subexpressions by
39
+ their index in the ` exprs ` array. Match experssions reference arms by their index in the
40
+ ` arms ` array.
41
+
34
42
[ HIR ] : ./hir.md
35
43
36
44
The THIR lives in [ ` rustc_mir_build::thir ` ] [ thir-docs ] . To construct a [ ` thir::Expr ` ] ,
@@ -40,7 +48,176 @@ which is useful to keep peak memory in check. Having a THIR representation of
40
48
all bodies of a crate in memory at the same time would be very heavy.
41
49
42
50
You can get a debug representation of the THIR by passing the ` -Zunpretty=thir-tree ` flag
43
- to ` rustc ` .
51
+ to ` rustc ` . Here is how a function with just the statement ` let x = 1 + 2; ` gets represented in
52
+ annotated THIR:
53
+ ``` rust
54
+ Thir {
55
+ // no match arms
56
+ arms : [],
57
+ exprs : [
58
+ // expression 0, a literal with a value of 1
59
+ Expr {
60
+ ty : i32 ,
61
+ temp_lifetime : Some (Node (6 )),
62
+ span : oneplustwo . rs: 2 : 13 : 2 : 14 (#0 ),
63
+ kind : Literal {
64
+ literal : Const {
65
+ ty : i32 ,
66
+ val : Value (Scalar (0x00000001 )),
67
+ },
68
+ user_ty : None ,
69
+ const_id : None ,
70
+ },
71
+ },
72
+ // expression 1, scope surronding literal 1
73
+ Expr {
74
+ ty : i32 ,
75
+ temp_lifetime : Some (Node (6 )),
76
+ span : oneplustwo . rs: 2 : 13 : 2 : 14 (#0 ),
77
+ kind : Scope {
78
+ region_scope : Node (1 ),
79
+ lint_level : Explicit (HirId {
80
+ owner : DefId (0 : 3 ~ oneplustwo [6ccc ]:: main ),
81
+ local_id : 1 ,
82
+ }),
83
+ // reference to expression 0 above
84
+ value : e0 ,
85
+ },
86
+ },
87
+ // expression 2, literal 2
88
+ Expr {
89
+ ty : i32 ,
90
+ temp_lifetime : Some (Node (6 )),
91
+ span : oneplustwo . rs: 2 : 17 : 2 : 18 (#0 ),
92
+ kind : Literal {
93
+ literal : Const {
94
+ ty : i32 ,
95
+ val : Value (Scalar (0x00000002 )),
96
+ },
97
+ user_ty : None ,
98
+ const_id : None ,
99
+ },
100
+ },
101
+ // expression 3, scope surrounding literal 2
102
+ Expr {
103
+ ty : i32 ,
104
+ temp_lifetime : Some (Node (6 )),
105
+ span : oneplustwo . rs: 2 : 17 : 2 : 18 (#0 ),
106
+ kind : Scope {
107
+ region_scope : Node (2 ),
108
+ lint_level : Explicit (HirId {
109
+ owner : DefId (0 : 3 ~ oneplustwo [6ccc ]:: main ),
110
+ local_id : 2 ,
111
+ }),
112
+ // reference to expression 2 above
113
+ value : e2 ,
114
+ },
115
+ },
116
+ // expression 4, represents 1 + 2
117
+ Expr {
118
+ ty : i32 ,
119
+ temp_lifetime : Some (Node (6 )),
120
+ span : oneplustwo . rs: 2 : 13 : 2 : 18 (#0 ),
121
+ kind : Binary {
122
+ op : Add ,
123
+ // references to scopes surronding literals above
124
+ lhs : e1 ,
125
+ rhs : e3 ,
126
+ },
127
+ },
128
+ // expression 5, scope surronding expression 4
129
+ Expr {
130
+ ty : i32 ,
131
+ temp_lifetime : Some (Node (6 )),
132
+ span : oneplustwo . rs: 2 : 13 : 2 : 18 (#0 ),
133
+ kind : Scope {
134
+ region_scope : Node (3 ),
135
+ lint_level : Explicit (HirId {
136
+ owner : DefId (0 : 3 ~ oneplustwo [6ccc ]:: main ),
137
+ local_id : 3 ,
138
+ }),
139
+ value : e4 ,
140
+ },
141
+ },
142
+ // expression 6, block around statement
143
+ Expr {
144
+ ty : (),
145
+ temp_lifetime : Some (Node (8 )),
146
+ span : oneplustwo . rs: 1 : 11 : 3 : 2 (#0 ),
147
+ kind : Block {
148
+ body : Block {
149
+ targeted_by_break : false ,
150
+ region_scope : Node (7 ),
151
+ opt_destruction_scope : None ,
152
+ span : oneplustwo . rs: 1 : 11 : 3 : 2 (#0 ),
153
+ // reference to statement 0 below
154
+ stmts : [ s0 ],
155
+ expr : None ,
156
+ safety_mode : Safe ,
157
+ },
158
+ },
159
+ },
160
+ // expression 7, scope around block in expression 6
161
+ Expr {
162
+ ty : (),
163
+ temp_lifetime : Some (
164
+ Node (8 ),
165
+ ),
166
+ span : oneplustwo . rs: 1 : 11 : 3 : 2 (#0 ),
167
+ kind : Scope {
168
+ region_scope : Node (8 ),
169
+ lint_level : Explicit (HirId {
170
+ owner : DefId (0 : 3 ~ oneplustwo [6ccc ]:: main ),
171
+ local_id : 8 ,
172
+ }),
173
+ value : e6 ,
174
+ },
175
+ },
176
+ // destruction scope around expression 7
177
+ Expr {
178
+ ty : (),
179
+ temp_lifetime : Some (Node (8 )),
180
+ span : oneplustwo . rs: 1 : 11 : 3 : 2 (#0 ),
181
+ kind : Scope {
182
+ region_scope : Destruction (8 ),
183
+ lint_level : Inherited ,
184
+ value : e7 ,
185
+ },
186
+ },
187
+ ],
188
+ stmts : [
189
+ // let statement
190
+ Stmt {
191
+ kind : Let {
192
+ remainder_scope : Remainder { block : 7 , first_statement_index : 0 },
193
+ init_scope : Node (6 ),
194
+ pattern : Pat {
195
+ ty : i32 ,
196
+ span : oneplustwo . rs: 2 : 9 : 2 : 10 (#0 ),
197
+ kind : Binding {
198
+ mutability : Not ,
199
+ name : " x" ,
200
+ mode : ByValue ,
201
+ var : HirId {
202
+ owner : DefId (0 : 3 ~ oneplustwo [6ccc ]:: main ),
203
+ local_id : 5 ,
204
+ },
205
+ ty : i32 ,
206
+ subpattern : None ,
207
+ is_primary : true ,
208
+ },
209
+ },
210
+ initializer : Some (e5 ),
211
+ lint_level : Explicit (HirId {
212
+ owner : DefId (0 : 3 ~ oneplustwo [6ccc ]:: main ),
213
+ local_id : 4 ,
214
+ }),
215
+ },
216
+ opt_destruction_scope : Some (Destruction (6 )),
217
+ },
218
+ ],
219
+ }
220
+ ```
44
221
45
222
[ thir-docs ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_build/thir/index.html
46
223
[ `thir::Expr` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/thir/struct.Expr.html
0 commit comments