Repository: rust-analyzer/rust-analyzer
Pull request #5566 (2020-07-29 09:59:17)

Owned AST IR


bors r+
🤖


Patch:
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs
index 0fede0d879..4c4d9f6fa9 100644
--- a/crates/ra_ide/src/lib.rs
+++ b/crates/ra_ide/src/lib.rs
@@ -510,10 +510,9 @@ impl Analysis {
         query: &str,
         parse_only: bool,
         position: FilePosition,
-        selections: Vec<FileRange>,
     ) -> Cancelable<Result<SourceChange, SsrError>> {
         self.with_db(|db| {
-            let edits = ssr::parse_search_replace(query, parse_only, db, position, selections)?;
+            let edits = ssr::parse_search_replace(query, parse_only, db, position)?;
             Ok(SourceChange::from(edits))
         })
     }
diff --git a/crates/ra_ide/src/ssr.rs b/crates/ra_ide/src/ssr.rs
index 4348b43beb..95d8f79b87 100644
--- a/crates/ra_ide/src/ssr.rs
+++ b/crates/ra_ide/src/ssr.rs
@@ -1,4 +1,4 @@
-use ra_db::{FilePosition, FileRange};
+use ra_db::FilePosition;
 use ra_ide_db::RootDatabase;
 
 use crate::SourceFileEdit;
@@ -24,9 +24,6 @@ use ra_ssr::{MatchFinder, SsrError, SsrRule};
 // Method calls should generally be written in UFCS form. e.g. `foo::Bar::baz($s, $a)` will match
 // `$s.baz($a)`, provided the method call `baz` resolves to the method `foo::Bar::baz`.
 //
-// The scope of the search / replace will be restricted to the current selection if any, otherwise
-// it will apply to the whole workspace.
-//
 // Placeholders may be given constraints by writing them as `${<name>:<constraint1>:<constraint2>...}`.
 //
 // Supported constraints:
@@ -59,11 +56,10 @@ pub fn parse_search_replace(
     rule: &str,
     parse_only: bool,
     db: &RootDatabase,
-    resolve_context: FilePosition,
-    selections: Vec<FileRange>,
+    position: FilePosition,
 ) -> Result<Vec<SourceFileEdit>, SsrError> {
     let rule: SsrRule = rule.parse()?;
-    let mut match_finder = MatchFinder::in_context(db, resolve_context, selections);
+    let mut match_finder = MatchFinder::in_context(db, position);
     match_finder.add_rule(rule)?;
     if parse_only {
         return Ok(Vec::new());
diff --git a/crates/ra_ssr/src/lib.rs b/crates/ra_ssr/src/lib.rs
index 73abfecb2e..7014a6ac66 100644
--- a/crates/ra_ssr/src/lib.rs
+++ b/crates/ra_ssr/src/lib.rs
@@ -52,7 +52,6 @@ pub struct MatchFinder<'db> {
     sema: Semantics<'db, ra_ide_db::RootDatabase>,
     rules: Vec<ResolvedRule>,
     resolution_scope: resolving::ResolutionScope<'db>,
-    restrict_ranges: Vec<FileRange>,
 }
 
 impl<'db> MatchFinder<'db> {
@@ -61,17 +60,10 @@ impl<'db> MatchFinder<'db> {
     pub fn in_context(
         db: &'db ra_ide_db::RootDatabase,
         lookup_context: FilePosition,
-        mut restrict_ranges: Vec<FileRange>,
     ) -> MatchFinder<'db> {
-        restrict_ranges.retain(|range| !range.range.is_empty());
         let sema = Semantics::new(db);
         let resolution_scope = resolving::ResolutionScope::new(&sema, lookup_context);
-        MatchFinder {
-            sema: Semantics::new(db),
-            rules: Vec::new(),
-            resolution_scope,
-            restrict_ranges,
-        }
+        MatchFinder { sema: Semantics::new(db), rules: Vec::new(), resolution_scope }
     }
 
     /// Constructs an instance using the start of the first file in `db` as the lookup context.
@@ -87,7 +79,6 @@ impl<'db> MatchFinder<'db> {
             Ok(MatchFinder::in_context(
                 db,
                 FilePosition { file_id: first_file_id, offset: 0.into() },
-                vec![],
             ))
         } else {
             bail!("No files to search");
diff --git a/crates/ra_ssr/src/matching.rs b/crates/ra_ssr/src/matching.rs
index c1b66748ec..4862622bde 100644
--- a/crates/ra_ssr/src/matching.rs
+++ b/crates/ra_ssr/src/matching.rs
@@ -706,8 +706,8 @@ mod tests {
         let rule: SsrRule = "foo($x) ==>> bar($x)".parse().unwrap();
         let input = "fn foo() {} fn bar() {} fn main() { foo(1+2); }";
 
-        let (db, position, selections) = crate::tests::single_file(input);
-        let mut match_finder = MatchFinder::in_context(&db, position, selections);
+        let (db, position) = crate::tests::single_file(input);
+        let mut match_finder = MatchFinder::in_context(&db, position);
         match_finder.add_rule(rule).unwrap();
         let matches = match_finder.matches();
         assert_eq!(matches.matches.len(), 1);
diff --git a/crates/ra_ssr/src/resolving.rs b/crates/ra_ssr/src/resolving.rs
index 78d4565467..123bd2bb24 100644
--- a/crates/ra_ssr/src/resolving.rs
+++ b/crates/ra_ssr/src/resolving.rs
@@ -141,14 +141,14 @@ impl Resolver<'_, '_> {
 impl<'db> ResolutionScope<'db> {
     pub(crate) fn new(
         sema: &hir::Semantics<'db, ra_ide_db::RootDatabase>,
-        resolve_context: FilePosition,
+        lookup_context: FilePosition,
     ) -> ResolutionScope<'db> {
         use ra_syntax::ast::AstNode;
-        let file = sema.parse(resolve_context.file_id);
+        let file = sema.parse(lookup_context.file_id);
         // Find a node at the requested position, falling back to the whole file.
         let node = file
             .syntax()
-            .token_at_offset(resolve_context.offset)
+            .token_at_offset(lookup_context.offset)
             .left_biased()
             .map(|token| token.parent())
             .unwrap_or_else(|| file.syntax().clone());
@@ -156,7 +156,7 @@ impl<'db> ResolutionScope<'db> {
         let scope = sema.scope(&node);
         ResolutionScope {
             scope,
-            hygiene: hir::Hygiene::new(sema.db, resolve_context.file_id.into()),
+            hygiene: hir::Hygiene::new(sema.db, lookup_context.file_id.into()),
         }
     }
 
diff --git a/crates/ra_ssr/src/search.rs b/crates/ra_ssr/src/search.rs
index 0f512cb62d..bcf0f04689 100644
--- a/crates/ra_ssr/src/search.rs
+++ b/crates/ra_ssr/src/search.rs
@@ -5,13 +5,12 @@ use crate::{
     resolving::{ResolvedPath, ResolvedPattern, ResolvedRule},
     Match, MatchFinder,
 };
-use ra_db::{FileId, FileRange};
+use ra_db::FileRange;
 use ra_ide_db::{
     defs::Definition,
     search::{Reference, SearchScope},
 };
 use ra_syntax::{ast, AstNode, SyntaxKind, SyntaxNode};
-use rustc_hash::FxHashSet;
 use test_utils::mark;
 
 /// A cache for the results of find_usages. This is for when we have multiple patterns that have the
@@ -55,7 +54,11 @@ impl<'db> MatchFinder<'db> {
                         mark::hit!(use_declaration_with_braces);
                         continue;
                     }
-                    self.try_add_match(rule, &node_to_match, &None, matches_out);
+                    if let Ok(m) =
+                        matching::get_match(false, rule, &node_to_match, &None, &self.sema)
+                    {
+                        matches_out.push(m);
+                    }
                 }
             }
         }
@@ -118,39 +121,25 @@ impl<'db> MatchFinder<'db> {
         // FIXME: We should ideally have a test that checks that we edit local roots and not library
         // roots. This probably would require some changes to fixtures, since currently everything
         // seems to get put into a single source root.
+        use ra_db::SourceDatabaseExt;
+        use ra_ide_db::symbol_index::SymbolsDatabase;
         let mut files = Vec::new();
-        self.search_files_do(|file_id| {
-            files.push(file_id);
-        });
+        for &root in self.sema.db.local_roots().iter() {
+            let sr = self.sema.db.source_root(root);
+            files.extend(sr.iter());
+        }
         SearchScope::files(&files)
     }
 
     fn slow_scan(&self, rule: &ResolvedRule, matches_out: &mut Vec<Match>) {
-        self.search_files_do(|file_id| {
-            let file = self.sema.parse(file_id);
-            let code = file.syntax();
-            self.slow_scan_node(code, rule, &None, matches_out);
-        })
-    }
-
-    fn search_files_do(&self, mut callback: impl FnMut(FileId)) {
-        if self.restrict_ranges.is_empty() {
-            // Unrestricted search.
-            use ra_db::SourceDatabaseExt;
-            use ra_ide_db::symbol_index::SymbolsDatabase;
-            for &root in self.sema.db.local_roots().iter() {
-                let sr = self.sema.db.source_root(root);
-                for file_id in sr.iter() {
-                    callback(file_id);
-                }
-            }
-        } else {
-            // Search is restricted, deduplicate file IDs (generally only one).
-            let mut files = FxHashSet::default();
-            for range in &self.restrict_ranges {
-                if files.insert(range.file_id) {
-                    callback(range.file_id);
-                }
+        use ra_db::SourceDatabaseExt;
+        use ra_ide_db::symbol_index::SymbolsDatabase;
+        for &root in self.sema.db.local_roots().iter() {
+            let sr = self.sema.db.source_root(root);
+            for file_id in sr.iter() {
+                let file = self.sema.parse(file_id);
+                let code = file.syntax();
+                self.slow_scan_node(code, rule, &None, matches_out);
             }
         }
     }
@@ -165,7 +154,9 @@ impl<'db> MatchFinder<'db> {
         if !is_search_permitted(code) {
             return;
         }
-        self.try_add_match(rule, &code, restrict_range, matches_out);
+        if let Ok(m) = matching::get_match(false, rule, &code, restrict_range, &self.sema) {
+            matches_out.push(m);
+        }
         // If we've got a macro call, we already tried matching it pre-expansion, which is the only
         // way to match the whole macro, now try expanding it and matching the expansion.
         if let Some(macro_call) = ast::MacroCall::cast(code.clone()) {
@@ -187,38 +178,6 @@ impl<'db> MatchFinder<'db> {
             self.slow_scan_node(&child, rule, restrict_range, matches_out);
         }
     }
-
-    fn try_add_match(
-        &self,
-        rule: &ResolvedRule,
-        code: &SyntaxNode,
-        restrict_range: &Option<FileRange>,
-        matches_out: &mut Vec<Match>,
-    ) {
-        if !self.within_range_restrictions(code) {
-            mark::hit!(replace_nonpath_within_selection);
-            return;
-        }
-        if let Ok(m) = matching::get_match(false, rule, code, restrict_range, &self.sema) {
-            matches_out.push(m);
-        }
-    }
-
-    /// Returns whether `code` is within one of our range restrictions if we have any. No range
-    /// restrictions is considered unrestricted and always returns true.
-    fn within_range_restrictions(&self, code: &SyntaxNode) -> bool {
-        if self.restrict_ranges.is_empty() {
-            // There is no range restriction.
-            return true;
-        }
-        let node_range = self.sema.original_range(code);
-        for range in &self.restrict_ranges {
-            if range.file_id == node_range.file_id && range.range.contains_range(node_range.range) {
-                return true;
-            }
-        }
-        false
-    }
 }
 
 /// Returns whether we support matching within `node` and all of its ancestors.
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index 1350bd4002..cd309ed744 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -1026,18 +1026,9 @@ pub(crate) fn handle_ssr(
     params: lsp_ext::SsrParams,
 ) -> Result<lsp_types::WorkspaceEdit> {
     let _p = profile("handle_ssr");
-    let selections = params
-        .selections
-        .iter()
-        .map(|range| from_proto::file_range(&snap, params.position.text_document.clone(), *range))
-        .collect::<Result<Vec<_>, _>>()?;
     let position = from_proto::file_position(&snap, params.position)?;
-    let source_change = snap.analysis.structural_search_replace(
-        &params.query,
-        params.parse_only,
-        position,
-        selections,
-    )??;
+    let source_change =
+        snap.analysis.structural_search_replace(&params.query, params.parse_only, position)??;
     to_proto::workspace_edit(&snap, source_change)
 }
 
diff --git a/crates/rust-analyzer/src/lsp_ext.rs b/crates/rust-analyzer/src/lsp_ext.rs
index 3976b6529e..113e0e070a 100644
--- a/crates/rust-analyzer/src/lsp_ext.rs
+++ b/crates/rust-analyzer/src/lsp_ext.rs
@@ -221,9 +221,6 @@ pub struct SsrParams {
     /// position.
     #[serde(flatten)]
     pub position: lsp_types::TextDocumentPositionParams,
-
-    /// Current selections. Search/replace will be restricted to these if non-empty.
-    pub selections: Vec<lsp_types::Range>,
 }
 
 pub enum StatusNotification {}
diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts
index d0faf4745a..c21e5597cb 100644
--- a/editors/code/src/commands.ts
+++ b/editors/code/src/commands.ts
@@ -190,7 +190,6 @@ export function ssr(ctx: Ctx): Cmd {
         if (!editor || !client) return;
 
         const position = editor.selection.active;
-        const selections = editor.selections;
         const textDocument = { uri: editor.document.uri.toString() };
 
         const options: vscode.InputBoxOptions = {
@@ -199,7 +198,7 @@ export function ssr(ctx: Ctx): Cmd {
             validateInput: async (x: string) => {
                 try {
                     await client.sendRequest(ra.ssr, {
-                        query: x, parseOnly: true, textDocument, position, selections,
+                        query: x, parseOnly: true, textDocument, position,
                     });
                 } catch (e) {
                     return e.toString();
@@ -216,7 +215,7 @@ export function ssr(ctx: Ctx): Cmd {
             cancellable: false,
         }, async (_progress, _token) => {
             const edit = await client.sendRequest(ra.ssr, {
-                query: request, parseOnly: false, textDocument, position, selections,
+                query: request, parseOnly: false, textDocument, position
             });
 
             await vscode.workspace.applyEdit(client.protocol2CodeConverter.asWorkspaceEdit(edit));
diff --git a/editors/code/src/lsp_ext.ts b/editors/code/src/lsp_ext.ts
index 494d51c83a..149f9a0d64 100644
--- a/editors/code/src/lsp_ext.ts
+++ b/editors/code/src/lsp_ext.ts
@@ -95,7 +95,6 @@ export interface SsrParams {
     parseOnly: boolean;
     textDocument: lc.TextDocumentIdentifier;
     position: lc.Position;
-    selections: lc.Range[];
 }
 export const ssr = new lc.RequestType<SsrParams, lc.WorkspaceEdit, void>('experimental/ssr');
 
diff --git a/xtask/src/ast_src.rs b/xtask/src/ast_src.rs
index 392648d713..425814d732 100644
--- a/xtask/src/ast_src.rs
+++ b/xtask/src/ast_src.rs
@@ -223,35 +223,35 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc {
     ],
 };
 
-pub(crate) struct AstSrc<'a> {
-    pub(crate) tokens: &'a [&'a str],
-    pub(crate) nodes: &'a [AstNodeSrc<'a>],
-    pub(crate) enums: &'a [AstEnumSrc<'a>],
+pub(crate) struct AstSrc {
+    pub(crate) tokens: Vec<String>,
+    pub(crate) nodes: Vec<AstNodeSrc>,
+    pub(crate) enums: Vec<AstEnumSrc>,
 }
 
-pub(crate) struct AstNodeSrc<'a> {
-    pub(crate) doc: &'a [&'a str],
-    pub(crate) name: &'a str,
-    pub(crate) traits: &'a [&'a str],
-    pub(crate) fields: &'a [Field<'a>],
+pub(crate) struct AstNodeSrc {
+    pub(crate) doc: Vec<String>,
+    pub(crate) name: String,
+    pub(crate) traits: Vec<String>,
+    pub(crate) fields: Vec<Field>,
 }
 
-pub(crate) enum Field<'a> {
-    Token(&'a str),
-    Node { name: &'a str, src: FieldSrc<'a> },
+pub(crate) enum Field {
+    Token(String),
+    Node { name: String, src: FieldSrc },
 }
 
-pub(crate) enum FieldSrc<'a> {
+pub(crate) enum FieldSrc {
     Shorthand,
-    Optional(&'a str),
-    Many(&'a str),
+    Optional(String),
+    Many(String),
 }
 
-pub(crate) struct AstEnumSrc<'a> {
-    pub(crate) doc: &'a [&'a str],
-    pub(crate) name: &'a str,
-    pub(crate) traits: &'a [&'a str],
-    pub(crate) variants: &'a [&'a str],
+pub(crate) struct AstEnumSrc {
+    pub(crate) doc: Vec<String>,
+    pub(crate) name: String,
+    pub(crate) traits: Vec<String>,
+    pub(crate) variants: Vec<String>,
 }
 
 macro_rules! ast_nodes {
@@ -261,12 +261,12 @@ macro_rules! ast_nodes {
             $($field_name:ident $(![$token:tt])? $(: $ty:tt)?),*$(,)?
         }
     )*) => {
-        [$(
+        vec![$(
             AstNodeSrc {
-                doc: &[$($doc),*],
-                name: stringify!($name),
-                traits: &[$($(stringify!($trait)),*)?],
-                fields: &[
+                doc: vec![$($doc.to_string()),*],
+                name: stringify!($name).to_string(),
+                traits: vec![$($(stringify!($trait).to_string()),*)?],
+                fields: vec![
                     $(field!($(T![$token])? $field_name $($ty)?)),*
                 ],
 
@@ -277,16 +277,22 @@ macro_rules! ast_nodes {
 
 macro_rules! field {
     (T![$token:tt] T) => {
-        Field::Token(stringify!($token))
+        Field::Token(stringify!($token).to_string())
     };
     ($field_name:ident) => {
-        Field::Node { name: stringify!($field_name), src: FieldSrc::Shorthand }
+        Field::Node { name: stringify!($field_name).to_string(), src: FieldSrc::Shorthand }
     };
     ($field_name:ident [$ty:ident]) => {
-        Field::Node { name: stringify!($field_name), src: FieldSrc::Many(stringify!($ty)) }
+        Field::Node {
+            name: stringify!($field_name).to_string(),
+            src: FieldSrc::Many(stringify!($ty).to_string()),
+        }
     };
     ($field_name:ident $ty:ident) => {
-        Field::Node { name: stringify!($field_name), src: FieldSrc::Optional(stringify!($ty)) }
+        Field::Node {
+            name: stringify!($field_name).to_string(),
+            src: FieldSrc::Optional(stringify!($ty).to_string()),
+        }
     };
 }
 
@@ -297,1947 +303,1949 @@ macro_rules! ast_enums {
             $($variant:ident),*$(,)?
         }
     )*) => {
-        [$(
+        vec![$(
             AstEnumSrc {
-                doc: &[$($doc),*],
-                name: stringify!($name),
-                traits: &[$($(stringify!($trait)),*)?],
-                variants: &[$(stringify!($variant)),*],
+                doc: vec![$($doc.to_string()),*],
+                name: stringify!($name).to_string(),
+                traits: vec![$($(stringify!($trait).to_string()),*)?],
+                variants: vec![$(stringify!($variant).to_string()),*],
             }
         ),*]
     };
 }
 
-pub(crate) const AST_SRC: AstSrc = AstSrc {
-    tokens: &["Whitespace", "Comment", "String", "RawString"],
-    nodes: &ast_nodes! {
-        /// The entire Rust source file. Includes all top-level inner attributes and module items.
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/crates-and-source-files.html)
-        struct SourceFile: ModuleItemOwner, AttrsOwner, DocCommentsOwner {
-            modules: [Module],
-        }
+pub(crate) fn rust_ast() -> AstSrc {
+    AstSrc {
+        tokens: vec!["Whitespace".into(), "Comment".into(), "String".into(), "RawString".into()],
+        nodes: ast_nodes! {
+            /// The entire Rust source file. Includes all top-level inner attributes and module items.
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/crates-and-source-files.html)
+            struct SourceFile: ModuleItemOwner, AttrsOwner, DocCommentsOwner {
+                modules: [Module],
+            }
 
-        /// Function definition either with body or not.
-        /// Includes all of its attributes and doc comments.
-        ///
-        /// ```
-        /// ❰
-        ///     /// Docs
-        ///     #[attr]
-        ///     pub extern "C" fn foo<T>(#[attr] Patern {p}: Pattern) -> u32
-        ///     where
-        ///         T: Debug
-        ///     {
-        ///         42
-        ///     }
-        /// ❱
-        ///
-        /// extern "C" {
-        ///     ❰ fn fn_decl(also_variadic_ffi: u32, ...) -> u32; ❱
-        /// }
-        /// ```
-        ///
-        /// - [Reference](https://doc.rust-lang.org/reference/items/functions.html)
-        /// - [Nomicon](https://doc.rust-lang.org/nomicon/ffi.html#variadic-functions)
-        struct FnDef: VisibilityOwner, NameOwner, TypeParamsOwner, DocCommentsOwner, AttrsOwner {
-            Abi,
-            T![const],
-            T![default],
-            T![async],
-            T![unsafe],
-            T![fn],
-            ParamList,
-            RetType,
-            body: BlockExpr,
-            T![;]
-        }
+            /// Function definition either with body or not.
+            /// Includes all of its attributes and doc comments.
+            ///
+            /// ```
+            /// ❰
+            ///     /// Docs
+            ///     #[attr]
+            ///     pub extern "C" fn foo<T>(#[attr] Patern {p}: Pattern) -> u32
+            ///     where
+            ///         T: Debug
+            ///     {
+            ///         42
+            ///     }
+            /// ❱
+            ///
+            /// extern "C" {
+            ///     ❰ fn fn_decl(also_variadic_ffi: u32, ...) -> u32; ❱
+            /// }
+            /// ```
+            ///
+            /// - [Reference](https://doc.rust-lang.org/reference/items/functions.html)
+            /// - [Nomicon](https://doc.rust-lang.org/nomicon/ffi.html#variadic-functions)
+            struct FnDef: VisibilityOwner, NameOwner, TypeParamsOwner, DocCommentsOwner, AttrsOwner {
+                Abi,
+                T![const],
+                T![default],
+                T![async],
+                T![unsafe],
+                T![fn],
+                ParamList,
+                RetType,
+                body: BlockExpr,
+                T![;]
+            }
 
-        /// Return type annotation.
-        ///
-        /// ```
-        /// fn foo(a: u32) ❰ -> Option<u32> ❱ { Some(a) }
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/items/functions.html)
-        struct RetType { T![->], TypeRef }
-
-        /// Struct definition.
-        /// Includes all of its attributes and doc comments.
-        ///
-        /// ```
-        /// ❰
-        ///     /// Docs
-        ///     #[attr]
-        ///     struct Foo<T> where T: Debug {
-        ///         /// Docs
-        ///         #[attr]
-        ///         pub a: u32,
-        ///         b: T,
-        ///     }
-        /// ❱
-        ///
-        /// ❰ struct Foo; ❱
-        /// ❰ struct Foo<T>(#[attr] T) where T: Debug; ❱
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/items/structs.html)
-        struct StructDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner {
-            T![struct],
-            FieldDefList,
-            T![;]
-        }
+            /// Return type annotation.
+            ///
+            /// ```
+            /// fn foo(a: u32) ❰ -> Option<u32> ❱ { Some(a) }
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/items/functions.html)
+            struct RetType { T![->], TypeRef }
+
+            /// Struct definition.
+            /// Includes all of its attributes and doc comments.
+            ///
+            /// ```
+            /// ❰
+            ///     /// Docs
+            ///     #[attr]
+            ///     struct Foo<T> where T: Debug {
+            ///         /// Docs
+            ///         #[attr]
+            ///         pub a: u32,
+            ///         b: T,
+            ///     }
+            /// ❱
+            ///
+            /// ❰ struct Foo; ❱
+            /// ❰ struct Foo<T>(#[attr] T) where T: Debug; ❱
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/items/structs.html)
+            struct StructDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner {
+                T![struct],
+                FieldDefList,
+                T![;]
+            }
 
-        /// Union definition.
-        /// Includes all of its attributes and doc comments.
-        ///
-        /// ```
-        /// ❰
-        ///     /// Docs
-        ///     #[attr]
-        ///     pub union Foo<T> where T: Debug {
-        ///         /// Docs
-        ///         #[attr]
-        ///         a: T,
-        ///         b: u32,
-        ///     }
-        /// ❱
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/items/unions.html)
-        struct UnionDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner {
-            T![union],
-            RecordFieldDefList,
-        }
+            /// Union definition.
+            /// Includes all of its attributes and doc comments.
+            ///
+            /// ```
+            /// ❰
+            ///     /// Docs
+            ///     #[attr]
+            ///     pub union Foo<T> where T: Debug {
+            ///         /// Docs
+            ///         #[attr]
+            ///         a: T,
+            ///         b: u32,
+            ///     }
+            /// ❱
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/items/unions.html)
+            struct UnionDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner {
+                T![union],
+                RecordFieldDefList,
+            }
 
-        /// Record field definition list including enclosing curly braces.
-        ///
-        /// ```
-        /// struct Foo // same for union
-        /// ❰
-        ///     {
-        ///         a: u32,
-        ///         b: bool,
-        ///     }
-        /// ❱
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/items/structs.html)
-        struct RecordFieldDefList { T!['{'], fields: [RecordFieldDef], T!['}'] }
-
-        /// Record field definition including its attributes and doc comments.
-        ///
-        /// ` ``
-        /// same for union
-        /// struct Foo {
-        ///      ❰
-        ///          /// Docs
-        ///          #[attr]
-        ///          pub a: u32
-        ///      ❱
-        ///
-        ///      ❰ b: bool ❱
-        /// }
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/items/structs.html)
-        struct RecordFieldDef: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner { }
-
-        /// Tuple field definition list including enclosing parens.
-        ///
-        /// ```
-        /// struct Foo ❰ (u32, String, Vec<u32>) ❱;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/items/structs.html)
-        struct TupleFieldDefList { T!['('], fields: [TupleFieldDef], T![')'] }
-
-        /// Tuple field definition including its attributes.
-        ///
-        /// ```
-        /// struct Foo(❰ #[attr] u32 ❱);
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/items/structs.html)
-        struct TupleFieldDef: VisibilityOwner, AttrsOwner {
-            TypeRef,
-        }
+            /// Record field definition list including enclosing curly braces.
+            ///
+            /// ```
+            /// struct Foo // same for union
+            /// ❰
+            ///     {
+            ///         a: u32,
+            ///         b: bool,
+            ///     }
+            /// ❱
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/items/structs.html)
+            struct RecordFieldDefList { T!['{'], fields: [RecordFieldDef], T!['}'] }
+
+            /// Record field definition including its attributes and doc comments.
+            ///
+            /// ` ``
+            /// same for union
+            /// struct Foo {
+            ///      ❰
+            ///          /// Docs
+            ///          #[attr]
+            ///          pub a: u32
+            ///      ❱
+            ///
+            ///      ❰ b: bool ❱
+            /// }
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/items/structs.html)
+            struct RecordFieldDef: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner { }
+
+            /// Tuple field definition list including enclosing parens.
+            ///
+            /// ```
+            /// struct Foo ❰ (u32, String, Vec<u32>) ❱;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/items/structs.html)
+            struct TupleFieldDefList { T!['('], fields: [TupleFieldDef], T![')'] }
+
+            /// Tuple field definition including its attributes.
+            ///
+            /// ```
+            /// struct Foo(❰ #[attr] u32 ❱);
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/items/structs.html)
+            struct TupleFieldDef: VisibilityOwner, AttrsOwner {
+                TypeRef,
+            }
 
-        /// Enum definition.
-        /// Includes all of its attributes and doc comments.
-        ///
-        /// ```
-        /// ❰
-        ///     /// Docs
-        ///     #[attr]
-        ///     pub enum Foo<T> where T: Debug {
-        ///         /// Docs
-        ///         #[attr]
-        ///         Bar,
-        ///         Baz(#[attr] u32),
-        ///         Bruh {
-        ///             a: u32,
-        ///             /// Docs
-        ///             #[attr]
-        ///             b: T,
-        ///         }
-        ///     }
-        /// ❱
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/items/enumerations.html)
-        struct EnumDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner {
-            T![enum],
-            variant_list: EnumVariantList,
-        }
+            /// Enum definition.
+            /// Includes all of its attributes and doc comments.
+            ///
+            /// ```
+            /// ❰
+            ///     /// Docs
+            ///     #[attr]
+            ///     pub enum Foo<T> where T: Debug {
+            ///         /// Docs
+            ///         #[attr]
+            ///         Bar,
+            ///         Baz(#[attr] u32),
+            ///         Bruh {
+            ///             a: u32,
+            ///             /// Docs
+            ///             #[attr]
+            ///             b: T,
+            ///         }
+            ///     }
+            /// ❱
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/items/enumerations.html)
+            struct EnumDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner {
+                T![enum],
+                variant_list: EnumVariantList,
+            }
 
-        /// Enum variant definition list including enclosing curly braces.
-        ///
-        /// ```
-        /// enum Foo
-        /// ❰
-        ///     {
-        ///         Bar,
-        ///         Baz(u32),
-        ///         Bruh {
-        ///             a: u32
-        ///         }
-        ///     }
-        /// ❱
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/items/enumerations.html)
-        struct EnumVariantList {
-            T!['{'],
-            variants: [EnumVariant],
-            T!['}']
-        }
+            /// Enum variant definition list including enclosing curly braces.
+            ///
+            /// ```
+            /// enum Foo
+            /// ❰
+            ///     {
+            ///         Bar,
+            ///         Baz(u32),
+            ///         Bruh {
+            ///             a: u32
+            ///         }
+            ///     }
+            /// ❱
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/items/enumerations.html)
+            struct EnumVariantList {
+                T!['{'],
+                variants: [EnumVariant],
+                T!['}']
+            }
 
-        /// Enum variant definition including its attributes and discriminant value definition.
-        ///
-        /// ```
-        /// enum Foo {
-        ///     ❰
-        ///         /// Docs
-        ///         #[attr]
-        ///         Bar
-        ///     ❱
-        ///
-        ///     // same for tuple and record variants
-        /// }
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/items/enumerations.html)
-        struct EnumVariant: VisibilityOwner, NameOwner, DocCommentsOwner, AttrsOwner {
-            FieldDefList,
-            T![=],
-            Expr
-        }
+            /// Enum variant definition including its attributes and discriminant value definition.
+            ///
+            /// ```
+            /// enum Foo {
+            ///     ❰
+            ///         /// Docs
+            ///         #[attr]
+            ///         Bar
+            ///     ❱
+            ///
+            ///     // same for tuple and record variants
+            /// }
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/items/enumerations.html)
+            struct EnumVariant: VisibilityOwner, NameOwner, DocCommentsOwner, AttrsOwner {
+                FieldDefList,
+                T![=],
+                Expr
+            }
 
-        /// Trait definition.
-        /// Includes all of its attributes and doc comments.
-        ///
-        /// ```
-        /// ❰
-        ///     /// Docs
-        ///     #[attr]
-        ///     pub unsafe trait Foo<T>: Debug where T: Debug {
-        ///         // ...
-        ///     }
-        /// ❱
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/items/traits.html)
-        struct TraitDef: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner, TypeParamsOwner, TypeBoundsOwner {
-            T![unsafe],
-            T![auto],
-            T![trait],
-            ItemList,
-        }
+            /// Trait definition.
+            /// Includes all of its attributes and doc comments.
+            ///
+            /// ```
+            /// ❰
+            ///     /// Docs
+            ///     #[attr]
+            ///     pub unsafe trait Foo<T>: Debug where T: Debug {
+            ///         // ...
+            ///     }
+            /// ❱
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/items/traits.html)
+            struct TraitDef: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner, TypeParamsOwner, TypeBoundsOwner {
+                T![unsafe],
+                T![auto],
+                T![trait],
+                ItemList,
+            }
 
-        /// Module definition either with body or not.
-        /// Includes all of its inner and outer attributes, module items, doc comments.
-        ///
-        /// ```
-        /// ❰
-        ///     /// Docs
-        ///     #[attr]
-        ///     pub mod foo;
-        /// ❱
-        ///
-        /// ❰
-        ///     /// Docs
-        ///     #[attr]
-        ///     pub mod bar {
-        ///        //! Inner docs
-        ///        #![inner_attr]
-        ///     }
-        /// ❱
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/items/modules.html)
-        struct Module: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner {
-            T![mod],
-            ItemList,
-            T![;]
-        }
+            /// Module definition either with body or not.
+            /// Includes all of its inner and outer attributes, module items, doc comments.
+            ///
+            /// ```
+            /// ❰
+            ///     /// Docs
+            ///     #[attr]
+            ///     pub mod foo;
+            /// ❱
+            ///
+            /// ❰
+            ///     /// Docs
+            ///     #[attr]
+            ///     pub mod bar {
+            ///        //! Inner docs
+            ///        #![inner_attr]
+            ///     }
+            /// ❱
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/items/modules.html)
+            struct Module: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner {
+                T![mod],
+                ItemList,
+                T![;]
+            }
 
-        /// Item defintion list.
-        /// This is used for both top-level items and impl block items.
-        ///
-        /// ```
-        /// ❰
-        ///     fn foo {}
-        ///     struct Bar;
-        ///     enum Baz;
-        ///     trait Bruh;
-        ///     const BRUUH: u32 = 42;
-        /// ❱
-        ///
-        /// impl Foo
-        /// ❰
-        ///     {
-        ///         fn bar() {}
-        ///         const BAZ: u32 = 42;
-        ///     }
-        /// ❱
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/items.html)
-        struct ItemList: ModuleItemOwner {
-            T!['{'],
-            assoc_items: [AssocItem],
-            T!['}']
-        }
+            /// Item defintion list.
+            /// This is used for both top-level items and impl block items.
+            ///
+            /// ```
+            /// ❰
+            ///     fn foo {}
+            ///     struct Bar;
+            ///     enum Baz;
+            ///     trait Bruh;
+            ///     const BRUUH: u32 = 42;
+            /// ❱
+            ///
+            /// impl Foo
+            /// ❰
+            ///     {
+            ///         fn bar() {}
+            ///         const BAZ: u32 = 42;
+            ///     }
+            /// ❱
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/items.html)
+            struct ItemList: ModuleItemOwner {
+                T!['{'],
+                assoc_items: [AssocItem],
+                T!['}']
+            }
 
-        /// Constant variable definition.
-        /// Includes all of its attributes and doc comments.
-        ///
-        /// ```
-        /// ❰
-        ///     /// Docs
-        ///     #[attr]
-        ///     pub const FOO: u32 = 42;
-        /// ❱
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/items/constant-items.html)
-        struct ConstDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner {
-            T![default],
-            T![const],
-            T![=],
-            body: Expr,
-            T![;]
-        }
+            /// Constant variable definition.
+            /// Includes all of its attributes and doc comments.
+            ///
+            /// ```
+            /// ❰
+            ///     /// Docs
+            ///     #[attr]
+            ///     pub const FOO: u32 = 42;
+            /// ❱
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/items/constant-items.html)
+            struct ConstDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner {
+                T![default],
+                T![const],
+                T![=],
+                body: Expr,
+                T![;]
+            }
 
 
-        /// Static variable definition.
-        /// Includes all of its attributes and doc comments.
-        ///
-        /// ```
-        /// ❰
-        ///     /// Docs
-        ///     #[attr]
-        ///     pub static mut FOO: u32 = 42;
-        /// ❱
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/items/static-items.html)
-        struct StaticDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner {
-            T![static],
-            T![mut],
-            T![=],
-            body: Expr,
-            T![;]
-        }
+            /// Static variable definition.
+            /// Includes all of its attributes and doc comments.
+            ///
+            /// ```
+            /// ❰
+            ///     /// Docs
+            ///     #[attr]
+            ///     pub static mut FOO: u32 = 42;
+            /// ❱
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/items/static-items.html)
+            struct StaticDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner {
+                T![static],
+                T![mut],
+                T![=],
+                body: Expr,
+                T![;]
+            }
 
