about summary refs log tree commit diff
path: root/src/doc/rustc-dev-guide
diff options
context:
space:
mode:
authorSmittyvb <me@smitop.com>2021-08-21 19:55:56 -0400
committerGitHub <noreply@github.com>2021-08-21 19:55:56 -0400
commit281a814146ee4b5c9b1cdbeacc2cce1936283382 (patch)
tree2dd8da3f0bbfc9c4a456bbdaf532fcdde22b520f /src/doc/rustc-dev-guide
parent4cba5b3f720fd58e489f666cfefb86901dcdb6f9 (diff)
downloadrust-281a814146ee4b5c9b1cdbeacc2cce1936283382.tar.gz
rust-281a814146ee4b5c9b1cdbeacc2cce1936283382.zip
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>
Diffstat (limited to 'src/doc/rustc-dev-guide')
-rw-r--r--src/doc/rustc-dev-guide/src/thir.md190
1 files changed, 183 insertions, 7 deletions
diff --git a/src/doc/rustc-dev-guide/src/thir.md b/src/doc/rustc-dev-guide/src/thir.md
index a1d38990792..95009e5529b 100644
--- a/src/doc/rustc-dev-guide/src/thir.md
+++ b/src/doc/rustc-dev-guide/src/thir.md
@@ -4,10 +4,11 @@
 
 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
-[type checking]. It is (as of <!-- date: 2021-03 --> March 2021) only used for
-[MIR construction] and [exhaustiveness checking], but
-[it may also soon be used for unsafety checking][thir-unsafeck] as a replacement
-for the current MIR unsafety checker.
+[type checking]. It is (as of <!-- date: 2021-08 --> August 2021) only used for
+[MIR construction] and [exhaustiveness checking]. There is also
+[an experimental unsafety checker][thir-unsafeck] that operates on the THIR as a replacement for
+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
 [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:
 
 - 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
-  has no representation for items like `struct`s or `trait`s.
+  function bodies, but also `const` initializers, for example. Specifically, all [body owners] have
+  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
   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
   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
+[`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`],
 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.
 
 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::Expr`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/thir/struct.Expr.html