Repository: rust-lang/rust-analyzer
Pull request #16879 (2024-03-18 22:09:15)

Add fuel to match checking 
Exhaustiveness checking is NP-hard hence can take extremely long to check some specific matches. This PR makes ehxaustiveness bail after a set number of steps. I chose a bound that takes ~100ms on my machine, which should be more than enough for normal matches.

I'd like someone with less recent hardware to run the test to see if that limit is low enough for them. Also curious if the r-a team thinks this is a good ballpark or if we should go lower/higher. I don't have much data on how complex real-life matches get, but we can definitely go lower than `500 000` steps.

The second commit is a drive-by soundness fix which doesn't matter much today but will matter once `min_exhaustive_patterns` is stabilized.

Fixes https://github.com/rust-lang/rust-analyzer/issues/9528 cc @matklad 


Patch:
diff --git a/.github/workflows/publish-libs.yaml b/.github/workflows/publish-libs.yaml
index 34ca53e2e5..862373ec1c 100644
--- a/.github/workflows/publish-libs.yaml
+++ b/.github/workflows/publish-libs.yaml
@@ -32,5 +32,4 @@ jobs:
           git config --global user.name "GitHub Action"
           # Remove r-a crates from the workspaces so we don't auto-publish them as well
           sed -i 's/ "crates\/\*"//' ./Cargo.toml
-          sed -i 's/ "xtask\/"//' ./Cargo.toml
           cargo workspaces publish --yes --exact --from-git --no-git-commit --allow-dirty
diff --git a/Cargo.lock b/Cargo.lock
index 3e1c56c356..a8e3dc338f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1869,16 +1869,20 @@ dependencies = [
  "itertools",
  "once_cell",
  "parser",
+ "proc-macro2",
+ "quote",
  "ra-ap-rustc_lexer",
  "rayon",
  "rowan",
  "rustc-hash",
  "smol_str",
+ "sourcegen",
  "stdx",
  "test-utils",
  "text-edit",
  "tracing",
  "triomphe",
+ "ungrammar",
 ]
 
 [[package]]
@@ -2434,12 +2438,8 @@ version = "0.1.0"
 dependencies = [
  "anyhow",
  "flate2",
- "itertools",
- "proc-macro2",
- "quote",
  "stdx",
  "time",
- "ungrammar",
  "write-json",
  "xflags",
  "xshell",
diff --git a/crates/hir-ty/Cargo.toml b/crates/hir-ty/Cargo.toml
index a2711f8cbe..3cfedcdcb4 100644
--- a/crates/hir-ty/Cargo.toml
+++ b/crates/hir-ty/Cargo.toml
@@ -53,7 +53,7 @@ expect-test = "1.4.0"
 tracing.workspace = true
 tracing-subscriber.workspace = true
 tracing-tree.workspace = true
-project-model.workspace = true
+project-model = { path = "../project-model" }
 
 # local deps
 test-utils.workspace = true
diff --git a/crates/hir-ty/src/diagnostics/expr.rs b/crates/hir-ty/src/diagnostics/expr.rs
index b3128712dc..20b0da441d 100644
--- a/crates/hir-ty/src/diagnostics/expr.rs
+++ b/crates/hir-ty/src/diagnostics/expr.rs
@@ -11,7 +11,6 @@ use hir_def::{ItemContainerId, Lookup};
 use hir_expand::name;
 use itertools::Itertools;
 use rustc_hash::FxHashSet;
-use rustc_pattern_analysis::usefulness::{compute_match_usefulness, PlaceValidity};
 use syntax::{ast, AstNode};
 use tracing::debug;
 use triomphe::Arc;
@@ -234,13 +233,7 @@ impl ExprValidator {
             return;
         }
 
-        let report = match compute_match_usefulness(
-            &cx,
-            m_arms.as_slice(),
-            scrut_ty.clone(),
-            PlaceValidity::ValidOnly,
-            None,
-        ) {
+        let report = match cx.compute_match_usefulness(m_arms.as_slice(), scrut_ty.clone()) {
             Ok(report) => report,
             Err(()) => return,
         };
@@ -282,13 +275,7 @@ impl ExprValidator {
                 continue;
             }
 
-            let report = match compute_match_usefulness(
-                &cx,
-                &[match_arm],
-                ty.clone(),
-                PlaceValidity::ValidOnly,
-                None,
-            ) {
+            let report = match cx.compute_match_usefulness(&[match_arm], ty.clone()) {
                 Ok(v) => v,
                 Err(e) => {
                     debug!(?e, "match usefulness error");
diff --git a/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs b/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
index 81ce51429c..f45beb4c92 100644
--- a/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
+++ b/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
@@ -8,6 +8,7 @@ use rustc_hash::FxHashMap;
 use rustc_pattern_analysis::{
     constructor::{Constructor, ConstructorSet, VariantVisibility},
     index::IdxContainer,
+    usefulness::{compute_match_usefulness, PlaceValidity, UsefulnessReport},
     Captures, PatCx, PrivateUninhabitedField,
 };
 use smallvec::{smallvec, SmallVec};
@@ -59,6 +60,18 @@ impl<'p> MatchCheckCtx<'p> {
         Self { module, body, db, exhaustive_patterns, min_exhaustive_patterns }
     }
 
+    pub(crate) fn compute_match_usefulness(
+        &self,
+        arms: &[MatchArm<'p>],
+        scrut_ty: Ty,
+    ) -> Result<UsefulnessReport<'p, Self>, ()> {
+        // FIXME: Determine place validity correctly. For now, err on the safe side.
+        let place_validity = PlaceValidity::MaybeInvalid;
+        // Measured to take ~100ms on modern hardware.
+        let complexity_limit = Some(500000);
+        compute_match_usefulness(self, arms, scrut_ty, place_validity, complexity_limit)
+    }
+
     fn is_uninhabited(&self, ty: &Ty) -> bool {
         is_ty_uninhabited_from(ty, self.module, self.db)
     }
@@ -465,7 +478,6 @@ impl<'p> PatCx for MatchCheckCtx<'p> {
     }
 
     fn complexity_exceeded(&self) -> Result<(), Self::Error> {
-        // FIXME(Nadrieril): make use of the complexity counter.
         Err(())
     }
 }
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 9d7be9a421..4f9697f7fe 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -3628,41 +3628,16 @@ impl Impl {
                     .filter(filter),
             );
         }
-
-        if let Some(block) =
-            ty.adt_id(Interner).and_then(|def| def.0.module(db.upcast()).containing_block())
-        {
-            if let Some(inherent_impls) = db.inherent_impls_in_block(block) {
-                all.extend(
-                    inherent_impls.for_self_ty(&ty).iter().cloned().map(Self::from).filter(filter),
-                );
-            }
-            if let Some(trait_impls) = db.trait_impls_in_block(block) {
-                all.extend(
-                    trait_impls
-                        .for_self_ty_without_blanket_impls(fp)
-                        .map(Self::from)
-                        .filter(filter),
-                );
-            }
-        }
-
         all
     }
 
     pub fn all_for_trait(db: &dyn HirDatabase, trait_: Trait) -> Vec<Impl> {
-        let module = trait_.module(db);
-        let krate = module.krate();
+        let krate = trait_.module(db).krate();
         let mut all = Vec::new();
         for Crate { id } in krate.transitive_reverse_dependencies(db) {
             let impls = db.trait_impls_in_crate(id);
             all.extend(impls.for_trait(trait_.id).map(Self::from))
         }
-        if let Some(block) = module.id.containing_block() {
-            if let Some(trait_impls) = db.trait_impls_in_block(block) {
-                all.extend(trait_impls.for_trait(trait_.id).map(Self::from));
-            }
-        }
         all
     }
 
diff --git a/crates/ide-diagnostics/src/handlers/missing_match_arms.rs b/crates/ide-diagnostics/src/handlers/missing_match_arms.rs
index 67daa172b2..045154614f 100644
--- a/crates/ide-diagnostics/src/handlers/missing_match_arms.rs
+++ b/crates/ide-diagnostics/src/handlers/missing_match_arms.rs
@@ -23,6 +23,7 @@ mod tests {
         },
         DiagnosticsConfig,
     };
+    use test_utils::skip_slow_tests;
 
     #[track_caller]
     fn check_diagnostics_no_bails(ra_fixture: &str) {
@@ -1004,6 +1005,32 @@ fn f() {
         );
     }
 
+    #[test]
+    fn exponential_match() {
+        if skip_slow_tests() {
+            return;
+        }
+        // Constructs a match where match checking takes exponential time. Ensures we bail early.
+        use std::fmt::Write;
+        let struct_arity = 50;
+        let mut code = String::new();
+        write!(code, "struct BigStruct {{").unwrap();
+        for i in 0..struct_arity {
+            write!(code, "  field{i}: bool,").unwrap();
+        }
+        write!(code, "}}").unwrap();
+        write!(code, "fn big_match(s: BigStruct) {{").unwrap();
+        write!(code, "  match s {{").unwrap();
+        for i in 0..struct_arity {
+            write!(code, "    BigStruct {{ field{i}: true, ..}} => {{}},").unwrap();
+            write!(code, "    BigStruct {{ field{i}: false, ..}} => {{}},").unwrap();
+        }
+        write!(code, "    _ => {{}},").unwrap();
+        write!(code, "  }}").unwrap();
+        write!(code, "}}").unwrap();
+        check_diagnostics_no_bails(&code);
+    }
+
     mod rust_unstable {
         use super::*;
 
diff --git a/crates/ide-diagnostics/src/handlers/mutability_errors.rs b/crates/ide-diagnostics/src/handlers/mutability_errors.rs
index 00352266dd..6602aca2fa 100644
--- a/crates/ide-diagnostics/src/handlers/mutability_errors.rs
+++ b/crates/ide-diagnostics/src/handlers/mutability_errors.rs
@@ -51,12 +51,8 @@ pub(crate) fn need_mut(ctx: &DiagnosticsContext<'_>, d: &hir::NeedMut) -> Option
 // Diagnostic: unused-mut
 //
 // This diagnostic is triggered when a mutable variable isn't actually mutated.
-pub(crate) fn unused_mut(ctx: &DiagnosticsContext<'_>, d: &hir::UnusedMut) -> Option<Diagnostic> {
+pub(crate) fn unused_mut(ctx: &DiagnosticsContext<'_>, d: &hir::UnusedMut) -> Diagnostic {
     let ast = d.local.primary_source(ctx.sema.db).syntax_ptr();
-    if ast.file_id.macro_file().is_some() {
-        // FIXME: Our infra can't handle allow from within macro expansions rn
-        return None;
-    }
     let fixes = (|| {
         let file_id = ast.file_id.file_id()?;
         let mut edit_builder = TextEdit::builder();
@@ -80,16 +76,14 @@ pub(crate) fn unused_mut(ctx: &DiagnosticsContext<'_>, d: &hir::UnusedMut) -> Op
         )])
     })();
     let ast = d.local.primary_source(ctx.sema.db).syntax_ptr();
-    Some(
-        Diagnostic::new_with_syntax_node_ptr(
-            ctx,
-            DiagnosticCode::RustcLint("unused_mut"),
-            "variable does not need to be mutable",
-            ast,
-        )
-        .experimental() // Not supporting `#[allow(unused_mut)]` in proc macros leads to false positive.
-        .with_fixes(fixes),
+    Diagnostic::new_with_syntax_node_ptr(
+        ctx,
+        DiagnosticCode::RustcLint("unused_mut"),
+        "variable does not need to be mutable",
+        ast,
     )
+    .experimental() // Not supporting `#[allow(unused_mut)]` in proc macros leads to false positive.
+    .with_fixes(fixes)
 }
 
 pub(super) fn token(parent: &SyntaxNode, kind: SyntaxKind) -> Option<SyntaxToken> {
diff --git a/crates/ide-diagnostics/src/lib.rs b/crates/ide-diagnostics/src/lib.rs
index 270cf844c6..dea802204a 100644
--- a/crates/ide-diagnostics/src/lib.rs
+++ b/crates/ide-diagnostics/src/lib.rs
@@ -387,10 +387,7 @@ pub fn diagnostics(
             AnyDiagnostic::UnresolvedMethodCall(d) => handlers::unresolved_method::unresolved_method(&ctx, &d),
             AnyDiagnostic::UnresolvedModule(d) => handlers::unresolved_module::unresolved_module(&ctx, &d),
             AnyDiagnostic::UnresolvedProcMacro(d) => handlers::unresolved_proc_macro::unresolved_proc_macro(&ctx, &d, config.proc_macros_enabled, config.proc_attr_macros_enabled),
-            AnyDiagnostic::UnusedMut(d) => match handlers::mutability_errors::unused_mut(&ctx, &d) {
-                Some(it) => it,
-                None => continue,
-            },
+            AnyDiagnostic::UnusedMut(d) => handlers::mutability_errors::unused_mut(&ctx, &d),
             AnyDiagnostic::UnusedVariable(d) => match handlers::unused_variables::unused_variables(&ctx, &d) {
                 Some(it) => it,
                 None => continue,
diff --git a/crates/ide/src/goto_implementation.rs b/crates/ide/src/goto_implementation.rs
index 76e5e9dd92..8a12cbaccc 100644
--- a/crates/ide/src/goto_implementation.rs
+++ b/crates/ide/src/goto_implementation.rs
@@ -337,77 +337,6 @@ impl Tr for S {
     const C: usize = 4;
         //^
 }
-"#,
-        );
-    }
-
-    #[test]
-    fn goto_adt_implementation_inside_block() {
-        check(
-            r#"
-//- minicore: copy, derive
-trait Bar {}
-
-fn test() {
-    #[derive(Copy)]
-  //^^^^^^^^^^^^^^^
-    struct Foo$0;
-
-    impl Foo {}
-       //^^^
-
-    trait Baz {}
-
-    impl Bar for Foo {}
-               //^^^
-
-    impl Baz for Foo {}
-               //^^^
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn goto_trait_implementation_inside_block() {
-        check(
-            r#"
-struct Bar;
-
-fn test() {
-    trait Foo$0 {}
-
-    struct Baz;
-
-    impl Foo for Bar {}
-               //^^^
-
-    impl Foo for Baz {}
-               //^^^
-}
-"#,
-        );
-        check(
-            r#"
-struct Bar;
-
-fn test() {
-    trait Foo {
-        fn foo$0() {}
-    }
-
-    struct Baz;
-
-    impl Foo for Bar {
-        fn foo() {}
-         //^^^
-    }
-
-    impl Foo for Baz {
-        fn foo() {}
-         //^^^
-    }
-}
 "#,
         );
     }
diff --git a/crates/parser/src/grammar/expressions/atom.rs b/crates/parser/src/grammar/expressions/atom.rs
index 54ed5f0ba2..72848a1f2b 100644
--- a/crates/parser/src/grammar/expressions/atom.rs
+++ b/crates/parser/src/grammar/expressions/atom.rs
@@ -490,18 +490,6 @@ fn match_expr(p: &mut Parser<'_>) -> CompletedMarker {
     m.complete(p, MATCH_EXPR)
 }
 
-// test_err match_arms_recovery
-// fn foo() {
-//     match () {
-//         _ => (),,
-//         _ => ,
-//         _ => (),
-//          => (),
-//         if true => (),
-//         _ => (),
-//         () if => (),
-//     }
-// }
 pub(crate) fn match_arm_list(p: &mut Parser<'_>) {
     assert!(p.at(T!['{']));
     let m = p.start();
@@ -523,10 +511,6 @@ pub(crate) fn match_arm_list(p: &mut Parser<'_>) {
             error_block(p, "expected match arm");
             continue;
         }
-        if p.at(T![,]) {
-            p.err_and_bump("expected pattern");
-            continue;
-        }
         match_arm(p);
     }
     p.expect(T!['}']);
@@ -560,30 +544,26 @@ fn match_arm(p: &mut Parser<'_>) {
     // }
     attributes::outer_attrs(p);
 
-    patterns::pattern_top_r(p, TokenSet::new(&[T![=], T![if]]));
+    patterns::pattern_top_r(p, TokenSet::EMPTY);
     if p.at(T![if]) {
         match_guard(p);
     }
     p.expect(T![=>]);
-    if p.eat(T![,]) {
-        p.error("expected expression");
-    } else {
-        let blocklike = match expr_stmt(p, None) {
-            Some((_, blocklike)) => blocklike,
-            None => BlockLike::NotBlock,
-        };
-
-        // test match_arms_commas
-        // fn foo() {
-        //     match () {
-        //         _ => (),
-        //         _ => {}
-        //         _ => ()
-        //     }
-        // }
-        if !p.eat(T![,]) && !blocklike.is_block() && !p.at(T!['}']) {
-            p.error("expected `,`");
-        }
+    let blocklike = match expr_stmt(p, None) {
+        Some((_, blocklike)) => blocklike,
+        None => BlockLike::NotBlock,
+    };
+
+    // test match_arms_commas
+    // fn foo() {
+    //     match () {
+    //         _ => (),
+    //         _ => {}
+    //         _ => ()
+    //     }
+    // }
+    if !p.eat(T![,]) && !blocklike.is_block() && !p.at(T!['}']) {
+        p.error("expected `,`");
     }
     m.complete(p, MATCH_ARM);
 }
@@ -599,11 +579,7 @@ fn match_guard(p: &mut Parser<'_>) -> CompletedMarker {
     assert!(p.at(T![if]));
     let m = p.start();
     p.bump(T![if]);
-    if p.at(T![=]) {
-        p.error("expected expression");
-    } else {
-        expr(p);
-    }
+    expr(p);
     m.complete(p, MATCH_GUARD)
 }
 
diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs
index 8b4d6d9941..1a138b17ba 100644
--- a/crates/project-model/src/workspace.rs
+++ b/crates/project-model/src/workspace.rs
@@ -1077,8 +1077,6 @@ fn cargo_to_crate_graph(
         }
     }
 
-    let mut delayed_dev_deps = vec![];
-
     // Now add a dep edge from all targets of upstream to the lib
     // target of downstream.
     for pkg in cargo.packages() {
@@ -1093,31 +1091,11 @@ fn cargo_to_crate_graph(
                     continue;
                 }
 
-                // If the dependency is a dev-dependency with both crates being member libraries of
-                // the workspace we delay adding the edge. The reason can be read up on in
-                // https://github.com/rust-lang/rust-analyzer/issues/14167
-                // but in short, such an edge is able to cause some form of cycle in the crate graph
-                // for normal dependencies. If we do run into a cycle like this, we want to prefer
-                // the non dev-dependency edge, and so the easiest way to do that is by adding the
-                // dev-dependency edges last.
-                if dep.kind == DepKind::Dev
-                    && matches!(kind, TargetKind::Lib { .. })
-                    && cargo[dep.pkg].is_member
-                    && cargo[pkg].is_member
-                {
-                    delayed_dev_deps.push((from, name.clone(), to));
-                    continue;
-                }
-
                 add_dep(crate_graph, from, name.clone(), to)
             }
         }
     }
 
-    for (from, name, to) in delayed_dev_deps {
-        add_dep(crate_graph, from, name, to);
-    }
-
     if has_private {
         // If the user provided a path to rustc sources, we add all the rustc_private crates
         // and create dependencies on them for the crates which opt-in to that
diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs
index ab7f944328..d9e7c72dd3 100644
--- a/crates/rust-analyzer/src/handlers/request.rs
+++ b/crates/rust-analyzer/src/handlers/request.rs
@@ -248,7 +248,7 @@ pub(crate) fn handle_discover_test(
     Ok(lsp_ext::DiscoverTestResults {
         tests: tests
             .into_iter()
-            .filter_map(|t| {
+            .map(|t| {
                 let line_index = t.file.and_then(|f| snap.file_line_index(f).ok());
                 to_proto::test_item(&snap, t, line_index.as_ref())
             })
diff --git a/crates/rust-analyzer/src/lsp/to_proto.rs b/crates/rust-analyzer/src/lsp/to_proto.rs
index 44f0b1c80f..f840ca8f61 100644
--- a/crates/rust-analyzer/src/lsp/to_proto.rs
+++ b/crates/rust-analyzer/src/lsp/to_proto.rs
@@ -1516,8 +1516,8 @@ pub(crate) fn test_item(
     snap: &GlobalStateSnapshot,
     test_item: ide::TestItem,
     line_index: Option<&LineIndex>,
-) -> Option<lsp_ext::TestItem> {
-    Some(lsp_ext::TestItem {
+) -> lsp_ext::TestItem {
+    lsp_ext::TestItem {
         id: test_item.id,
         label: test_item.label,
         kind: match test_item.kind {
@@ -1532,9 +1532,9 @@ pub(crate) fn test_item(
                     | project_model::TargetKind::Example
                     | project_model::TargetKind::BuildScript
                     | project_model::TargetKind::Other => lsp_ext::TestItemKind::Package,
-                    project_model::TargetKind::Test => lsp_ext::TestItemKind::Test,
-                    // benches are not tests needed to be shown in the test explorer
-                    project_model::TargetKind::Bench => return None,
+                    project_model::TargetKind::Test | project_model::TargetKind::Bench => {
+                        lsp_ext::TestItemKind::Test
+                    }
                 }
             }
             ide::TestItemKind::Module => lsp_ext::TestItemKind::Module,
@@ -1550,7 +1550,7 @@ pub(crate) fn test_item(
             .map(|f| lsp_types::TextDocumentIdentifier { uri: url(snap, f) }),
         range: line_index.and_then(|l| Some(range(l, test_item.text_range?))),
         runnable: test_item.runnable.and_then(|r| runnable(snap, r).ok()),
-    })
+    }
 }
 
 pub(crate) mod command {
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index 945d169a69..ffe56e4143 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -552,7 +552,7 @@ impl GlobalState {
                 Task::DiscoverTest(lsp_ext::DiscoverTestResults {
                     tests: tests
                         .into_iter()
-                        .filter_map(|t| {
+                        .map(|t| {
                             let line_index = t.file.and_then(|f| snapshot.file_line_index(f).ok());
                             to_proto::test_item(&snapshot, t, line_index.as_ref())
                         })
@@ -653,7 +653,7 @@ impl GlobalState {
                 };
 
                 if let Some(state) = state {
-                    self.report_progress("Building build-artifacts", state, msg, None, None);
+                    self.report_progress("Building", state, msg, None, None);
                 }
             }
             Task::LoadProcMacros(progress) => {
@@ -669,7 +669,7 @@ impl GlobalState {
                 };
 
                 if let Some(state) = state {
-                    self.report_progress("Loading proc-macros", state, msg, None, None);
+                    self.report_progress("Loading", state, msg, None, None);
                 }
             }
             Task::BuildDepsHaveChanged => self.build_deps_changed = true,
@@ -861,7 +861,7 @@ impl GlobalState {
                 let title = if self.flycheck.len() == 1 {
                     format!("{}", self.config.flycheck())
                 } else {
-                    format!("{} (#{})", self.config.flycheck(), id + 1)
+                    format!("cargo check (#{})", id + 1)
                 };
                 self.report_progress(
                     &title,
diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs
index ff7958feae..c2725e1fad 100644
--- a/crates/rust-analyzer/src/reload.rs
+++ b/crates/rust-analyzer/src/reload.rs
@@ -526,13 +526,6 @@ impl GlobalState {
         // crate graph construction relies on these paths, record them so when one of them gets
         // deleted or created we trigger a reconstruction of the crate graph
         let mut crate_graph_file_dependencies = FxHashSet::default();
-        self.report_progress(
-            "Building CrateGraph",
-            crate::lsp::utils::Progress::Begin,
-            None,
-            None,
-            None,
-        );
 
         let (crate_graph, proc_macro_paths, layouts, toolchains) = {
             // Create crate graph from all the workspaces
@@ -571,13 +564,6 @@ impl GlobalState {
         change.set_toolchains(toolchains);
         self.analysis_host.apply_change(change);
         self.crate_graph_file_dependencies = crate_graph_file_dependencies;
-        self.report_progress(
-            "Building CrateGraph",
-            crate::lsp::utils::Progress::End,
-            None,
-            None,
-            None,
-        );
 
         self.process_changes();
         self.reload_flycheck();
diff --git a/crates/syntax/Cargo.toml b/crates/syntax/Cargo.toml
index 1809ca7dea..9a8d73cf7f 100644
--- a/crates/syntax/Cargo.toml
+++ b/crates/syntax/Cargo.toml
@@ -33,8 +33,12 @@ text-edit.workspace = true
 [dev-dependencies]
 rayon.workspace = true
 expect-test = "1.4.0"
+proc-macro2 = "1.0.47"
+quote = "1.0.20"
+ungrammar = "1.16.1"
 
 test-utils.workspace = true
+sourcegen.workspace = true
 
 [features]
 in-rust-tree = []
diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs
index c82bc4151a..e880165366 100644
--- a/crates/syntax/src/ast/generated/nodes.rs
+++ b/crates/syntax/src/ast/generated/nodes.rs
@@ -44,10 +44,10 @@ pub struct ArrayType {
 }
 impl ArrayType {
     pub fn const_arg(&self) -> Option<ConstArg> { support::child(&self.syntax) }
-    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
     pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
     pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
     pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -56,12 +56,12 @@ pub struct AsmExpr {
 }
 impl ast::HasAttrs for AsmExpr {}
 impl AsmExpr {
+    pub fn asm_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![asm]) }
+    pub fn builtin_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![builtin]) }
     pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
-    pub fn pound_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![#]) }
     pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+    pub fn pound_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![#]) }
     pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
-    pub fn asm_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![asm]) }
-    pub fn builtin_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![builtin]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -82,12 +82,12 @@ pub struct AssocTypeArg {
 impl ast::HasTypeBounds for AssocTypeArg {}
 impl AssocTypeArg {
     pub fn const_arg(&self) -> Option<ConstArg> { support::child(&self.syntax) }
+    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
     pub fn generic_arg_list(&self) -> Option<GenericArgList> { support::child(&self.syntax) }
     pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
     pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) }
     pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) }
     pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
-    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -95,10 +95,10 @@ pub struct Attr {
     pub(crate) syntax: SyntaxNode,
 }
 impl Attr {
-    pub fn meta(&self) -> Option<Meta> { support::child(&self.syntax) }
     pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) }
-    pub fn pound_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![#]) }
     pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
+    pub fn meta(&self) -> Option<Meta> { support::child(&self.syntax) }
+    pub fn pound_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![#]) }
     pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
 }
 
@@ -108,9 +108,9 @@ pub struct AwaitExpr {
 }
 impl ast::HasAttrs for AwaitExpr {}
 impl AwaitExpr {
-    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
-    pub fn dot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![.]) }
     pub fn await_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![await]) }
+    pub fn dot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![.]) }
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -119,8 +119,8 @@ pub struct BecomeExpr {
 }
 impl ast::HasAttrs for BecomeExpr {}
 impl BecomeExpr {
-    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
     pub fn become_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![become]) }
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -136,10 +136,10 @@ pub struct BlockExpr {
 }
 impl ast::HasAttrs for BlockExpr {}
 impl BlockExpr {
-    pub fn label(&self) -> Option<Label> { support::child(&self.syntax) }
-    pub fn stmt_list(&self) -> Option<StmtList> { support::child(&self.syntax) }
     pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) }
     pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
+    pub fn label(&self) -> Option<Label> { support::child(&self.syntax) }
+    pub fn stmt_list(&self) -> Option<StmtList> { support::child(&self.syntax) }
     pub fn try_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![try]) }
     pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
 }
@@ -149,8 +149,8 @@ pub struct BoxPat {
     pub(crate) syntax: SyntaxNode,
 }
 impl BoxPat {
-    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
     pub fn box_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![box]) }
+    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -159,9 +159,9 @@ pub struct BreakExpr {
 }
 impl ast::HasAttrs for BreakExpr {}
 impl BreakExpr {
+    pub fn break_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![break]) }
     pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
     pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
-    pub fn break_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![break]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -180,9 +180,9 @@ pub struct CastExpr {
 }
 impl ast::HasAttrs for CastExpr {}
 impl CastExpr {
+    pub fn as_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![as]) }
     pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
     pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
-    pub fn as_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![as]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -191,14 +191,14 @@ pub struct ClosureExpr {
 }
 impl ast::HasAttrs for ClosureExpr {}
 impl ClosureExpr {
-    pub fn body(&self) -> Option<Expr> { support::child(&self.syntax) }
-    pub fn generic_param_list(&self) -> Option<GenericParamList> { support::child(&self.syntax) }
-    pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) }
-    pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) }
     pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) }