-        /// Type alias definition.
-        /// Includes associated type clauses with type bounds.
-        ///
-        /// ```
-        /// ❰
-        ///     /// Docs
-        ///     #[attr]
-        ///     pub type Foo<T> where T: Debug = T;
-        /// ❱
-        ///
-        /// trait Bar {
-        ///     ❰ type Baz: Debug; ❱
-        ///     ❰ type Bruh = String; ❱
-        ///     ❰ type Bruuh: Debug = u32; ❱
-        /// }
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/items/type-aliases.html)
-        struct TypeAliasDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeBoundsOwner {
-            T![default],
-            T![type],
-            T![=],
-            TypeRef,
-            T![;]
-        }
+            /// Type alias definition.
+            /// Includes associated type clauses with type bounds.
+            ///
+            /// ```
+            /// ❰
+            ///     /// Docs
+            ///     #[attr]
+            ///     pub type Foo<T> where T: Debug = T;
+            /// ❱
+            ///
+            /// trait Bar {
+            ///     ❰ type Baz: Debug; ❱
+            ///     ❰ type Bruh = String; ❱
+            ///     ❰ type Bruuh: Debug = u32; ❱
+            /// }
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/items/type-aliases.html)
+            struct TypeAliasDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeBoundsOwner {
+                T![default],
+                T![type],
+                T![=],
+                TypeRef,
+                T![;]
+            }
 
-        /// Inherent and trait impl definition.
-        /// Includes all of its inner and outer attributes.
-        ///
-        /// ```
-        /// ❰
-        ///     #[attr]
-        ///     unsafe impl<T> const !Foo for Bar where T: Debug {
-        ///         #![inner_attr]
-        ///         // ...
-        ///     }
-        /// ❱
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/items/implementations.html)
-        struct ImplDef: TypeParamsOwner, AttrsOwner, DocCommentsOwner {
-            T![default],
-            T![const],
-            T![unsafe],
-            T![impl],
-            T![!],
-            T![for],
-            ItemList,
-        }
+            /// Inherent and trait impl definition.
+            /// Includes all of its inner and outer attributes.
+            ///
+            /// ```
+            /// ❰
+            ///     #[attr]
+            ///     unsafe impl<T> const !Foo for Bar where T: Debug {
+            ///         #![inner_attr]
+            ///         // ...
+            ///     }
+            /// ❱
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/items/implementations.html)
+            struct ImplDef: TypeParamsOwner, AttrsOwner, DocCommentsOwner {
+                T![default],
+                T![const],
+                T![unsafe],
+                T![impl],
+                T![!],
+                T![for],
+                ItemList,
+            }
 
 
-        /// Parenthesized type reference.
-        /// Note: parens are only used for grouping, this is not a tuple type.
-        ///
-        /// ```
-        /// // This is effectively just `u32`.
-        /// // Single-item tuple must be defined with a trailing comma: `(u32,)`
-        /// type Foo = ❰ (u32) ❱;
-        ///
-        /// let bar: &'static ❰ (dyn Debug) ❱ = "bruh";
-        /// ```
-        struct ParenType { T!['('], TypeRef, T![')'] }
-
-        /// Unnamed tuple type.
-        ///
-        /// ```
-        /// let foo: ❰ (u32, bool) ❱ = (42, true);
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/types/tuple.html)
-        struct TupleType { T!['('], fields: [TypeRef], T![')'] }
-
-        /// The never type (i.e. the exclamation point).
-        ///
-        /// ```
-        /// type T = ❰ ! ❱;
-        ///
-        /// fn no_return() -> ❰ ! ❱ {
-        ///     loop {}
-        /// }
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/types/never.html)
-        struct NeverType { T![!] }
-
-        /// Path to a type.
-        /// Includes single identifier type names and elaborate paths with
-        /// generic parameters.
-        ///
-        /// ```
-        /// type Foo = ❰ String ❱;
-        /// type Bar = ❰ std::vec::Vec<T> ❱;
-        /// type Baz = ❰ ::bruh::<Bruuh as Iterator>::Item ❱;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/paths.html)
-        struct PathType { Path }
-
-        /// Raw pointer type.
-        ///
-        /// ```
-        /// type Foo = ❰ *const u32 ❱;
-        /// type Bar = ❰ *mut u32 ❱;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/types/pointer.html#raw-pointers-const-and-mut)
-        struct PointerType { T![*], T![const], T![mut], TypeRef }
-
-        /// Array type.
-        ///
-        /// ```
-        /// type Foo = ❰ [u32; 24 - 3] ❱;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/types/array.html)
-        struct ArrayType { T!['['], TypeRef, T![;], Expr, T![']'] }
-
-        /// Slice type.
-        ///
-        /// ```
-        /// type Foo = ❰ [u8] ❱;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/types/slice.html)
-        struct SliceType { T!['['], TypeRef, T![']'] }
-
-        /// Reference type.
-        ///
-        /// ```
-        /// type Foo = ❰ &'static str ❱;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/types/pointer.html)
-        struct ReferenceType { T![&], T![lifetime], T![mut], TypeRef }
-
-        /// Placeholder type (i.e. the underscore).
-        ///
-        /// ```
-        /// let foo: ❰ _ ❱ = 42_u32;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/types/inferred.html)
-        struct PlaceholderType { T![_] }
-
-        /// Function pointer type (not to be confused with `Fn*` family of traits).
-        ///
-        /// ```
-        /// type Foo = ❰ async fn(#[attr] u32, named: bool) -> u32 ❱;
-        ///
-        /// type Bar = ❰ extern "C" fn(variadic: u32, #[attr] ...) ❱;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/types/function-pointer.html)
-        struct FnPointerType { Abi, T![unsafe], T![fn], ParamList, RetType }
-
-        /// Higher order type.
-        ///
-        /// ```
-        /// type Foo = ❰ for<'a> fn(&'a str) ❱;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/nomicon/hrtb.html)
-        struct ForType { T![for], TypeParamList, TypeRef }
-
-        /// Opaque `impl Trait` type.
-        ///
-        /// ```
-        /// fn foo(bar: ❰ impl Debug + Eq ❱) {}
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/types/impl-trait.html)
-        struct ImplTraitType: TypeBoundsOwner { T![impl] }
-
-        /// Trait object type.
-        ///
-        /// ```
-        /// type Foo = ❰ dyn Debug ❱;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/types/trait-object.html)
-        struct DynTraitType: TypeBoundsOwner { T![dyn] }
-
-        /// Tuple literal.
-        ///
-        /// ```
-        /// ❰ (42, true) ❱;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/expressions/tuple-expr.html)
-        struct TupleExpr: AttrsOwner { T!['('], exprs: [Expr], T![')'] }
-
-        /// Array literal.
-        ///
-        /// ```
-        /// ❰ [#![inner_attr] true, false, true] ❱;
-        ///
-        /// ❰ ["baz"; 24] ❱;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/expressions/array-expr.html)
-        struct ArrayExpr: AttrsOwner { T!['['], exprs: [Expr], T![;], T![']'] }
-
-        /// Parenthesized expression.
-        /// Note: parens are only used for grouping, this is not a tuple literal.
-        ///
-        /// ```
-        /// ❰ (#![inner_attr] 2 + 2) ❱ * 2;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/expressions/grouped-expr.html)
-        struct ParenExpr: AttrsOwner { T!['('], Expr, T![')'] }
-
-        /// Path to a symbol in expression context.
-        /// Includes single identifier variable names and elaborate paths with
-        /// generic parameters.
-        ///
-        /// ```
-        /// ❰ Some::<i32> ❱;
-        /// ❰ foo ❱ + 42;
-        /// ❰ Vec::<i32>::push ❱;
-        /// ❰ <[i32]>::reverse ❱;
-        /// ❰ <String as std::borrow::Borrow<str>>::borrow ❱;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/expressions/path-expr.html)
-        struct PathExpr { Path }
-
-        /// Anonymous callable object literal a.k.a. closure, lambda or functor.
-        ///
-        /// ```
-        /// ❰ || 42 ❱;
-        /// ❰ |a: u32| val + 1 ❱;
-        /// ❰ async |#[attr] Pattern(_): Pattern| { bar } ❱;
-        /// ❰ move || baz ❱;
-        /// ❰ || -> u32 { closure_with_ret_type_annotation_requires_block_expr } ❱
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/expressions/closure-expr.html)
-        struct LambdaExpr: AttrsOwner {
-            T![static], // Note(@matklad): I belive this is (used to be?) syntax for generators
-            T![async],
-            T![move],
-            ParamList,
-            RetType,
-            body: Expr,
-        }
+            /// Parenthesized type reference.
+            /// Note: parens are only used for grouping, this is not a tuple type.
+            ///
+            /// ```
+            /// // This is effectively just `u32`.
+            /// // Single-item tuple must be defined with a trailing comma: `(u32,)`
+            /// type Foo = ❰ (u32) ❱;
+            ///
+            /// let bar: &'static ❰ (dyn Debug) ❱ = "bruh";
+            /// ```
+            struct ParenType { T!['('], TypeRef, T![')'] }
+
+            /// Unnamed tuple type.
+            ///
+            /// ```
+            /// let foo: ❰ (u32, bool) ❱ = (42, true);
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/types/tuple.html)
+            struct TupleType { T!['('], fields: [TypeRef], T![')'] }
+
+            /// The never type (i.e. the exclamation point).
+            ///
+            /// ```
+            /// type T = ❰ ! ❱;
+            ///
+            /// fn no_return() -> ❰ ! ❱ {
+            ///     loop {}
+            /// }
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/types/never.html)
+            struct NeverType { T![!] }
+
+            /// Path to a type.
+            /// Includes single identifier type names and elaborate paths with
+            /// generic parameters.
+            ///
+            /// ```
+            /// type Foo = ❰ String ❱;
+            /// type Bar = ❰ std::vec::Vec<T> ❱;
+            /// type Baz = ❰ ::bruh::<Bruuh as Iterator>::Item ❱;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/paths.html)
+            struct PathType { Path }
+
+            /// Raw pointer type.
+            ///
+            /// ```
+            /// type Foo = ❰ *const u32 ❱;
+            /// type Bar = ❰ *mut u32 ❱;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/types/pointer.html#raw-pointers-const-and-mut)
+            struct PointerType { T![*], T![const], T![mut], TypeRef }
+
+            /// Array type.
+            ///
+            /// ```
+            /// type Foo = ❰ [u32; 24 - 3] ❱;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/types/array.html)
+            struct ArrayType { T!['['], TypeRef, T![;], Expr, T![']'] }
+
+            /// Slice type.
+            ///
+            /// ```
+            /// type Foo = ❰ [u8] ❱;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/types/slice.html)
+            struct SliceType { T!['['], TypeRef, T![']'] }
+
+            /// Reference type.
+            ///
+            /// ```
+            /// type Foo = ❰ &'static str ❱;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/types/pointer.html)
+            struct ReferenceType { T![&], T![lifetime], T![mut], TypeRef }
+
+            /// Placeholder type (i.e. the underscore).
+            ///
+            /// ```
+            /// let foo: ❰ _ ❱ = 42_u32;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/types/inferred.html)
+            struct PlaceholderType { T![_] }
+
+            /// Function pointer type (not to be confused with `Fn*` family of traits).
+            ///
+            /// ```
+            /// type Foo = ❰ async fn(#[attr] u32, named: bool) -> u32 ❱;
+            ///
+            /// type Bar = ❰ extern "C" fn(variadic: u32, #[attr] ...) ❱;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/types/function-pointer.html)
+            struct FnPointerType { Abi, T![unsafe], T![fn], ParamList, RetType }
+
+            /// Higher order type.
+            ///
+            /// ```
+            /// type Foo = ❰ for<'a> fn(&'a str) ❱;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/nomicon/hrtb.html)
+            struct ForType { T![for], TypeParamList, TypeRef }
+
+            /// Opaque `impl Trait` type.
+            ///
+            /// ```
+            /// fn foo(bar: ❰ impl Debug + Eq ❱) {}
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/types/impl-trait.html)
+            struct ImplTraitType: TypeBoundsOwner { T![impl] }
+
+            /// Trait object type.
+            ///
+            /// ```
+            /// type Foo = ❰ dyn Debug ❱;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/types/trait-object.html)
+            struct DynTraitType: TypeBoundsOwner { T![dyn] }
+
+            /// Tuple literal.
+            ///
+            /// ```
+            /// ❰ (42, true) ❱;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/expressions/tuple-expr.html)
+            struct TupleExpr: AttrsOwner { T!['('], exprs: [Expr], T![')'] }
+
+            /// Array literal.
+            ///
+            /// ```
+            /// ❰ [#![inner_attr] true, false, true] ❱;
+            ///
+            /// ❰ ["baz"; 24] ❱;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/expressions/array-expr.html)
+            struct ArrayExpr: AttrsOwner { T!['['], exprs: [Expr], T![;], T![']'] }
+
+            /// Parenthesized expression.
+            /// Note: parens are only used for grouping, this is not a tuple literal.
+            ///
+            /// ```
+            /// ❰ (#![inner_attr] 2 + 2) ❱ * 2;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/expressions/grouped-expr.html)
+            struct ParenExpr: AttrsOwner { T!['('], Expr, T![')'] }
+
+            /// Path to a symbol in expression context.
+            /// Includes single identifier variable names and elaborate paths with
+            /// generic parameters.
+            ///
+            /// ```
+            /// ❰ Some::<i32> ❱;
+            /// ❰ foo ❱ + 42;
+            /// ❰ Vec::<i32>::push ❱;
+            /// ❰ <[i32]>::reverse ❱;
+            /// ❰ <String as std::borrow::Borrow<str>>::borrow ❱;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/expressions/path-expr.html)
+            struct PathExpr { Path }
+
+            /// Anonymous callable object literal a.k.a. closure, lambda or functor.
+            ///
+            /// ```
+            /// ❰ || 42 ❱;
+            /// ❰ |a: u32| val + 1 ❱;
+            /// ❰ async |#[attr] Pattern(_): Pattern| { bar } ❱;
+            /// ❰ move || baz ❱;
+            /// ❰ || -> u32 { closure_with_ret_type_annotation_requires_block_expr } ❱
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/expressions/closure-expr.html)
+            struct LambdaExpr: AttrsOwner {
+                T![static], // Note(@matklad): I belive this is (used to be?) syntax for generators
+                T![async],
+                T![move],
+                ParamList,
+                RetType,
+                body: Expr,
+            }
 
-        /// If expression. Includes both regular `if` and `if let` forms.
-        /// Beware that `else if` is a special case syntax sugar, because in general
-        /// there has to be block expression after `else`.
-        ///
-        /// ```
-        /// ❰ if bool_cond { 42 } ❱
-        /// ❰ if bool_cond { 42 } else { 24 } ❱
-        /// ❰ if bool_cond { 42 } else if bool_cond2 { 42 } ❱
-        ///
-        /// ❰
-        ///     if let Pattern(foo) = bar {
-        ///         foo
-        ///     } else {
-        ///         panic!();
-        ///     }
-        /// ❱
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/expressions/if-expr.html)
-        struct IfExpr: AttrsOwner { T![if], Condition }
-
-        /// Unconditional loop expression.
-        ///
-        /// ```
-        /// ❰
-        ///     loop {
-        ///         // yeah, it's that simple...
-        ///     }
-        /// ❱
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html)
-        struct LoopExpr: AttrsOwner, LoopBodyOwner { T![loop] }
-
-        /// Block expression with an optional prefix (label, try ketword,
-        /// unsafe keyword, async keyword...).
-        ///
-        /// ```
-        /// ❰
-        ///     'label: try {
-        ///         None?
-        ///     }
-        /// ❱
-        /// ```
-        ///
-        /// - [try block](https://doc.rust-lang.org/unstable-book/language-features/try-blocks.html)
-        /// - [unsafe block](https://doc.rust-lang.org/reference/expressions/block-expr.html#unsafe-blocks)
-        /// - [async block](https://doc.rust-lang.org/reference/expressions/block-expr.html#async-blocks)
-        struct EffectExpr: AttrsOwner { Label, T![try], T![unsafe], T![async], BlockExpr }
-
-
-        /// For loop expression.
-        /// Note: record struct literals are not valid as iterable expression
-        /// due to ambiguity.
-        ///
-        /// ```
-        /// ❰
-        /// for i in (0..4) {
-        ///     dbg!(i);
-        /// }
-        /// ❱
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html#iterator-loops)
-        struct ForExpr: AttrsOwner, LoopBodyOwner {
-            T![for],
-            Pat,
-            T![in],
-            iterable: Expr,
-        }
+            /// If expression. Includes both regular `if` and `if let` forms.
+            /// Beware that `else if` is a special case syntax sugar, because in general
+            /// there has to be block expression after `else`.
+            ///
+            /// ```
+            /// ❰ if bool_cond { 42 } ❱
+            /// ❰ if bool_cond { 42 } else { 24 } ❱
+            /// ❰ if bool_cond { 42 } else if bool_cond2 { 42 } ❱
+            ///
+            /// ❰
+            ///     if let Pattern(foo) = bar {
+            ///         foo
+            ///     } else {
+            ///         panic!();
+            ///     }
+            /// ❱
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/expressions/if-expr.html)
+            struct IfExpr: AttrsOwner { T![if], Condition }
+
+            /// Unconditional loop expression.
+            ///
+            /// ```
+            /// ❰
+            ///     loop {
+            ///         // yeah, it's that simple...
+            ///     }
+            /// ❱
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html)
+            struct LoopExpr: AttrsOwner, LoopBodyOwner { T![loop] }
+
+            /// Block expression with an optional prefix (label, try ketword,
+            /// unsafe keyword, async keyword...).
+            ///
+            /// ```
+            /// ❰
+            ///     'label: try {
+            ///         None?
+            ///     }
+            /// ❱
+            /// ```
+            ///
+            /// - [try block](https://doc.rust-lang.org/unstable-book/language-features/try-blocks.html)
+            /// - [unsafe block](https://doc.rust-lang.org/reference/expressions/block-expr.html#unsafe-blocks)
+            /// - [async block](https://doc.rust-lang.org/reference/expressions/block-expr.html#async-blocks)
+            struct EffectExpr: AttrsOwner { Label, T![try], T![unsafe], T![async], BlockExpr }
+
+
+            /// For loop expression.
+            /// Note: record struct literals are not valid as iterable expression
+            /// due to ambiguity.
+            ///
+            /// ```
+            /// ❰
+            /// for i in (0..4) {
+            ///     dbg!(i);
+            /// }
+            /// ❱
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html#iterator-loops)
+            struct ForExpr: AttrsOwner, LoopBodyOwner {
+                T![for],
+                Pat,
+                T![in],
+                iterable: Expr,
+            }
 
