]>
Commit | Line | Data |
---|---|---|
a1dfa0c6 XL |
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 | |
16 | (but with some flags, to know that the user didn't write them) | |
17 | * Existential `impl Trait` | |
18 | * Converted to a virtual `existential type` declaration | |
19 | ||
20 | Lowering needs to uphold several invariants in order to not trigger the | |
6a06907d | 21 | sanity checks in `compiler/rustc_middle/src/hir/map/hir_id_validator.rs`: |
a1dfa0c6 XL |
22 | |
23 | 1. A `HirId` must be used if created. So if you use the `lower_node_id`, | |
24 | you *must* use the resulting `NodeId` or `HirId` (either is fine, since | |
25 | any `NodeId`s in the `HIR` are checked for existing `HirId`s) | |
26 | 2. Lowering a `HirId` must be done in the scope of the *owning* item. | |
27 | This means you need to use `with_hir_id_owner` if you are creating parts | |
28 | of an item other than the one being currently lowered. This happens for | |
29 | example during the lowering of existential `impl Trait` | |
30 | 3. A `NodeId` that will be placed into a HIR structure must be lowered, | |
31 | even if its `HirId` is unused. Calling | |
32 | `let _ = self.lower_node_id(node_id);` is perfectly legitimate. | |
33 | 4. If you are creating new nodes that didn't exist in the `AST`, you *must* | |
34 | create new ids for them. This is done by calling the `next_id` method, | |
35 | which produces both a new `NodeId` as well as automatically lowering it | |
36 | for you so you also get the `HirId`. | |
37 | ||
38 | If you are creating new `DefId`s, since each `DefId` needs to have a | |
39 | corresponding `NodeId`, it is advisable to add these `NodeId`s to the | |
40 | `AST` so you don't have to generate new ones during lowering. This has | |
41 | the advantage of creating a way to find the `DefId` of something via its | |
42 | `NodeId`. If lowering needs this `DefId` in multiple places, you can't | |
43 | generate a new `NodeId` in all those places because you'd also get a new | |
44 | `DefId` then. With a `NodeId` from the `AST` this is not an issue. | |
45 | ||
46 | Having the `NodeId` also allows the `DefCollector` to generate the `DefId`s | |
47 | instead of lowering having to do it on the fly. Centralizing the `DefId` | |
48 | generation in one place makes it easier to refactor and reason about. |