+    pub fn body(&self) -> Option<Expr> { support::child(&self.syntax) }
     pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
     pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
+    pub fn generic_param_list(&self) -> Option<GenericParamList> { support::child(&self.syntax) }
     pub fn move_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![move]) }
+    pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) }
+    pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) }
     pub fn static_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![static]) }
 }
 
@@ -212,13 +212,13 @@ impl ast::HasName for Const {}
 impl ast::HasVisibility for Const {}
 impl Const {
     pub fn body(&self) -> Option<Expr> { support::child(&self.syntax) }
-    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
     pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
-    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
-    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
-    pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) }
     pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
     pub fn default_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![default]) }
+    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
+    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+    pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -245,11 +245,11 @@ pub struct ConstParam {
 impl ast::HasAttrs for ConstParam {}
 impl ast::HasName for ConstParam {}
 impl ConstParam {
-    pub fn default_val(&self) -> Option<ConstArg> { support::child(&self.syntax) }
-    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
     pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
-    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
     pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
+    pub fn default_val(&self) -> Option<ConstArg> { support::child(&self.syntax) }
+    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -258,10 +258,10 @@ pub struct ContinueExpr {
 }
 impl ast::HasAttrs for ContinueExpr {}
 impl ContinueExpr {
-    pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
     pub fn continue_token(&self) -> Option<SyntaxToken> {
         support::token(&self.syntax, T![continue])
     }
+    pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -269,8 +269,8 @@ pub struct DynTraitType {
     pub(crate) syntax: SyntaxNode,
 }
 impl DynTraitType {
-    pub fn type_bound_list(&self) -> Option<TypeBoundList> { support::child(&self.syntax) }
     pub fn dyn_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![dyn]) }
+    pub fn type_bound_list(&self) -> Option<TypeBoundList> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -283,8 +283,8 @@ impl ast::HasGenericParams for Enum {}
 impl ast::HasName for Enum {}
 impl ast::HasVisibility for Enum {}
 impl Enum {
-    pub fn variant_list(&self) -> Option<VariantList> { support::child(&self.syntax) }
     pub fn enum_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![enum]) }
+    pub fn variant_list(&self) -> Option<VariantList> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -316,11 +316,11 @@ impl ast::HasAttrs for ExternCrate {}
 impl ast::HasDocComments for ExternCrate {}
 impl ast::HasVisibility for ExternCrate {}
 impl ExternCrate {
+    pub fn crate_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![crate]) }
+    pub fn extern_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![extern]) }
     pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
     pub fn rename(&self) -> Option<Rename> { support::child(&self.syntax) }
     pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