-        /// While loop expression. Includes both regular `while` and `while let` forms.
-        ///
-        /// ```
-        /// ❰
-        ///     while bool_cond {
-        ///         42;
-        ///     }
-        /// ❱
-        /// ❰
-        ///     while let Pattern(foo) = bar {
-        ///         bar += 1;
-        ///     }
-        /// ❱
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html#predicate-loops)
-        struct WhileExpr: AttrsOwner, LoopBodyOwner { T![while], Condition }
-
-        /// Continue expression.
-        ///
-        /// ```
-        /// while bool_cond {
-        ///     ❰ continue ❱;
-        /// }
-        ///
-        /// 'outer: loop {
-        ///     loop {
-        ///         ❰ continue 'outer ❱;
-        ///     }
-        /// }
-        ///
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html#continue-expressions)
-        struct ContinueExpr: AttrsOwner { T![continue], T![lifetime] }
-
-        /// Break expression.
-        ///
-        /// ```
-        /// while bool_cond {
-        ///     ❰ break ❱;
-        /// }
-        /// 'outer: loop {
-        ///     for foo in bar {
-        ///         ❰ break 'outer ❱;
-        ///     }
-        /// }
-        /// 'outer: loop {
-        ///     loop {
-        ///         ❰ break 'outer 42 ❱;
-        ///     }
-        /// }
-        /// ```
-        ///
-        /// [Refernce](https://doc.rust-lang.org/reference/expressions/loop-expr.html#break-expressions)
-        struct BreakExpr: AttrsOwner { T![break], T![lifetime], Expr }
-
-        /// Label.
-        ///
-        /// ```
-        /// ❰ 'outer: ❱ loop {}
-        ///
-        /// let foo = ❰ 'bar: ❱ loop {}
-        ///
-        /// ❰ 'baz: ❱ {
-        ///     break 'baz;
-        /// }
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html?highlight=label#loop-labels)
-        /// [Labels for blocks RFC](https://github.com/rust-lang/rfcs/blob/master/text/2046-label-break-value.md)
-        struct Label { T![lifetime] }
-
-        /// Block expression. Includes unsafe blocks and block labels.
-        ///
-        /// ```
-        ///     let foo = ❰
-        ///         {
-        ///             #![inner_attr]
-        ///             ❰ { } ❱
-        ///
-        ///             ❰ 'label: { break 'label } ❱
-        ///         }
-        ///     ❱;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/expressions/block-expr.html)
-        /// [Labels for blocks RFC](https://github.com/rust-lang/rfcs/blob/master/text/2046-label-break-value.md)
-        struct BlockExpr: AttrsOwner, ModuleItemOwner {
-            Label, T!['{'], statements: [Stmt], Expr, T!['}'],
-        }
+            /// While loop expression. Includes both regular `while` and `while let` forms.
+            ///
+            /// ```
+            /// ❰
+            ///     while bool_cond {
+            ///         42;
+            ///     }
+            /// ❱
+            /// ❰
+            ///     while let Pattern(foo) = bar {
+            ///         bar += 1;
+            ///     }
+            /// ❱
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html#predicate-loops)
+            struct WhileExpr: AttrsOwner, LoopBodyOwner { T![while], Condition }
+
+            /// Continue expression.
+            ///
+            /// ```
+            /// while bool_cond {
+            ///     ❰ continue ❱;
+            /// }
+            ///
+            /// 'outer: loop {
+            ///     loop {
+            ///         ❰ continue 'outer ❱;
+            ///     }
+            /// }
+            ///
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html#continue-expressions)
+            struct ContinueExpr: AttrsOwner { T![continue], T![lifetime] }
+
+            /// Break expression.
+            ///
+            /// ```
+            /// while bool_cond {
+            ///     ❰ break ❱;
+            /// }
+            /// 'outer: loop {
+            ///     for foo in bar {
+            ///         ❰ break 'outer ❱;
+            ///     }
+            /// }
+            /// 'outer: loop {
+            ///     loop {
+            ///         ❰ break 'outer 42 ❱;
+            ///     }
+            /// }
+            /// ```
+            ///
+            /// [Refernce](https://doc.rust-lang.org/reference/expressions/loop-expr.html#break-expressions)
+            struct BreakExpr: AttrsOwner { T![break], T![lifetime], Expr }
+
+            /// Label.
+            ///
+            /// ```
+            /// ❰ 'outer: ❱ loop {}
+            ///
+            /// let foo = ❰ 'bar: ❱ loop {}
+            ///
+            /// ❰ 'baz: ❱ {
+            ///     break 'baz;
+            /// }
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html?highlight=label#loop-labels)
+            /// [Labels for blocks RFC](https://github.com/rust-lang/rfcs/blob/master/text/2046-label-break-value.md)
+            struct Label { T![lifetime] }
+
+            /// Block expression. Includes unsafe blocks and block labels.
+            ///
+            /// ```
+            ///     let foo = ❰
+            ///         {
+            ///             #![inner_attr]
+            ///             ❰ { } ❱
+            ///
+            ///             ❰ 'label: { break 'label } ❱
+            ///         }
+            ///     ❱;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/expressions/block-expr.html)
+            /// [Labels for blocks RFC](https://github.com/rust-lang/rfcs/blob/master/text/2046-label-break-value.md)
+            struct BlockExpr: AttrsOwner, ModuleItemOwner {
+                Label, T!['{'], statements: [Stmt], Expr, T!['}'],
+            }
 
-        /// Return expression.
-        ///
-        /// ```
-        /// || ❰ return 42 ❱;
-        ///
-        /// fn bar() {
-        ///     ❰ return ❱;
-        /// }
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/expressions/return-expr.html)
-        struct ReturnExpr: AttrsOwner { Expr }
-
-        /// Call expression (not to be confused with method call expression, it is
-        /// a separate ast node).
-        ///
-        /// ```
-        /// ❰ foo() ❱;
-        /// ❰ &str::len("bar") ❱;
-        /// ❰ <&str as PartialEq<&str>>::eq(&"", &"") ❱;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/expressions/call-expr.html)
-        struct CallExpr: ArgListOwner { Expr }
-
-        /// Method call expression.
-        ///
-        /// ```
-        /// ❰ receiver_expr.method() ❱;
-        /// ❰ receiver_expr.method::<T>(42, true) ❱;
-        ///
-        /// ❰ ❰ ❰ foo.bar() ❱ .baz() ❱ .bruh() ❱;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/expressions/method-call-expr.html)
-        struct MethodCallExpr: AttrsOwner, ArgListOwner {
-            Expr, T![.], NameRef, TypeArgList,
-        }
+            /// Return expression.
+            ///
+            /// ```
+            /// || ❰ return 42 ❱;
+            ///
+            /// fn bar() {
+            ///     ❰ return ❱;
+            /// }
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/expressions/return-expr.html)
+            struct ReturnExpr: AttrsOwner { Expr }
+
+            /// Call expression (not to be confused with method call expression, it is
+            /// a separate ast node).
+            ///
+            /// ```
+            /// ❰ foo() ❱;
+            /// ❰ &str::len("bar") ❱;
+            /// ❰ <&str as PartialEq<&str>>::eq(&"", &"") ❱;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/expressions/call-expr.html)
+            struct CallExpr: ArgListOwner { Expr }
+
+            /// Method call expression.
+            ///
+            /// ```
+            /// ❰ receiver_expr.method() ❱;
+            /// ❰ receiver_expr.method::<T>(42, true) ❱;
+            ///
+            /// ❰ ❰ ❰ foo.bar() ❱ .baz() ❱ .bruh() ❱;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/expressions/method-call-expr.html)
+            struct MethodCallExpr: AttrsOwner, ArgListOwner {
+                Expr, T![.], NameRef, TypeArgList,
+            }
 
-        /// Index expression a.k.a. subscript operator call.
-        ///
-        /// ```
-        /// ❰ foo[42] ❱;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/expressions/array-expr.html)
-        struct IndexExpr: AttrsOwner { T!['['], T![']'] }
-
-        /// Field access expression.
-        ///
-        /// ```
-        /// ❰ expr.bar ❱;
-        ///
-        /// ❰ ❰ ❰ foo.bar ❱ .baz ❱ .bruh ❱;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/expressions/field-expr.html)
-        struct FieldExpr: AttrsOwner { Expr, T![.], NameRef }
-
-        /// Await operator call expression.
-        ///
-        /// ```
-        /// ❰ expr.await ❱;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/expressions/await-expr.html)
-        struct AwaitExpr: AttrsOwner { Expr, T![.], T![await] }
-
-        /// The question mark operator call.
-        ///
-        /// ```
-        /// ❰ expr? ❱;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#the-question-mark-operator)
-        struct TryExpr: AttrsOwner { Expr, T![?] }
-
-        /// Type cast expression.
-        ///
-        /// ```
-        /// ❰ expr as T ❱;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions)
-        struct CastExpr: AttrsOwner { Expr, T![as], TypeRef }
-
-
-        /// Borrow operator call.
-        ///
-        /// ```
-        /// ❰ &foo ❱;
-        /// ❰ &mut bar ❱;
-        /// ❰ &raw const bar ❱;
-        /// ❰ &raw mut bar ❱;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#borrow-operators)
-        struct RefExpr: AttrsOwner { T![&], T![raw], T![mut], T![const], Expr }
-
-        /// Prefix operator call. This is either `!` or `*` or `-`.
-        ///
-        /// ```
-        /// ❰ !foo ❱;
-        /// ❰ *bar ❱;
-        /// ❰ -42 ❱;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html)
-        struct PrefixExpr: AttrsOwner { /*PrefixOp,*/ Expr }
-
-        /// Box operator call.
-        ///
-        /// ```
-        /// ❰ box 42 ❱;
-        /// ```
-        ///
-        /// [RFC](https://github.com/rust-lang/rfcs/blob/0806be4f282144cfcd55b1d20284b43f87cbe1c6/text/0809-box-and-in-for-stdlib.md)
-        struct BoxExpr: AttrsOwner { T![box], Expr }
-
-        /// Range operator call.
-        ///
-        /// ```
-        /// ❰ 0..42 ❱;
-        /// ❰ ..42 ❱;
-        /// ❰ 0.. ❱;
-        /// ❰ .. ❱;
-        /// ❰ 0..=42 ❱;
-        /// ❰ ..=42 ❱;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/expressions/range-expr.html)
-        struct RangeExpr: AttrsOwner { /*RangeOp*/ }
-
-
-        /// Binary operator call.
-        /// Includes all arithmetic, logic, bitwise and assignment operators.
-        ///
-        /// ```
-        /// ❰ 2 + ❰ 2 * 2 ❱ ❱;
-        /// ❰ ❰ true && false ❱ || true ❱;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#arithmetic-and-logical-binary-operators)
-        struct BinExpr: AttrsOwner { /*BinOp*/ }
-
-
-        /// [Raw] string, [raw] byte string, char, byte, integer, float or bool literal.
-        ///
-        /// ```
-        /// ❰ "str" ❱;
-        /// ❰ br##"raw byte str"## ❱;
-        /// ❰ 'c' ❱;
-        /// ❰ b'c' ❱;
-        /// ❰ 42 ❱;
-        /// ❰ 1e9 ❱;
-        /// ❰ true ❱;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/expressions/literal-expr.html)
-        struct Literal { /*LiteralToken*/ }
-
-        /// Match expression.
-        ///
-        /// ```
-        /// ❰
-        ///     match expr {
-        ///         Pat1 => {}
-        ///         Pat2(_) => 42,
-        ///     }
-        /// ❱
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/expressions/match-expr.html)
-        struct MatchExpr: AttrsOwner { T![match], Expr, MatchArmList }
-
-        /// Match arm list part of match expression. Includes its inner attributes.
-        ///
-        /// ```
-        /// match expr
-        /// ❰
-        ///     {
-        ///         #![inner_attr]
-        ///         Pat1 => {}
-        ///         Pat2(_) => 42,
-        ///     }
-        /// ❱
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/expressions/match-expr.html)
-        struct MatchArmList: AttrsOwner { T!['{'], arms: [MatchArm], T!['}'] }
-
-
-        /// Match arm.
-        /// Note: record struct literals are not valid as target match expression
-        /// due to ambiguity.
-        /// ```
-        /// match expr {
-        ///     ❰ #[attr] Pattern(it) if bool_cond => it ❱,
-        /// }
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/expressions/match-expr.html)
-        struct MatchArm: AttrsOwner {
-            pat: Pat,
-            guard: MatchGuard,
-            T![=>],
-            Expr,
-        }
+            /// Index expression a.k.a. subscript operator call.
+            ///
+            /// ```
+            /// ❰ foo[42] ❱;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/expressions/array-expr.html)
+            struct IndexExpr: AttrsOwner { T!['['], T![']'] }
+
+            /// Field access expression.
+            ///
+            /// ```
+            /// ❰ expr.bar ❱;
+            ///
+            /// ❰ ❰ ❰ foo.bar ❱ .baz ❱ .bruh ❱;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/expressions/field-expr.html)
+            struct FieldExpr: AttrsOwner { Expr, T![.], NameRef }
+
+            /// Await operator call expression.
+            ///
+            /// ```
+            /// ❰ expr.await ❱;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/expressions/await-expr.html)
+            struct AwaitExpr: AttrsOwner { Expr, T![.], T![await] }
+
+            /// The question mark operator call.
+            ///
+            /// ```
+            /// ❰ expr? ❱;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#the-question-mark-operator)
+            struct TryExpr: AttrsOwner { Expr, T![?] }
+
+            /// Type cast expression.
+            ///
+            /// ```
+            /// ❰ expr as T ❱;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions)
+            struct CastExpr: AttrsOwner { Expr, T![as], TypeRef }
+
+
+            /// Borrow operator call.
+            ///
+            /// ```
+            /// ❰ &foo ❱;
+            /// ❰ &mut bar ❱;
+            /// ❰ &raw const bar ❱;
+            /// ❰ &raw mut bar ❱;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#borrow-operators)
+            struct RefExpr: AttrsOwner { T![&], T![raw], T![mut], T![const], Expr }
+
+            /// Prefix operator call. This is either `!` or `*` or `-`.
+            ///
+            /// ```
+            /// ❰ !foo ❱;
+            /// ❰ *bar ❱;
+            /// ❰ -42 ❱;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html)
+            struct PrefixExpr: AttrsOwner { /*PrefixOp,*/ Expr }
+
+            /// Box operator call.
+            ///
+            /// ```
+            /// ❰ box 42 ❱;
+            /// ```
+            ///
+            /// [RFC](https://github.com/rust-lang/rfcs/blob/0806be4f282144cfcd55b1d20284b43f87cbe1c6/text/0809-box-and-in-for-stdlib.md)
+            struct BoxExpr: AttrsOwner { T![box], Expr }
+
+            /// Range operator call.
+            ///
+            /// ```
+            /// ❰ 0..42 ❱;
+            /// ❰ ..42 ❱;
+            /// ❰ 0.. ❱;
+            /// ❰ .. ❱;
+            /// ❰ 0..=42 ❱;
+            /// ❰ ..=42 ❱;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/expressions/range-expr.html)
+            struct RangeExpr: AttrsOwner { /*RangeOp*/ }
+
+
+            /// Binary operator call.
+            /// Includes all arithmetic, logic, bitwise and assignment operators.
+            ///
+            /// ```
+            /// ❰ 2 + ❰ 2 * 2 ❱ ❱;
+            /// ❰ ❰ true && false ❱ || true ❱;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#arithmetic-and-logical-binary-operators)
+            struct BinExpr: AttrsOwner { /*BinOp*/ }
+
+
+            /// [Raw] string, [raw] byte string, char, byte, integer, float or bool literal.
+            ///
+            /// ```
+            /// ❰ "str" ❱;
+            /// ❰ br##"raw byte str"## ❱;
+            /// ❰ 'c' ❱;
+            /// ❰ b'c' ❱;
+            /// ❰ 42 ❱;
+            /// ❰ 1e9 ❱;
+            /// ❰ true ❱;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/expressions/literal-expr.html)
+            struct Literal { /*LiteralToken*/ }
+
+            /// Match expression.
+            ///
+            /// ```
+            /// ❰
+            ///     match expr {
+            ///         Pat1 => {}
+            ///         Pat2(_) => 42,
+            ///     }
+            /// ❱
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/expressions/match-expr.html)
+            struct MatchExpr: AttrsOwner { T![match], Expr, MatchArmList }
+
+            /// Match arm list part of match expression. Includes its inner attributes.
+            ///
+            /// ```
+            /// match expr
+            /// ❰
+            ///     {
+            ///         #![inner_attr]
+            ///         Pat1 => {}
+            ///         Pat2(_) => 42,
+            ///     }
+            /// ❱
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/expressions/match-expr.html)
+            struct MatchArmList: AttrsOwner { T!['{'], arms: [MatchArm], T!['}'] }
+
+
+            /// Match arm.
+            /// Note: record struct literals are not valid as target match expression
+            /// due to ambiguity.
+            /// ```
+            /// match expr {
+            ///     ❰ #[attr] Pattern(it) if bool_cond => it ❱,
+            /// }
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/expressions/match-expr.html)
+            struct MatchArm: AttrsOwner {
+                pat: Pat,
+                guard: MatchGuard,
+                T![=>],
+                Expr,
+            }
 
