Skip to content

Commit a403aa1

Browse files
committed
Add some explanation of lowering ids
1 parent 7fe7f74 commit a403aa1

File tree

2 files changed

+37
-1
lines changed

2 files changed

+37
-1
lines changed

src/high-level-overview.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ take:
105105
3. **Lowering to HIR**
106106
- Once name resolution completes, we convert the AST into the HIR,
107107
or "[high-level intermediate representation]". The HIR is defined in
108-
`src/librustc/hir/`; that module also includes the lowering code.
108+
`src/librustc/hir/`; that module also includes the [lowering] code.
109109
- The HIR is a lightly desugared variant of the AST. It is more processed
110110
than the AST and more suitable for the analyses that follow.
111111
It is **not** required to match the syntax of the Rust language.
@@ -139,3 +139,4 @@ take:
139139

140140
[query model]: query.html
141141
[high-level intermediate representation]: hir.html
142+
[lowering]: lowering.html

src/lowering.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Lowering
2+
3+
The lowering step converts AST to [HIR](hir.html).
4+
This means many structures are removed if they are irrelevant
5+
for type analysis or similar syntax agnostic analyses. Examples
6+
of such structures include but are not limited to
7+
8+
* Parenthesis
9+
* Removed without replacement, the tree structure makes order explicit
10+
* `for` loops and `while (let)` loops
11+
* Converted to `loop` + `match` and some `let` bindings
12+
* `if let`
13+
* Converted to `match`
14+
* Universal `impl Trait`
15+
* Converted to generic arguments (but with some flags, to know that the user didn't write them)
16+
* Existential `impl Trait`
17+
* Converted to a virtual `existential type` declaration
18+
19+
Lowering needs to uphold several invariants in order to not trigger the
20+
sanity checks in `src/librustc/hir/map/hir_id_validator.rs`:
21+
22+
1. A `HirId` must be used if created. So if you use the `lower_node_id`,
23+
you *must* use the resulting `NodeId` or `HirId` (either is fine, since
24+
any `NodeId`s in the `HIR` are checked for existing `HirId`s)
25+
2. Lowering a `HirId` must be done in the scope of the *owning* item.
26+
This means you need to use `with_hir_id_owner` if you are creating parts
27+
of another item than the one being currently lowered. This happens for
28+
example during the lowering of existential `impl Trait`
29+
3. A `NodeId` that will be placed into a HIR structure must be lowered,
30+
even if its `HirId` is unused. Calling
31+
`let _ = self.lower_node_id(node_id);` is perfectly legitimate.
32+
4. If you are creating new nodes that didn't exist in the `AST`, you *must*
33+
create new ids for them. This is done by calling the `next_id` method,
34+
which produces both a new `NodeId` as well as automatically lowering it
35+
for you so you also get the `HirId`.

0 commit comments

Comments
 (0)