-    pub fn crate_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![crate]) }
-    pub fn extern_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![extern]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -340,9 +340,9 @@ pub struct FieldExpr {
 }
 impl ast::HasAttrs for FieldExpr {}
 impl FieldExpr {
+    pub fn dot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![.]) }
     pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
     pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
-    pub fn dot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![.]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -356,14 +356,14 @@ impl ast::HasName for Fn {}
 impl ast::HasVisibility for Fn {}
 impl Fn {
     pub fn abi(&self) -> Option<Abi> { support::child(&self.syntax) }
-    pub fn body(&self) -> Option<BlockExpr> { support::child(&self.syntax) }
-    pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) }
-    pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) }
-    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
     pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) }
+    pub fn body(&self) -> Option<BlockExpr> { support::child(&self.syntax) }
     pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
     pub fn default_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![default]) }
     pub fn fn_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![fn]) }
+    pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) }
+    pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) }
+    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
     pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
 }
 
@@ -373,11 +373,11 @@ pub struct FnPtrType {
 }
 impl FnPtrType {
     pub fn abi(&self) -> Option<Abi> { support::child(&self.syntax) }
-    pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) }
-    pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) }
     pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) }
     pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
     pub fn fn_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![fn]) }
+    pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) }
+    pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) }
     pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
 }
 
@@ -387,9 +387,9 @@ pub struct ForExpr {
 }
 impl ast::HasAttrs for ForExpr {}
 impl ForExpr {
-    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
     pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
     pub fn in_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![in]) }
+    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -397,9 +397,9 @@ pub struct ForType {
     pub(crate) syntax: SyntaxNode,
 }
 impl ForType {
+    pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
     pub fn generic_param_list(&self) -> Option<GenericParamList> { support::child(&self.syntax) }
     pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
-    pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -408,8 +408,8 @@ pub struct FormatArgsArg {
 }
 impl ast::HasName for FormatArgsArg {}
 impl FormatArgsArg {
-    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
     pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -419,15 +419,15 @@ pub struct FormatArgsExpr {
 impl ast::HasAttrs for FormatArgsExpr {}
 impl FormatArgsExpr {
     pub fn args(&self) -> AstChildren<FormatArgsArg> { support::children(&self.syntax) }
-    pub fn template(&self) -> Option<Expr> { support::child(&self.syntax) }
-    pub fn pound_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![#]) }
-    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
-    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
-    pub fn comma_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![,]) }
     pub fn builtin_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![builtin]) }
+    pub fn comma_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![,]) }
     pub fn format_args_token(&self) -> Option<SyntaxToken> {
         support::token(&self.syntax, T![format_args])
     }
+    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+    pub fn pound_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![#]) }
+    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+    pub fn template(&self) -> Option<Expr> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -435,8 +435,8 @@ pub struct GenericArgList {
     pub(crate) syntax: SyntaxNode,
 }
 impl GenericArgList {
-    pub fn generic_args(&self) -> AstChildren<GenericArg> { support::children(&self.syntax) }
     pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
+    pub fn generic_args(&self) -> AstChildren<GenericArg> { support::children(&self.syntax) }
     pub fn l_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) }
     pub fn r_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) }
 }
@@ -458,9 +458,9 @@ pub struct IdentPat {
 impl ast::HasAttrs for IdentPat {}
 impl ast::HasName for IdentPat {}
 impl IdentPat {
-    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
     pub fn at_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![@]) }
     pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
+    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
     pub fn ref_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![ref]) }
 }
 
@@ -484,9 +484,9 @@ impl ast::HasGenericParams for Impl {}
 impl ast::HasVisibility for Impl {}
 impl Impl {
     pub fn assoc_item_list(&self) -> Option<AssocItemList> { support::child(&self.syntax) }
-    pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) }
     pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
     pub fn default_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![default]) }
+    pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) }
     pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
     pub fn impl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![impl]) }
     pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
@@ -497,8 +497,8 @@ pub struct ImplTraitType {
     pub(crate) syntax: SyntaxNode,
 }
 impl ImplTraitType {
-    pub fn type_bound_list(&self) -> Option<TypeBoundList> { support::child(&self.syntax) }
     pub fn impl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![impl]) }
+    pub fn type_bound_list(&self) -> Option<TypeBoundList> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -535,8 +535,8 @@ pub struct Label {
     pub(crate) syntax: SyntaxNode,
 }
 impl Label {
-    pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
     pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
+    pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -554,10 +554,10 @@ pub struct LetExpr {
 }
 impl ast::HasAttrs for LetExpr {}
 impl LetExpr {
-    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
-    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
     pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
     pub fn let_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![let]) }
+    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -566,14 +566,14 @@ pub struct LetStmt {
 }
 impl ast::HasAttrs for LetStmt {}
 impl LetStmt {
+    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
+    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
     pub fn initializer(&self) -> Option<Expr> { support::child(&self.syntax) }
     pub fn let_else(&self) -> Option<LetElse> { support::child(&self.syntax) }
+    pub fn let_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![let]) }
     pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
-    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
-    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
     pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
-    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
-    pub fn let_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![let]) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -637,10 +637,10 @@ pub struct MacroCall {
 impl ast::HasAttrs for MacroCall {}
 impl ast::HasDocComments for MacroCall {}
 impl MacroCall {
-    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
-    pub fn token_tree(&self) -> Option<TokenTree> { support::child(&self.syntax) }
     pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) }
+    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
     pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
+    pub fn token_tree(&self) -> Option<TokenTree> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -663,12 +663,12 @@ pub struct MacroEagerInput {
 }
 impl MacroEagerInput {
     pub fn exprs(&self) -> AstChildren<Expr> { support::children(&self.syntax) }
-    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
-    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
     pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
-    pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
     pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
+    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+    pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
     pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
+    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -703,11 +703,11 @@ impl ast::HasDocComments for MacroRules {}
 impl ast::HasName for MacroRules {}
 impl ast::HasVisibility for MacroRules {}
 impl MacroRules {
-    pub fn token_tree(&self) -> Option<TokenTree> { support::child(&self.syntax) }
     pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) }
     pub fn macro_rules_token(&self) -> Option<SyntaxToken> {
         support::token(&self.syntax, T![macro_rules])
     }
+    pub fn token_tree(&self) -> Option<TokenTree> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -733,11 +733,11 @@ pub struct MatchArm {
 }
 impl ast::HasAttrs for MatchArm {}
 impl MatchArm {
+    pub fn comma_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![,]) }
     pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn fat_arrow_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=>]) }
     pub fn guard(&self) -> Option<MatchGuard> { support::child(&self.syntax) }
     pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
-    pub fn comma_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![,]) }
-    pub fn fat_arrow_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=>]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -775,10 +775,10 @@ pub struct Meta {
     pub(crate) syntax: SyntaxNode,
 }
 impl Meta {
+    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
     pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
     pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
     pub fn token_tree(&self) -> Option<TokenTree> { support::child(&self.syntax) }
-    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -788,10 +788,10 @@ pub struct MethodCallExpr {
 impl ast::HasArgList for MethodCallExpr {}
 impl ast::HasAttrs for MethodCallExpr {}
 impl MethodCallExpr {
+    pub fn dot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![.]) }
     pub fn generic_arg_list(&self) -> Option<GenericArgList> { support::child(&self.syntax) }
     pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
     pub fn receiver(&self) -> Option<Expr> { support::child(&self.syntax) }
-    pub fn dot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![.]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -804,8 +804,8 @@ impl ast::HasName for Module {}
 impl ast::HasVisibility for Module {}
 impl Module {
     pub fn item_list(&self) -> Option<ItemList> { support::child(&self.syntax) }
-    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
     pub fn mod_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mod]) }
+    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -843,16 +843,16 @@ pub struct OffsetOfExpr {
 }
 impl ast::HasAttrs for OffsetOfExpr {}
 impl OffsetOfExpr {
+    pub fn builtin_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![builtin]) }
+    pub fn comma_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![,]) }
     pub fn fields(&self) -> AstChildren<NameRef> { support::children(&self.syntax) }
-    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
-    pub fn pound_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![#]) }
     pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
-    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
-    pub fn comma_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![,]) }
-    pub fn builtin_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![builtin]) }
     pub fn offset_of_token(&self) -> Option<SyntaxToken> {
         support::token(&self.syntax, T![offset_of])
     }
+    pub fn pound_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![#]) }
+    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -869,10 +869,10 @@ pub struct Param {
 }
 impl ast::HasAttrs for Param {}
 impl Param {
+    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
+    pub fn dotdotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![...]) }
     pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
     pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
-    pub fn dotdotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![...]) }
-    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -880,12 +880,12 @@ pub struct ParamList {
     pub(crate) syntax: SyntaxNode,
 }
 impl ParamList {
-    pub fn params(&self) -> AstChildren<Param> { support::children(&self.syntax) }
-    pub fn self_param(&self) -> Option<SelfParam> { support::child(&self.syntax) }
-    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
-    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
     pub fn comma_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![,]) }
+    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+    pub fn params(&self) -> AstChildren<Param> { support::children(&self.syntax) }
     pub fn pipe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![|]) }
+    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+    pub fn self_param(&self) -> Option<SelfParam> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -904,8 +904,8 @@ pub struct ParenPat {
     pub(crate) syntax: SyntaxNode,
 }
 impl ParenPat {
-    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
     pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
     pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
 }
 
@@ -914,9 +914,9 @@ pub struct ParenType {
     pub(crate) syntax: SyntaxNode,
 }
 impl ParenType {
-    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
     pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
     pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -924,9 +924,9 @@ pub struct Path {
     pub(crate) syntax: SyntaxNode,
 }
 impl Path {
+    pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
     pub fn qualifier(&self) -> Option<Path> { support::child(&self.syntax) }
     pub fn segment(&self) -> Option<PathSegment> { support::child(&self.syntax) }
-    pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -951,16 +951,16 @@ pub struct PathSegment {
     pub(crate) syntax: SyntaxNode,
 }
 impl PathSegment {
+    pub fn as_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![as]) }
+    pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
     pub fn generic_arg_list(&self) -> Option<GenericArgList> { support::child(&self.syntax) }
+    pub fn l_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) }
     pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
     pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) }
     pub fn path_type(&self) -> Option<PathType> { support::child(&self.syntax) }
+    pub fn r_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) }
     pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) }
     pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
-    pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
-    pub fn l_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) }
-    pub fn r_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) }
-    pub fn as_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![as]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -985,10 +985,10 @@ pub struct PtrType {
     pub(crate) syntax: SyntaxNode,
 }
 impl PtrType {
-    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
-    pub fn star_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![*]) }
     pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
     pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