-        /// Match guard.
-        ///
-        /// ```
-        /// match expr {
-        ///     Pattern(it) ❰ if bool_cond ❱ => it,
-        /// }
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/expressions/match-expr.html#match-guards)
-        struct MatchGuard { T![if], Expr }
-
-        /// Record literal expression. The same syntax is used for structs,
-        /// unions and record enum variants.
-        ///
-        /// ```
-        /// ❰
-        ///     foo::Bar {
-        ///         #![inner_attr]
-        ///         baz: 42,
-        ///         bruh: true,
-        ///         ..spread
-        ///     }
-        /// ❱
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/expressions/struct-expr.html)
-        struct RecordLit { Path, RecordFieldList}
-
-        /// Record field list including enclosing curly braces.
-        ///
-        /// foo::Bar ❰
-        ///     {
-        ///         baz: 42,
-        ///         ..spread
-        ///     }
-        /// ❱
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/expressions/struct-expr.html)
-        struct RecordFieldList {
-            T!['{'],
-            fields: [RecordField],
-            T![..],
-            spread: Expr,
-            T!['}']
-        }
+            /// Match guard.
+            ///
+            /// ```
+            /// match expr {
+            ///     Pattern(it) ❰ if bool_cond ❱ => it,
+            /// }
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/expressions/match-expr.html#match-guards)
+            struct MatchGuard { T![if], Expr }
+
+            /// Record literal expression. The same syntax is used for structs,
+            /// unions and record enum variants.
+            ///
+            /// ```
+            /// ❰
+            ///     foo::Bar {
+            ///         #![inner_attr]
+            ///         baz: 42,
+            ///         bruh: true,
+            ///         ..spread
+            ///     }
+            /// ❱
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/expressions/struct-expr.html)
+            struct RecordLit { Path, RecordFieldList}
+
+            /// Record field list including enclosing curly braces.
+            ///
+            /// foo::Bar ❰
+            ///     {
+            ///         baz: 42,
+            ///         ..spread
+            ///     }
+            /// ❱
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/expressions/struct-expr.html)
+            struct RecordFieldList {
+                T!['{'],
+                fields: [RecordField],
+                T![..],
+                spread: Expr,
+                T!['}']
+            }
 
-        /// Record field.
-        ///
-        /// ```
-        /// foo::Bar {
-        ///     ❰ #[attr] baz: 42 ❱
-        /// }
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/expressions/struct-expr.html)
-        struct RecordField: AttrsOwner { NameRef, T![:], Expr }
-
-        /// Disjunction of patterns.
-        ///
-        /// ```
-        /// let ❰ Foo(it) | Bar(it) | Baz(it) ❱ = bruh;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/patterns.html)
-        struct OrPat { pats: [Pat] }
-
-        /// Parenthesized pattern.
-        /// Note: parens are only used for grouping, this is not a tuple pattern.
-        ///
-        /// ```
-        /// if let ❰ &(0..=42) ❱ = foo {}
-        /// ```
-        ///
-        /// https://doc.rust-lang.org/reference/patterns.html#grouped-patterns
-        struct ParenPat { T!['('], Pat, T![')'] }
-
-        /// Reference pattern.
-        /// Note: this has nothing to do with `ref` keyword, the latter is used in bind patterns.
-        ///
-        /// ```
-        /// let ❰ &mut foo ❱ = bar;
-        ///
-        /// let ❰ & ❰ &mut ❰ &_ ❱ ❱ ❱ = baz;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/patterns.html#reference-patterns)
-        struct RefPat { T![&], T![mut], Pat }
-
-        /// Box pattern.
-        ///
-        /// ```
-        /// let ❰ box foo ❱ = box 42;
-        /// ```
-        ///
-        /// [Unstable book](https://doc.rust-lang.org/unstable-book/language-features/box-patterns.html)
-        struct BoxPat { T![box], Pat }
-
-        /// Bind pattern.
-        ///
-        /// ```
-        /// match foo {
-        ///     Some(❰ ref mut bar ❱) => {}
-        ///     ❰ baz @ None ❱ => {}
-        /// }
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/patterns.html#identifier-patterns)
-        struct BindPat: AttrsOwner, NameOwner { T![ref], T![mut], T![@], Pat }
-
-        /// Placeholder pattern a.k.a. the wildcard pattern or the underscore.
-        ///
-        /// ```
-        /// let ❰ _ ❱ = foo;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/patterns.html#wildcard-pattern)
-        struct PlaceholderPat { T![_] }
-
-        /// Rest-of-the record/tuple pattern.
-        /// Note: this is not the unbonded range pattern (even more: it doesn't exist).
-        ///
-        /// ```
-        /// let Foo { bar, ❰ .. ❱ } = baz;
-        /// let (❰ .. ❱, bruh) = (42, 24, 42);
-        /// let Bruuh(❰ .. ❱) = bruuuh;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/patterns.html#struct-patterns)
-        struct DotDotPat { T![..] }
-
-        /// Path pattern.
-        /// Doesn't include the underscore pattern (it is a special case, namely `PlaceholderPat`).
-        ///
-        /// ```
-        /// let ❰ foo::bar::Baz ❱ { .. } = bruh;
-        /// if let ❰ CONST ❱ = 42 {}
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/patterns.html#path-patterns)
-        struct PathPat { Path }
-
-        /// Slice pattern.
-        ///
-        /// ```
-        /// let ❰ [foo, bar, baz] ❱ = [1, 2, 3];
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/patterns.html#slice-patterns)
-        struct SlicePat { T!['['], args: [Pat], T![']'] }
-
-        /// Range pattern.
-        ///
-        /// ```
-        /// match foo {
-        ///     ❰ 0..42 ❱ => {}
-        ///     ❰ 0..=42 ❱ => {}
-        /// }
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/patterns.html#range-patterns)
-        struct RangePat { } // FIXME(@matklad): here should be T![..], T![..=] I think, if we don't already have an accessor in expresions_ext
-
-        /// Literal pattern.
-        /// Includes only bool, number, char, and string literals.
-        ///
-        /// ```
-        /// match foo {
-        ///     Number(❰ 42 ❱) => {}
-        ///     String(❰ "42" ❱) => {}
-        ///     Bool(❰ true ❱) => {}
-        /// }
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/patterns.html#literal-patterns)
-        struct LiteralPat { Literal }
-
-        /// Macro invocation in pattern position.
-        ///
-        /// ```
-        /// let ❰ foo!(my custom syntax) ❱ = baz;
-        ///
-        /// ```
-        /// [Reference](https://doc.rust-lang.org/reference/macros.html#macro-invocation)
-        struct MacroPat { MacroCall }
-
-        /// Record literal pattern.
-        ///
-        /// ```
-        /// let ❰ foo::Bar { baz, .. } ❱ = bruh;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/patterns.html#struct-patterns)
-        struct RecordPat { RecordFieldPatList, Path }
-
-        /// Record literal's field patterns list including enclosing curly braces.
-        ///
-        /// ```
-        /// let foo::Bar ❰ { baz, bind @ bruh, .. } ❱ = bruuh;
-        /// ``
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/patterns.html#struct-patterns)
-        struct RecordFieldPatList {
-            T!['{'],
-            pats: [RecordInnerPat],
-            record_field_pats: [RecordFieldPat],
-            bind_pats: [BindPat],
-            T![..],
-            T!['}']
-        }
+            /// Record field.
+            ///
+            /// ```
+            /// foo::Bar {
+            ///     ❰ #[attr] baz: 42 ❱
+            /// }
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/expressions/struct-expr.html)
+            struct RecordField: AttrsOwner { NameRef, T![:], Expr }
+
+            /// Disjunction of patterns.
+            ///
+            /// ```
+            /// let ❰ Foo(it) | Bar(it) | Baz(it) ❱ = bruh;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/patterns.html)
+            struct OrPat { pats: [Pat] }
+
+            /// Parenthesized pattern.
+            /// Note: parens are only used for grouping, this is not a tuple pattern.
+            ///
+            /// ```
+            /// if let ❰ &(0..=42) ❱ = foo {}
+            /// ```
+            ///
+            /// https://doc.rust-lang.org/reference/patterns.html#grouped-patterns
+            struct ParenPat { T!['('], Pat, T![')'] }
+
+            /// Reference pattern.
+            /// Note: this has nothing to do with `ref` keyword, the latter is used in bind patterns.
+            ///
+            /// ```
+            /// let ❰ &mut foo ❱ = bar;
+            ///
+            /// let ❰ & ❰ &mut ❰ &_ ❱ ❱ ❱ = baz;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/patterns.html#reference-patterns)
+            struct RefPat { T![&], T![mut], Pat }
+
+            /// Box pattern.
+            ///
+            /// ```
+            /// let ❰ box foo ❱ = box 42;
+            /// ```
+            ///
+            /// [Unstable book](https://doc.rust-lang.org/unstable-book/language-features/box-patterns.html)
+            struct BoxPat { T![box], Pat }
+
+            /// Bind pattern.
+            ///
+            /// ```
+            /// match foo {
+            ///     Some(❰ ref mut bar ❱) => {}
+            ///     ❰ baz @ None ❱ => {}
+            /// }
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/patterns.html#identifier-patterns)
+            struct BindPat: AttrsOwner, NameOwner { T![ref], T![mut], T![@], Pat }
+
+            /// Placeholder pattern a.k.a. the wildcard pattern or the underscore.
+            ///
+            /// ```
+            /// let ❰ _ ❱ = foo;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/patterns.html#wildcard-pattern)
+            struct PlaceholderPat { T![_] }
+
+            /// Rest-of-the record/tuple pattern.
+            /// Note: this is not the unbonded range pattern (even more: it doesn't exist).
+            ///
+            /// ```
+            /// let Foo { bar, ❰ .. ❱ } = baz;
+            /// let (❰ .. ❱, bruh) = (42, 24, 42);
+            /// let Bruuh(❰ .. ❱) = bruuuh;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/patterns.html#struct-patterns)
+            struct DotDotPat { T![..] }
+
+            /// Path pattern.
+            /// Doesn't include the underscore pattern (it is a special case, namely `PlaceholderPat`).
+            ///
+            /// ```
+            /// let ❰ foo::bar::Baz ❱ { .. } = bruh;
+            /// if let ❰ CONST ❱ = 42 {}
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/patterns.html#path-patterns)
+            struct PathPat { Path }
+
+            /// Slice pattern.
+            ///
+            /// ```
+            /// let ❰ [foo, bar, baz] ❱ = [1, 2, 3];
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/patterns.html#slice-patterns)
+            struct SlicePat { T!['['], args: [Pat], T![']'] }
+
+            /// Range pattern.
+            ///
+            /// ```
+            /// match foo {
+            ///     ❰ 0..42 ❱ => {}
+            ///     ❰ 0..=42 ❱ => {}
+            /// }
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/patterns.html#range-patterns)
+            struct RangePat { } // FIXME(@matklad): here should be T![..], T![..=] I think, if we don't already have an accessor in expresions_ext
+
+            /// Literal pattern.
+            /// Includes only bool, number, char, and string literals.
+            ///
+            /// ```
+            /// match foo {
+            ///     Number(❰ 42 ❱) => {}
+            ///     String(❰ "42" ❱) => {}
+            ///     Bool(❰ true ❱) => {}
+            /// }
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/patterns.html#literal-patterns)
+            struct LiteralPat { Literal }
+
+            /// Macro invocation in pattern position.
+            ///
+            /// ```
+            /// let ❰ foo!(my custom syntax) ❱ = baz;
+            ///
+            /// ```
+            /// [Reference](https://doc.rust-lang.org/reference/macros.html#macro-invocation)
+            struct MacroPat { MacroCall }
+
+            /// Record literal pattern.
+            ///
+            /// ```
+            /// let ❰ foo::Bar { baz, .. } ❱ = bruh;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/patterns.html#struct-patterns)
+            struct RecordPat { RecordFieldPatList, Path }
+
+            /// Record literal's field patterns list including enclosing curly braces.
+            ///
+            /// ```
+            /// let foo::Bar ❰ { baz, bind @ bruh, .. } ❱ = bruuh;
+            /// ``
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/patterns.html#struct-patterns)
+            struct RecordFieldPatList {
+                T!['{'],
+                pats: [RecordInnerPat],
+                record_field_pats: [RecordFieldPat],
+                bind_pats: [BindPat],
+                T![..],
+                T!['}']
+            }
 
-        /// Record literal's field pattern.
-        /// Note: record literal can also match tuple structs.
-        ///
-        /// ```
-        /// let Foo { ❰ bar: _ ❱ } = baz;
-        /// let TupleStruct { ❰ 0: _ ❱ } = bruh;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/patterns.html#struct-patterns)
-        struct RecordFieldPat: AttrsOwner { NameRef, T![:], Pat }
-
-        /// Tuple struct literal pattern.
-        ///
-        /// ```
-        /// let ❰ foo::Bar(baz, bruh) ❱ = bruuh;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/patterns.html#tuple-struct-patterns)
-        struct TupleStructPat { Path, T!['('], args: [Pat], T![')'] }
-
-        /// Tuple pattern.
-        /// Note: this doesn't include tuple structs (see `TupleStructPat`)
-        ///
-        /// ```
-        /// let ❰ (foo, bar, .., baz) ❱ = bruh;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/patterns.html#tuple-patterns)
-        struct TuplePat { T!['('], args: [Pat], T![')'] }
-
-        /// Visibility.
-        ///
-        /// ```
-        /// ❰ pub mod ❱ foo;
-        /// ❰ pub(crate) ❱ struct Bar;
-        /// ❰ pub(self) ❱ enum Baz {}
-        /// ❰ pub(super) ❱ fn bruh() {}
-        /// ❰ pub(in bruuh::bruuuh) ❱ type T = u64;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/visibility-and-privacy.html)
-        struct Visibility { T![pub], T![super], T![self], T![crate] }
-
-        /// Single identifier.
-        /// Note(@matklad): `Name` is for things that install a new name into the scope,
-        /// `NameRef` is a usage of a name. Most of the time, this definition/reference
-        /// distinction can be determined purely syntactically, ie in
-        /// ```
-        /// fn foo() { foo() }
-        /// ```
-        /// the first foo is `Name`, the second one is `NameRef`.
-        /// The notable exception are patterns, where in
-        /// ``
-        /// let x = 92
-        /// ```
-        /// `x` can be semantically either a name or a name ref, depeding on
-        /// wether there's an `x` constant in scope.
-        /// We use `Name` for patterns, and disambiguate semantically (see `NameClass` in ide_db).
-        ///
-        /// ```
-        /// let ❰ foo ❱ = bar;
-        /// struct ❰ Baz ❱;
-        /// fn ❰ bruh ❱() {}
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/identifiers.html)
-        struct Name { T![ident] }
-
-        /// Reference to a name.
-        /// See the explanation on the difference between `Name` and `NameRef`
-        /// in `Name` ast node docs.
-        ///
-        /// ```
-        /// let foo = ❰ bar ❱(❰ Baz(❰ bruh ❱) ❱;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/identifiers.html)
-        struct NameRef { }
-
-        /// Macro call.
-        /// Includes all of its attributes and doc comments.
-        ///
-        /// ```
-        /// ❰
-        ///     /// Docs
-        ///     #[attr]
-        ///     macro_rules! foo {   // macro rules is also a macro call
-        ///         ($bar: tt) => {}
-        ///     }
-        /// ❱
-        ///
-        /// // semicolon is a part of `MacroCall` when it is used in item positions
-        /// ❰ foo!(); ❱
-        ///
-        /// fn main() {
-        ///     ❰ foo!() ❱; // macro call in expression positions doesn't include the semi
-        /// }
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/macros.html)
-        struct MacroCall: NameOwner, AttrsOwner, DocCommentsOwner {
-            Path, T![!], TokenTree, T![;]
-        }
+            /// Record literal's field pattern.
+            /// Note: record literal can also match tuple structs.
+            ///
+            /// ```
+            /// let Foo { ❰ bar: _ ❱ } = baz;
+            /// let TupleStruct { ❰ 0: _ ❱ } = bruh;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/patterns.html#struct-patterns)
+            struct RecordFieldPat: AttrsOwner { NameRef, T![:], Pat }
+
+            /// Tuple struct literal pattern.
+            ///
+            /// ```
+            /// let ❰ foo::Bar(baz, bruh) ❱ = bruuh;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/patterns.html#tuple-struct-patterns)
+            struct TupleStructPat { Path, T!['('], args: [Pat], T![')'] }
+
+            /// Tuple pattern.
+            /// Note: this doesn't include tuple structs (see `TupleStructPat`)
+            ///
+            /// ```
+            /// let ❰ (foo, bar, .., baz) ❱ = bruh;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/patterns.html#tuple-patterns)
+            struct TuplePat { T!['('], args: [Pat], T![')'] }
+
+            /// Visibility.
+            ///
+            /// ```
+            /// ❰ pub mod ❱ foo;
+            /// ❰ pub(crate) ❱ struct Bar;
+            /// ❰ pub(self) ❱ enum Baz {}
+            /// ❰ pub(super) ❱ fn bruh() {}
+            /// ❰ pub(in bruuh::bruuuh) ❱ type T = u64;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/visibility-and-privacy.html)
+            struct Visibility { T![pub], T![super], T![self], T![crate] }
+
+            /// Single identifier.
+            /// Note(@matklad): `Name` is for things that install a new name into the scope,
+            /// `NameRef` is a usage of a name. Most of the time, this definition/reference
+            /// distinction can be determined purely syntactically, ie in
+            /// ```
+            /// fn foo() { foo() }
+            /// ```
+            /// the first foo is `Name`, the second one is `NameRef`.
+            /// The notable exception are patterns, where in
+            /// ``
+            /// let x = 92
+            /// ```
+            /// `x` can be semantically either a name or a name ref, depeding on
+            /// wether there's an `x` constant in scope.
+            /// We use `Name` for patterns, and disambiguate semantically (see `NameClass` in ide_db).
+            ///
+            /// ```
+            /// let ❰ foo ❱ = bar;
+            /// struct ❰ Baz ❱;
+            /// fn ❰ bruh ❱() {}
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/identifiers.html)
+            struct Name { T![ident] }
+
+            /// Reference to a name.
+            /// See the explanation on the difference between `Name` and `NameRef`
+            /// in `Name` ast node docs.
+            ///
+            /// ```
+            /// let foo = ❰ bar ❱(❰ Baz(❰ bruh ❱) ❱;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/identifiers.html)
+            struct NameRef { }
+
+            /// Macro call.
+            /// Includes all of its attributes and doc comments.
+            ///
+            /// ```
+            /// ❰
+            ///     /// Docs
+            ///     #[attr]
+            ///     macro_rules! foo {   // macro rules is also a macro call
+            ///         ($bar: tt) => {}
+            ///     }
+            /// ❱
+            ///
+            /// // semicolon is a part of `MacroCall` when it is used in item positions
+            /// ❰ foo!(); ❱
+            ///
+            /// fn main() {
+            ///     ❰ foo!() ❱; // macro call in expression positions doesn't include the semi
+            /// }
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/macros.html)
+            struct MacroCall: NameOwner, AttrsOwner, DocCommentsOwner {
+                Path, T![!], TokenTree, T![;]
+            }
 
