From 693325fc39363c04d4efcf4a2e575b6ab1bac383 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 23 May 2021 23:09:38 +0200 Subject: [PATCH] internal: document ItemTree design --- crates/hir_def/src/item_tree.rs | 34 +++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index 528270d49d3..4a5f44027ed 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs @@ -1,4 +1,34 @@ //! A simplified AST that only contains items. +//! +//! This is the primary IR used throughout `hir_def`. It is the input to the name resolution +//! algorithm, as well as to the queries defined in `adt.rs`, `data.rs`, and most things in +//! `attr.rs`. +//! +//! `ItemTree`s are built per `HirFileId`, from the syntax tree of the parsed file. This means that +//! they are crate-independent: they don't know which `#[cfg]`s are active or which module they +//! belong to, since those concepts don't exist at this level (a single `ItemTree` might be part of +//! multiple crates, or might be included into the same crate twice via `#[path]`). +//! +//! One important purpose of this layer is to provide an "invalidation barrier" for incremental +//! computations: when typing inside an item body, the `ItemTree` of the modified file is typically +//! unaffected, so we don't have to recompute name resolution results or item data (see `data.rs`). +//! +//! The `ItemTree` for the currently open file can be displayed by using the VS Code command +//! "Rust Analyzer: Debug ItemTree". +//! +//! Compared to rustc's architecture, `ItemTree` has properties from both rustc's AST and HIR: many +//! syntax-level Rust features are already desugared to simpler forms in the `ItemTree`, but name +//! resolution has not yet been performed. `ItemTree`s are per-file, while rustc's AST and HIR are +//! per-crate, because we are interested in incrementally computing it. +//! +//! The representation of items in the `ItemTree` should generally mirror the surface syntax: it is +//! usually a bad idea to desugar a syntax-level construct to something that is structurally +//! different here. Name resolution needs to be able to process attributes and expand macros +//! (including attribute macros), and having a 1-to-1 mapping between syntax and the `ItemTree` +//! avoids introducing subtle bugs. +//! +//! In general, any item in the `ItemTree` stores its `AstId`, which allows mapping it back to its +//! surface syntax. mod lower; mod pretty; @@ -500,8 +530,8 @@ pub struct Import { pub alias: Option, pub visibility: RawVisibilityId, pub is_glob: bool, - /// AST ID of the `use` or `extern crate` item this import was derived from. Note that many - /// `Import`s can map to the same `use` item. + /// AST ID of the `use` item this import was derived from. Note that many `Import`s can map to + /// the same `use` item. pub ast_id: FileAstId, /// Index of this `Import` when the containing `Use` is visited via `ModPath::expand_use_item`. ///