Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 28 additions & 1 deletion src/hir/lowering.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,26 @@ of such structures include but are not limited to
* Existential `impl Trait`
* Converted to a virtual `existential type` declaration

The implementation of AST lowering is in the [`rustc_ast_lowering`] crate.
The entry point is [`lower_to_hir`], which retrieves the post-expansion AST
and resolver data from [`TyCtxt`] and builds the [`hir::Crate`] for the whole crate.

Lowering is organized around HIR owners. [`lower_to_hir`] first indexes the
crate and then [`ItemLowerer::lower_node`] lowers each crate, item, associated
item, and foreign item.

Most of the lowering logic lives on [`LoweringContext`]. The implementation is
split across multiple files in the [`rustc_ast_lowering`] crate such as `item.rs`,
`expr.rs`, `pat.rs`, `path.rs`, and others, but they all share the same [`LoweringContext`]
state and ID‑lowering machinery.

Each owner is lowered in its own [`with_hir_id_owner`] scope. This is why the
`HirId` invariants below matter: `lower_node_id` maps AST `NodeId`s into the
current owner, while `next_id` creates fresh HIR-only nodes introduced during
desugaring.

Lowering needs to uphold several invariants in order to not trigger the
sanity checks in `compiler/rustc_passes/src/hir_id_validator.rs`:
sanity checks in [`compiler/rustc_passes/src/hir_id_validator.rs`][hir_id_validator]:

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
Expand All @@ -33,6 +51,15 @@ sanity checks in `compiler/rustc_passes/src/hir_id_validator.rs`:
which produces both a new `NodeId` as well as automatically lowering it
for you so you also get the `HirId`.

[`rustc_ast_lowering`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast_lowering/index.html
[`lower_to_hir`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast_lowering/fn.lower_to_hir.html
[`TyCtxt`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html
[`hir::Crate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/struct.Crate.html
[`ItemLowerer::lower_node`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast_lowering/item/struct.ItemLowerer.html
[`LoweringContext`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast_lowering/struct.LoweringContext.html
[`with_hir_id_owner`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast_lowering/struct.LoweringContext.html#method.with_hir_id_owner
[hir_id_validator]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_passes/src/hir_id_validator.rs

If you are creating new `DefId`s, since each `DefId` needs to have a
corresponding `NodeId`, it is advisable to add these `NodeId`s to the
`AST` so you don't have to generate new ones during lowering. This has
Expand Down
Loading