-        /// Attribute.
-        ///
-        /// ```
-        /// ❰ #![inner_attr] ❱
-        ///
-        /// ❰ #[attr] ❱
-        /// ❰ #[foo = "bar"] ❱
-        /// ❰ #[baz(bruh::bruuh = "42")] ❱
-        /// struct Foo;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/attributes.html)
-        struct Attr { T![#], T![!], T!['['], Path, T![=], input: AttrInput, T![']'] }
-
-        /// Stores a list of lexer tokens and other `TokenTree`s.
-        /// It appears in attributes, macro_rules and macro call (foo!)
-        ///
-        /// ```
-        /// macro_call! ❰ { my syntax here } ❱;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/macros.html)
-        struct TokenTree {}
-
-        /// Generic lifetime, type and constants parameters list **declaration**.
-        ///
-        /// ```
-        /// fn foo❰ <'a, 'b, T, U, const BAR: u64> ❱() {}
-        ///
-        /// struct Baz❰ <T> ❱(T);
-        ///
-        /// impl❰ <T> ❱ Bruh<T> {}
-        ///
-        /// type Bruuh = for❰ <'a> ❱ fn(&'a str) -> &'a str;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/items/generics.html)
-        struct TypeParamList {
-            T![<],
-            generic_params: [GenericParam],
-            type_params: [TypeParam],
-            lifetime_params: [LifetimeParam],
-            const_params: [ConstParam],
-            T![>]
-        }
+            /// Attribute.
+            ///
+            /// ```
+            /// ❰ #![inner_attr] ❱
+            ///
+            /// ❰ #[attr] ❱
+            /// ❰ #[foo = "bar"] ❱
+            /// ❰ #[baz(bruh::bruuh = "42")] ❱
+            /// struct Foo;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/attributes.html)
+            struct Attr { T![#], T![!], T!['['], Path, T![=], input: AttrInput, T![']'] }
+
+            /// Stores a list of lexer tokens and other `TokenTree`s.
+            /// It appears in attributes, macro_rules and macro call (foo!)
+            ///
+            /// ```
+            /// macro_call! ❰ { my syntax here } ❱;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/macros.html)
+            struct TokenTree {}
+
+            /// Generic lifetime, type and constants parameters list **declaration**.
+            ///
+            /// ```
+            /// fn foo❰ <'a, 'b, T, U, const BAR: u64> ❱() {}
+            ///
+            /// struct Baz❰ <T> ❱(T);
+            ///
+            /// impl❰ <T> ❱ Bruh<T> {}
+            ///
+            /// type Bruuh = for❰ <'a> ❱ fn(&'a str) -> &'a str;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/items/generics.html)
+            struct TypeParamList {
+                T![<],
+                generic_params: [GenericParam],
+                type_params: [TypeParam],
+                lifetime_params: [LifetimeParam],
+                const_params: [ConstParam],
+                T![>]
+            }
 
-        /// Single type parameter **declaration**.
-        ///
-        /// ```
-        /// fn foo<❰ K ❱, ❰ I ❱, ❰ E: Debug ❱, ❰ V = DefaultType ❱>() {}
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/items/generics.html)
-        struct TypeParam: NameOwner, AttrsOwner, TypeBoundsOwner {
-            T![=],
-            default_type: TypeRef,
-        }
+            /// Single type parameter **declaration**.
+            ///
+            /// ```
+            /// fn foo<❰ K ❱, ❰ I ❱, ❰ E: Debug ❱, ❰ V = DefaultType ❱>() {}
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/items/generics.html)
+            struct TypeParam: NameOwner, AttrsOwner, TypeBoundsOwner {
+                T![=],
+                default_type: TypeRef,
+            }
 
-        /// Const generic parameter **declaration**.
-        /// ```
-        /// fn foo<T, U, ❰ const BAR: usize ❱, ❰ const BAZ: bool ❱>() {}
-        /// ```
-        ///
-        /// [RFC](https://github.com/rust-lang/rfcs/blob/master/text/2000-const-generics.md#declaring-a-const-parameter)
-        struct ConstParam: NameOwner, AttrsOwner, TypeAscriptionOwner {
-            T![=],
-            default_val: Expr,
-        }
+            /// Const generic parameter **declaration**.
+            /// ```
+            /// fn foo<T, U, ❰ const BAR: usize ❱, ❰ const BAZ: bool ❱>() {}
+            /// ```
+            ///
+            /// [RFC](https://github.com/rust-lang/rfcs/blob/master/text/2000-const-generics.md#declaring-a-const-parameter)
+            struct ConstParam: NameOwner, AttrsOwner, TypeAscriptionOwner {
+                T![=],
+                default_val: Expr,
+            }
 
-        /// Lifetime parameter **declaration**.
-        ///
-        /// ```
-        /// fn foo<❰ 'a ❱, ❰ 'b ❱, V, G, D>(bar: &'a str, baz: &'b mut str) {}
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/items/generics.html)
-        struct LifetimeParam: AttrsOwner { T![lifetime] }
-
-        /// Type bound declaration clause.
-        ///
-        /// ```
-        /// fn foo<T: ❰ ?Sized ❱ + ❰ Debug ❱>() {}
-        ///
-        /// trait Bar<T>
-        /// where
-        ///     T: ❰ Send ❱ + ❰ Sync ❱
-        /// {
-        ///     type Baz: ❰ !Sync ❱ + ❰ Debug ❱ + ❰ ?const Add ❱;
-        /// }
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/trait-bounds.html)
-        struct TypeBound { T![lifetime], /* Question,  */ T![const], /* Question, */ TypeRef }
-
-        /// Type bounds list.
-        ///
-        /// ```
-        ///
-        /// fn foo<T: ❰ ?Sized + Debug ❱>() {}
-        ///
-        /// trait Bar<T>
-        /// where
-        ///     T: ❰ Send + Sync ❱
-        /// {
-        ///     type Baz: ❰ !Sync + Debug ❱;
-        /// }
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/trait-bounds.html)
-        struct TypeBoundList { bounds: [TypeBound] }
-
-        /// Single where predicate.
-        ///
-        /// ```
-        /// trait Foo<'a, 'b, T>
-        /// where
-        ///     ❰ 'a: 'b ❱,
-        ///     ❰ T: IntoIterator ❱,
-        ///     ❰ for<'c> <T as IntoIterator>::Item: Bar<'c> ❱
-        /// {}
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/items/generics.html#where-clauses)
-        struct WherePred: TypeBoundsOwner { T![for], TypeParamList, T![lifetime], TypeRef }
-
-        /// Where clause.
-        ///
-        /// ```
-        /// trait Foo<'a, T> ❰ where 'a: 'static, T: Debug ❱ {}
-        ///
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/items/generics.html#where-clauses)
-        struct WhereClause { T![where], predicates: [WherePred] }
-
-        /// Abi declaration.
-        /// Note: the abi string is optional.
-        ///
-        /// ```
-        /// ❰ extern "C" ❱ {
-        ///     fn foo() {}
-        /// }
-        ///
-        /// type Bar = ❰ extern ❱ fn() -> u32;
-        ///
-        /// type Baz = ❰ extern r#"stdcall"# ❱ fn() -> bool;
-        /// ```
-        ///
-        /// - [Extern blocks reference](https://doc.rust-lang.org/reference/items/external-blocks.html)
-        /// - [FFI function pointers reference](https://doc.rust-lang.org/reference/items/functions.html#functions)
-        struct Abi { /*String*/ }
-
-        /// Expression statement.
-        ///
-        /// ```
-        /// ❰ 42; ❱
-        /// ❰ foo(); ❱
-        /// ❰ (); ❱
-        /// ❰ {}; ❱
-        ///
-        /// // constructions with trailing curly brace can omit the semicolon
-        /// // but only when there are satements immediately after them (this is important!)
-        /// ❰ if bool_cond { } ❱
-        /// ❰ loop {} ❱
-        /// ❰ somestatment; ❱
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/statements.html)
-        struct ExprStmt: AttrsOwner { Expr, T![;] }
-
-        /// Let statement.
-        ///
-        /// ```
-        /// ❰ #[attr] let foo; ❱
-        /// ❰ let bar: u64; ❱
-        /// ❰ let baz = 42; ❱
-        /// ❰ let bruh: bool = true; ❱
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/statements.html#let-statements)
-        struct LetStmt: AttrsOwner, TypeAscriptionOwner {
-            T![let],
-            Pat,
-            T![=],
-            initializer: Expr,
-            T![;],
-        }
+            /// Lifetime parameter **declaration**.
+            ///
+            /// ```
+            /// fn foo<❰ 'a ❱, ❰ 'b ❱, V, G, D>(bar: &'a str, baz: &'b mut str) {}
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/items/generics.html)
+            struct LifetimeParam: AttrsOwner { T![lifetime] }
+
+            /// Type bound declaration clause.
+            ///
+            /// ```
+            /// fn foo<T: ❰ ?Sized ❱ + ❰ Debug ❱>() {}
+            ///
+            /// trait Bar<T>
+            /// where
+            ///     T: ❰ Send ❱ + ❰ Sync ❱
+            /// {
+            ///     type Baz: ❰ !Sync ❱ + ❰ Debug ❱ + ❰ ?const Add ❱;
+            /// }
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/trait-bounds.html)
+            struct TypeBound { T![lifetime], /* Question,  */ T![const], /* Question, */ TypeRef }
+
+            /// Type bounds list.
+            ///
+            /// ```
+            ///
+            /// fn foo<T: ❰ ?Sized + Debug ❱>() {}
+            ///
+            /// trait Bar<T>
+            /// where
+            ///     T: ❰ Send + Sync ❱
+            /// {
+            ///     type Baz: ❰ !Sync + Debug ❱;
+            /// }
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/trait-bounds.html)
+            struct TypeBoundList { bounds: [TypeBound] }
+
+            /// Single where predicate.
+            ///
+            /// ```
+            /// trait Foo<'a, 'b, T>
+            /// where
+            ///     ❰ 'a: 'b ❱,
+            ///     ❰ T: IntoIterator ❱,
+            ///     ❰ for<'c> <T as IntoIterator>::Item: Bar<'c> ❱
+            /// {}
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/items/generics.html#where-clauses)
+            struct WherePred: TypeBoundsOwner { T![for], TypeParamList, T![lifetime], TypeRef }
+
+            /// Where clause.
+            ///
+            /// ```
+            /// trait Foo<'a, T> ❰ where 'a: 'static, T: Debug ❱ {}
+            ///
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/items/generics.html#where-clauses)
+            struct WhereClause { T![where], predicates: [WherePred] }
+
+            /// Abi declaration.
+            /// Note: the abi string is optional.
+            ///
+            /// ```
+            /// ❰ extern "C" ❱ {
+            ///     fn foo() {}
+            /// }
+            ///
+            /// type Bar = ❰ extern ❱ fn() -> u32;
+            ///
+            /// type Baz = ❰ extern r#"stdcall"# ❱ fn() -> bool;
+            /// ```
+            ///
+            /// - [Extern blocks reference](https://doc.rust-lang.org/reference/items/external-blocks.html)
+            /// - [FFI function pointers reference](https://doc.rust-lang.org/reference/items/functions.html#functions)
+            struct Abi { /*String*/ }
+
+            /// Expression statement.
+            ///
+            /// ```
+            /// ❰ 42; ❱
+            /// ❰ foo(); ❱
+            /// ❰ (); ❱
+            /// ❰ {}; ❱
+            ///
+            /// // constructions with trailing curly brace can omit the semicolon
+            /// // but only when there are satements immediately after them (this is important!)
+            /// ❰ if bool_cond { } ❱
+            /// ❰ loop {} ❱
+            /// ❰ somestatment; ❱
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/statements.html)
+            struct ExprStmt: AttrsOwner { Expr, T![;] }
+
+            /// Let statement.
+            ///
+            /// ```
+            /// ❰ #[attr] let foo; ❱
+            /// ❰ let bar: u64; ❱
+            /// ❰ let baz = 42; ❱
+            /// ❰ let bruh: bool = true; ❱
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/statements.html#let-statements)
+            struct LetStmt: AttrsOwner, TypeAscriptionOwner {
+                T![let],
+                Pat,
+                T![=],
+                initializer: Expr,
+                T![;],
+            }
 
-        /// Condition of `if` or `while` expression.
-        ///
-        /// ```
-        /// if ❰ true ❱ {}
-        /// if ❰ let Pat(foo) = bar ❱ {}
-        ///
-        /// while ❰ true ❱ {}
-        /// while ❰ let Pat(baz) = bruh ❱ {}
-        /// ```
-        ///
-        /// [If expression reference](https://doc.rust-lang.org/reference/expressions/if-expr.html)
-        /// [While expression reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html#predicate-loops)
-        struct Condition { T![let], Pat, T![=], Expr }
-
-        /// Parameter list **declaration**.
-        ///
-        /// ```
-        /// fn foo❰ (a: u32, b: bool) ❱ -> u32 {}
-        /// let bar = ❰ |a, b| ❱ {};
-        ///
-        /// impl Baz {
-        ///     fn bruh❰ (&self, a: u32) ❱ {}
-        /// }
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/items/functions.html)ocs to codegen script
-        struct ParamList { // FIXME: this node is used by closure expressions too, but hey use pipes instead of parens...
-            T!['('],
-            SelfParam,
-            params: [Param],
-            T![')']
-        }
+            /// Condition of `if` or `while` expression.
+            ///
+            /// ```
+            /// if ❰ true ❱ {}
+            /// if ❰ let Pat(foo) = bar ❱ {}
+            ///
+            /// while ❰ true ❱ {}
+            /// while ❰ let Pat(baz) = bruh ❱ {}
+            /// ```
+            ///
+            /// [If expression reference](https://doc.rust-lang.org/reference/expressions/if-expr.html)
+            /// [While expression reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html#predicate-loops)
+            struct Condition { T![let], Pat, T![=], Expr }
+
+            /// Parameter list **declaration**.
+            ///
+            /// ```
+            /// fn foo❰ (a: u32, b: bool) ❱ -> u32 {}
+            /// let bar = ❰ |a, b| ❱ {};
+            ///
+            /// impl Baz {
+            ///     fn bruh❰ (&self, a: u32) ❱ {}
+            /// }
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/items/functions.html)ocs to codegen script
+            struct ParamList { // FIXME: this node is used by closure expressions too, but hey use pipes instead of parens...
+                T!['('],
+                SelfParam,
+                params: [Param],
+                T![')']
+            }
 
-        /// Self parameter **declaration**.
-        ///
-        /// ```
-        /// impl Bruh {
-        ///     fn foo(❰ self ❱) {}
-        ///     fn bar(❰ &self ❱) {}
-        ///     fn baz(❰ &mut self ❱) {}
-        ///     fn blah<'a>(❰ &'a self ❱) {}
-        ///     fn blin(❰ self: Box<Self> ❱) {}
-        /// }
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/items/functions.html)
-        struct SelfParam: TypeAscriptionOwner, AttrsOwner { T![&], T![mut], T![lifetime], T![self] }
-
-        /// Parameter **declaration**.
-        ///
-        /// ```
-        /// fn foo(❰ #[attr] Pat(bar): Pat(u32) ❱, ❰ #[attr] _: bool ❱) {}
-        ///
-        /// extern "C" {
-        ///     fn bar(❰ baz: u32 ❱, ❰ ... ❱) -> u32;
-        /// }
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/items/functions.html)
-        struct Param: TypeAscriptionOwner, AttrsOwner {
-            Pat,
-            T![...]
-        }
+            /// Self parameter **declaration**.
+            ///
+            /// ```
+            /// impl Bruh {
+            ///     fn foo(❰ self ❱) {}
+            ///     fn bar(❰ &self ❱) {}
+            ///     fn baz(❰ &mut self ❱) {}
+            ///     fn blah<'a>(❰ &'a self ❱) {}
+            ///     fn blin(❰ self: Box<Self> ❱) {}
+            /// }
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/items/functions.html)
+            struct SelfParam: TypeAscriptionOwner, AttrsOwner { T![&], T![mut], T![lifetime], T![self] }
+
+            /// Parameter **declaration**.
+            ///
+            /// ```
+            /// fn foo(❰ #[attr] Pat(bar): Pat(u32) ❱, ❰ #[attr] _: bool ❱) {}
+            ///
+            /// extern "C" {
+            ///     fn bar(❰ baz: u32 ❱, ❰ ... ❱) -> u32;
+            /// }
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/items/functions.html)
+            struct Param: TypeAscriptionOwner, AttrsOwner {
+                Pat,
+                T![...]
+            }
 
