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>
This commit is contained in:
parent
b5814b34da
commit
cfffdd92ea
190
src/thir.md
190
src/thir.md
|
|
@ -4,10 +4,11 @@
|
||||||
|
|
||||||
The THIR ("Typed High-Level Intermediate Representation"), previously called HAIR for
|
The THIR ("Typed High-Level Intermediate Representation"), previously called HAIR for
|
||||||
"High-Level Abstract IR", is another IR used by rustc that is generated after
|
"High-Level Abstract IR", is another IR used by rustc that is generated after
|
||||||
[type checking]. It is (as of <!-- date: 2021-03 --> March 2021) only used for
|
[type checking]. It is (as of <!-- date: 2021-08 --> August 2021) only used for
|
||||||
[MIR construction] and [exhaustiveness checking], but
|
[MIR construction] and [exhaustiveness checking]. There is also
|
||||||
[it may also soon be used for unsafety checking][thir-unsafeck] as a replacement
|
[an experimental unsafety checker][thir-unsafeck] that operates on the THIR as a replacement for
|
||||||
for the current MIR unsafety checker.
|
the current MIR unsafety checker, and can be used instead of the MIR unsafety checker by passing
|
||||||
|
the `-Z thir-unsafeck` flag to `rustc`.
|
||||||
|
|
||||||
[type checking]: ./type-checking.md
|
[type checking]: ./type-checking.md
|
||||||
[MIR construction]: ./mir/construction.md
|
[MIR construction]: ./mir/construction.md
|
||||||
|
|
@ -19,8 +20,8 @@ the types have been filled in, which is possible after type checking has complet
|
||||||
But it has some other interesting features that distinguish it from the HIR:
|
But it has some other interesting features that distinguish it from the HIR:
|
||||||
|
|
||||||
- Like the MIR, the THIR only represents bodies, i.e. "executable code"; this includes
|
- Like the MIR, the THIR only represents bodies, i.e. "executable code"; this includes
|
||||||
function bodies, but also `const` initializers, for example. Consequently, the THIR
|
function bodies, but also `const` initializers, for example. Specifically, all [body owners] have
|
||||||
has no representation for items like `struct`s or `trait`s.
|
THIR created. Consequently, the THIR has no representation for items like `struct`s or `trait`s.
|
||||||
|
|
||||||
- Each body of THIR is only stored temporarily and is dropped as soon as it's no longer
|
- Each body of THIR is only stored temporarily and is dropped as soon as it's no longer
|
||||||
needed, as opposed to being stored until the end of the compilation process (which
|
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:
|
||||||
are made explicit, and method calls and overloaded operators are converted into
|
are made explicit, and method calls and overloaded operators are converted into
|
||||||
plain function calls. Destruction scopes are also made explicit.
|
plain function calls. Destruction scopes are also made explicit.
|
||||||
|
|
||||||
|
- Statements, expressions, and match arms are stored separately. For example, statements in the
|
||||||
|
`stmts` array reference expressions by their index (represented as a [`ExprId`]) in the `exprs`
|
||||||
|
array.
|
||||||
|
|
||||||
[HIR]: ./hir.md
|
[HIR]: ./hir.md
|
||||||
|
[`ExprId`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/thir/struct.ExprId.html
|
||||||
|
[body owners]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/enum.BodyOwnerKind.html
|
||||||
|
|
||||||
The THIR lives in [`rustc_mir_build::thir`][thir-docs]. To construct a [`thir::Expr`],
|
The THIR lives in [`rustc_mir_build::thir`][thir-docs]. To construct a [`thir::Expr`],
|
||||||
you can use the [`thir_body`] function, passing in the memory arena where the THIR
|
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
|
||||||
all bodies of a crate in memory at the same time would be very heavy.
|
all bodies of a crate in memory at the same time would be very heavy.
|
||||||
|
|
||||||
You can get a debug representation of the THIR by passing the `-Zunpretty=thir-tree` flag
|
You can get a debug representation of the THIR by passing the `-Zunpretty=thir-tree` flag
|
||||||
to `rustc`.
|
to `rustc`. Here is how a function with just the statement `let x = 1 + 2;` gets represented in
|
||||||
|
THIR:
|
||||||
|
```rust
|
||||||
|
Thir {
|
||||||
|
// no match arms
|
||||||
|
arms: [],
|
||||||
|
exprs: [
|
||||||
|
// expression 0, a literal with a value of 1
|
||||||
|
Expr {
|
||||||
|
ty: i32,
|
||||||
|
temp_lifetime: Some(Node(6)),
|
||||||
|
span: oneplustwo.rs:2:13: 2:14 (#0),
|
||||||
|
kind: Literal {
|
||||||
|
literal: Const {
|
||||||
|
ty: i32,
|
||||||
|
val: Value(Scalar(0x00000001)),
|
||||||
|
},
|
||||||
|
user_ty: None,
|
||||||
|
const_id: None,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// expression 1, scope surronding literal 1
|
||||||
|
Expr {
|
||||||
|
ty: i32,
|
||||||
|
temp_lifetime: Some(Node(6)),
|
||||||
|
span: oneplustwo.rs:2:13: 2:14 (#0),
|
||||||
|
kind: Scope {
|
||||||
|
region_scope: Node(1),
|
||||||
|
lint_level: Explicit(HirId {
|
||||||
|
owner: DefId(0:3 ~ oneplustwo[6ccc]::main),
|
||||||
|
local_id: 1,
|
||||||
|
}),
|
||||||
|
// reference to expression 0 above
|
||||||
|
value: e0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// expression 2, literal 2
|
||||||
|
Expr {
|
||||||
|
ty: i32,
|
||||||
|
temp_lifetime: Some(Node(6)),
|
||||||
|
span: oneplustwo.rs:2:17: 2:18 (#0),
|
||||||
|
kind: Literal {
|
||||||
|
literal: Const {
|
||||||
|
ty: i32,
|
||||||
|
val: Value(Scalar(0x00000002)),
|
||||||
|
},
|
||||||
|
user_ty: None,
|
||||||
|
const_id: None,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// expression 3, scope surrounding literal 2
|
||||||
|
Expr {
|
||||||
|
ty: i32,
|
||||||
|
temp_lifetime: Some(Node(6)),
|
||||||
|
span: oneplustwo.rs:2:17: 2:18 (#0),
|
||||||
|
kind: Scope {
|
||||||
|
region_scope: Node(2),
|
||||||
|
lint_level: Explicit(HirId {
|
||||||
|
owner: DefId(0:3 ~ oneplustwo[6ccc]::main),
|
||||||
|
local_id: 2,
|
||||||
|
}),
|
||||||
|
// reference to expression 2 above
|
||||||
|
value: e2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// expression 4, represents 1 + 2
|
||||||
|
Expr {
|
||||||
|
ty: i32,
|
||||||
|
temp_lifetime: Some(Node(6)),
|
||||||
|
span: oneplustwo.rs:2:13: 2:18 (#0),
|
||||||
|
kind: Binary {
|
||||||
|
op: Add,
|
||||||
|
// references to scopes surronding literals above
|
||||||
|
lhs: e1,
|
||||||
|
rhs: e3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// expression 5, scope surronding expression 4
|
||||||
|
Expr {
|
||||||
|
ty: i32,
|
||||||
|
temp_lifetime: Some(Node(6)),
|
||||||
|
span: oneplustwo.rs:2:13: 2:18 (#0),
|
||||||
|
kind: Scope {
|
||||||
|
region_scope: Node(3),
|
||||||
|
lint_level: Explicit(HirId {
|
||||||
|
owner: DefId(0:3 ~ oneplustwo[6ccc]::main),
|
||||||
|
local_id: 3,
|
||||||
|
}),
|
||||||
|
value: e4,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// expression 6, block around statement
|
||||||
|
Expr {
|
||||||
|
ty: (),
|
||||||
|
temp_lifetime: Some(Node(8)),
|
||||||
|
span: oneplustwo.rs:1:11: 3:2 (#0),
|
||||||
|
kind: Block {
|
||||||
|
body: Block {
|
||||||
|
targeted_by_break: false,
|
||||||
|
region_scope: Node(7),
|
||||||
|
opt_destruction_scope: None,
|
||||||
|
span: oneplustwo.rs:1:11: 3:2 (#0),
|
||||||
|
// reference to statement 0 below
|
||||||
|
stmts: [ s0 ],
|
||||||
|
expr: None,
|
||||||
|
safety_mode: Safe,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// expression 7, scope around block in expression 6
|
||||||
|
Expr {
|
||||||
|
ty: (),
|
||||||
|
temp_lifetime: Some(
|
||||||
|
Node(8),
|
||||||
|
),
|
||||||
|
span: oneplustwo.rs:1:11: 3:2 (#0),
|
||||||
|
kind: Scope {
|
||||||
|
region_scope: Node(8),
|
||||||
|
lint_level: Explicit(HirId {
|
||||||
|
owner: DefId(0:3 ~ oneplustwo[6ccc]::main),
|
||||||
|
local_id: 8,
|
||||||
|
}),
|
||||||
|
value: e6,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// destruction scope around expression 7
|
||||||
|
Expr {
|
||||||
|
ty: (),
|
||||||
|
temp_lifetime: Some(Node(8)),
|
||||||
|
span: oneplustwo.rs:1:11: 3:2 (#0),
|
||||||
|
kind: Scope {
|
||||||
|
region_scope: Destruction(8),
|
||||||
|
lint_level: Inherited,
|
||||||
|
value: e7,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
stmts: [
|
||||||
|
// let statement
|
||||||
|
Stmt {
|
||||||
|
kind: Let {
|
||||||
|
remainder_scope: Remainder { block: 7, first_statement_index: 0},
|
||||||
|
init_scope: Node(6),
|
||||||
|
pattern: Pat {
|
||||||
|
ty: i32,
|
||||||
|
span: oneplustwo.rs:2:9: 2:10 (#0),
|
||||||
|
kind: Binding {
|
||||||
|
mutability: Not,
|
||||||
|
name: "x",
|
||||||
|
mode: ByValue,
|
||||||
|
var: HirId {
|
||||||
|
owner: DefId(0:3 ~ oneplustwo[6ccc]::main),
|
||||||
|
local_id: 5,
|
||||||
|
},
|
||||||
|
ty: i32,
|
||||||
|
subpattern: None,
|
||||||
|
is_primary: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
initializer: Some(e5),
|
||||||
|
lint_level: Explicit(HirId {
|
||||||
|
owner: DefId(0:3 ~ oneplustwo[6ccc]::main),
|
||||||
|
local_id: 4,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
opt_destruction_scope: Some(Destruction(6)),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
[thir-docs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_build/thir/index.html
|
[thir-docs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_build/thir/index.html
|
||||||
[`thir::Expr`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/thir/struct.Expr.html
|
[`thir::Expr`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/thir/struct.Expr.html
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue