Skip to content

Commit 77a9813

Browse files
syvbLeSeulArtichaut
andauthoredAug 21, 2021
Expand THIR section with more details (#1183)
* Expand THIR section with more details * Remove incorrect reference to `HirId`s Co-authored-by: Léo Lanteri Thauvin <leseulartichaut@gmail.com>
1 parent 9a6bd9f commit 77a9813

File tree

1 file changed

+183
-7
lines changed

1 file changed

+183
-7
lines changed
 

‎src/thir.md

+183-7
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@
44

55
The THIR ("Typed High-Level Intermediate Representation"), previously called HAIR for
66
"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`.
1112

1213
[type checking]: ./type-checking.md
1314
[MIR construction]: ./mir/construction.md
@@ -19,8 +20,8 @@ the types have been filled in, which is possible after type checking has complet
1920
But it has some other interesting features that distinguish it from the HIR:
2021

2122
- 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, all [body owners] have
24+
THIR created. Consequently, the THIR has no representation for items like `struct`s or `trait`s.
2425

2526
- Each body of THIR is only stored temporarily and is dropped as soon as it's no longer
2627
needed, as opposed to being stored until the end of the compilation process (which
@@ -31,7 +32,13 @@ But it has some other interesting features that distinguish it from the HIR:
3132
are made explicit, and method calls and overloaded operators are converted into
3233
plain function calls. Destruction scopes are also made explicit.
3334

35+
- Statements, expressions, and match arms are stored separately. For example, statements in the
36+
`stmts` array reference expressions by their index (represented as a [`ExprId`]) in the `exprs`
37+
array.
38+
3439
[HIR]: ./hir.md
40+
[`ExprId`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/thir/struct.ExprId.html
41+
[body owners]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/enum.BodyOwnerKind.html
3542

3643
The THIR lives in [`rustc_mir_build::thir`][thir-docs]. To construct a [`thir::Expr`],
3744
you can use the [`thir_body`] function, passing in the memory arena where the THIR
@@ -40,7 +47,176 @@ which is useful to keep peak memory in check. Having a THIR representation of
4047
all bodies of a crate in memory at the same time would be very heavy.
4148

4249
You can get a debug representation of the THIR by passing the `-Zunpretty=thir-tree` flag
43-
to `rustc`.
50+
to `rustc`. Here is how a function with just the statement `let x = 1 + 2;` gets represented in
51+
THIR:
52+
```rust
53+
Thir {
54+
// no match arms
55+
arms: [],
56+
exprs: [
57+
// expression 0, a literal with a value of 1
58+
Expr {
59+
ty: i32,
60+
temp_lifetime: Some(Node(6)),
61+
span: oneplustwo.rs:2:13: 2:14 (#0),
62+
kind: Literal {
63+
literal: Const {
64+
ty: i32,
65+
val: Value(Scalar(0x00000001)),
66+
},
67+
user_ty: None,
68+
const_id: None,
69+
},
70+
},
71+
// expression 1, scope surronding literal 1
72+
Expr {
73+
ty: i32,
74+
temp_lifetime: Some(Node(6)),
75+
span: oneplustwo.rs:2:13: 2:14 (#0),
76+
kind: Scope {
77+
region_scope: Node(1),
78+
lint_level: Explicit(HirId {
79+
owner: DefId(0:3 ~ oneplustwo[6ccc]::main),
80+
local_id: 1,
81+
}),
82+
// reference to expression 0 above
83+
value: e0,
84+
},
85+
},
86+
// expression 2, literal 2
87+
Expr {
88+
ty: i32,
89+
temp_lifetime: Some(Node(6)),
90+
span: oneplustwo.rs:2:17: 2:18 (#0),
91+
kind: Literal {
92+
literal: Const {
93+
ty: i32,
94+
val: Value(Scalar(0x00000002)),
95+
},
96+
user_ty: None,
97+
const_id: None,
98+
},
99+
},
100+
// expression 3, scope surrounding literal 2
101+
Expr {
102+
ty: i32,
103+
temp_lifetime: Some(Node(6)),
104+
span: oneplustwo.rs:2:17: 2:18 (#0),
105+
kind: Scope {
106+
region_scope: Node(2),
107+
lint_level: Explicit(HirId {
108+
owner: DefId(0:3 ~ oneplustwo[6ccc]::main),
109+
local_id: 2,
110+
}),
111+
// reference to expression 2 above
112+
value: e2,
113+
},
114+
},
115+
// expression 4, represents 1 + 2
116+
Expr {
117+
ty: i32,
118+
temp_lifetime: Some(Node(6)),
119+
span: oneplustwo.rs:2:13: 2:18 (#0),
120+
kind: Binary {
121+
op: Add,
122+
// references to scopes surronding literals above
123+
lhs: e1,
124+
rhs: e3,
125+
},
126+
},
127+
// expression 5, scope surronding expression 4
128+
Expr {
129+
ty: i32,
130+
temp_lifetime: Some(Node(6)),
131+
span: oneplustwo.rs:2:13: 2:18 (#0),
132+
kind: Scope {
133+
region_scope: Node(3),
134+
lint_level: Explicit(HirId {
135+
owner: DefId(0:3 ~ oneplustwo[6ccc]::main),
136+
local_id: 3,
137+
}),
138+
value: e4,
139+
},
140+
},
141+
// expression 6, block around statement
142+
Expr {
143+
ty: (),
144+
temp_lifetime: Some(Node(8)),
145+
span: oneplustwo.rs:1:11: 3:2 (#0),
146+
kind: Block {
147+
body: Block {
148+
targeted_by_break: false,
149+
region_scope: Node(7),
150+
opt_destruction_scope: None,
151+
span: oneplustwo.rs:1:11: 3:2 (#0),
152+
// reference to statement 0 below
153+
stmts: [ s0 ],
154+
expr: None,
155+
safety_mode: Safe,
156+
},
157+
},
158+
},
159+
// expression 7, scope around block in expression 6
160+
Expr {
161+
ty: (),
162+
temp_lifetime: Some(
163+
Node(8),
164+
),
165+
span: oneplustwo.rs:1:11: 3:2 (#0),
166+
kind: Scope {
167+
region_scope: Node(8),
168+
lint_level: Explicit(HirId {
169+
owner: DefId(0:3 ~ oneplustwo[6ccc]::main),
170+
local_id: 8,
171+
}),
172+
value: e6,
173+
},
174+
},
175+
// destruction scope around expression 7
176+
Expr {
177+
ty: (),
178+
temp_lifetime: Some(Node(8)),
179+
span: oneplustwo.rs:1:11: 3:2 (#0),
180+
kind: Scope {
181+
region_scope: Destruction(8),
182+
lint_level: Inherited,
183+
value: e7,
184+
},
185+
},
186+
],
187+
stmts: [
188+
// let statement
189+
Stmt {
190+
kind: Let {
191+
remainder_scope: Remainder { block: 7, first_statement_index: 0},
192+
init_scope: Node(6),
193+
pattern: Pat {
194+
ty: i32,
195+
span: oneplustwo.rs:2:9: 2:10 (#0),
196+
kind: Binding {
197+
mutability: Not,
198+
name: "x",
199+
mode: ByValue,
200+
var: HirId {
201+
owner: DefId(0:3 ~ oneplustwo[6ccc]::main),
202+
local_id: 5,
203+
},
204+
ty: i32,
205+
subpattern: None,
206+
is_primary: true,
207+
},
208+
},
209+
initializer: Some(e5),
210+
lint_level: Explicit(HirId {
211+
owner: DefId(0:3 ~ oneplustwo[6ccc]::main),
212+
local_id: 4,
213+
}),
214+
},
215+
opt_destruction_scope: Some(Destruction(6)),
216+
},
217+
],
218+
}
219+
```
44220

45221
[thir-docs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_build/thir/index.html
46222
[`thir::Expr`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/thir/struct.Expr.html

0 commit comments

Comments
 (0)