-        /// Use declaration.
-        ///
-        /// ```
-        /// ❰ #[attr] pub use foo; ❱
-        /// ❰ use bar as baz; ❱
-        /// ❰ use bruh::{self, bruuh}; ❱
-        /// ❰ use { blin::blen, blah::* };
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/items/use-declarations.html)
-        struct UseItem: AttrsOwner, VisibilityOwner {
-            T![use],
-            UseTree,
-        }
+            /// Use declaration.
+            ///
+            /// ```
+            /// ❰ #[attr] pub use foo; ❱
+            /// ❰ use bar as baz; ❱
+            /// ❰ use bruh::{self, bruuh}; ❱
+            /// ❰ use { blin::blen, blah::* };
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/items/use-declarations.html)
+            struct UseItem: AttrsOwner, VisibilityOwner {
+                T![use],
+                UseTree,
+            }
 
-        /// Use tree.
-        ///
-        /// ```
-        /// pub use ❰ foo::❰ * ❱ ❱;
-        /// use ❰ bar as baz ❱;
-        /// use ❰ bruh::bruuh::{ ❰ self ❱, ❰ blin ❱ } ❱;
-        /// use ❰ { ❰ blin::blen ❱ } ❱
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/items/use-declarations.html)
-        struct UseTree {
-            Path, T![*], UseTreeList, Alias
-        }
+            /// Use tree.
+            ///
+            /// ```
+            /// pub use ❰ foo::❰ * ❱ ❱;
+            /// use ❰ bar as baz ❱;
+            /// use ❰ bruh::bruuh::{ ❰ self ❱, ❰ blin ❱ } ❱;
+            /// use ❰ { ❰ blin::blen ❱ } ❱
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/items/use-declarations.html)
+            struct UseTree {
+                Path, T![*], UseTreeList, Alias
+            }
 
-        /// Item alias.
-        /// Note: this is not the type alias.
-        ///
-        /// ```
-        /// use foo ❰ as bar ❱;
-        /// use baz::{bruh ❰ as _ ❱};
-        /// extern crate bruuh ❰ as blin ❱;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/items/use-declarations.html)
-        struct Alias: NameOwner { T![as] }
-
-        /// Sublist of use trees.
-        ///
-        /// ```
-        /// use bruh::bruuh::❰ { ❰ self ❱, ❰ blin ❱ } ❱;
-        /// use ❰ { blin::blen::❰ {} ❱ } ❱
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/items/use-declarations.html)
-        struct UseTreeList { T!['{'], use_trees: [UseTree], T!['}'] }
-
-        /// Extern crate item.
-        ///
-        /// ```
-        /// ❰ #[attr] pub extern crate foo; ❱
-        /// ❰ extern crate self as bar; ❱
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/items/extern-crates.html)
-        struct ExternCrateItem: AttrsOwner, VisibilityOwner {
-            T![extern], T![crate], NameRef, Alias,
-        }
+            /// Item alias.
+            /// Note: this is not the type alias.
+            ///
+            /// ```
+            /// use foo ❰ as bar ❱;
+            /// use baz::{bruh ❰ as _ ❱};
+            /// extern crate bruuh ❰ as blin ❱;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/items/use-declarations.html)
+            struct Alias: NameOwner { T![as] }
+
+            /// Sublist of use trees.
+            ///
+            /// ```
+            /// use bruh::bruuh::❰ { ❰ self ❱, ❰ blin ❱ } ❱;
+            /// use ❰ { blin::blen::❰ {} ❱ } ❱
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/items/use-declarations.html)
+            struct UseTreeList { T!['{'], use_trees: [UseTree], T!['}'] }
+
+            /// Extern crate item.
+            ///
+            /// ```
+            /// ❰ #[attr] pub extern crate foo; ❱
+            /// ❰ extern crate self as bar; ❱
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/items/extern-crates.html)
+            struct ExternCrateItem: AttrsOwner, VisibilityOwner {
+                T![extern], T![crate], NameRef, Alias,
+            }
 
-        /// Call site arguments list.
-        ///
-        /// ```
-        /// foo::<T, U>❰ (42, true) ❱;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/expressions/call-expr.html)
-        struct ArgList {
-            T!['('],
-            args: [Expr],
-            T![')']
-        }
+            /// Call site arguments list.
+            ///
+            /// ```
+            /// foo::<T, U>❰ (42, true) ❱;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/expressions/call-expr.html)
+            struct ArgList {
+                T!['('],
+                args: [Expr],
+                T![')']
+            }
 
-        /// Path to a symbol. Includes single identifier names and elaborate paths with
-        /// generic parameters.
-        ///
-        /// ```
-        /// (0..10).❰ ❰ collect ❱ ::<Vec<_>> ❱();
-        /// ❰ ❰ ❰ Vec ❱ ::<u8> ❱ ::with_capacity ❱(1024);
-        /// ❰ ❰ <❰ Foo ❱ as ❰ ❰ bar ❱ ::Bar ❱> ❱ ::baz ❱();
-        /// ❰ ❰ <❰ bruh ❱> ❱ ::bruuh ❱();
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/paths.html)
-        struct Path {
-            segment: PathSegment,
-            T![::],
-            qualifier: Path,
-        }
+            /// Path to a symbol. Includes single identifier names and elaborate paths with
+            /// generic parameters.
+            ///
+            /// ```
+            /// (0..10).❰ ❰ collect ❱ ::<Vec<_>> ❱();
+            /// ❰ ❰ ❰ Vec ❱ ::<u8> ❱ ::with_capacity ❱(1024);
+            /// ❰ ❰ <❰ Foo ❱ as ❰ ❰ bar ❱ ::Bar ❱> ❱ ::baz ❱();
+            /// ❰ ❰ <❰ bruh ❱> ❱ ::bruuh ❱();
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/paths.html)
+            struct Path {
+                segment: PathSegment,
+                T![::],
+                qualifier: Path,
+            }
 
-        /// Segment of the path to a symbol.
-        /// Only path segment of an absolute path holds the `::` token,
-        /// all other `::` tokens that connect path segments reside under `Path` itself.`
-        ///
-        /// ```
-        /// (0..10).❰ collect ❱ :: ❰ <Vec<_>> ❱();
-        /// ❰ Vec ❱ :: ❰ <u8> ❱ :: ❰ with_capacity ❱(1024);
-        /// ❰ <❰ Foo ❱ as ❰ bar ❱ :: ❰ Bar ❱> ❱ :: ❰ baz ❱();
-        /// ❰ <❰ bruh ❱> ❱ :: ❰ bruuh ❱();
-        ///
-        /// // Note that only in this case `::` token is inlcuded:
-        /// ❰ ::foo ❱;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/paths.html)
-        struct PathSegment {
-            T![::], T![crate], T![self], T![super], T![<], NameRef, TypeArgList, ParamList, RetType, PathType, T![>]
-        }
+            /// Segment of the path to a symbol.
+            /// Only path segment of an absolute path holds the `::` token,
+            /// all other `::` tokens that connect path segments reside under `Path` itself.`
+            ///
+            /// ```
+            /// (0..10).❰ collect ❱ :: ❰ <Vec<_>> ❱();
+            /// ❰ Vec ❱ :: ❰ <u8> ❱ :: ❰ with_capacity ❱(1024);
+            /// ❰ <❰ Foo ❱ as ❰ bar ❱ :: ❰ Bar ❱> ❱ :: ❰ baz ❱();
+            /// ❰ <❰ bruh ❱> ❱ :: ❰ bruuh ❱();
+            ///
+            /// // Note that only in this case `::` token is inlcuded:
+            /// ❰ ::foo ❱;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/paths.html)
+            struct PathSegment {
+                T![::], T![crate], T![self], T![super], T![<], NameRef, TypeArgList, ParamList, RetType, PathType, T![>]
+            }
 
-        /// List of type arguments that are passed at generic instantiation site.
-        ///
-        /// ```
-        /// type _ = Foo ❰ ::<'a, u64, Item = Bar, 42, {true}> ❱::Bar;
-        ///
-        /// Vec❰ ::<bool> ❱::();
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/paths.html#paths-in-expressions)
-        struct TypeArgList {
-            T![::],
-            T![<],
-            generic_args: [GenericArg],
-            type_args: [TypeArg],
-            lifetime_args: [LifetimeArg],
-            assoc_type_args: [AssocTypeArg],
-            const_args: [ConstArg],
-            T![>]
-        }
+            /// List of type arguments that are passed at generic instantiation site.
+            ///
+            /// ```
+            /// type _ = Foo ❰ ::<'a, u64, Item = Bar, 42, {true}> ❱::Bar;
+            ///
+            /// Vec❰ ::<bool> ❱::();
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/paths.html#paths-in-expressions)
+            struct TypeArgList {
+                T![::],
+                T![<],
+                generic_args: [GenericArg],
+                type_args: [TypeArg],
+                lifetime_args: [LifetimeArg],
+                assoc_type_args: [AssocTypeArg],
+                const_args: [ConstArg],
+                T![>]
+            }
 
-        /// Type argument that is passed at generic instantiation site.
-        ///
-        /// ```
-        /// type _ = Foo::<'a, ❰ u64 ❱, ❰ bool ❱, Item = Bar, 42>::Baz;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/paths.html#paths-in-expressions)
-        struct TypeArg { TypeRef }
-
-        /// Associated type argument that is passed at generic instantiation site.
-        /// ```
-        /// type Foo = Bar::<'a, u64, bool, ❰ Item = Baz ❱, 42>::Bruh;
-        ///
-        /// trait Bruh<T>: Iterator<❰ Item: Debug ❱> {}
-        /// ```
-        ///
-        struct AssocTypeArg : TypeBoundsOwner { NameRef, T![=], TypeRef }
-
-        /// Lifetime argument that is passed at generic instantiation site.
-        ///
-        /// ```
-        /// fn foo<'a>(s: &'a str) {
-        ///     bar::<❰ 'a ❱>(s);
-        /// }
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/paths.html#paths-in-expressions)
-        struct LifetimeArg { T![lifetime] }
-
-        /// Constant value argument that is passed at generic instantiation site.
-        ///
-        /// ```
-        /// foo::<u32, ❰ { true } ❱>();
-        ///
-        /// bar::<❰ { 2 + 2} ❱>();
-        /// ```
-        ///
-        /// [RFC](https://github.com/rust-lang/rfcs/blob/master/text/2000-const-generics.md#declaring-a-const-parameter)
-        struct ConstArg { Literal, BlockExpr }
-
-
-        /// FIXME: (@edwin0cheng) Remove it to use ItemList instead
-        /// https://github.com/rust-analyzer/rust-analyzer/pull/4083#discussion_r422666243
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/macros.html)
-        struct MacroItems: ModuleItemOwner { }
-
-        /// FIXME: (@edwin0cheng) add some documentation here. As per the writing
-        /// of this comment this ast node is not used.
-        ///
-        /// ```
-        /// // FIXME: example here
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/macros.html)
-        struct MacroStmts {
-            statements: [Stmt],
-            Expr,
-        }
+            /// Type argument that is passed at generic instantiation site.
+            ///
+            /// ```
+            /// type _ = Foo::<'a, ❰ u64 ❱, ❰ bool ❱, Item = Bar, 42>::Baz;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/paths.html#paths-in-expressions)
+            struct TypeArg { TypeRef }
+
+            /// Associated type argument that is passed at generic instantiation site.
+            /// ```
+            /// type Foo = Bar::<'a, u64, bool, ❰ Item = Baz ❱, 42>::Bruh;
+            ///
+            /// trait Bruh<T>: Iterator<❰ Item: Debug ❱> {}
+            /// ```
+            ///
+            struct AssocTypeArg : TypeBoundsOwner { NameRef, T![=], TypeRef }
+
+            /// Lifetime argument that is passed at generic instantiation site.
+            ///
+            /// ```
+            /// fn foo<'a>(s: &'a str) {
+            ///     bar::<❰ 'a ❱>(s);
+            /// }
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/paths.html#paths-in-expressions)
+            struct LifetimeArg { T![lifetime] }
+
+            /// Constant value argument that is passed at generic instantiation site.
+            ///
+            /// ```
+            /// foo::<u32, ❰ { true } ❱>();
+            ///
+            /// bar::<❰ { 2 + 2} ❱>();
+            /// ```
+            ///
+            /// [RFC](https://github.com/rust-lang/rfcs/blob/master/text/2000-const-generics.md#declaring-a-const-parameter)
+            struct ConstArg { Literal, BlockExpr }
+
+
+            /// FIXME: (@edwin0cheng) Remove it to use ItemList instead
+            /// https://github.com/rust-analyzer/rust-analyzer/pull/4083#discussion_r422666243
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/macros.html)
+            struct MacroItems: ModuleItemOwner { }
+
+            /// FIXME: (@edwin0cheng) add some documentation here. As per the writing
+            /// of this comment this ast node is not used.
+            ///
+            /// ```
+            /// // FIXME: example here
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/macros.html)
+            struct MacroStmts {
+                statements: [Stmt],
+                Expr,
+            }
 
-        /// List of items in an extern block.
-        ///
-        /// ```
-        /// extern "C" ❰
-        ///     {
-        ///         fn foo();
-        ///         static var: u32;
-        ///     }
-        /// ❱
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/items/external-blocks.html)
-        struct ExternItemList: ModuleItemOwner {
-            T!['{'],
-            extern_items: [ExternItem],
-            T!['}']
-        }
+            /// List of items in an extern block.
+            ///
+            /// ```
+            /// extern "C" ❰
+            ///     {
+            ///         fn foo();
+            ///         static var: u32;
+            ///     }
+            /// ❱
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/items/external-blocks.html)
+            struct ExternItemList: ModuleItemOwner {
+                T!['{'],
+                extern_items: [ExternItem],
+                T!['}']
+            }
 
-        /// Extern block.
-        ///
-        /// ```
-        /// ❰
-        ///     extern "C" {
-        ///         fn foo();
-        ///     }
-        /// ❱
-        ///
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/items/external-blocks.html)
-        struct ExternBlock {
-            Abi,
-            ExternItemList
-        }
+            /// Extern block.
+            ///
+            /// ```
+            /// ❰
+            ///     extern "C" {
+            ///         fn foo();
+            ///     }
+            /// ❱
+            ///
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/items/external-blocks.html)
+            struct ExternBlock {
+                Abi,
+                ExternItemList
+            }
 
-        /// Meta item in an attribute.
-        ///
-        /// ```
-        /// #[❰ bar::baz = "42" ❱]
-        /// #[❰ bruh(bruuh("true")) ❱]
-        /// struct Foo;
-        /// ```
-        ///
-        /// [Reference](https://doc.rust-lang.org/reference/attributes.html?highlight=meta,item#meta-item-attribute-syntax)
-        struct MetaItem {
-            Path, T![=], AttrInput, nested_meta_items: [MetaItem]
-        }
+            /// Meta item in an attribute.
+            ///
+            /// ```
+            /// #[❰ bar::baz = "42" ❱]
+            /// #[❰ bruh(bruuh("true")) ❱]
+            /// struct Foo;
+            /// ```
+            ///
+            /// [Reference](https://doc.rust-lang.org/reference/attributes.html?highlight=meta,item#meta-item-attribute-syntax)
+            struct MetaItem {
+                Path, T![=], AttrInput, nested_meta_items: [MetaItem]
+            }
 
