diff --git a/src/high-level-overview.md b/src/high-level-overview.md index 60b9e80e..733c523c 100644 --- a/src/high-level-overview.md +++ b/src/high-level-overview.md @@ -105,7 +105,7 @@ take: 3. **Lowering to HIR** - Once name resolution completes, we convert the AST into the HIR, or "[high-level intermediate representation]". The HIR is defined in - `src/librustc/hir/`; that module also includes the lowering code. + `src/librustc/hir/`; that module also includes the [lowering] code. - The HIR is a lightly desugared variant of the AST. It is more processed than the AST and more suitable for the analyses that follow. It is **not** required to match the syntax of the Rust language. @@ -139,3 +139,4 @@ take: [query model]: query.html [high-level intermediate representation]: hir.html +[lowering]: lowering.html \ No newline at end of file diff --git a/src/lowering.md b/src/lowering.md new file mode 100644 index 00000000..33551334 --- /dev/null +++ b/src/lowering.md @@ -0,0 +1,35 @@ +# Lowering + +The lowering step converts AST to [HIR](hir.html). +This means many structures are removed if they are irrelevant +for type analysis or similar syntax agnostic analyses. Examples +of such structures include but are not limited to + +* Parenthesis + * Removed without replacement, the tree structure makes order explicit +* `for` loops and `while (let)` loops + * Converted to `loop` + `match` and some `let` bindings +* `if let` + * Converted to `match` +* Universal `impl Trait` + * Converted to generic arguments (but with some flags, to know that the user didn't write them) +* Existential `impl Trait` + * Converted to a virtual `existential type` declaration + +Lowering needs to uphold several invariants in order to not trigger the +sanity checks in `src/librustc/hir/map/hir_id_validator.rs`: + +1. A `HirId` must be used if created. So if you use the `lower_node_id`, + you *must* use the resulting `NodeId` or `HirId` (either is fine, since + any `NodeId`s in the `HIR` are checked for existing `HirId`s) +2. Lowering a `HirId` must be done in the scope of the *owning* item. + This means you need to use `with_hir_id_owner` if you are creating parts + of another item than the one being currently lowered. This happens for + example during the lowering of existential `impl Trait` +3. A `NodeId` that will be placed into a HIR structure must be lowered, + even if its `HirId` is unused. Calling + `let _ = self.lower_node_id(node_id);` is perfectly legitimate. +4. If you are creating new nodes that didn't exist in the `AST`, you *must* + create new ids for them. This is done by calling the `next_id` method, + which produces both a new `NodeId` as well as automatically lowering it + for you so you also get the `HirId`. \ No newline at end of file