+    pub fn star_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![*]) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -1021,9 +1021,9 @@ pub struct RecordExprField {
 }
 impl ast::HasAttrs for RecordExprField {}
 impl RecordExprField {
+    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
     pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
     pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
-    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -1032,11 +1032,11 @@ pub struct RecordExprFieldList {
 }
 impl ast::HasAttrs for RecordExprFieldList {}
 impl RecordExprFieldList {
+    pub fn dotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![..]) }
     pub fn fields(&self) -> AstChildren<RecordExprField> { support::children(&self.syntax) }
-    pub fn spread(&self) -> Option<Expr> { support::child(&self.syntax) }
     pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
     pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
-    pub fn dotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![..]) }
+    pub fn spread(&self) -> Option<Expr> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -1048,8 +1048,8 @@ impl ast::HasDocComments for RecordField {}
 impl ast::HasName for RecordField {}
 impl ast::HasVisibility for RecordField {}
 impl RecordField {
-    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
     pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -1079,9 +1079,9 @@ pub struct RecordPatField {
 }
 impl ast::HasAttrs for RecordPatField {}
 impl RecordPatField {
+    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
     pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
     pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
-    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -1090,9 +1090,9 @@ pub struct RecordPatFieldList {
 }
 impl RecordPatFieldList {
     pub fn fields(&self) -> AstChildren<RecordPatField> { support::children(&self.syntax) }
-    pub fn rest_pat(&self) -> Option<RestPat> { support::child(&self.syntax) }
     pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
     pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
+    pub fn rest_pat(&self) -> Option<RestPat> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -1101,9 +1101,9 @@ pub struct RefExpr {
 }
 impl ast::HasAttrs for RefExpr {}
 impl RefExpr {
-    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
     pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) }
     pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
     pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
     pub fn raw_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![raw]) }
 }
@@ -1113,9 +1113,9 @@ pub struct RefPat {
     pub(crate) syntax: SyntaxNode,
 }
 impl RefPat {
-    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
     pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) }
     pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
+    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -1123,10 +1123,10 @@ pub struct RefType {
     pub(crate) syntax: SyntaxNode,
 }
 impl RefType {
-    pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
-    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
     pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) }
+    pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
     pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -1135,8 +1135,8 @@ pub struct Rename {
 }
 impl ast::HasName for Rename {}
 impl Rename {
-    pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) }
     pub fn as_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![as]) }
+    pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -1153,8 +1153,8 @@ pub struct RetType {
     pub(crate) syntax: SyntaxNode,
 }
 impl RetType {
-    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
     pub fn thin_arrow_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![->]) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -1174,11 +1174,11 @@ pub struct SelfParam {
 impl ast::HasAttrs for SelfParam {}
 impl ast::HasName for SelfParam {}
 impl SelfParam {
-    pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
-    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
     pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) }
     pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
+    pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
     pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -1186,8 +1186,8 @@ pub struct SlicePat {
     pub(crate) syntax: SyntaxNode,
 }
 impl SlicePat {
-    pub fn pats(&self) -> AstChildren<Pat> { support::children(&self.syntax) }
     pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
+    pub fn pats(&self) -> AstChildren<Pat> { support::children(&self.syntax) }
     pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
 }
 
@@ -1196,9 +1196,9 @@ pub struct SliceType {
     pub(crate) syntax: SyntaxNode,
 }
 impl SliceType {
-    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
     pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
     pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -1222,12 +1222,12 @@ impl ast::HasName for Static {}
 impl ast::HasVisibility for Static {}
 impl Static {
     pub fn body(&self) -> Option<Expr> { support::child(&self.syntax) }
-    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
     pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
-    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
     pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
     pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
+    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
     pub fn static_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![static]) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -1236,10 +1236,10 @@ pub struct StmtList {
 }
 impl ast::HasAttrs for StmtList {}
 impl StmtList {
-    pub fn statements(&self) -> AstChildren<Stmt> { support::children(&self.syntax) }
-    pub fn tail_expr(&self) -> Option<Expr> { support::child(&self.syntax) }
     pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
     pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
+    pub fn statements(&self) -> AstChildren<Stmt> { support::children(&self.syntax) }
+    pub fn tail_expr(&self) -> Option<Expr> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -1262,12 +1262,12 @@ pub struct TokenTree {
     pub(crate) syntax: SyntaxNode,
 }
 impl TokenTree {
-    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
-    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
     pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
-    pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
     pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
+    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+    pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
     pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
+    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -1297,10 +1297,10 @@ impl ast::HasGenericParams for TraitAlias {}
 impl ast::HasName for TraitAlias {}
 impl ast::HasVisibility for TraitAlias {}
 impl TraitAlias {
-    pub fn type_bound_list(&self) -> Option<TypeBoundList> { support::child(&self.syntax) }
-    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
     pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
+    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
     pub fn trait_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![trait]) }
+    pub fn type_bound_list(&self) -> Option<TypeBoundList> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -1361,8 +1361,8 @@ pub struct TupleStructPat {
 }
 impl TupleStructPat {
     pub fn fields(&self) -> AstChildren<Pat> { support::children(&self.syntax) }
-    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
     pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
     pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
 }
 
@@ -1387,10 +1387,10 @@ impl ast::HasName for TypeAlias {}
 impl ast::HasTypeBounds for TypeAlias {}
 impl ast::HasVisibility for TypeAlias {}
 impl TypeAlias {
-    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
-    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
-    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
     pub fn default_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![default]) }
+    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
+    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
     pub fn type_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![type]) }
 }
 
@@ -1407,12 +1407,12 @@ pub struct TypeBound {
     pub(crate) syntax: SyntaxNode,
 }
 impl TypeBound {
-    pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
-    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
-    pub fn question_mark_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![?]) }
     pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) }
     pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
+    pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
+    pub fn question_mark_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![?]) }
     pub fn tilde_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![~]) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -1466,9 +1466,9 @@ impl ast::HasAttrs for Use {}
 impl ast::HasDocComments for Use {}
 impl ast::HasVisibility for Use {}
 impl Use {
-    pub fn use_tree(&self) -> Option<UseTree> { support::child(&self.syntax) }
     pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
     pub fn use_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![use]) }
+    pub fn use_tree(&self) -> Option<UseTree> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -1476,11 +1476,11 @@ pub struct UseTree {
     pub(crate) syntax: SyntaxNode,
 }
 impl UseTree {
+    pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
     pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
     pub fn rename(&self) -> Option<Rename> { support::child(&self.syntax) }
-    pub fn use_tree_list(&self) -> Option<UseTreeList> { support::child(&self.syntax) }
     pub fn star_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![*]) }