-        /// Macro 2.0 definition.
-        /// Their syntax is still WIP by rustc team...
-        /// ```
-        /// ❰
-        ///     macro foo { }
-        /// ❱
-        /// ```
-        ///
-        /// [RFC](https://github.com/rust-lang/rfcs/blob/master/text/1584-macros.md)
-        struct MacroDef {
-            Name, TokenTree
-        }
-    },
-    enums: &ast_enums! {
-        /// Any kind of nominal type definition.
-        enum NominalDef: NameOwner, TypeParamsOwner, AttrsOwner {
-            StructDef, EnumDef, UnionDef,
-        }
+            /// Macro 2.0 definition.
+            /// Their syntax is still WIP by rustc team...
+            /// ```
+            /// ❰
+            ///     macro foo { }
+            /// ❱
+            /// ```
+            ///
+            /// [RFC](https://github.com/rust-lang/rfcs/blob/master/text/1584-macros.md)
+            struct MacroDef {
+                Name, TokenTree
+            }
+        },
+        enums: ast_enums! {
+            /// Any kind of nominal type definition.
+            enum NominalDef: NameOwner, TypeParamsOwner, AttrsOwner {
+                StructDef, EnumDef, UnionDef,
+            }
 
-        /// Any kind of **declared** generic parameter
-        enum GenericParam {
-            LifetimeParam,
-            TypeParam,
-            ConstParam
-        }
+            /// Any kind of **declared** generic parameter
+            enum GenericParam {
+                LifetimeParam,
+                TypeParam,
+                ConstParam
+            }
 
-        /// Any kind of generic argument passed at instantiation site
-        enum GenericArg {
-            LifetimeArg,
-            TypeArg,
-            ConstArg,
-            AssocTypeArg
-        }
+            /// Any kind of generic argument passed at instantiation site
+            enum GenericArg {
+                LifetimeArg,
+                TypeArg,
+                ConstArg,
+                AssocTypeArg
+            }
 
-        /// Any kind of construct valid in type context
-        enum TypeRef {
-            ParenType,
-            TupleType,
-            NeverType,
-            PathType,
-            PointerType,
-            ArrayType,
-            SliceType,
-            ReferenceType,
-            PlaceholderType,
-            FnPointerType,
-            ForType,
-            ImplTraitType,
-            DynTraitType,
-        }
+            /// Any kind of construct valid in type context
+            enum TypeRef {
+                ParenType,
+                TupleType,
+                NeverType,
+                PathType,
+                PointerType,
+                ArrayType,
+                SliceType,
+                ReferenceType,
+                PlaceholderType,
+                FnPointerType,
+                ForType,
+                ImplTraitType,
+                DynTraitType,
+            }
 
-        /// Any kind of top-level item that may appear in a module
-        enum ModuleItem: NameOwner, AttrsOwner, VisibilityOwner {
-            StructDef,
-            UnionDef,
-            EnumDef,
-            FnDef,
-            TraitDef,
-            TypeAliasDef,
-            ImplDef,
-            UseItem,
-            ExternCrateItem,
-            ConstDef,
-            StaticDef,
-            Module,
-            MacroCall,
-            ExternBlock
-        }
+            /// Any kind of top-level item that may appear in a module
+            enum ModuleItem: NameOwner, AttrsOwner, VisibilityOwner {
+                StructDef,
+                UnionDef,
+                EnumDef,
+                FnDef,
+                TraitDef,
+                TypeAliasDef,
+                ImplDef,
+                UseItem,
+                ExternCrateItem,
+                ConstDef,
+                StaticDef,
+                Module,
+                MacroCall,
+                ExternBlock
+            }
 
 
 
-        /// Any kind of item that may appear in an impl block
-        ///
-        /// // FIXME: impl blocks can also contain MacroCall
-        enum AssocItem: NameOwner, AttrsOwner {
-            FnDef, TypeAliasDef, ConstDef
-        }
+            /// Any kind of item that may appear in an impl block
+            ///
+            /// // FIXME: impl blocks can also contain MacroCall
+            enum AssocItem: NameOwner, AttrsOwner {
+                FnDef, TypeAliasDef, ConstDef
+            }
 
-        /// Any kind of item that may appear in an extern block
-        ///
-        /// // FIXME: extern blocks can also contain MacroCall
-        enum ExternItem: NameOwner, AttrsOwner, VisibilityOwner {
-            FnDef, StaticDef
-        }
+            /// Any kind of item that may appear in an extern block
+            ///
+            /// // FIXME: extern blocks can also contain MacroCall
+            enum ExternItem: NameOwner, AttrsOwner, VisibilityOwner {
+                FnDef, StaticDef
+            }
 
-        /// Any kind of expression
-        enum Expr: AttrsOwner {
-            TupleExpr,
-            ArrayExpr,
-            ParenExpr,
-            PathExpr,
-            LambdaExpr,
-            IfExpr,
-            LoopExpr,
-            ForExpr,
-            WhileExpr,
-            ContinueExpr,
-            BreakExpr,
-            Label,
-            BlockExpr,
-            ReturnExpr,
-            MatchExpr,
-            RecordLit,
-            CallExpr,
-            IndexExpr,
-            MethodCallExpr,
-            FieldExpr,
-            AwaitExpr,
-            TryExpr,
-            EffectExpr,
-            CastExpr,
-            RefExpr,
-            PrefixExpr,
-            RangeExpr,
-            BinExpr,
-            Literal,
-            MacroCall,
-            BoxExpr,
-        }
+            /// Any kind of expression
+            enum Expr: AttrsOwner {
+                TupleExpr,
+                ArrayExpr,
+                ParenExpr,
+                PathExpr,
+                LambdaExpr,
+                IfExpr,
+                LoopExpr,
+                ForExpr,
+                WhileExpr,
+                ContinueExpr,
+                BreakExpr,
+                Label,
+                BlockExpr,
+                ReturnExpr,
+                MatchExpr,
+                RecordLit,
+                CallExpr,
+                IndexExpr,
+                MethodCallExpr,
+                FieldExpr,
+                AwaitExpr,
+                TryExpr,
+                EffectExpr,
+                CastExpr,
+                RefExpr,
+                PrefixExpr,
+                RangeExpr,
+                BinExpr,
+                Literal,
+                MacroCall,
+                BoxExpr,
+            }
 
-        /// Any kind of pattern
-        enum Pat {
-            OrPat,
-            ParenPat,
-            RefPat,
-            BoxPat,
-            BindPat,
-            PlaceholderPat,
-            DotDotPat,
-            PathPat,
-            RecordPat,
-            TupleStructPat,
-            TuplePat,
-            SlicePat,
-            RangePat,
-            LiteralPat,
-            MacroPat,
-        }
+            /// Any kind of pattern
+            enum Pat {
+                OrPat,
+                ParenPat,
+                RefPat,
+                BoxPat,
+                BindPat,
+                PlaceholderPat,
+                DotDotPat,
+                PathPat,
+                RecordPat,
+                TupleStructPat,
+                TuplePat,
+                SlicePat,
+                RangePat,
+                LiteralPat,
+                MacroPat,
+            }
 
-        /// Any kind of pattern that appears directly inside of the curly
-        /// braces of a record pattern
-        enum RecordInnerPat {
-            RecordFieldPat,
-            BindPat
-        }
+            /// Any kind of pattern that appears directly inside of the curly
+            /// braces of a record pattern
+            enum RecordInnerPat {
+                RecordFieldPat,
+                BindPat
+            }
 
-        /// Any kind of input to an attribute
-        enum AttrInput { Literal, TokenTree }
+            /// Any kind of input to an attribute
+            enum AttrInput { Literal, TokenTree }
 
-        /// Any kind of statement
-        /// Note: there are no empty statements, these are just represented as
-        /// bare semicolons without a dedicated statement ast node.
-        enum Stmt {
-            LetStmt,
-            ExprStmt,
-            // macro calls are parsed as expression statements
-        }
+            /// Any kind of statement
+            /// Note: there are no empty statements, these are just represented as
+            /// bare semicolons without a dedicated statement ast node.
+            enum Stmt {
+                LetStmt,
+                ExprStmt,
+                // macro calls are parsed as expression statements
+            }
 
-        /// Any kind of fields list (record or tuple field lists)
-        enum FieldDefList {
-            RecordFieldDefList,
-            TupleFieldDefList,
-        }
-    },
-};
+            /// Any kind of fields list (record or tuple field lists)
+            enum FieldDefList {
+                RecordFieldDefList,
+                TupleFieldDefList,
+            }
+        },
+    }
+}
diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs
index 745a25862b..5a18b3e2b3 100644
--- a/xtask/src/codegen/gen_syntax.rs
+++ b/xtask/src/codegen/gen_syntax.rs
@@ -9,28 +9,29 @@ use proc_macro2::{Punct, Spacing};
 use quote::{format_ident, quote};
 
 use crate::{
-    ast_src::{AstSrc, Field, FieldSrc, KindsSrc, AST_SRC, KINDS_SRC},
+    ast_src::{rust_ast, AstSrc, Field, FieldSrc, KindsSrc, KINDS_SRC},
     codegen::{self, update, Mode},
     project_root, Result,
 };
 
 pub fn generate_syntax(mode: Mode) -> Result<()> {
+    let ast = rust_ast();
     let syntax_kinds_file = project_root().join(codegen::SYNTAX_KINDS);
     let syntax_kinds = generate_syntax_kinds(KINDS_SRC)?;
     update(syntax_kinds_file.as_path(), &syntax_kinds, mode)?;
 
     let ast_tokens_file = project_root().join(codegen::AST_TOKENS);
-    let contents = generate_tokens(AST_SRC)?;
+    let contents = generate_tokens(&ast)?;
     update(ast_tokens_file.as_path(), &contents, mode)?;
 
     let ast_nodes_file = project_root().join(codegen::AST_NODES);
-    let contents = generate_nodes(KINDS_SRC, AST_SRC)?;
+    let contents = generate_nodes(KINDS_SRC, &ast)?;
     update(ast_nodes_file.as_path(), &contents, mode)?;
 
     Ok(())
 }
 
-fn generate_tokens(grammar: AstSrc<'_>) -> Result<String> {
+fn generate_tokens(grammar: &AstSrc) -> Result<String> {
     let tokens = grammar.tokens.iter().map(|token| {
         let name = format_ident!("{}", token);
         let kind = format_ident!("{}", to_upper_snake_case(token));
@@ -62,13 +63,13 @@ fn generate_tokens(grammar: AstSrc<'_>) -> Result<String> {
     Ok(pretty)
 }
 
-fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
+fn generate_nodes(kinds: KindsSrc<'_>, grammar: &AstSrc) -> Result<String> {
     let (node_defs, node_boilerplate_impls): (Vec<_>, Vec<_>) = grammar
         .nodes
         .iter()
         .map(|node| {
             let name = format_ident!("{}", node.name);
-            let kind = format_ident!("{}", to_upper_snake_case(node.name));
+            let kind = format_ident!("{}", to_upper_snake_case(&node.name));
             let traits = node.traits.iter().map(|trait_name| {
                 let trait_name = format_ident!("{}", trait_name);
                 quote!(impl ast::#trait_name for #name {})
@@ -192,8 +193,8 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
         })
         .unzip();
 
-    let enum_names = grammar.enums.iter().map(|it| it.name);
-    let node_names = grammar.nodes.iter().map(|it| it.name);
+    let enum_names = grammar.enums.iter().map(|it| &it.name);
+    let node_names = grammar.nodes.iter().map(|it| &it.name);
 
     let display_impls =
         enum_names.chain(node_names.clone()).map(|it| format_ident!("{}", it)).map(|name| {
@@ -212,7 +213,7 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
         .nodes
         .iter()
         .map(|kind| to_pascal_case(kind))
-        .filter(|name| !defined_nodes.contains(name.as_str()))
+        .filter(|name| !defined_nodes.iter().any(|&it| it == name))
     {
         eprintln!("Warning: node {} not defined in ast source", node);
     }
@@ -236,12 +237,12 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
     let mut res = String::with_capacity(ast.len() * 2);
 
     let mut docs =
-        grammar.nodes.iter().map(|it| it.doc).chain(grammar.enums.iter().map(|it| it.doc));
+        grammar.nodes.iter().map(|it| &it.doc).chain(grammar.enums.iter().map(|it| &it.doc));
 
     for chunk in ast.split("# [ pretty_doc_comment_placeholder_workaround ]") {
         res.push_str(chunk);
         if let Some(doc) = docs.next() {
-            write_doc_comment(doc, &mut res);
+            write_doc_comment(&doc, &mut res);
         }
     }
 
@@ -249,7 +250,7 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
     Ok(pretty)
 }
 
-fn write_doc_comment(contents: &[&str], dest: &mut String) {
+fn write_doc_comment(contents: &[String], dest: &mut String) {
     for line in contents {
         writeln!(dest, "///{}", line).unwrap();
     }
@@ -413,7 +414,7 @@ fn to_pascal_case(s: &str) -> String {
     buf
 }
 
-impl Field<'_> {
+impl Field {
     fn is_many(&self) -> bool {
         matches!(self, Field::Node { src: FieldSrc::Many(_), .. })
     }
@@ -429,7 +430,7 @@ impl Field<'_> {
     fn method_name(&self) -> proc_macro2::Ident {
         match self {
             Field::Token(name) => {
-                let name = match *name {
+                let name = match name.as_str() {
                     ";" => "semicolon",
                     "->" => "thin_arrow",
                     "'{'" => "l_curly",


Test patch:
diff --git a/crates/ra_ssr/src/tests.rs b/crates/ra_ssr/src/tests.rs
index f5ffff7ccb..851e573aec 100644
--- a/crates/ra_ssr/src/tests.rs
+++ b/crates/ra_ssr/src/tests.rs
@@ -1,9 +1,9 @@
 use crate::{MatchFinder, SsrRule};
 use expect::{expect, Expect};
-use ra_db::{salsa::Durability, FileId, FilePosition, FileRange, SourceDatabaseExt};
+use ra_db::{salsa::Durability, FileId, FilePosition, SourceDatabaseExt};
 use rustc_hash::FxHashSet;
 use std::sync::Arc;
-use test_utils::{mark, RangeOrOffset};
+use test_utils::mark;
 
 fn parse_error_text(query: &str) -> String {
     format!("{}", query.parse::<SsrRule>().unwrap_err())
@@ -60,32 +60,20 @@ fn parser_undefined_placeholder_in_replacement() {
 }
 
 /// `code` may optionally contain a cursor marker `<|>`. If it doesn't, then the position will be
-/// the start of the file. If there's a second cursor marker, then we'll return a single range.
-pub(crate) fn single_file(code: &str) -> (ra_ide_db::RootDatabase, FilePosition, Vec<FileRange>) {
+/// the start of the file.
+pub(crate) fn single_file(code: &str) -> (ra_ide_db::RootDatabase, FilePosition) {
     use ra_db::fixture::WithFixture;
     use ra_ide_db::symbol_index::SymbolsDatabase;
-    let (mut db, file_id, range_or_offset) = if code.contains(test_utils::CURSOR_MARKER) {
-        ra_ide_db::RootDatabase::with_range_or_offset(code)
+    let (mut db, position) = if code.contains(test_utils::CURSOR_MARKER) {
+        ra_ide_db::RootDatabase::with_position(code)
     } else {
         let (db, file_id) = ra_ide_db::RootDatabase::with_single_file(code);
-        (db, file_id, RangeOrOffset::Offset(0.into()))
+        (db, FilePosition { file_id, offset: 0.into() })
     };
-    let selections;
-    let position;
-    match range_or_offset {
-        RangeOrOffset::Range(range) => {
-            position = FilePosition { file_id, offset: range.start() };
-            selections = vec![FileRange { file_id, range: range }];
-        }
-        RangeOrOffset::Offset(offset) => {
-            position = FilePosition { file_id, offset };
-            selections = vec![];
-        }
-    }
     let mut local_roots = FxHashSet::default();
     local_roots.insert(ra_db::fixture::WORKSPACE);
     db.set_local_roots_with_durability(Arc::new(local_roots), Durability::HIGH);
-    (db, position, selections)
+    (db, position)
 }
 
 fn assert_ssr_transform(rule: &str, input: &str, expected: Expect) {
@@ -93,8 +81,8 @@ fn assert_ssr_transform(rule: &str, input: &str, expected: Expect) {
 }
 
 fn assert_ssr_transforms(rules: &[&str], input: &str, expected: Expect) {
-    let (db, position, selections) = single_file(input);
-    let mut match_finder = MatchFinder::in_context(&db, position, selections);
+    let (db, position) = single_file(input);
+    let mut match_finder = MatchFinder::in_context(&db, position);
     for rule in rules {
         let rule: SsrRule = rule.parse().unwrap();
         match_finder.add_rule(rule).unwrap();
@@ -124,8 +112,8 @@ fn print_match_debug_info(match_finder: &MatchFinder, file_id: FileId, snippet:
 }
 
 fn assert_matches(pattern: &str, code: &str, expected: &[&str]) {
-    let (db, position, selections) = single_file(code);
-    let mut match_finder = MatchFinder::in_context(&db, position, selections);
+    let (db, position) = single_file(code);
+    let mut match_finder = MatchFinder::in_context(&db, position);
     match_finder.add_search_pattern(pattern.parse().unwrap()).unwrap();
     let matched_strings: Vec<String> =
         match_finder.matches().flattened().matches.iter().map(|m| m.matched_text()).collect();
@@ -136,8 +124,8 @@ fn assert_matches(pattern: &str, code: &str, expected: &[&str]) {
 }
 
 fn assert_no_match(pattern: &str, code: &str) {
-    let (db, position, selections) = single_file(code);
-    let mut match_finder = MatchFinder::in_context(&db, position, selections);
+    let (db, position) = single_file(code);
+    let mut match_finder = MatchFinder::in_context(&db, position);
     match_finder.add_search_pattern(pattern.parse().unwrap()).unwrap();
     let matches = match_finder.matches().flattened().matches;
     if !matches.is_empty() {
@@ -147,8 +135,8 @@ fn assert_no_match(pattern: &str, code: &str) {
 }
 
 fn assert_match_failure_reason(pattern: &str, code: &str, snippet: &str, expected_reason: &str) {
-    let (db, position, selections) = single_file(code);
-    let mut match_finder = MatchFinder::in_context(&db, position, selections);
+    let (db, position) = single_file(code);
+    let mut match_finder = MatchFinder::in_context(&db, position);
     match_finder.add_search_pattern(pattern.parse().unwrap()).unwrap();
     let mut reasons = Vec::new();
     for d in match_finder.debug_where_text_equal(position.file_id, snippet) {
@@ -502,10 +490,9 @@ fn no_match_split_expression() {
 
 #[test]
 fn replace_function_call() {
-    // This test also makes sure that we ignore empty-ranges.
     assert_ssr_transform(
         "foo() ==>> bar()",
-        "fn foo() {<|><|>} fn bar() {} fn f1() {foo(); foo();}",
+        "fn foo() {} fn bar() {} fn f1() {foo(); foo();}",
         expect![["fn foo() {} fn bar() {} fn f1() {bar(); bar();}"]],
     );
 }
@@ -974,52 +961,3 @@ fn replace_local_variable_reference() {
         "#]],
     )
 }
-
-#[test]
-fn replace_path_within_selection() {
-    assert_ssr_transform(
-        "foo ==>> bar",
-        r#"
-        fn main() {
-            let foo = 41;
-            let bar = 42;
-            do_stuff(foo);
-            do_stuff(foo);<|>
-            do_stuff(foo);
-            do_stuff(foo);<|>
-            do_stuff(foo);
-        }"#,
-        expect![[r#"
-            fn main() {
-                let foo = 41;
-                let bar = 42;
-                do_stuff(foo);
-                do_stuff(foo);
-                do_stuff(bar);
-                do_stuff(bar);
-                do_stuff(foo);
-            }"#]],
-    );
-}
-
-#[test]
-fn replace_nonpath_within_selection() {
-    mark::check!(replace_nonpath_within_selection);
-    assert_ssr_transform(
-        "$a + $b ==>> $b * $a",
-        r#"
-        fn main() {
-            let v = 1 + 2;<|>
-            let v2 = 3 + 3;
-            let v3 = 4 + 5;<|>
-            let v4 = 6 + 7;
-        }"#,
-        expect![[r#"
-            fn main() {
-                let v = 1 + 2;
-                let v2 = 3 * 3;
-                let v3 = 5 * 4;
-                let v4 = 6 + 7;
-            }"#]],
-    );
-}