-    pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
+    pub fn use_tree_list(&self) -> Option<UseTreeList> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -1488,9 +1488,9 @@ pub struct UseTreeList {
     pub(crate) syntax: SyntaxNode,
 }
 impl UseTreeList {
-    pub fn use_trees(&self) -> AstChildren<UseTree> { support::children(&self.syntax) }
     pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
     pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
+    pub fn use_trees(&self) -> AstChildren<UseTree> { support::children(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -1502,9 +1502,9 @@ impl ast::HasDocComments for Variant {}
 impl ast::HasName for Variant {}
 impl ast::HasVisibility for Variant {}
 impl Variant {
+    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
     pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
     pub fn field_list(&self) -> Option<FieldList> { support::child(&self.syntax) }
-    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -1512,9 +1512,9 @@ pub struct VariantList {
     pub(crate) syntax: SyntaxNode,
 }
 impl VariantList {
-    pub fn variants(&self) -> AstChildren<Variant> { support::children(&self.syntax) }
     pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
     pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
+    pub fn variants(&self) -> AstChildren<Variant> { support::children(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -1522,11 +1522,11 @@ pub struct Visibility {
     pub(crate) syntax: SyntaxNode,
 }
 impl Visibility {
-    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
-    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
-    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
     pub fn in_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![in]) }
+    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
     pub fn pub_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![pub]) }
+    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -1544,10 +1544,10 @@ pub struct WherePred {
 }
 impl ast::HasTypeBounds for WherePred {}
 impl WherePred {
+    pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
     pub fn generic_param_list(&self) -> Option<GenericParamList> { support::child(&self.syntax) }
     pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
     pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
-    pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -1573,8 +1573,8 @@ pub struct YeetExpr {
 }
 impl ast::HasAttrs for YeetExpr {}
 impl YeetExpr {
-    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
     pub fn do_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![do]) }
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
     pub fn yeet_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![yeet]) }
 }
 
@@ -4123,78 +4123,78 @@ impl AstNode for AnyHasAttrs {
     fn can_cast(kind: SyntaxKind) -> bool {
         matches!(
             kind,
-            ARRAY_EXPR
-                | ASM_EXPR
+            MACRO_CALL
+                | SOURCE_FILE
+                | CONST
+                | ENUM
+                | EXTERN_BLOCK
+                | EXTERN_CRATE
+                | FN
+                | IMPL
+                | MACRO_RULES
+                | MACRO_DEF
+                | MODULE
+                | STATIC
+                | STRUCT
+                | TRAIT
+                | TRAIT_ALIAS
+                | TYPE_ALIAS
+                | UNION
+                | USE
+                | ITEM_LIST
+                | BLOCK_EXPR
+                | SELF_PARAM
+                | PARAM
+                | RECORD_FIELD
+                | TUPLE_FIELD
+                | VARIANT
                 | ASSOC_ITEM_LIST
+                | EXTERN_ITEM_LIST
+                | CONST_PARAM
+                | LIFETIME_PARAM
+                | TYPE_PARAM
+                | LET_STMT
+                | ARRAY_EXPR
+                | ASM_EXPR
                 | AWAIT_EXPR
-                | BECOME_EXPR
                 | BIN_EXPR
-                | BLOCK_EXPR
                 | BREAK_EXPR
                 | CALL_EXPR
                 | CAST_EXPR
                 | CLOSURE_EXPR
-                | CONST
-                | CONST_PARAM
                 | CONTINUE_EXPR
-                | ENUM
-                | EXTERN_BLOCK
-                | EXTERN_CRATE
-                | EXTERN_ITEM_LIST
                 | FIELD_EXPR
-                | FN
                 | FOR_EXPR
                 | FORMAT_ARGS_EXPR
-                | IDENT_PAT
                 | IF_EXPR
-                | IMPL
                 | INDEX_EXPR
-                | ITEM_LIST
-                | LET_EXPR
-                | LET_STMT
-                | LIFETIME_PARAM
                 | LITERAL
                 | LOOP_EXPR
-                | MACRO_CALL
-                | MACRO_DEF
-                | MACRO_RULES
-                | MATCH_ARM
-                | MATCH_ARM_LIST
                 | MATCH_EXPR
                 | METHOD_CALL_EXPR
-                | MODULE
                 | OFFSET_OF_EXPR
-                | PARAM
                 | PAREN_EXPR
                 | PATH_EXPR
                 | PREFIX_EXPR
                 | RANGE_EXPR
-                | RECORD_EXPR_FIELD
-                | RECORD_EXPR_FIELD_LIST
-                | RECORD_FIELD
-                | RECORD_PAT_FIELD
                 | REF_EXPR
-                | REST_PAT
                 | RETURN_EXPR
-                | SELF_PARAM
-                | SOURCE_FILE
-                | STATIC
-                | STMT_LIST
-                | STRUCT
-                | TRAIT
-                | TRAIT_ALIAS
+                | BECOME_EXPR
                 | TRY_EXPR
                 | TUPLE_EXPR
-                | TUPLE_FIELD
-                | TYPE_ALIAS
-                | TYPE_PARAM
-                | UNDERSCORE_EXPR
-                | UNION
-                | USE
-                | VARIANT
                 | WHILE_EXPR
-                | YEET_EXPR
                 | YIELD_EXPR
+                | YEET_EXPR
+                | LET_EXPR
+                | UNDERSCORE_EXPR
+                | STMT_LIST
+                | RECORD_EXPR_FIELD_LIST
+                | RECORD_EXPR_FIELD
+                | MATCH_ARM_LIST
+                | MATCH_ARM
+                | IDENT_PAT
+                | REST_PAT
+                | RECORD_PAT_FIELD
         )
     }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4212,26 +4212,26 @@ impl AstNode for AnyHasDocComments {
     fn can_cast(kind: SyntaxKind) -> bool {
         matches!(
             kind,
-            CONST
+            MACRO_CALL
+                | SOURCE_FILE
+                | CONST
                 | ENUM
                 | EXTERN_BLOCK
                 | EXTERN_CRATE
                 | FN
                 | IMPL
-                | MACRO_CALL
-                | MACRO_DEF
                 | MACRO_RULES
+                | MACRO_DEF
                 | MODULE
-                | RECORD_FIELD
-                | SOURCE_FILE
                 | STATIC
                 | STRUCT
                 | TRAIT
                 | TRAIT_ALIAS
-                | TUPLE_FIELD
                 | TYPE_ALIAS
                 | UNION
                 | USE
+                | RECORD_FIELD
+                | TUPLE_FIELD
                 | VARIANT
         )
     }
@@ -4275,7 +4275,7 @@ impl AnyHasModuleItem {
     }
 }
 impl AstNode for AnyHasModuleItem {
-    fn can_cast(kind: SyntaxKind) -> bool { matches!(kind, ITEM_LIST | MACRO_ITEMS | SOURCE_FILE) }
+    fn can_cast(kind: SyntaxKind) -> bool { matches!(kind, MACRO_ITEMS | SOURCE_FILE | ITEM_LIST) }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         Self::can_cast(syntax.kind()).then_some(AnyHasModuleItem { syntax })
     }
@@ -4292,25 +4292,25 @@ impl AstNode for AnyHasName {
         matches!(
             kind,
             CONST
-                | CONST_PARAM
                 | ENUM
                 | FN
-                | FORMAT_ARGS_ARG
-                | IDENT_PAT
-                | MACRO_DEF
                 | MACRO_RULES
+                | MACRO_DEF
                 | MODULE
-                | RECORD_FIELD
-                | RENAME
-                | SELF_PARAM
                 | STATIC
                 | STRUCT
                 | TRAIT
                 | TRAIT_ALIAS
                 | TYPE_ALIAS
-                | TYPE_PARAM
                 | UNION
+                | RENAME
+                | SELF_PARAM
+                | RECORD_FIELD
                 | VARIANT
+                | CONST_PARAM
+                | TYPE_PARAM
+                | FORMAT_ARGS_ARG
+                | IDENT_PAT
         )
     }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4328,7 +4328,7 @@ impl AstNode for AnyHasTypeBounds {
     fn can_cast(kind: SyntaxKind) -> bool {
         matches!(
             kind,
-            ASSOC_TYPE_ARG | LIFETIME_PARAM | TRAIT | TYPE_ALIAS | TYPE_PARAM | WHERE_PRED
+            ASSOC_TYPE_ARG | TRAIT | TYPE_ALIAS | LIFETIME_PARAM | TYPE_PARAM | WHERE_PRED
         )
     }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4351,18 +4351,18 @@ impl AstNode for AnyHasVisibility {
                 | EXTERN_CRATE
                 | FN
                 | IMPL
-                | MACRO_DEF
                 | MACRO_RULES
+                | MACRO_DEF
                 | MODULE
-                | RECORD_FIELD
                 | STATIC
                 | STRUCT
                 | TRAIT
                 | TRAIT_ALIAS
-                | TUPLE_FIELD
                 | TYPE_ALIAS
                 | UNION
                 | USE
+                | RECORD_FIELD
+                | TUPLE_FIELD
                 | VARIANT
         )
     }
@@ -4371,62 +4371,12 @@ impl AstNode for AnyHasVisibility {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl std::fmt::Display for Adt {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        std::fmt::Display::fmt(self.syntax(), f)
-    }
-}
-impl std::fmt::Display for AssocItem {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        std::fmt::Display::fmt(self.syntax(), f)
-    }
-}
-impl std::fmt::Display for Expr {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        std::fmt::Display::fmt(self.syntax(), f)
-    }
-}
-impl std::fmt::Display for ExternItem {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        std::fmt::Display::fmt(self.syntax(), f)
-    }
-}
-impl std::fmt::Display for FieldList {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        std::fmt::Display::fmt(self.syntax(), f)
-    }
-}
-impl std::fmt::Display for GenericArg {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        std::fmt::Display::fmt(self.syntax(), f)
-    }
-}
-impl std::fmt::Display for GenericParam {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        std::fmt::Display::fmt(self.syntax(), f)
-    }
-}
-impl std::fmt::Display for Item {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        std::fmt::Display::fmt(self.syntax(), f)
-    }
-}
-impl std::fmt::Display for Pat {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        std::fmt::Display::fmt(self.syntax(), f)
-    }
-}
-impl std::fmt::Display for Stmt {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        std::fmt::Display::fmt(self.syntax(), f)
-    }
-}
-impl std::fmt::Display for Type {
+impl std::fmt::Display for Abi {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for Abi {
+impl std::fmt::Display for Adt {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
@@ -4451,6 +4401,11 @@ impl std::fmt::Display for AsmExpr {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
+impl std::fmt::Display for AssocItem {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
 impl std::fmt::Display for AssocItemList {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
@@ -4546,6 +4501,11 @@ impl std::fmt::Display for Enum {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
+impl std::fmt::Display for Expr {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
 impl std::fmt::Display for ExprStmt {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
@@ -4561,6 +4521,11 @@ impl std::fmt::Display for ExternCrate {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
+impl std::fmt::Display for ExternItem {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
 impl std::fmt::Display for ExternItemList {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
@@ -4571,6 +4536,11 @@ impl std::fmt::Display for FieldExpr {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
+impl std::fmt::Display for FieldList {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
 impl std::fmt::Display for Fn {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
@@ -4601,11 +4571,21 @@ impl std::fmt::Display for FormatArgsExpr {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
+impl std::fmt::Display for GenericArg {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
 impl std::fmt::Display for GenericArgList {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
+impl std::fmt::Display for GenericParam {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
 impl std::fmt::Display for GenericParamList {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
@@ -4641,6 +4621,11 @@ impl std::fmt::Display for InferType {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
+impl std::fmt::Display for Item {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
 impl std::fmt::Display for ItemList {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
@@ -4826,6 +4811,11 @@ impl std::fmt::Display for ParenType {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
+impl std::fmt::Display for Pat {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
 impl std::fmt::Display for Path {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
@@ -4971,6 +4961,11 @@ impl std::fmt::Display for Static {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
+impl std::fmt::Display for Stmt {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
 impl std::fmt::Display for StmtList {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
@@ -5031,6 +5026,11 @@ impl std::fmt::Display for TupleType {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
+impl std::fmt::Display for Type {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
 impl std::fmt::Display for TypeAlias {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
diff --git a/crates/syntax/src/ast/generated/tokens.rs b/crates/syntax/src/ast/generated/tokens.rs
index 651a8ebbf7..f5863e9efe 100644
--- a/crates/syntax/src/ast/generated/tokens.rs
+++ b/crates/syntax/src/ast/generated/tokens.rs
@@ -7,16 +7,16 @@ use crate::{
 };
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Byte {
+pub struct Whitespace {
     pub(crate) syntax: SyntaxToken,
 }
-impl std::fmt::Display for Byte {
+impl std::fmt::Display for Whitespace {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(&self.syntax, f)
     }
 }
-impl AstToken for Byte {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == BYTE }
+impl AstToken for Whitespace {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == WHITESPACE }
     fn cast(syntax: SyntaxToken) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -28,16 +28,16 @@ impl AstToken for Byte {
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct ByteString {
+pub struct Comment {
     pub(crate) syntax: SyntaxToken,
 }
-impl std::fmt::Display for ByteString {
+impl std::fmt::Display for Comment {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(&self.syntax, f)
     }
 }
-impl AstToken for ByteString {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == BYTE_STRING }
+impl AstToken for Comment {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == COMMENT }
     fn cast(syntax: SyntaxToken) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -49,16 +49,16 @@ impl AstToken for ByteString {
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct CString {
+pub struct String {
     pub(crate) syntax: SyntaxToken,
 }
-impl std::fmt::Display for CString {
+impl std::fmt::Display for String {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(&self.syntax, f)
     }
 }
-impl AstToken for CString {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == C_STRING }
+impl AstToken for String {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == STRING }
     fn cast(syntax: SyntaxToken) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -70,16 +70,16 @@ impl AstToken for CString {
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Char {
+pub struct ByteString {
     pub(crate) syntax: SyntaxToken,
 }
-impl std::fmt::Display for Char {
+impl std::fmt::Display for ByteString {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(&self.syntax, f)
     }
 }
-impl AstToken for Char {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == CHAR }
+impl AstToken for ByteString {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == BYTE_STRING }
     fn cast(syntax: SyntaxToken) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -91,16 +91,16 @@ impl AstToken for Char {
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Comment {
+pub struct CString {
     pub(crate) syntax: SyntaxToken,
 }
-impl std::fmt::Display for Comment {
+impl std::fmt::Display for CString {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(&self.syntax, f)
     }
 }
-impl AstToken for Comment {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == COMMENT }
+impl AstToken for CString {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == C_STRING }
     fn cast(syntax: SyntaxToken) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -112,16 +112,16 @@ impl AstToken for Comment {
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct FloatNumber {
+pub struct IntNumber {
     pub(crate) syntax: SyntaxToken,
 }
-impl std::fmt::Display for FloatNumber {
+impl std::fmt::Display for IntNumber {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(&self.syntax, f)
     }
 }
-impl AstToken for FloatNumber {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == FLOAT_NUMBER }
+impl AstToken for IntNumber {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == INT_NUMBER }
     fn cast(syntax: SyntaxToken) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -133,16 +133,16 @@ impl AstToken for FloatNumber {
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Ident {
+pub struct FloatNumber {
     pub(crate) syntax: SyntaxToken,
 }
-impl std::fmt::Display for Ident {
+impl std::fmt::Display for FloatNumber {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(&self.syntax, f)
     }
 }
-impl AstToken for Ident {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == IDENT }
+impl AstToken for FloatNumber {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == FLOAT_NUMBER }
     fn cast(syntax: SyntaxToken) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -154,16 +154,16 @@ impl AstToken for Ident {
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct IntNumber {
+pub struct Char {
     pub(crate) syntax: SyntaxToken,
 }
-impl std::fmt::Display for IntNumber {
+impl std::fmt::Display for Char {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(&self.syntax, f)
     }
 }
-impl AstToken for IntNumber {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == INT_NUMBER }
+impl AstToken for Char {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == CHAR }
     fn cast(syntax: SyntaxToken) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -175,16 +175,16 @@ impl AstToken for IntNumber {
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct String {
+pub struct Byte {
     pub(crate) syntax: SyntaxToken,
 }
-impl std::fmt::Display for String {
+impl std::fmt::Display for Byte {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(&self.syntax, f)
     }
 }
-impl AstToken for String {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == STRING }
+impl AstToken for Byte {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == BYTE }
     fn cast(syntax: SyntaxToken) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -196,16 +196,16 @@ impl AstToken for String {
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Whitespace {
+pub struct Ident {
     pub(crate) syntax: SyntaxToken,
 }
-impl std::fmt::Display for Whitespace {
+impl std::fmt::Display for Ident {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(&self.syntax, f)
     }
 }
-impl AstToken for Whitespace {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == WHITESPACE }
+impl AstToken for Ident {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == IDENT }
     fn cast(syntax: SyntaxToken) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
diff --git a/xtask/src/codegen/grammar/ast_src.rs b/crates/syntax/src/tests/ast_src.rs
similarity index 100%
rename from xtask/src/codegen/grammar/ast_src.rs
rename to crates/syntax/src/tests/ast_src.rs
diff --git a/xtask/src/codegen/grammar.rs b/crates/syntax/src/tests/sourcegen_ast.rs
similarity index 92%
rename from xtask/src/codegen/grammar.rs
rename to crates/syntax/src/tests/sourcegen_ast.rs
index cc2fadc975..1572bbe32c 100644
--- a/xtask/src/codegen/grammar.rs
+++ b/crates/syntax/src/tests/sourcegen_ast.rs
@@ -3,45 +3,37 @@
 //! Specifically, it generates the `SyntaxKind` enum and a number of newtype
 //! wrappers around `SyntaxNode` which implement `syntax::AstNode`.
 
-#![allow(clippy::disallowed_types)]
-
-use std::{
-    collections::{BTreeSet, HashSet},
-    fmt::Write,
-    fs,
-};
+use std::{collections::BTreeSet, fmt::Write};
 
 use itertools::Itertools;
 use proc_macro2::{Punct, Spacing};
 use quote::{format_ident, quote};
+use rustc_hash::FxHashSet;
 use ungrammar::{Grammar, Rule};
 
-use crate::{
-    codegen::{add_preamble, ensure_file_contents, reformat},
-    project_root,
+use crate::tests::ast_src::{
+    AstEnumSrc, AstNodeSrc, AstSrc, Cardinality, Field, KindsSrc, KINDS_SRC,
 };
 
-mod ast_src;
-use self::ast_src::{AstEnumSrc, AstNodeSrc, AstSrc, Cardinality, Field, KindsSrc, KINDS_SRC};
-
-pub(crate) fn generate(check: bool) {
+#[test]
+fn sourcegen_ast() {
     let syntax_kinds = generate_syntax_kinds(KINDS_SRC);
-    let syntax_kinds_file = project_root().join("crates/parser/src/syntax_kind/generated.rs");
-    ensure_file_contents(syntax_kinds_file.as_path(), &syntax_kinds, check);
+    let syntax_kinds_file =
+        sourcegen::project_root().join("crates/parser/src/syntax_kind/generated.rs");
+    sourcegen::ensure_file_contents(syntax_kinds_file.as_path(), &syntax_kinds);
 
-    let grammar = fs::read_to_string(project_root().join("crates/syntax/rust.ungram"))
-        .unwrap()
-        .parse()
-        .unwrap();
+    let grammar =
+        include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/rust.ungram")).parse().unwrap();
     let ast = lower(&grammar);
 
     let ast_tokens = generate_tokens(&ast);
-    let ast_tokens_file = project_root().join("crates/syntax/src/ast/generated/tokens.rs");
-    ensure_file_contents(ast_tokens_file.as_path(), &ast_tokens, check);
+    let ast_tokens_file =
+        sourcegen::project_root().join("crates/syntax/src/ast/generated/tokens.rs");
+    sourcegen::ensure_file_contents(ast_tokens_file.as_path(), &ast_tokens);
 
     let ast_nodes = generate_nodes(KINDS_SRC, &ast);
-    let ast_nodes_file = project_root().join("crates/syntax/src/ast/generated/nodes.rs");
-    ensure_file_contents(ast_nodes_file.as_path(), &ast_nodes, check);
+    let ast_nodes_file = sourcegen::project_root().join("crates/syntax/src/ast/generated/nodes.rs");
+    sourcegen::ensure_file_contents(ast_nodes_file.as_path(), &ast_nodes);
 }
 
 fn generate_tokens(grammar: &AstSrc) -> String {
@@ -68,9 +60,9 @@ fn generate_tokens(grammar: &AstSrc) -> String {
         }
     });
 
-    add_preamble(
+    sourcegen::add_preamble(
         "sourcegen_ast",
-        reformat(
+        sourcegen::reformat(
             quote! {
                 use crate::{SyntaxKind::{self, *}, SyntaxToken, ast::AstToken};
                 #(#tokens)*
@@ -85,6 +77,7 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: &AstSrc) -> String {
     let (node_defs, node_boilerplate_impls): (Vec<_>, Vec<_>) = grammar
         .nodes
         .iter()
+        .sorted_by_key(|it| it.name.clone())
         .map(|node| {
             let name = format_ident!("{}", node.name);
             let kind = format_ident!("{}", to_upper_snake_case(&node.name));
@@ -96,12 +89,13 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: &AstSrc) -> String {
                     node.name != "ForExpr" && node.name != "WhileExpr"
                         || trait_name.as_str() != "HasLoopBody"
                 })
+                .sorted()
                 .map(|trait_name| {
                     let trait_name = format_ident!("{}", trait_name);
                     quote!(impl ast::#trait_name for #name {})
                 });
 
-            let methods = node.fields.iter().map(|field| {
+            let methods = node.fields.iter().sorted_by_key(|it| it.method_name()).map(|field| {
                 let method_name = field.method_name();
                 let ty = field.ty();
 
@@ -157,6 +151,7 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: &AstSrc) -> String {
     let (enum_defs, enum_boilerplate_impls): (Vec<_>, Vec<_>) = grammar
         .enums
         .iter()
+        .sorted_by_key(|it| it.name.clone())
         .map(|en| {
             let variants: Vec<_> =
                 en.variants.iter().map(|var| format_ident!("{}", var)).sorted().collect();
@@ -221,13 +216,14 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: &AstSrc) -> String {
             )
         })
         .unzip();
+
     let (any_node_defs, any_node_boilerplate_impls): (Vec<_>, Vec<_>) = grammar
         .nodes
         .iter()
         .flat_map(|node| node.traits.iter().map(move |t| (t, node)))
         .into_group_map()
         .into_iter()
-        .sorted_by_key(|(name, _)| *name)
+        .sorted_by_key(|(k, _)| *k)
         .map(|(trait_name, nodes)| {
             let name = format_ident!("Any{}", trait_name);
             let trait_name = format_ident!("{}", trait_name);
@@ -274,17 +270,19 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: &AstSrc) -> String {
     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| {
-            quote! {
-                impl std::fmt::Display for #name {
-                    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-                        std::fmt::Display::fmt(self.syntax(), f)
+        enum_names.chain(node_names.clone()).map(|it| format_ident!("{}", it)).sorted().map(
+            |name| {
+                quote! {
+                    impl std::fmt::Display for #name {
+                        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+                            std::fmt::Display::fmt(self.syntax(), f)
+                        }
                     }
                 }
-            }
-        });
+            },
+        );
 
-    let defined_nodes: HashSet<_> = node_names.collect();
+    let defined_nodes: FxHashSet<_> = node_names.collect();
 
     for node in kinds
         .nodes
@@ -328,7 +326,7 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: &AstSrc) -> String {
         }
     }
 
-    let res = add_preamble("sourcegen_ast", reformat(res));
+    let res = sourcegen::add_preamble("sourcegen_ast", sourcegen::reformat(res));
     res.replace("#[derive", "\n#[derive")
 }
 
@@ -458,7 +456,7 @@ fn generate_syntax_kinds(grammar: KindsSrc<'_>) -> String {
         }
     };
 
-    add_preamble("sourcegen_ast", reformat(ast.to_string()))
+    sourcegen::add_preamble("sourcegen_ast", sourcegen::reformat(ast.to_string()))
 }
 
 fn to_upper_snake_case(s: &str) -> String {
@@ -608,20 +606,6 @@ fn lower(grammar: &Grammar) -> AstSrc {
     extract_enums(&mut res);
     extract_struct_traits(&mut res);
     extract_enum_traits(&mut res);
-    res.nodes.sort_by_key(|it| it.name.clone());
-    res.enums.sort_by_key(|it| it.name.clone());
-    res.tokens.sort();
-    res.nodes.iter_mut().for_each(|it| {
-        it.traits.sort();
-        it.fields.sort_by_key(|it| match it {
-            Field::Token(name) => (true, name.clone()),
-            Field::Node { name, .. } => (false, name.clone()),
-        });
-    });
-    res.enums.iter_mut().for_each(|it| {
-        it.traits.sort();
-        it.variants.sort();
-    });
     res
 }
 
diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml
index a83d32e414..5e758e0190 100644
--- a/xtask/Cargo.toml
+++ b/xtask/Cargo.toml
@@ -15,10 +15,6 @@ xflags = "0.3.0"
 time = { version = "0.3", default-features = false }
 zip = { version = "0.6", default-features = false, features = ["deflate", "time"] }
 stdx.workspace = true
-proc-macro2 = "1.0.47"
-quote = "1.0.20"
-ungrammar = "1.16.1"
-itertools.workspace = true
 # Avoid adding more dependencies to this crate
 
 [lints]
diff --git a/xtask/src/codegen.rs b/xtask/src/codegen.rs
index 7dc1b40783..40f872a24a 100644
--- a/xtask/src/codegen.rs
+++ b/xtask/src/codegen.rs
@@ -9,7 +9,6 @@ use crate::{flags, project_root};
 
 pub(crate) mod assists_doc_tests;
 pub(crate) mod diagnostics_docs;
-mod grammar;
 mod lints;
 
 impl flags::Codegen {
@@ -21,7 +20,6 @@ impl flags::Codegen {
                 // lints::generate(self.check) Updating clones the rust repo, so don't run it unless
                 // explicitly asked for
             }
-            flags::CodegenType::Grammar => grammar::generate(self.check),
             flags::CodegenType::AssistsDocTests => assists_doc_tests::generate(self.check),
             flags::CodegenType::DiagnosticsDocs => diagnostics_docs::generate(self.check),
             flags::CodegenType::LintDefinitions => lints::generate(self.check),
diff --git a/xtask/src/flags.rs b/xtask/src/flags.rs
index f7ae0eb1b4..681c588bd0 100644
--- a/xtask/src/flags.rs
+++ b/xtask/src/flags.rs
@@ -91,7 +91,6 @@ pub struct Codegen {
 pub enum CodegenType {
     #[default]
     All,
-    Grammar,
     AssistsDocTests,
     DiagnosticsDocs,
     LintDefinitions,
@@ -102,7 +101,6 @@ impl FromStr for CodegenType {
     fn from_str(s: &str) -> Result<Self, Self::Err> {
         match s {
             "all" => Ok(Self::All),
-            "grammar" => Ok(Self::Grammar),
             "assists-doc-tests" => Ok(Self::AssistsDocTests),
             "diagnostics-docs" => Ok(Self::DiagnosticsDocs),
             "lints-definitions" => Ok(Self::LintDefinitions),


Test patch:
diff --git a/crates/flycheck/src/test_runner.rs b/crates/flycheck/src/test_runner.rs
index 9f761c9ead..31378716b3 100644
--- a/crates/flycheck/src/test_runner.rs
+++ b/crates/flycheck/src/test_runner.rs
@@ -55,16 +55,13 @@ pub struct CargoTestHandle {
 }
 
 // Example of a cargo test command:
-// cargo test --workspace --no-fail-fast -- module::func -Z unstable-options --format=json
+// cargo test -- module::func -Z unstable-options --format=json
 
 impl CargoTestHandle {
     pub fn new(path: Option<&str>) -> std::io::Result<Self> {
         let mut cmd = Command::new(Tool::Cargo.path());
         cmd.env("RUSTC_BOOTSTRAP", "1");
         cmd.arg("test");
-        cmd.arg("--workspace");
-        // --no-fail-fast is needed to ensure that all requested tests will run
-        cmd.arg("--no-fail-fast");
         cmd.arg("--");
         if let Some(path) = path {
             cmd.arg(path);
diff --git a/crates/parser/test_data/parser/inline/err/0034_match_arms_recovery.rast b/crates/parser/test_data/parser/inline/err/0034_match_arms_recovery.rast
deleted file mode 100644
index 5b191945e4..0000000000
--- a/crates/parser/test_data/parser/inline/err/0034_match_arms_recovery.rast
+++ /dev/null
@@ -1,113 +0,0 @@
-SOURCE_FILE
-  FN
-    FN_KW "fn"
-    WHITESPACE " "
-    NAME
-      IDENT "foo"
-    PARAM_LIST
-      L_PAREN "("
-      R_PAREN ")"
-    WHITESPACE " "
-    BLOCK_EXPR
-      STMT_LIST
-        L_CURLY "{"
-        WHITESPACE "\n    "
-        MATCH_EXPR
-          MATCH_KW "match"
-          WHITESPACE " "
-          TUPLE_EXPR
-            L_PAREN "("
-            R_PAREN ")"
-          WHITESPACE " "
-          MATCH_ARM_LIST
-            L_CURLY "{"
-            WHITESPACE "\n        "
-            MATCH_ARM
-              WILDCARD_PAT
-                UNDERSCORE "_"
-              WHITESPACE " "
-              FAT_ARROW "=>"
-              WHITESPACE " "
-              TUPLE_EXPR
-                L_PAREN "("
-                R_PAREN ")"
-              COMMA ","
-            ERROR
-              COMMA ","
-            WHITESPACE "\n        "
-            MATCH_ARM
-              WILDCARD_PAT
-                UNDERSCORE "_"
-              WHITESPACE " "
-              FAT_ARROW "=>"
-              WHITESPACE " "
-              COMMA ","
-            WHITESPACE "\n        "
-            MATCH_ARM
-              WILDCARD_PAT
-                UNDERSCORE "_"
-              WHITESPACE " "
-              FAT_ARROW "=>"
-              WHITESPACE " "
-              TUPLE_EXPR
-                L_PAREN "("
-                R_PAREN ")"
-              COMMA ","
-            WHITESPACE "\n         "
-            MATCH_ARM
-              FAT_ARROW "=>"
-              WHITESPACE " "
-              TUPLE_EXPR
-                L_PAREN "("
-                R_PAREN ")"
-              COMMA ","
-            WHITESPACE "\n        "
-            MATCH_ARM
-              MATCH_GUARD
-                IF_KW "if"
-                WHITESPACE " "
-                LITERAL
-                  TRUE_KW "true"
-              WHITESPACE " "
-              FAT_ARROW "=>"
-              WHITESPACE " "
-              TUPLE_EXPR
-                L_PAREN "("
-                R_PAREN ")"
-              COMMA ","
-            WHITESPACE "\n        "
-            MATCH_ARM
-              WILDCARD_PAT
-                UNDERSCORE "_"
-              WHITESPACE " "
-              FAT_ARROW "=>"
-              WHITESPACE " "
-              TUPLE_EXPR
-                L_PAREN "("
-                R_PAREN ")"
-              COMMA ","
-            WHITESPACE "\n        "
-            MATCH_ARM
-              TUPLE_PAT
-                L_PAREN "("
-                R_PAREN ")"
-              WHITESPACE " "
-              MATCH_GUARD
-                IF_KW "if"
-              WHITESPACE " "
-              FAT_ARROW "=>"
-              WHITESPACE " "
-              TUPLE_EXPR
-                L_PAREN "("
-                R_PAREN ")"
-              COMMA ","
-            WHITESPACE "\n    "
-            R_CURLY "}"
-        WHITESPACE "\n"
-        R_CURLY "}"
-  WHITESPACE "\n"
-error 42: expected pattern
-error 58: expected expression
-error 85: expected pattern
-error 100: expected pattern
-error 145: expected expression
diff --git a/crates/parser/test_data/parser/inline/err/0034_match_arms_recovery.rs b/crates/parser/test_data/parser/inline/err/0034_match_arms_recovery.rs
deleted file mode 100644
index 173103b2e3..0000000000
--- a/crates/parser/test_data/parser/inline/err/0034_match_arms_recovery.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-fn foo() {
-    match () {
-        _ => (),,
-        _ => ,
-        _ => (),
-         => (),
-        if true => (),
-        _ => (),
-        () if => (),
-    }
-}
diff --git a/crates/syntax/src/tests.rs b/crates/syntax/src/tests.rs
index 439daa358a..5400071c4b 100644
--- a/crates/syntax/src/tests.rs
+++ b/crates/syntax/src/tests.rs
@@ -1,3 +1,8 @@
+#[cfg(not(feature = "in-rust-tree"))]
+mod ast_src;
+#[cfg(not(feature = "in-rust-tree"))]
+mod sourcegen_ast;
+
 use std::{
     fs,
     path::{Path, PathBuf},
@@ -77,25 +82,7 @@ fn reparse_fuzz_tests() {
 fn self_hosting_parsing() {
     let crates_dir = project_root().join("crates");
 
-    let mut files = Vec::new();
-    let mut work = vec![crates_dir.to_path_buf()];
-    while let Some(dir) = work.pop() {
-        for entry in dir.read_dir().unwrap() {
-            let entry = entry.unwrap();
-            let file_type = entry.file_type().unwrap();
-            let path = entry.path();
-            let file_name = &path.file_name().unwrap_or_default().to_str().unwrap_or_default();
-            let is_hidden = file_name.starts_with('.');
-            if !is_hidden {
-                if file_type.is_dir() {
-                    work.push(path);
-                } else if file_type.is_file() && file_name.ends_with(".rs") {
-                    files.push(path);
-                }
-            }
-        }
-    }
-
+    let mut files = ::sourcegen::list_rust_files(&crates_dir);
     files.retain(|path| {
         // Get all files which are not in the crates/syntax/test_data folder
         !path.components().any(|component| component.as_os_str() == "test_data")
diff --git a/editors/code/src/test_explorer.ts b/editors/code/src/test_explorer.ts
index ae5351a185..ac4ffb1926 100644
--- a/editors/code/src/test_explorer.ts
+++ b/editors/code/src/test_explorer.ts
@@ -105,9 +105,8 @@ export const prepareTestExplorer = (
             testSet.add(test.id);
         }
         // FIXME(hack_recover_crate_name): We eagerly resolve every test if we got a lazy top level response (detected
-        // by checking that `scope` is empty). This is not a good thing and wastes cpu and memory unnecessarily, so we
-        // should remove it.
-        if (scope.length === 0) {
+        // by `!scope`). ctx is not a good thing and wastes cpu and memory unnecessarily, so we should remove it.
+        if (!scope) {
             for (const test of tests) {
                 void testController.resolveHandler!(idToTestMap.get(test.id));
             }