Repository: rust-lang/rust-analyzer
Pull request #16889 (2024-03-19 12:06:18)

internal: Enforce utf8 paths
Cargo already requires this, and I highly doubt r-a works with non-utf8 paths generally either. This just makes dealing with paths a lot easier.


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..ce2cccf53a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -732,6 +732,7 @@ dependencies = [
  "ide-db",
  "itertools",
  "once_cell",
+ "paths",
  "serde_json",
  "stdx",
  "syntax",
@@ -931,6 +932,7 @@ dependencies = [
  "hir-expand",
  "ide-db",
  "itertools",
+ "paths",
  "proc-macro-api",
  "project-model",
  "span",
@@ -1225,6 +1227,9 @@ checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
 [[package]]
 name = "paths"
 version = "0.0.0"
+dependencies = [
+ "camino",
+]
 
 [[package]]
 name = "percent-encoding"
@@ -1598,6 +1603,7 @@ dependencies = [
  "oorandom",
  "parking_lot",
  "parser",
+ "paths",
  "proc-macro-api",
  "profile",
  "project-model",
@@ -1869,16 +1875,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]]
@@ -2020,6 +2030,7 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
 name = "toolchain"
 version = "0.0.0"
 dependencies = [
+ "camino",
  "home",
 ]
 
@@ -2434,12 +2445,8 @@ version = "0.1.0"
 dependencies = [
  "anyhow",
  "flate2",
- "itertools",
- "proc-macro2",
- "quote",
  "stdx",
  "time",
- "ungrammar",
  "write-json",
  "xflags",
  "xshell",
diff --git a/Cargo.toml b/Cargo.toml
index e940741009..d9343d2b96 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -105,6 +105,7 @@ anyhow = "1.0.75"
 arrayvec = "0.7.4"
 bitflags = "2.4.1"
 cargo_metadata = "0.18.1"
+camino = "1.1.6"
 chalk-solve = { version = "0.96.0", default-features = false }
 chalk-ir = "0.96.0"
 chalk-recursive = { version = "0.96.0", default-features = false }
diff --git a/crates/flycheck/src/lib.rs b/crates/flycheck/src/lib.rs
index f8efb52022..4ee86954ac 100644
--- a/crates/flycheck/src/lib.rs
+++ b/crates/flycheck/src/lib.rs
@@ -8,10 +8,10 @@
 
 #![warn(rust_2018_idioms, unused_lifetimes)]
 
-use std::{fmt, io, path::PathBuf, process::Command, time::Duration};
+use std::{fmt, io, process::Command, time::Duration};
 
 use crossbeam_channel::{never, select, unbounded, Receiver, Sender};
-use paths::{AbsPath, AbsPathBuf};
+use paths::{AbsPath, AbsPathBuf, Utf8PathBuf};
 use rustc_hash::FxHashMap;
 use serde::Deserialize;
 
@@ -53,7 +53,7 @@ pub enum FlycheckConfig {
         extra_args: Vec<String>,
         extra_env: FxHashMap<String, String>,
         ansi_color_output: bool,
-        target_dir: Option<PathBuf>,
+        target_dir: Option<Utf8PathBuf>,
     },
     CustomCommand {
         command: String,
@@ -363,7 +363,7 @@ impl FlycheckActor {
                 });
 
                 cmd.arg("--manifest-path");
-                cmd.arg(self.root.join("Cargo.toml").as_os_str());
+                cmd.arg(self.root.join("Cargo.toml"));
 
                 for target in target_triples {
                     cmd.args(["--target", target.as_str()]);
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/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/Cargo.toml b/crates/ide-diagnostics/Cargo.toml
index 8ccea99e9e..edd0500933 100644
--- a/crates/ide-diagnostics/Cargo.toml
+++ b/crates/ide-diagnostics/Cargo.toml
@@ -26,6 +26,7 @@ text-edit.workspace = true
 cfg.workspace = true
 hir.workspace = true
 ide-db.workspace = true
+paths.workspace = true
 
 [dev-dependencies]
 expect-test = "1.4.0"
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/handlers/unlinked_file.rs b/crates/ide-diagnostics/src/handlers/unlinked_file.rs
index becc24ab21..b9327f8556 100644
--- a/crates/ide-diagnostics/src/handlers/unlinked_file.rs
+++ b/crates/ide-diagnostics/src/handlers/unlinked_file.rs
@@ -8,6 +8,7 @@ use ide_db::{
     source_change::SourceChange,
     RootDatabase,
 };
+use paths::Utf8Component;
 use syntax::{
     ast::{self, edit::IndentLevel, HasModuleItem, HasName},
     AstNode, TextRange,
@@ -84,10 +85,10 @@ fn fixes(ctx: &DiagnosticsContext<'_>, file_id: FileId) -> Option<Vec<Assist>> {
 
         // try resolving the relative difference of the paths as inline modules
         let mut current = root_module;
-        for ele in rel.as_ref().components() {
+        for ele in rel.as_utf8_path().components() {
             let seg = match ele {
-                std::path::Component::Normal(seg) => seg.to_str()?,
-                std::path::Component::RootDir => continue,
+                Utf8Component::Normal(seg) => seg,
+                Utf8Component::RootDir => continue,
                 // shouldn't occur
                 _ => continue 'crates,
             };
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/doc_links.rs b/crates/ide/src/doc_links.rs
index d10bdca50d..64b4ccc5bd 100644
--- a/crates/ide/src/doc_links.rs
+++ b/crates/ide/src/doc_links.rs
@@ -5,8 +5,6 @@ mod tests;
 
 mod intra_doc_links;
 
-use std::ffi::OsStr;
-
 use pulldown_cmark::{BrokenLink, CowStr, Event, InlineStr, LinkType, Options, Parser, Tag};
 use pulldown_cmark_to_cmark::{cmark_resume_with_options, Options as CMarkOptions};
 use stdx::format_to;
@@ -134,8 +132,8 @@ pub(crate) fn remove_links(markdown: &str) -> String {
 pub(crate) fn external_docs(
     db: &RootDatabase,
     FilePosition { file_id, offset }: FilePosition,
-    target_dir: Option<&OsStr>,
-    sysroot: Option<&OsStr>,
+    target_dir: Option<&str>,
+    sysroot: Option<&str>,
 ) -> Option<DocumentationLinks> {
     let sema = &Semantics::new(db);
     let file = sema.parse(file_id).syntax().clone();
@@ -331,8 +329,8 @@ fn broken_link_clone_cb(link: BrokenLink<'_>) -> Option<(CowStr<'_>, CowStr<'_>)
 fn get_doc_links(
     db: &RootDatabase,
     def: Definition,
-    target_dir: Option<&OsStr>,
-    sysroot: Option<&OsStr>,
+    target_dir: Option<&str>,
+    sysroot: Option<&str>,
 ) -> DocumentationLinks {
     let join_url = |base_url: Option<Url>, path: &str| -> Option<Url> {
         base_url.and_then(|url| url.join(path).ok())
@@ -479,15 +477,13 @@ fn map_links<'e>(
 fn get_doc_base_urls(
     db: &RootDatabase,
     def: Definition,
-    target_dir: Option<&OsStr>,
-    sysroot: Option<&OsStr>,
+    target_dir: Option<&str>,
+    sysroot: Option<&str>,
 ) -> (Option<Url>, Option<Url>) {
     let local_doc = target_dir
-        .and_then(|path| path.to_str())
         .and_then(|path| Url::parse(&format!("file:///{path}/")).ok())
         .and_then(|it| it.join("doc/").ok());
     let system_doc = sysroot
-        .and_then(|it| it.to_str())
         .map(|sysroot| format!("file:///{sysroot}/share/doc/rust/html/"))
         .and_then(|it| Url::parse(&it).ok());
 
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/ide/src/lib.rs b/crates/ide/src/lib.rs
index 1c57f4f8f6..11eaa88c5c 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -58,8 +58,6 @@ mod view_item_tree;
 mod view_memory_layout;
 mod view_mir;
 
-use std::ffi::OsStr;
-
 use cfg::CfgOptions;
 use fetch_crates::CrateInfo;
 use hir::ChangeWithProcMacros;
@@ -511,8 +509,8 @@ impl Analysis {
     pub fn external_docs(
         &self,
         position: FilePosition,
-        target_dir: Option<&OsStr>,
-        sysroot: Option<&OsStr>,
+        target_dir: Option<&str>,
+        sysroot: Option<&str>,
     ) -> Cancellable<doc_links::DocumentationLinks> {
         self.with_db(|db| {
             doc_links::external_docs(db, position, target_dir, sysroot).unwrap_or_default()
diff --git a/crates/load-cargo/Cargo.toml b/crates/load-cargo/Cargo.toml
index 05412e176b..48e84a7b25 100644
--- a/crates/load-cargo/Cargo.toml
+++ b/crates/load-cargo/Cargo.toml
@@ -20,6 +20,7 @@ tracing.workspace = true
 
 hir-expand.workspace = true
 ide-db.workspace = true
+paths.workspace = true
 proc-macro-api.workspace = true
 project-model.workspace = true
 span.workspace = true
diff --git a/crates/load-cargo/src/lib.rs b/crates/load-cargo/src/lib.rs
index fe680e47fe..bb88500a0f 100644
--- a/crates/load-cargo/src/lib.rs
+++ b/crates/load-cargo/src/lib.rs
@@ -38,7 +38,7 @@ pub fn load_workspace_at(
     load_config: &LoadCargoConfig,
     progress: &dyn Fn(String),
 ) -> anyhow::Result<(RootDatabase, vfs::Vfs, Option<ProcMacroServer>)> {
-    let root = AbsPathBuf::assert(std::env::current_dir()?.join(root));
+    let root = AbsPathBuf::assert_utf8(std::env::current_dir()?.join(root));
     let root = ProjectManifest::discover_single(&root)?;
     let mut workspace = ProjectWorkspace::load(root, cargo_config, progress)?;
 
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/paths/Cargo.toml b/crates/paths/Cargo.toml
index 3d8752b5a8..59a4ad9a25 100644
--- a/crates/paths/Cargo.toml
+++ b/crates/paths/Cargo.toml
@@ -12,10 +12,14 @@ rust-version.workspace = true
 doctest = false
 
 [dependencies]
+camino.workspace = true
 # Adding this dep sadly puts a lot of rust-analyzer crates after the
 # serde-derive crate. Even though we don't activate the derive feature here,
 # someone else in the crate graph certainly does!
 # serde.workspace = true
 
+[features]
+serde1 = ["camino/serde1"]
+
 [lints]
-workspace = true
\ No newline at end of file
+workspace = true
diff --git a/crates/paths/src/lib.rs b/crates/paths/src/lib.rs
index a63d251c20..3ffe4e11e9 100644
--- a/crates/paths/src/lib.rs
+++ b/crates/paths/src/lib.rs
@@ -1,4 +1,4 @@
-//! Thin wrappers around `std::path`, distinguishing between absolute and
+//! Thin wrappers around `std::path`/`camino::path`, distinguishing between absolute and
 //! relative paths.
 
 #![warn(rust_2018_idioms, unused_lifetimes)]
@@ -7,16 +7,24 @@ use std::{
     borrow::Borrow,
     ffi::OsStr,
     fmt, ops,
-    path::{Component, Path, PathBuf},
+    path::{Path, PathBuf},
 };
 
-/// Wrapper around an absolute [`PathBuf`].
+pub use camino::*;
+
+/// Wrapper around an absolute [`Utf8PathBuf`].
 #[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
-pub struct AbsPathBuf(PathBuf);
+pub struct AbsPathBuf(Utf8PathBuf);
+
+impl From<AbsPathBuf> for Utf8PathBuf {
+    fn from(AbsPathBuf(path_buf): AbsPathBuf) -> Utf8PathBuf {
+        path_buf
+    }
+}
 
 impl From<AbsPathBuf> for PathBuf {
     fn from(AbsPathBuf(path_buf): AbsPathBuf) -> PathBuf {
-        path_buf
+        path_buf.into()
     }
 }
 
@@ -27,9 +35,21 @@ impl ops::Deref for AbsPathBuf {
     }
 }
 
+impl AsRef<Utf8Path> for AbsPathBuf {
+    fn as_ref(&self) -> &Utf8Path {
+        self.0.as_path()
+    }
+}
+
+impl AsRef<OsStr> for AbsPathBuf {
+    fn as_ref(&self) -> &OsStr {
+        self.0.as_ref()
+    }
+}
+
 impl AsRef<Path> for AbsPathBuf {
     fn as_ref(&self) -> &Path {
-        self.0.as_path()
+        self.0.as_ref()
     }
 }
 
@@ -45,20 +65,30 @@ impl Borrow<AbsPath> for AbsPathBuf {
     }
 }
 
+impl TryFrom<Utf8PathBuf> for AbsPathBuf {
+    type Error = Utf8PathBuf;
+    fn try_from(path_buf: Utf8PathBuf) -> Result<AbsPathBuf, Utf8PathBuf> {
+        if !path_buf.is_absolute() {
+            return Err(path_buf);
+        }
+        Ok(AbsPathBuf(path_buf))
+    }
+}
+
 impl TryFrom<PathBuf> for AbsPathBuf {
     type Error = PathBuf;
     fn try_from(path_buf: PathBuf) -> Result<AbsPathBuf, PathBuf> {
         if !path_buf.is_absolute() {
             return Err(path_buf);
         }
-        Ok(AbsPathBuf(path_buf))
+        Ok(AbsPathBuf(Utf8PathBuf::from_path_buf(path_buf)?))
     }
 }
 
 impl TryFrom<&str> for AbsPathBuf {
-    type Error = PathBuf;
-    fn try_from(path: &str) -> Result<AbsPathBuf, PathBuf> {
-        AbsPathBuf::try_from(PathBuf::from(path))
+    type Error = Utf8PathBuf;
+    fn try_from(path: &str) -> Result<AbsPathBuf, Utf8PathBuf> {
+        AbsPathBuf::try_from(Utf8PathBuf::from(path))
     }
 }
 
@@ -74,19 +104,31 @@ impl AbsPathBuf {
     /// # Panics
     ///
     /// Panics if `path` is not absolute.
-    pub fn assert(path: PathBuf) -> AbsPathBuf {
+    pub fn assert(path: Utf8PathBuf) -> AbsPathBuf {
         AbsPathBuf::try_from(path)
-            .unwrap_or_else(|path| panic!("expected absolute path, got {}", path.display()))
+            .unwrap_or_else(|path| panic!("expected absolute path, got {}", path))
+    }
+
+    /// Wrap the given absolute path in `AbsPathBuf`
+    ///
+    /// # Panics
+    ///
+    /// Panics if `path` is not absolute.
+    pub fn assert_utf8(path: PathBuf) -> AbsPathBuf {
+        AbsPathBuf::assert(
+            Utf8PathBuf::from_path_buf(path)
+                .unwrap_or_else(|path| panic!("expected utf8 path, got {}", path.display())),
+        )
     }
 
     /// Coerces to an `AbsPath` slice.
     ///
-    /// Equivalent of [`PathBuf::as_path`] for `AbsPathBuf`.
+    /// Equivalent of [`Utf8PathBuf::as_path`] for `AbsPathBuf`.
     pub fn as_path(&self) -> &AbsPath {
         AbsPath::assert(self.0.as_path())
     }
 
-    /// Equivalent of [`PathBuf::pop`] for `AbsPathBuf`.
+    /// Equivalent of [`Utf8PathBuf::pop`] for `AbsPathBuf`.
     ///
     /// Note that this won't remove the root component, so `self` will still be
     /// absolute.
@@ -97,18 +139,30 @@ impl AbsPathBuf {
 
 impl fmt::Display for AbsPathBuf {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Display::fmt(&self.0.display(), f)
+        fmt::Display::fmt(&self.0, f)
     }
 }
 
-/// Wrapper around an absolute [`Path`].
+/// Wrapper around an absolute [`Utf8Path`].
 #[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash)]
 #[repr(transparent)]
-pub struct AbsPath(Path);
+pub struct AbsPath(Utf8Path);
+
+impl AsRef<Utf8Path> for AbsPath {
+    fn as_ref(&self) -> &Utf8Path {
+        &self.0
+    }
+}
 
 impl AsRef<Path> for AbsPath {
     fn as_ref(&self) -> &Path {
-        &self.0
+        self.0.as_ref()
+    }
+}
+
+impl AsRef<OsStr> for AbsPath {
+    fn as_ref(&self) -> &OsStr {
+        self.0.as_ref()
     }
 }
 
@@ -120,9 +174,9 @@ impl ToOwned for AbsPath {
     }
 }
 
-impl<'a> TryFrom<&'a Path> for &'a AbsPath {
-    type Error = &'a Path;
-    fn try_from(path: &'a Path) -> Result<&'a AbsPath, &'a Path> {
+impl<'a> TryFrom<&'a Utf8Path> for &'a AbsPath {
+    type Error = &'a Utf8Path;
+    fn try_from(path: &'a Utf8Path) -> Result<&'a AbsPath, &'a Utf8Path> {
         if !path.is_absolute() {
             return Err(path);
         }
@@ -136,24 +190,24 @@ impl AbsPath {
     /// # Panics
     ///
     /// Panics if `path` is not absolute.
-    pub fn assert(path: &Path) -> &AbsPath {
+    pub fn assert(path: &Utf8Path) -> &AbsPath {
         assert!(path.is_absolute());
-        unsafe { &*(path as *const Path as *const AbsPath) }
+        unsafe { &*(path as *const Utf8Path as *const AbsPath) }
     }
 
-    /// Equivalent of [`Path::parent`] for `AbsPath`.
+    /// Equivalent of [`Utf8Path::parent`] for `AbsPath`.
     pub fn parent(&self) -> Option<&AbsPath> {
         self.0.parent().map(AbsPath::assert)
     }
 
-    /// Equivalent of [`Path::join`] for `AbsPath` with an additional normalize step afterwards.
-    pub fn absolutize(&self, path: impl AsRef<Path>) -> AbsPathBuf {
+    /// Equivalent of [`Utf8Path::join`] for `AbsPath` with an additional normalize step afterwards.
+    pub fn absolutize(&self, path: impl AsRef<Utf8Path>) -> AbsPathBuf {
         self.join(path).normalize()
     }
 
-    /// Equivalent of [`Path::join`] for `AbsPath`.
-    pub fn join(&self, path: impl AsRef<Path>) -> AbsPathBuf {
-        self.as_ref().join(path).try_into().unwrap()
+    /// Equivalent of [`Utf8Path::join`] for `AbsPath`.
+    pub fn join(&self, path: impl AsRef<Utf8Path>) -> AbsPathBuf {
+        Utf8Path::join(self.as_ref(), path).try_into().unwrap()
     }
 
     /// Normalize the given path:
@@ -172,7 +226,7 @@ impl AbsPath {
         AbsPathBuf(normalize_path(&self.0))
     }
 
-    /// Equivalent of [`Path::to_path_buf`] for `AbsPath`.
+    /// Equivalent of [`Utf8Path::to_path_buf`] for `AbsPath`.
     pub fn to_path_buf(&self) -> AbsPathBuf {
         AbsPathBuf::try_from(self.0.to_path_buf()).unwrap()
     }
@@ -181,7 +235,7 @@ impl AbsPath {
         panic!("We explicitly do not provide canonicalization API, as that is almost always a wrong solution, see #14430")
     }
 
-    /// Equivalent of [`Path::strip_prefix`] for `AbsPath`.
+    /// Equivalent of [`Utf8Path::strip_prefix`] for `AbsPath`.
     ///
     /// Returns a relative path.
     pub fn strip_prefix(&self, base: &AbsPath) -> Option<&RelPath> {
@@ -195,57 +249,61 @@ impl AbsPath {
     }
 
     pub fn name_and_extension(&self) -> Option<(&str, Option<&str>)> {
-        Some((
-            self.file_stem()?.to_str()?,
-            self.extension().and_then(|extension| extension.to_str()),
-        ))
+        Some((self.file_stem()?, self.extension()))
     }
 
     // region:delegate-methods
 
-    // Note that we deliberately don't implement `Deref<Target = Path>` here.
+    // Note that we deliberately don't implement `Deref<Target = Utf8Path>` here.
     //
-    // The problem with `Path` is that it directly exposes convenience IO-ing
-    // methods. For example, `Path::exists` delegates to `fs::metadata`.
+    // The problem with `Utf8Path` is that it directly exposes convenience IO-ing
+    // methods. For example, `Utf8Path::exists` delegates to `fs::metadata`.
     //
     // For `AbsPath`, we want to make sure that this is a POD type, and that all
     // IO goes via `fs`. That way, it becomes easier to mock IO when we need it.
 
-    pub fn file_name(&self) -> Option<&OsStr> {
+    pub fn file_name(&self) -> Option<&str> {
         self.0.file_name()
     }
-    pub fn extension(&self) -> Option<&OsStr> {
+    pub fn extension(&self) -> Option<&str> {
         self.0.extension()
     }
-    pub fn file_stem(&self) -> Option<&OsStr> {
+    pub fn file_stem(&self) -> Option<&str> {
         self.0.file_stem()
     }
     pub fn as_os_str(&self) -> &OsStr {
         self.0.as_os_str()
     }
+    pub fn as_str(&self) -> &str {
+        self.0.as_str()
+    }
     #[deprecated(note = "use Display instead")]
-    pub fn display(&self) -> std::path::Display<'_> {
-        self.0.display()
+    pub fn display(&self) -> ! {
+        unimplemented!()
     }
     #[deprecated(note = "use std::fs::metadata().is_ok() instead")]
-    pub fn exists(&self) -> bool {
-        self.0.exists()
+    pub fn exists(&self) -> ! {
+        unimplemented!()
+    }
+
+    pub fn components(&self) -> Utf8Components<'_> {
+        self.0.components()
     }
     // endregion:delegate-methods
 }
 
 impl fmt::Display for AbsPath {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Display::fmt(&self.0.display(), f)
+        fmt::Display::fmt(&self.0, f)
     }
 }
 
-/// Wrapper around a relative [`PathBuf`].
+/// Wrapper around a relative [`Utf8PathBuf`].
 #[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
-pub struct RelPathBuf(PathBuf);
+pub struct RelPathBuf(Utf8PathBuf);
 
-impl From<RelPathBuf> for PathBuf {
-    fn from(RelPathBuf(path_buf): RelPathBuf) -> PathBuf {
+impl From<RelPathBuf> for Utf8PathBuf {
+    fn from(RelPathBuf(path_buf): RelPathBuf) -> Utf8PathBuf {
         path_buf
     }
 }
@@ -257,15 +315,21 @@ impl ops::Deref for RelPathBuf {
     }
 }
 
+impl AsRef<Utf8Path> for RelPathBuf {
+    fn as_ref(&self) -> &Utf8Path {
+        self.0.as_path()
+    }
+}
+
 impl AsRef<Path> for RelPathBuf {
     fn as_ref(&self) -> &Path {
-        self.0.as_path()
+        self.0.as_ref()
     }
 }
 
-impl TryFrom<PathBuf> for RelPathBuf {
-    type Error = PathBuf;
-    fn try_from(path_buf: PathBuf) -> Result<RelPathBuf, PathBuf> {
+impl TryFrom<Utf8PathBuf> for RelPathBuf {
+    type Error = Utf8PathBuf;
+    fn try_from(path_buf: Utf8PathBuf) -> Result<RelPathBuf, Utf8PathBuf> {
         if !path_buf.is_relative() {
             return Err(path_buf);
         }
@@ -274,65 +338,79 @@ impl TryFrom<PathBuf> for RelPathBuf {
 }
 
 impl TryFrom<&str> for RelPathBuf {
-    type Error = PathBuf;
-    fn try_from(path: &str) -> Result<RelPathBuf, PathBuf> {
-        RelPathBuf::try_from(PathBuf::from(path))
+    type Error = Utf8PathBuf;
+    fn try_from(path: &str) -> Result<RelPathBuf, Utf8PathBuf> {
+        RelPathBuf::try_from(Utf8PathBuf::from(path))
     }
 }
 
 impl RelPathBuf {
     /// Coerces to a `RelPath` slice.
     ///
-    /// Equivalent of [`PathBuf::as_path`] for `RelPathBuf`.
+    /// Equivalent of [`Utf8PathBuf::as_path`] for `RelPathBuf`.
     pub fn as_path(&self) -> &RelPath {
         RelPath::new_unchecked(self.0.as_path())
     }
 }
 
-/// Wrapper around a relative [`Path`].
+/// Wrapper around a relative [`Utf8Path`].
 #[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash)]
 #[repr(transparent)]
-pub struct RelPath(Path);
+pub struct RelPath(Utf8Path);
+
+impl AsRef<Utf8Path> for RelPath {
+    fn as_ref(&self) -> &Utf8Path {
+        &self.0
+    }
+}
 
 impl AsRef<Path> for RelPath {
     fn as_ref(&self) -> &Path {
-        &self.0
+        self.0.as_ref()
     }
 }
 
 impl RelPath {
     /// Creates a new `RelPath` from `path`, without checking if it is relative.
-    pub fn new_unchecked(path: &Path) -> &RelPath {
-        unsafe { &*(path as *const Path as *const RelPath) }
+    pub fn new_unchecked(path: &Utf8Path) -> &RelPath {
+        unsafe { &*(path as *const Utf8Path as *const RelPath) }
     }
 
-    /// Equivalent of [`Path::to_path_buf`] for `RelPath`.
+    /// Equivalent of [`Utf8Path::to_path_buf`] for `RelPath`.
     pub fn to_path_buf(&self) -> RelPathBuf {
         RelPathBuf::try_from(self.0.to_path_buf()).unwrap()
     }
+
+    pub fn as_utf8_path(&self) -> &Utf8Path {
+        self.as_ref()
+    }
+
+    pub fn as_str(&self) -> &str {
+        self.0.as_str()
+    }
 }
 
 /// Taken from <https://github.com/rust-lang/cargo/blob/79c769c3d7b4c2cf6a93781575b7f592ef974255/src/cargo/util/paths.rs#L60-L85>
-fn normalize_path(path: &Path) -> PathBuf {
+fn normalize_path(path: &Utf8Path) -> Utf8PathBuf {
     let mut components = path.components().peekable();
-    let mut ret = if let Some(c @ Component::Prefix(..)) = components.peek().copied() {
+    let mut ret = if let Some(c @ Utf8Component::Prefix(..)) = components.peek().copied() {
         components.next();
-        PathBuf::from(c.as_os_str())
+        Utf8PathBuf::from(c.as_str())
     } else {
-        PathBuf::new()
+        Utf8PathBuf::new()
     };
 
     for component in components {
         match component {
-            Component::Prefix(..) => unreachable!(),
-            Component::RootDir => {
-                ret.push(component.as_os_str());
+            Utf8Component::Prefix(..) => unreachable!(),
+            Utf8Component::RootDir => {
+                ret.push(component.as_str());
             }
-            Component::CurDir => {}
-            Component::ParentDir => {
+            Utf8Component::CurDir => {}
+            Utf8Component::ParentDir => {
                 ret.pop();
             }
-            Component::Normal(c) => {
+            Utf8Component::Normal(c) => {
                 ret.push(c);
             }
         }
diff --git a/crates/proc-macro-api/Cargo.toml b/crates/proc-macro-api/Cargo.toml
index 978ad15560..f30f6a0f23 100644
--- a/crates/proc-macro-api/Cargo.toml
+++ b/crates/proc-macro-api/Cargo.toml
@@ -23,7 +23,7 @@ snap = "1.1.0"
 indexmap = "2.1.0"
 
 # local deps
-paths.workspace = true
+paths = { workspace = true, features = ["serde1"] }
 tt.workspace = true
 stdx.workspace = true
 text-size.workspace = true
diff --git a/crates/proc-macro-api/src/msg.rs b/crates/proc-macro-api/src/msg.rs
index aa5aff455f..ad0e1f187b 100644
--- a/crates/proc-macro-api/src/msg.rs
+++ b/crates/proc-macro-api/src/msg.rs
@@ -1,11 +1,9 @@
 //! Defines messages for cross-process message passing based on `ndjson` wire protocol
 pub(crate) mod flat;
 
-use std::{
-    io::{self, BufRead, Write},
-    path::PathBuf,
-};
+use std::io::{self, BufRead, Write};
 
+use paths::Utf8PathBuf;
 use serde::{de::DeserializeOwned, Deserialize, Serialize};
 
 use crate::ProcMacroKind;
@@ -27,7 +25,7 @@ pub const CURRENT_API_VERSION: u32 = RUST_ANALYZER_SPAN_SUPPORT;
 #[derive(Debug, Serialize, Deserialize)]
 pub enum Request {
     /// Since [`NO_VERSION_CHECK_VERSION`]
-    ListMacros { dylib_path: PathBuf },
+    ListMacros { dylib_path: Utf8PathBuf },
     /// Since [`NO_VERSION_CHECK_VERSION`]
     ExpandMacro(Box<ExpandMacro>),
     /// Since [`VERSION_CHECK_VERSION`]
@@ -89,7 +87,7 @@ pub struct ExpandMacro {
     /// Possible attributes for the attribute-like macros.
     pub attributes: Option<FlatTree>,
 
-    pub lib: PathBuf,
+    pub lib: Utf8PathBuf,
 
     /// Environment variables to set during macro expansion.
     pub env: Vec<(String, String)>,
@@ -273,7 +271,7 @@ mod tests {
             macro_body: FlatTree::new(&tt, CURRENT_API_VERSION, &mut span_data_table),
             macro_name: Default::default(),
             attributes: None,
-            lib: std::env::current_dir().unwrap(),
+            lib: Utf8PathBuf::from_path_buf(std::env::current_dir().unwrap()).unwrap(),
             env: Default::default(),
             current_dir: Default::default(),
             has_global_spans: ExpnGlobals {
diff --git a/crates/proc-macro-api/src/process.rs b/crates/proc-macro-api/src/process.rs
index 72f95643c8..35d48a1554 100644
--- a/crates/proc-macro-api/src/process.rs
+++ b/crates/proc-macro-api/src/process.rs
@@ -175,7 +175,7 @@ fn mk_child(
     env: &FxHashMap<String, String>,
     null_stderr: bool,
 ) -> io::Result<Child> {
-    let mut cmd = Command::new(path.as_os_str());
+    let mut cmd = Command::new(path);
     cmd.envs(env)
         .env("RUST_ANALYZER_INTERNALS_DO_NOT_USE", "this is unstable")
         .stdin(Stdio::piped())
@@ -183,7 +183,7 @@ fn mk_child(
         .stderr(if null_stderr { Stdio::null() } else { Stdio::inherit() });
     if cfg!(windows) {
         let mut path_var = std::ffi::OsString::new();
-        path_var.push(path.parent().unwrap().parent().unwrap().as_os_str());
+        path_var.push(path.parent().unwrap().parent().unwrap());
         path_var.push("\\bin;");
         path_var.push(std::env::var_os("PATH").unwrap_or_default());
         cmd.env("PATH", path_var);
diff --git a/crates/proc-macro-srv/src/dylib.rs b/crates/proc-macro-srv/src/dylib.rs
index 52b4cced5f..22c34ff167 100644
--- a/crates/proc-macro-srv/src/dylib.rs
+++ b/crates/proc-macro-srv/src/dylib.rs
@@ -1,16 +1,11 @@
 //! Handles dynamic library loading for proc macro
 
-use std::{
-    fmt,
-    fs::File,
-    io,
-    path::{Path, PathBuf},
-};
+use std::{fmt, fs::File, io};
 
 use libloading::Library;
 use memmap2::Mmap;
 use object::Object;
-use paths::AbsPath;
+use paths::{AbsPath, Utf8Path, Utf8PathBuf};
 use proc_macro::bridge;
 use proc_macro_api::{read_dylib_info, ProcMacroKind};
 
@@ -26,7 +21,7 @@ fn is_derive_registrar_symbol(symbol: &str) -> bool {
     symbol.contains(NEW_REGISTRAR_SYMBOL)
 }
 
-fn find_registrar_symbol(file: &Path) -> io::Result<Option<String>> {
+fn find_registrar_symbol(file: &Utf8Path) -> io::Result<Option<String>> {
     let file = File::open(file)?;
     let buffer = unsafe { Mmap::map(&file)? };
 
@@ -62,12 +57,12 @@ fn find_registrar_symbol(file: &Path) -> io::Result<Option<String>> {
 ///
 /// It seems that on Windows that behaviour is default, so we do nothing in that case.
 #[cfg(windows)]
-fn load_library(file: &Path) -> Result<Library, libloading::Error> {
+fn load_library(file: &Utf8Path) -> Result<Library, libloading::Error> {
     unsafe { Library::new(file) }
 }
 
 #[cfg(unix)]
-fn load_library(file: &Path) -> Result<Library, libloading::Error> {
+fn load_library(file: &Utf8Path) -> Result<Library, libloading::Error> {
     use libloading::os::unix::Library as UnixLibrary;
     use std::os::raw::c_int;
 
@@ -116,14 +111,14 @@ struct ProcMacroLibraryLibloading {
 }
 
 impl ProcMacroLibraryLibloading {
-    fn open(file: &Path) -> Result<Self, LoadProcMacroDylibError> {
+    fn open(file: &Utf8Path) -> Result<Self, LoadProcMacroDylibError> {
         let symbol_name = find_registrar_symbol(file)?.ok_or_else(|| {
-            invalid_data_err(format!("Cannot find registrar symbol in file {}", file.display()))
+            invalid_data_err(format!("Cannot find registrar symbol in file {file}"))
         })?;
 
-        let abs_file: &AbsPath = file.try_into().map_err(|_| {
-            invalid_data_err(format!("expected an absolute path, got {}", file.display()))
-        })?;
+        let abs_file: &AbsPath = file
+            .try_into()
+            .map_err(|_| invalid_data_err(format!("expected an absolute path, got {file}")))?;
         let version_info = read_dylib_info(abs_file)?;
 
         let lib = load_library(file).map_err(invalid_data_err)?;
@@ -138,10 +133,10 @@ pub struct Expander {
 }
 
 impl Expander {
-    pub fn new(lib: &Path) -> Result<Expander, LoadProcMacroDylibError> {
+    pub fn new(lib: &Utf8Path) -> Result<Expander, LoadProcMacroDylibError> {
         // Some libraries for dynamic loading require canonicalized path even when it is
         // already absolute
-        let lib = lib.canonicalize()?;
+        let lib = lib.canonicalize_utf8()?;
 
         let lib = ensure_file_with_lock_free_access(&lib)?;
 
@@ -176,30 +171,26 @@ impl Expander {
 
 /// Copy the dylib to temp directory to prevent locking in Windows
 #[cfg(windows)]
-fn ensure_file_with_lock_free_access(path: &Path) -> io::Result<PathBuf> {
+fn ensure_file_with_lock_free_access(path: &Utf8Path) -> io::Result<Utf8PathBuf> {
     use std::collections::hash_map::RandomState;
-    use std::ffi::OsString;
     use std::hash::{BuildHasher, Hasher};
 
     if std::env::var("RA_DONT_COPY_PROC_MACRO_DLL").is_ok() {
         return Ok(path.to_path_buf());
     }
 
-    let mut to = std::env::temp_dir();
+    let mut to = Utf8PathBuf::from_path_buf(std::env::temp_dir()).unwrap();
 
     let file_name = path.file_name().ok_or_else(|| {
-        io::Error::new(
-            io::ErrorKind::InvalidInput,
-            format!("File path is invalid: {}", path.display()),
-        )
+        io::Error::new(io::ErrorKind::InvalidInput, format!("File path is invalid: {path}"))
     })?;
 
     // Generate a unique number by abusing `HashMap`'s hasher.
     // Maybe this will also "inspire" a libs team member to finally put `rand` in libstd.
     let t = RandomState::new().build_hasher().finish();
 
-    let mut unique_name = OsString::from(t.to_string());
-    unique_name.push(file_name);
+    let mut unique_name = t.to_string();
+    unique_name.push_str(file_name);
 
     to.push(unique_name);
     std::fs::copy(path, &to).unwrap();
@@ -207,6 +198,6 @@ fn ensure_file_with_lock_free_access(path: &Path) -> io::Result<PathBuf> {
 }
 
 #[cfg(unix)]
-fn ensure_file_with_lock_free_access(path: &Path) -> io::Result<PathBuf> {
-    Ok(path.to_path_buf())
+fn ensure_file_with_lock_free_access(path: &Utf8Path) -> io::Result<Utf8PathBuf> {
+    Ok(path.to_owned())
 }
diff --git a/crates/proc-macro-srv/src/lib.rs b/crates/proc-macro-srv/src/lib.rs
index 831632c64c..d7e0a708b1 100644
--- a/crates/proc-macro-srv/src/lib.rs
+++ b/crates/proc-macro-srv/src/lib.rs
@@ -33,12 +33,11 @@ use std::{
     collections::{hash_map::Entry, HashMap},
     env,
     ffi::OsString,
-    fs,
-    path::{Path, PathBuf},
-    thread,
+    fs, thread,
     time::SystemTime,
 };
 
+use paths::{Utf8Path, Utf8PathBuf};
 use proc_macro_api::{
     msg::{
         self, deserialize_span_data_index_map, serialize_span_data_index_map, ExpnGlobals,
@@ -81,7 +80,7 @@ impl ProcMacroSrvSpan for Span {
 
 #[derive(Default)]
 pub struct ProcMacroSrv {
-    expanders: HashMap<(PathBuf, SystemTime), dylib::Expander>,
+    expanders: HashMap<(Utf8PathBuf, SystemTime), dylib::Expander>,
     span_mode: SpanMode,
 }
 
@@ -149,23 +148,22 @@ impl ProcMacroSrv {
 
     pub fn list_macros(
         &mut self,
-        dylib_path: &Path,
+        dylib_path: &Utf8Path,
     ) -> Result<Vec<(String, ProcMacroKind)>, String> {
         let expander = self.expander(dylib_path)?;
         Ok(expander.list_macros())
     }
 
-    fn expander(&mut self, path: &Path) -> Result<&dylib::Expander, String> {
+    fn expander(&mut self, path: &Utf8Path) -> Result<&dylib::Expander, String> {
         let time = fs::metadata(path)
             .and_then(|it| it.modified())
-            .map_err(|err| format!("Failed to get file metadata for {}: {err}", path.display()))?;
+            .map_err(|err| format!("Failed to get file metadata for {path}: {err}",))?;
 
         Ok(match self.expanders.entry((path.to_path_buf(), time)) {
-            Entry::Vacant(v) => {
-                v.insert(dylib::Expander::new(path).map_err(|err| {
-                    format!("Cannot create expander for {}: {err}", path.display())
-                })?)
-            }
+            Entry::Vacant(v) => v.insert(
+                dylib::Expander::new(path)
+                    .map_err(|err| format!("Cannot create expander for {path}: {err}",))?,
+            ),
             Entry::Occupied(e) => e.into_mut(),
         })
     }
@@ -306,6 +304,6 @@ impl Drop for EnvSnapshot {
 mod tests;
 
 #[cfg(test)]
-pub fn proc_macro_test_dylib_path() -> std::path::PathBuf {
+pub fn proc_macro_test_dylib_path() -> paths::Utf8PathBuf {
     proc_macro_test::PROC_MACRO_TEST_LOCATION.into()
 }
diff --git a/crates/project-model/Cargo.toml b/crates/project-model/Cargo.toml
index 924a4a89e2..139689975d 100644
--- a/crates/project-model/Cargo.toml
+++ b/crates/project-model/Cargo.toml
@@ -26,7 +26,7 @@ itertools.workspace = true
 # local deps
 base-db.workspace = true
 cfg.workspace = true
-paths.workspace = true
+paths = { workspace = true, features = ["serde1"] }
 stdx.workspace = true
 toolchain.workspace = true
 
diff --git a/crates/project-model/src/build_scripts.rs b/crates/project-model/src/build_scripts.rs
index 709fc03717..d40eb26063 100644
--- a/crates/project-model/src/build_scripts.rs
+++ b/crates/project-model/src/build_scripts.rs
@@ -77,7 +77,7 @@ impl WorkspaceBuildScripts {
                 cmd.args(&config.extra_args);
 
                 cmd.arg("--manifest-path");
-                cmd.arg(workspace_root.join("Cargo.toml").as_os_str());
+                cmd.arg(workspace_root.join("Cargo.toml"));
 
                 if let Some(target_dir) = &config.target_dir {
                     cmd.arg("--target-dir").arg(target_dir);
@@ -354,16 +354,11 @@ impl WorkspaceBuildScripts {
                             }
                             // cargo_metadata crate returns default (empty) path for
                             // older cargos, which is not absolute, so work around that.
-                            let out_dir = mem::take(&mut message.out_dir).into_os_string();
-                            if !out_dir.is_empty() {
-                                let out_dir = AbsPathBuf::assert(PathBuf::from(out_dir));
+                            let out_dir = mem::take(&mut message.out_dir);
+                            if !out_dir.as_str().is_empty() {
+                                let out_dir = AbsPathBuf::assert(out_dir);
                                 // inject_cargo_env(package, package_build_data);
-                                // NOTE: cargo and rustc seem to hide non-UTF-8 strings from env! and option_env!()
-                                if let Some(out_dir) =
-                                    out_dir.as_os_str().to_str().map(|s| s.to_owned())
-                                {
-                                    data.envs.push(("OUT_DIR".to_owned(), out_dir));
-                                }
+                                data.envs.push(("OUT_DIR".to_owned(), out_dir.as_str().to_owned()));
                                 data.out_dir = Some(out_dir);
                                 data.cfgs = cfgs;
                             }
@@ -377,8 +372,8 @@ impl WorkspaceBuildScripts {
                                 if let Some(filename) =
                                     message.filenames.iter().find(|name| is_dylib(name))
                                 {
-                                    let filename = AbsPathBuf::assert(PathBuf::from(&filename));
-                                    data.proc_macro_dylib_path = Some(filename);
+                                    let filename = AbsPath::assert(filename);
+                                    data.proc_macro_dylib_path = Some(filename.to_owned());
                                 }
                             }
                         });
diff --git a/crates/project-model/src/cargo_workspace.rs b/crates/project-model/src/cargo_workspace.rs
index 53b41ea1e8..4f6bac08f6 100644
--- a/crates/project-model/src/cargo_workspace.rs
+++ b/crates/project-model/src/cargo_workspace.rs
@@ -1,14 +1,13 @@
 //! See [`CargoWorkspace`].
 
 use std::ops;
-use std::path::PathBuf;
 use std::str::from_utf8;
 
 use anyhow::Context;
 use base_db::Edition;
 use cargo_metadata::{CargoOpt, MetadataCommand};
 use la_arena::{Arena, Idx};
-use paths::{AbsPath, AbsPathBuf};
+use paths::{AbsPath, AbsPathBuf, Utf8PathBuf};
 use rustc_hash::{FxHashMap, FxHashSet};
 use serde::Deserialize;
 use serde_json::from_value;
@@ -100,7 +99,7 @@ pub struct CargoConfig {
     pub invocation_strategy: InvocationStrategy,
     pub invocation_location: InvocationLocation,
     /// Optional path to use instead of `target` when building
-    pub target_dir: Option<PathBuf>,
+    pub target_dir: Option<Utf8PathBuf>,
 }
 
 pub type Package = Idx<PackageData>;
@@ -262,7 +261,7 @@ impl CargoWorkspace {
                 }
             }
         }
-        meta.current_dir(current_dir.as_os_str());
+        meta.current_dir(current_dir);
 
         let mut other_options = vec![];
         // cargo metadata only supports a subset of flags of what cargo usually accepts, and usually
@@ -351,7 +350,7 @@ impl CargoWorkspace {
                 id: id.repr.clone(),
                 name,
                 version,
-                manifest: AbsPathBuf::assert(manifest_path.into()).try_into().unwrap(),
+                manifest: AbsPathBuf::assert(manifest_path).try_into().unwrap(),
                 targets: Vec::new(),
                 is_local,
                 is_member,
@@ -370,7 +369,7 @@ impl CargoWorkspace {
                 let tgt = targets.alloc(TargetData {
                     package: pkg,
                     name,
-                    root: AbsPathBuf::assert(src_path.into()),
+                    root: AbsPathBuf::assert(src_path),
                     kind: TargetKind::new(&kind),
                     required_features,
                 });
@@ -393,11 +392,9 @@ impl CargoWorkspace {
             packages[source].active_features.extend(node.features);
         }
 
-        let workspace_root =
-            AbsPathBuf::assert(PathBuf::from(meta.workspace_root.into_os_string()));
+        let workspace_root = AbsPathBuf::assert(meta.workspace_root);
 
-        let target_directory =
-            AbsPathBuf::assert(PathBuf::from(meta.target_directory.into_os_string()));
+        let target_directory = AbsPathBuf::assert(meta.target_directory);
 
         CargoWorkspace { packages, targets, workspace_root, target_directory }
     }
diff --git a/crates/project-model/src/lib.rs b/crates/project-model/src/lib.rs
index 5b91f5d805..51bb4fe303 100644
--- a/crates/project-model/src/lib.rs
+++ b/crates/project-model/src/lib.rs
@@ -126,9 +126,8 @@ impl ProjectManifest {
             entities
                 .filter_map(Result::ok)
                 .map(|it| it.path().join("Cargo.toml"))
-                .filter(|it| it.exists())
-                .map(AbsPathBuf::assert)
-                .filter_map(|it| it.try_into().ok())
+                .map(AbsPathBuf::try_from)
+                .filter_map(|it| it.ok()?.try_into().ok())
                 .collect()
         }
     }
diff --git a/crates/project-model/src/project_json.rs b/crates/project-model/src/project_json.rs
index fba0aaa8ce..0b6e8caf5d 100644
--- a/crates/project-model/src/project_json.rs
+++ b/crates/project-model/src/project_json.rs
@@ -51,10 +51,9 @@
 
 use base_db::{CrateDisplayName, CrateId, CrateName, Dependency, Edition};
 use la_arena::RawIdx;
-use paths::{AbsPath, AbsPathBuf};
+use paths::{AbsPath, AbsPathBuf, Utf8PathBuf};
 use rustc_hash::FxHashMap;
 use serde::{de, Deserialize};
-use std::path::PathBuf;
 
 use crate::cfg_flag::CfgFlag;
 
@@ -113,7 +112,7 @@ impl ProjectJson {
                         .unwrap_or_else(|| root_module.starts_with(base));
                     let (include, exclude) = match crate_data.source {
                         Some(src) => {
-                            let absolutize = |dirs: Vec<PathBuf>| {
+                            let absolutize = |dirs: Vec<Utf8PathBuf>| {
                                 dirs.into_iter().map(absolutize_on_base).collect::<Vec<_>>()
                             };
                             (absolutize(src.include_dirs), absolutize(src.exclude_dirs))
@@ -176,15 +175,15 @@ impl ProjectJson {
 
 #[derive(Deserialize, Debug, Clone)]
 pub struct ProjectJsonData {
-    sysroot: Option<PathBuf>,
-    sysroot_src: Option<PathBuf>,
+    sysroot: Option<Utf8PathBuf>,
+    sysroot_src: Option<Utf8PathBuf>,
     crates: Vec<CrateData>,
 }
 
 #[derive(Deserialize, Debug, Clone)]
 struct CrateData {
     display_name: Option<String>,
-    root_module: PathBuf,
+    root_module: Utf8PathBuf,
     edition: EditionData,
     #[serde(default)]
     version: Option<semver::Version>,
@@ -194,7 +193,7 @@ struct CrateData {
     target: Option<String>,
     #[serde(default)]
     env: FxHashMap<String, String>,
-    proc_macro_dylib_path: Option<PathBuf>,
+    proc_macro_dylib_path: Option<Utf8PathBuf>,
     is_workspace_member: Option<bool>,
     source: Option<CrateSource>,
     #[serde(default)]
@@ -238,8 +237,8 @@ struct DepData {
 
 #[derive(Deserialize, Debug, Clone)]
 struct CrateSource {
-    include_dirs: Vec<PathBuf>,
-    exclude_dirs: Vec<PathBuf>,
+    include_dirs: Vec<Utf8PathBuf>,
+    exclude_dirs: Vec<Utf8PathBuf>,
 }
 
 fn deserialize_crate_name<'de, D>(de: D) -> std::result::Result<CrateName, D::Error>
diff --git a/crates/project-model/src/sysroot.rs b/crates/project-model/src/sysroot.rs
index 3127bae8b0..1142d6243d 100644
--- a/crates/project-model/src/sysroot.rs
+++ b/crates/project-model/src/sysroot.rs
@@ -4,13 +4,13 @@
 //! but we can't process `.rlib` and need source code instead. The source code
 //! is typically installed with `rustup component add rust-src` command.
 
-use std::{env, fs, iter, ops, path::PathBuf, process::Command, sync::Arc};
+use std::{env, fs, iter, ops, process::Command, sync::Arc};
 
 use anyhow::{format_err, Result};
 use base_db::CrateName;
 use itertools::Itertools;
 use la_arena::{Arena, Idx};
-use paths::{AbsPath, AbsPathBuf};
+use paths::{AbsPath, AbsPathBuf, Utf8PathBuf};
 use rustc_hash::FxHashMap;
 use toolchain::{probe_for_binary, Tool};
 
@@ -419,7 +419,7 @@ fn discover_sysroot_dir(
     rustc.current_dir(current_dir).args(["--print", "sysroot"]);
     tracing::debug!("Discovering sysroot by {:?}", rustc);
     let stdout = utf8_stdout(rustc)?;
-    Ok(AbsPathBuf::assert(PathBuf::from(stdout)))
+    Ok(AbsPathBuf::assert(Utf8PathBuf::from(stdout)))
 }
 
 fn discover_sysroot_src_dir(sysroot_path: &AbsPathBuf) -> Option<AbsPathBuf> {
diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs
index 8b4d6d9941..c6642efca2 100644
--- a/crates/project-model/src/workspace.rs
+++ b/crates/project-model/src/workspace.rs
@@ -1173,7 +1173,6 @@ fn detached_files_to_crate_graph(
         };
         let display_name = detached_file
             .file_stem()
-            .and_then(|os_str| os_str.to_str())
             .map(|file_stem| CrateDisplayName::from_canonical_name(file_stem.to_owned()));
         let detached_file_crate = crate_graph.add_crate_root(
             file_id,
@@ -1555,7 +1554,7 @@ fn inject_cargo_env(package: &PackageData, env: &mut Env) {
     // CARGO_BIN_NAME, CARGO_BIN_EXE_<name>
 
     let manifest_dir = package.manifest.parent();
-    env.set("CARGO_MANIFEST_DIR", manifest_dir.as_os_str().to_string_lossy().into_owned());
+    env.set("CARGO_MANIFEST_DIR", manifest_dir.as_str().to_owned());
 
     // Not always right, but works for common cases.
     env.set("CARGO", "cargo".into());
diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml
index e6984d6f41..6d70124188 100644
--- a/crates/rust-analyzer/Cargo.toml
+++ b/crates/rust-analyzer/Cargo.toml
@@ -43,6 +43,7 @@ nohash-hasher.workspace = true
 always-assert = "0.2.0"
 walkdir = "2.3.2"
 semver.workspace = true
+memchr = "2.7.1"
 
 cfg.workspace = true
 flycheck.workspace = true
@@ -63,7 +64,7 @@ parser.workspace = true
 toolchain.workspace = true
 vfs-notify.workspace = true
 vfs.workspace = true
-memchr = "2.7.1"
+paths.workspace = true
 
 [target.'cfg(windows)'.dependencies]
 winapi = "0.3.9"
diff --git a/crates/rust-analyzer/src/bin/main.rs b/crates/rust-analyzer/src/bin/main.rs
index e747ec87b1..78920f3aba 100644
--- a/crates/rust-analyzer/src/bin/main.rs
+++ b/crates/rust-analyzer/src/bin/main.rs
@@ -190,7 +190,7 @@ fn run_server() -> anyhow::Result<()> {
         Some(it) => it,
         None => {
             let cwd = env::current_dir()?;
-            AbsPathBuf::assert(cwd)
+            AbsPathBuf::assert_utf8(cwd)
         }
     };
 
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs
index 5c474908e7..c636f7494a 100644
--- a/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -70,7 +70,7 @@ impl flags::AnalysisStats {
 
         let mut db_load_sw = self.stop_watch();
 
-        let path = AbsPathBuf::assert(env::current_dir()?.join(&self.path));
+        let path = AbsPathBuf::assert_utf8(env::current_dir()?.join(&self.path));
         let manifest = ProjectManifest::discover_single(&path)?;
 
         let mut workspace = ProjectWorkspace::load(manifest, &cargo_config, no_progress)?;
diff --git a/crates/rust-analyzer/src/cli/diagnostics.rs b/crates/rust-analyzer/src/cli/diagnostics.rs
index bd2646126d..79d6226deb 100644
--- a/crates/rust-analyzer/src/cli/diagnostics.rs
+++ b/crates/rust-analyzer/src/cli/diagnostics.rs
@@ -16,7 +16,7 @@ impl flags::Diagnostics {
         let cargo_config =
             CargoConfig { sysroot: Some(RustLibSource::Discover), ..Default::default() };
         let with_proc_macro_server = if let Some(p) = &self.proc_macro_srv {
-            let path = vfs::AbsPathBuf::assert(std::env::current_dir()?.join(p));
+            let path = vfs::AbsPathBuf::assert_utf8(std::env::current_dir()?.join(p));
             ProcMacroServerChoice::Explicit(path)
         } else {
             ProcMacroServerChoice::Sysroot
diff --git a/crates/rust-analyzer/src/cli/lsif.rs b/crates/rust-analyzer/src/cli/lsif.rs
index f3f5ec1ebd..3ff9be7102 100644
--- a/crates/rust-analyzer/src/cli/lsif.rs
+++ b/crates/rust-analyzer/src/cli/lsif.rs
@@ -283,7 +283,7 @@ impl flags::Lsif {
             with_proc_macro_server: ProcMacroServerChoice::Sysroot,
             prefill_caches: false,
         };
-        let path = AbsPathBuf::assert(env::current_dir()?.join(self.path));
+        let path = AbsPathBuf::assert_utf8(env::current_dir()?.join(self.path));
         let manifest = ProjectManifest::discover_single(&path)?;
 
         let workspace = ProjectWorkspace::load(manifest, &cargo_config, no_progress)?;
diff --git a/crates/rust-analyzer/src/cli/scip.rs b/crates/rust-analyzer/src/cli/scip.rs
index 1061a433a5..aef2c1be22 100644
--- a/crates/rust-analyzer/src/cli/scip.rs
+++ b/crates/rust-analyzer/src/cli/scip.rs
@@ -27,7 +27,8 @@ impl flags::Scip {
             with_proc_macro_server: ProcMacroServerChoice::Sysroot,
             prefill_caches: true,
         };
-        let root = vfs::AbsPathBuf::assert(std::env::current_dir()?.join(&self.path)).normalize();
+        let root =
+            vfs::AbsPathBuf::assert_utf8(std::env::current_dir()?.join(&self.path)).normalize();
 
         let mut config = crate::config::Config::new(
             root.clone(),
@@ -63,12 +64,7 @@ impl flags::Scip {
                 special_fields: Default::default(),
             })
             .into(),
-            project_root: format!(
-                "file://{}",
-                root.as_os_str()
-                    .to_str()
-                    .ok_or(anyhow::format_err!("Unable to normalize project_root path"))?
-            ),
+            project_root: format!("file://{root}"),
             text_document_encoding: scip_types::TextEncoding::UTF8.into(),
             special_fields: Default::default(),
         };
@@ -216,7 +212,7 @@ fn get_relative_filepath(
     rootpath: &vfs::AbsPathBuf,
     file_id: ide::FileId,
 ) -> Option<String> {
-    Some(vfs.file_path(file_id).as_path()?.strip_prefix(rootpath)?.as_ref().to_str()?.to_owned())
+    Some(vfs.file_path(file_id).as_path()?.strip_prefix(rootpath)?.as_str().to_owned())
 }
 
 // SCIP Ranges have a (very large) optimization that ranges if they are on the same line
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index cbf1524659..e6b60f6906 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -7,11 +7,7 @@
 //! configure the server itself, feature flags are passed into analysis, and
 //! tweak things like automatic insertion of `()` in completions.
 
-use std::{
-    fmt, iter,
-    ops::Not,
-    path::{Path, PathBuf},
-};
+use std::{fmt, iter, ops::Not};
 
 use cfg::{CfgAtom, CfgDiff};
 use flycheck::FlycheckConfig;
@@ -27,6 +23,7 @@ use ide_db::{
 };
 use itertools::Itertools;
 use lsp_types::{ClientCapabilities, MarkupKind};
+use paths::{Utf8Path, Utf8PathBuf};
 use project_model::{
     CargoConfig, CargoFeatures, ProjectJson, ProjectJsonData, ProjectManifest, RustLibSource,
 };
@@ -327,7 +324,7 @@ config_data! {
         /// These directories will be ignored by rust-analyzer. They are
         /// relative to the workspace root, and globs are not supported. You may
         /// also need to add the folders to Code's `files.watcherExclude`.
-        files_excludeDirs: Vec<PathBuf> = "[]",
+        files_excludeDirs: Vec<Utf8PathBuf> = "[]",
         /// Controls file watching implementation.
         files_watcher: FilesWatcherDef = "\"client\"",
 
@@ -516,7 +513,7 @@ config_data! {
         /// This config takes a map of crate names with the exported proc-macro names to ignore as values.
         procMacro_ignored: FxHashMap<Box<str>, Box<[Box<str>]>>          = "{}",
         /// Internal config, path to proc-macro server executable.
-        procMacro_server: Option<PathBuf>          = "null",
+        procMacro_server: Option<Utf8PathBuf>          = "null",
 
         /// Exclude imports from find-all-references.
         references_excludeImports: bool = "false",
@@ -864,7 +861,7 @@ impl Config {
         }
         let mut errors = Vec::new();
         self.detached_files =
-            get_field::<Vec<PathBuf>>(&mut json, &mut errors, "detachedFiles", None, "[]")
+            get_field::<Vec<Utf8PathBuf>>(&mut json, &mut errors, "detachedFiles", None, "[]")
                 .into_iter()
                 .map(AbsPathBuf::assert)
                 .collect();
@@ -956,7 +953,7 @@ impl Config {
     pub fn has_linked_projects(&self) -> bool {
         !self.data.linkedProjects.is_empty()
     }
-    pub fn linked_manifests(&self) -> impl Iterator<Item = &Path> + '_ {
+    pub fn linked_manifests(&self) -> impl Iterator<Item = &Utf8Path> + '_ {
         self.data.linkedProjects.iter().filter_map(|it| match it {
             ManifestOrProjectJson::Manifest(p) => Some(&**p),
             ManifestOrProjectJson::ProjectJson(_) => None,
@@ -1410,9 +1407,11 @@ impl Config {
         }
     }
 
-    fn target_dir_from_config(&self) -> Option<PathBuf> {
+    fn target_dir_from_config(&self) -> Option<Utf8PathBuf> {
         self.data.cargo_targetDir.as_ref().and_then(|target_dir| match target_dir {
-            TargetDirectory::UseSubdirectory(true) => Some(PathBuf::from("target/rust-analyzer")),
+            TargetDirectory::UseSubdirectory(true) => {
+                Some(Utf8PathBuf::from("target/rust-analyzer"))
+            }
             TargetDirectory::UseSubdirectory(false) => None,
             TargetDirectory::Directory(dir) if dir.is_relative() => Some(dir.clone()),
             TargetDirectory::Directory(_) => None,
@@ -1951,7 +1950,7 @@ where
 #[derive(Deserialize, Debug, Clone)]
 #[serde(untagged)]
 enum ManifestOrProjectJson {
-    Manifest(PathBuf),
+    Manifest(Utf8PathBuf),
     ProjectJson(ProjectJsonData),
 }
 
@@ -2134,7 +2133,7 @@ pub enum MemoryLayoutHoverRenderKindDef {
 #[serde(untagged)]
 pub enum TargetDirectory {
     UseSubdirectory(bool),
-    Directory(PathBuf),
+    Directory(Utf8PathBuf),
 }
 
 macro_rules! _config_data {
@@ -2263,7 +2262,7 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json
             "type": "array",
             "items": { "type": "string" },
         },
-        "Vec<PathBuf>" => set! {
+        "Vec<Utf8PathBuf>" => set! {
             "type": "array",
             "items": { "type": "string" },
         },
@@ -2291,7 +2290,7 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json
         "Option<String>" => set! {
             "type": ["null", "string"],
         },
-        "Option<PathBuf>" => set! {
+        "Option<Utf8PathBuf>" => set! {
             "type": ["null", "string"],
         },
         "Option<bool>" => set! {
@@ -2774,7 +2773,7 @@ mod tests {
             .unwrap();
         assert_eq!(config.data.cargo_targetDir, Some(TargetDirectory::UseSubdirectory(true)));
         assert!(
-            matches!(config.flycheck(), FlycheckConfig::CargoCommand { target_dir, .. } if target_dir == Some(PathBuf::from("target/rust-analyzer")))
+            matches!(config.flycheck(), FlycheckConfig::CargoCommand { target_dir, .. } if target_dir == Some(Utf8PathBuf::from("target/rust-analyzer")))
         );
     }
 
@@ -2793,10 +2792,10 @@ mod tests {
             .unwrap();
         assert_eq!(
             config.data.cargo_targetDir,
-            Some(TargetDirectory::Directory(PathBuf::from("other_folder")))
+            Some(TargetDirectory::Directory(Utf8PathBuf::from("other_folder")))
         );
         assert!(
-            matches!(config.flycheck(), FlycheckConfig::CargoCommand { target_dir, .. } if target_dir == Some(PathBuf::from("other_folder")))
+            matches!(config.flycheck(), FlycheckConfig::CargoCommand { target_dir, .. } if target_dir == Some(Utf8PathBuf::from("other_folder")))
         );
     }
 }
diff --git a/crates/rust-analyzer/src/diagnostics/to_proto.rs b/crates/rust-analyzer/src/diagnostics/to_proto.rs
index 6e6cc53c25..7c4deac93f 100644
--- a/crates/rust-analyzer/src/diagnostics/to_proto.rs
+++ b/crates/rust-analyzer/src/diagnostics/to_proto.rs
@@ -519,14 +519,13 @@ fn clippy_code_description(code: Option<&str>) -> Option<lsp_types::CodeDescript
 #[cfg(test)]
 #[cfg(not(windows))]
 mod tests {
-    use std::path::Path;
-
     use crate::{config::Config, global_state::GlobalState};
 
     use super::*;
 
     use expect_test::{expect_file, ExpectFile};
     use lsp_types::ClientCapabilities;
+    use paths::Utf8Path;
 
     fn check(diagnostics_json: &str, expect: ExpectFile) {
         check_with_config(DiagnosticsMapConfig::default(), diagnostics_json, expect)
@@ -534,7 +533,7 @@ mod tests {
 
     fn check_with_config(config: DiagnosticsMapConfig, diagnostics_json: &str, expect: ExpectFile) {
         let diagnostic: flycheck::Diagnostic = serde_json::from_str(diagnostics_json).unwrap();
-        let workspace_root: &AbsPath = Path::new("/test/").try_into().unwrap();
+        let workspace_root: &AbsPath = Utf8Path::new("/test/").try_into().unwrap();
         let (sender, _) = crossbeam_channel::unbounded();
         let state = GlobalState::new(
             sender,
diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs
index ab7f944328..4d4103a7ad 100644
--- a/crates/rust-analyzer/src/handlers/request.rs
+++ b/crates/rust-analyzer/src/handlers/request.rs
@@ -4,7 +4,6 @@
 use std::{
     fs,
     io::Write as _,
-    path::PathBuf,
     process::{self, Stdio},
 };
 
@@ -27,6 +26,7 @@ use lsp_types::{
     SemanticTokensParams, SemanticTokensRangeParams, SemanticTokensRangeResult,
     SemanticTokensResult, SymbolInformation, SymbolTag, TextDocumentIdentifier, Url, WorkspaceEdit,
 };
+use paths::Utf8PathBuf;
 use project_model::{ManifestPath, ProjectWorkspace, TargetKind};
 use serde_json::json;
 use stdx::{format_to, never};
@@ -1737,8 +1737,8 @@ pub(crate) fn handle_open_docs(
         _ => (None, None),
     };
 
-    let sysroot = sysroot.map(|p| p.root().as_os_str());
-    let target_dir = cargo.map(|cargo| cargo.target_directory()).map(|p| p.as_os_str());
+    let sysroot = sysroot.map(|p| p.root().as_str());
+    let target_dir = cargo.map(|cargo| cargo.target_directory()).map(|p| p.as_str());
 
     let Ok(remote_urls) = snap.analysis.external_docs(position, target_dir, sysroot) else {
         return if snap.config.local_docs() {
@@ -2043,7 +2043,7 @@ fn run_rustfmt(
             cmd
         }
         RustfmtConfig::CustomCommand { command, args } => {
-            let cmd = PathBuf::from(&command);
+            let cmd = Utf8PathBuf::from(&command);
             let workspace = CargoTargetSpec::for_file(snap, file_id)?;
             let mut cmd = match workspace {
                 Some(spec) => {
diff --git a/crates/rust-analyzer/src/integrated_benchmarks.rs b/crates/rust-analyzer/src/integrated_benchmarks.rs
index 1c5a862c70..2731e845f3 100644
--- a/crates/rust-analyzer/src/integrated_benchmarks.rs
+++ b/crates/rust-analyzer/src/integrated_benchmarks.rs
@@ -52,7 +52,7 @@ fn integrated_highlighting_benchmark() {
 
     let file_id = {
         let file = workspace_to_load.join(file);
-        let path = VfsPath::from(AbsPathBuf::assert(file));
+        let path = VfsPath::from(AbsPathBuf::assert_utf8(file));
         vfs.file_id(&path).unwrap_or_else(|| panic!("can't find virtual file for {path}"))
     };
 
@@ -112,7 +112,7 @@ fn integrated_completion_benchmark() {
 
     let file_id = {
         let file = workspace_to_load.join(file);
-        let path = VfsPath::from(AbsPathBuf::assert(file));
+        let path = VfsPath::from(AbsPathBuf::assert_utf8(file));
         vfs.file_id(&path).unwrap_or_else(|| panic!("can't find virtual file for {path}"))
     };
 
@@ -274,7 +274,7 @@ fn integrated_diagnostics_benchmark() {
 
     let file_id = {
         let file = workspace_to_load.join(file);
-        let path = VfsPath::from(AbsPathBuf::assert(file));
+        let path = VfsPath::from(AbsPathBuf::assert_utf8(file));
         vfs.file_id(&path).unwrap_or_else(|| panic!("can't find virtual file for {path}"))
     };
 
diff --git a/crates/rust-analyzer/src/lsp/to_proto.rs b/crates/rust-analyzer/src/lsp/to_proto.rs
index 44f0b1c80f..d8bb12528b 100644
--- a/crates/rust-analyzer/src/lsp/to_proto.rs
+++ b/crates/rust-analyzer/src/lsp/to_proto.rs
@@ -1,7 +1,7 @@
 //! Conversion of rust-analyzer specific types to lsp_types equivalents.
 use std::{
     iter::once,
-    mem, path,
+    mem,
     sync::atomic::{AtomicU32, Ordering},
 };
 
@@ -15,6 +15,7 @@ use ide::{
 };
 use ide_db::{rust_doc::format_docs, FxHasher};
 use itertools::Itertools;
+use paths::{Utf8Component, Utf8Prefix};
 use semver::VersionReq;
 use serde_json::to_value;
 use vfs::AbsPath;
@@ -816,9 +817,9 @@ pub(crate) fn url(snap: &GlobalStateSnapshot, file_id: FileId) -> lsp_types::Url
 /// When processing non-windows path, this is essentially the same as `Url::from_file_path`.
 pub(crate) fn url_from_abs_path(path: &AbsPath) -> lsp_types::Url {
     let url = lsp_types::Url::from_file_path(path).unwrap();
-    match path.as_ref().components().next() {
-        Some(path::Component::Prefix(prefix))
-            if matches!(prefix.kind(), path::Prefix::Disk(_) | path::Prefix::VerbatimDisk(_)) =>
+    match path.components().next() {
+        Some(Utf8Component::Prefix(prefix))
+            if matches!(prefix.kind(), Utf8Prefix::Disk(_) | Utf8Prefix::VerbatimDisk(_)) =>
         {
             // Need to lowercase driver letter
         }
@@ -2730,12 +2731,12 @@ struct ProcMacro {
     #[test]
     #[cfg(target_os = "windows")]
     fn test_lowercase_drive_letter() {
-        use std::path::Path;
+        use paths::Utf8Path;
 
-        let url = url_from_abs_path(Path::new("C:\\Test").try_into().unwrap());
+        let url = url_from_abs_path(Utf8Path::new("C:\\Test").try_into().unwrap());
         assert_eq!(url.to_string(), "file:///c:/Test");
 
-        let url = url_from_abs_path(Path::new(r#"\\localhost\C$\my_dir"#).try_into().unwrap());
+        let url = url_from_abs_path(Utf8Path::new(r#"\\localhost\C$\my_dir"#).try_into().unwrap());
         assert_eq!(url.to_string(), "file://localhost/C$/my_dir");
     }
 }
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index 945d169a69..d602506939 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -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,
@@ -714,10 +714,9 @@ impl GlobalState {
                     message += &format!(
                         ": {}",
                         match dir.strip_prefix(self.config.root_path()) {
-                            Some(relative_path) => relative_path.as_ref(),
+                            Some(relative_path) => relative_path.as_utf8_path(),
                             None => dir.as_ref(),
                         }
-                        .display()
                     );
                 }
 
@@ -861,7 +860,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..967904a01a 100644
--- a/crates/rust-analyzer/src/reload.rs
+++ b/crates/rust-analyzer/src/reload.rs
@@ -185,10 +185,8 @@ impl GlobalState {
                 message.push_str(
                     "`rust-analyzer.linkedProjects` have been specified, which may be incorrect. Specified project paths:\n",
                 );
-                message.push_str(&format!(
-                    "    {}",
-                    self.config.linked_manifests().map(|it| it.display()).format("\n    ")
-                ));
+                message
+                    .push_str(&format!("    {}", self.config.linked_manifests().format("\n    ")));
                 if self.config.has_linked_project_jsons() {
                     message.push_str("\nAdditionally, one or more project jsons are specified")
                 }
@@ -526,13 +524,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 +562,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();
@@ -753,7 +737,7 @@ pub(crate) fn should_refresh_for_change(path: &AbsPath, change_kind: ChangeKind)
     const IMPLICIT_TARGET_FILES: &[&str] = &["build.rs", "src/main.rs", "src/lib.rs"];
     const IMPLICIT_TARGET_DIRS: &[&str] = &["src/bin", "examples", "tests", "benches"];
 
-    let file_name = match path.file_name().unwrap_or_default().to_str() {
+    let file_name = match path.file_name() {
         Some(it) => it,
         None => return false,
     };
@@ -768,18 +752,18 @@ pub(crate) fn should_refresh_for_change(path: &AbsPath, change_kind: ChangeKind)
     // .cargo/config{.toml}
     if path.extension().unwrap_or_default() != "rs" {
         let is_cargo_config = matches!(file_name, "config.toml" | "config")
-            && path.parent().map(|parent| parent.as_ref().ends_with(".cargo")).unwrap_or(false);
+            && path.parent().map(|parent| parent.as_str().ends_with(".cargo")).unwrap_or(false);
         return is_cargo_config;
     }
 
-    if IMPLICIT_TARGET_FILES.iter().any(|it| path.as_ref().ends_with(it)) {
+    if IMPLICIT_TARGET_FILES.iter().any(|it| path.as_str().ends_with(it)) {
         return true;
     }
     let parent = match path.parent() {
         Some(it) => it,
         None => return false,
     };
-    if IMPLICIT_TARGET_DIRS.iter().any(|it| parent.as_ref().ends_with(it)) {
+    if IMPLICIT_TARGET_DIRS.iter().any(|it| parent.as_str().ends_with(it)) {
         return true;
     }
     if file_name == "main.rs" {
@@ -787,7 +771,7 @@ pub(crate) fn should_refresh_for_change(path: &AbsPath, change_kind: ChangeKind)
             Some(it) => it,
             None => return false,
         };
-        if IMPLICIT_TARGET_DIRS.iter().any(|it| grand_parent.as_ref().ends_with(it)) {
+        if IMPLICIT_TARGET_DIRS.iter().any(|it| grand_parent.as_str().ends_with(it)) {
             return true;
         }
     }
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/crates/toolchain/Cargo.toml b/crates/toolchain/Cargo.toml
index f9b120772f..c85efd432b 100644
--- a/crates/toolchain/Cargo.toml
+++ b/crates/toolchain/Cargo.toml
@@ -13,6 +13,7 @@ doctest = false
 
 [dependencies]
 home = "0.5.4"
+camino.workspace = true
 
 [lints]
-workspace = true
\ No newline at end of file
+workspace = true
diff --git a/crates/toolchain/src/lib.rs b/crates/toolchain/src/lib.rs
index a77fed585a..b577723612 100644
--- a/crates/toolchain/src/lib.rs
+++ b/crates/toolchain/src/lib.rs
@@ -2,10 +2,9 @@
 
 #![warn(rust_2018_idioms, unused_lifetimes)]
 
-use std::{
-    env, iter,
-    path::{Path, PathBuf},
-};
+use std::{env, iter, path::PathBuf};
+
+use camino::{Utf8Path, Utf8PathBuf};
 
 #[derive(Copy, Clone)]
 pub enum Tool {
@@ -16,7 +15,7 @@ pub enum Tool {
 }
 
 impl Tool {
-    pub fn proxy(self) -> Option<PathBuf> {
+    pub fn proxy(self) -> Option<Utf8PathBuf> {
         cargo_proxy(self.name())
     }
 
@@ -33,7 +32,7 @@ impl Tool {
     ///      example: for cargo, this tries all paths in $PATH with appended `cargo`, returning the
     ///      first that exists
     /// 4) If all else fails, we just try to use the executable name directly
-    pub fn prefer_proxy(self) -> PathBuf {
+    pub fn prefer_proxy(self) -> Utf8PathBuf {
         invoke(&[cargo_proxy, lookup_as_env_var, lookup_in_path], self.name())
     }
 
@@ -50,11 +49,11 @@ impl Tool {
     ///      example: for cargo, this tries $CARGO_HOME/bin/cargo, or ~/.cargo/bin/cargo if $CARGO_HOME is unset.
     ///      It seems that this is a reasonable place to try for cargo, rustc, and rustup
     /// 4) If all else fails, we just try to use the executable name directly
-    pub fn path(self) -> PathBuf {
+    pub fn path(self) -> Utf8PathBuf {
         invoke(&[lookup_as_env_var, lookup_in_path, cargo_proxy], self.name())
     }
 
-    pub fn path_in(self, path: &Path) -> Option<PathBuf> {
+    pub fn path_in(self, path: &Utf8Path) -> Option<Utf8PathBuf> {
         probe_for_binary(path.join(self.name()))
     }
 
@@ -68,42 +67,50 @@ impl Tool {
     }
 }
 
-fn invoke(list: &[fn(&str) -> Option<PathBuf>], executable: &str) -> PathBuf {
+fn invoke(list: &[fn(&str) -> Option<Utf8PathBuf>], executable: &str) -> Utf8PathBuf {
     list.iter().find_map(|it| it(executable)).unwrap_or_else(|| executable.into())
 }
 
 /// Looks up the binary as its SCREAMING upper case in the env variables.
-fn lookup_as_env_var(executable_name: &str) -> Option<PathBuf> {
-    env::var_os(executable_name.to_ascii_uppercase()).map(Into::into)
+fn lookup_as_env_var(executable_name: &str) -> Option<Utf8PathBuf> {
+    env::var_os(executable_name.to_ascii_uppercase())
+        .map(PathBuf::from)
+        .map(Utf8PathBuf::try_from)
+        .and_then(Result::ok)
 }
 
 /// Looks up the binary in the cargo home directory if it exists.
-fn cargo_proxy(executable_name: &str) -> Option<PathBuf> {
+fn cargo_proxy(executable_name: &str) -> Option<Utf8PathBuf> {
     let mut path = get_cargo_home()?;
     path.push("bin");
     path.push(executable_name);
     probe_for_binary(path)
 }
 
-fn get_cargo_home() -> Option<PathBuf> {
+fn get_cargo_home() -> Option<Utf8PathBuf> {
     if let Some(path) = env::var_os("CARGO_HOME") {
-        return Some(path.into());
+        return Utf8PathBuf::try_from(PathBuf::from(path)).ok();
     }
 
     if let Some(mut path) = home::home_dir() {
         path.push(".cargo");
-        return Some(path);
+        return Utf8PathBuf::try_from(path).ok();
     }
 
     None
 }
 
-fn lookup_in_path(exec: &str) -> Option<PathBuf> {
+fn lookup_in_path(exec: &str) -> Option<Utf8PathBuf> {
     let paths = env::var_os("PATH").unwrap_or_default();
-    env::split_paths(&paths).map(|path| path.join(exec)).find_map(probe_for_binary)
+    env::split_paths(&paths)
+        .map(|path| path.join(exec))
+        .map(PathBuf::from)
+        .map(Utf8PathBuf::try_from)
+        .filter_map(Result::ok)
+        .find_map(probe_for_binary)
 }
 
-pub fn probe_for_binary(path: PathBuf) -> Option<PathBuf> {
+pub fn probe_for_binary(path: Utf8PathBuf) -> Option<Utf8PathBuf> {
     let with_extension = match env::consts::EXE_EXTENSION {
         "" => None,
         it => Some(path.with_extension(it)),
diff --git a/crates/vfs-notify/src/lib.rs b/crates/vfs-notify/src/lib.rs
index 15a0ea5409..94fd6cb78c 100644
--- a/crates/vfs-notify/src/lib.rs
+++ b/crates/vfs-notify/src/lib.rs
@@ -13,7 +13,7 @@ use std::fs;
 
 use crossbeam_channel::{never, select, unbounded, Receiver, Sender};
 use notify::{Config, RecommendedWatcher, RecursiveMode, Watcher};
-use paths::{AbsPath, AbsPathBuf};
+use paths::{AbsPath, AbsPathBuf, Utf8Path};
 use vfs::loader;
 use walkdir::WalkDir;
 
@@ -205,7 +205,7 @@ impl NotifyActor {
                             if !entry.file_type().is_dir() {
                                 return true;
                             }
-                            let path = AbsPath::assert(entry.path());
+                            let path = AbsPath::assert(Utf8Path::from_path(entry.path()).unwrap());
                             root == path
                                 || dirs.exclude.iter().chain(&dirs.include).all(|it| it != path)
                         });
@@ -214,7 +214,7 @@ impl NotifyActor {
                         let depth = entry.depth();
                         let is_dir = entry.file_type().is_dir();
                         let is_file = entry.file_type().is_file();
-                        let abs_path = AbsPathBuf::assert(entry.into_path());
+                        let abs_path = AbsPathBuf::try_from(entry.into_path()).unwrap();
                         if depth < 2 && is_dir {
                             self.send(make_message(abs_path.clone()));
                         }
diff --git a/crates/vfs/src/vfs_path.rs b/crates/vfs/src/vfs_path.rs
index 52ada32bdf..2d3fb9d88c 100644
--- a/crates/vfs/src/vfs_path.rs
+++ b/crates/vfs/src/vfs_path.rs
@@ -326,7 +326,7 @@ impl VirtualPath {
     }
 
     fn strip_prefix(&self, base: &VirtualPath) -> Option<&RelPath> {
-        <_ as AsRef<std::path::Path>>::as_ref(&self.0)
+        <_ as AsRef<paths::Utf8Path>>::as_ref(&self.0)
             .strip_prefix(&base.0)
             .ok()
             .map(RelPath::new_unchecked)
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/ide/src/doc_links/tests.rs b/crates/ide/src/doc_links/tests.rs
index 60e8d29a71..ac44908a90 100644
--- a/crates/ide/src/doc_links/tests.rs
+++ b/crates/ide/src/doc_links/tests.rs
@@ -1,4 +1,4 @@
-use std::{ffi::OsStr, iter};
+use std::iter;
 
 use expect_test::{expect, Expect};
 use hir::Semantics;
@@ -18,10 +18,10 @@ use crate::{
 
 fn check_external_docs(
     ra_fixture: &str,
-    target_dir: Option<&OsStr>,
+    target_dir: Option<&str>,
     expect_web_url: Option<Expect>,
     expect_local_url: Option<Expect>,
-    sysroot: Option<&OsStr>,
+    sysroot: Option<&str>,
 ) {
     let (analysis, position) = fixture::position(ra_fixture);
     let links = analysis.external_docs(position, target_dir, sysroot).unwrap();
@@ -127,10 +127,10 @@ fn external_docs_doc_builtin_type() {
 //- /main.rs crate:foo
 let x: u3$02 = 0;
 "#,
-        Some(OsStr::new("/home/user/project")),
+        Some("/home/user/project"),
         Some(expect![[r#"https://doc.rust-lang.org/nightly/core/primitive.u32.html"#]]),
         Some(expect![[r#"file:///sysroot/share/doc/rust/html/core/primitive.u32.html"#]]),
-        Some(OsStr::new("/sysroot")),
+        Some("/sysroot"),
     );
 }
 
@@ -143,10 +143,10 @@ use foo$0::Foo;
 //- /lib.rs crate:foo
 pub struct Foo;
 "#,
-        Some(OsStr::new("/home/user/project")),
+        Some("/home/user/project"),
         Some(expect![[r#"https://docs.rs/foo/*/foo/index.html"#]]),
         Some(expect![[r#"file:///home/user/project/doc/foo/index.html"#]]),
-        Some(OsStr::new("/sysroot")),
+        Some("/sysroot"),
     );
 }
 
@@ -157,10 +157,10 @@ fn external_docs_doc_url_std_crate() {
 //- /main.rs crate:std
 use self$0;
 "#,
-        Some(OsStr::new("/home/user/project")),
+        Some("/home/user/project"),
         Some(expect!["https://doc.rust-lang.org/stable/std/index.html"]),
         Some(expect!["file:///sysroot/share/doc/rust/html/std/index.html"]),
-        Some(OsStr::new("/sysroot")),
+        Some("/sysroot"),
     );
 }
 
@@ -171,10 +171,10 @@ fn external_docs_doc_url_struct() {
 //- /main.rs crate:foo
 pub struct Fo$0o;
 "#,
-        Some(OsStr::new("/home/user/project")),
+        Some("/home/user/project"),
         Some(expect![[r#"https://docs.rs/foo/*/foo/struct.Foo.html"#]]),
         Some(expect![[r#"file:///home/user/project/doc/foo/struct.Foo.html"#]]),
-        Some(OsStr::new("/sysroot")),
+        Some("/sysroot"),
     );
 }
 
@@ -185,10 +185,10 @@ fn external_docs_doc_url_windows_backslash_path() {
 //- /main.rs crate:foo
 pub struct Fo$0o;
 "#,
-        Some(OsStr::new(r"C:\Users\user\project")),
+        Some(r"C:\Users\user\project"),
         Some(expect![[r#"https://docs.rs/foo/*/foo/struct.Foo.html"#]]),
         Some(expect![[r#"file:///C:/Users/user/project/doc/foo/struct.Foo.html"#]]),
-        Some(OsStr::new("/sysroot")),
+        Some("/sysroot"),
     );
 }
 
@@ -199,10 +199,10 @@ fn external_docs_doc_url_windows_slash_path() {
 //- /main.rs crate:foo
 pub struct Fo$0o;
 "#,
-        Some(OsStr::new(r"C:/Users/user/project")),
+        Some("C:/Users/user/project"),
         Some(expect![[r#"https://docs.rs/foo/*/foo/struct.Foo.html"#]]),
         Some(expect![[r#"file:///C:/Users/user/project/doc/foo/struct.Foo.html"#]]),
-        Some(OsStr::new("/sysroot")),
+        Some("/sysroot"),
     );
 }
 
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/project-model/src/tests.rs b/crates/project-model/src/tests.rs
index b9b1b701f6..fc0b507b33 100644
--- a/crates/project-model/src/tests.rs
+++ b/crates/project-model/src/tests.rs
@@ -1,12 +1,9 @@
-use std::{
-    ops::Deref,
-    path::{Path, PathBuf},
-};
+use std::ops::Deref;
 
 use base_db::{CrateGraph, FileId, ProcMacroPaths};
 use cfg::{CfgAtom, CfgDiff};
 use expect_test::{expect_file, ExpectFile};
-use paths::{AbsPath, AbsPathBuf};
+use paths::{AbsPath, AbsPathBuf, Utf8Path, Utf8PathBuf};
 use rustc_hash::FxHashMap;
 use serde::de::DeserializeOwned;
 use triomphe::Arc;
@@ -113,17 +110,16 @@ fn replace_root(s: &mut String, direction: bool) {
 fn replace_fake_sys_root(s: &mut String) {
     let fake_sysroot_path = get_test_path("fake-sysroot");
     let fake_sysroot_path = if cfg!(windows) {
-        let normalized_path =
-            fake_sysroot_path.to_str().expect("expected str").replace('\\', r#"\\"#);
+        let normalized_path = fake_sysroot_path.as_str().replace('\\', r#"\\"#);
         format!(r#"{}\\"#, normalized_path)
     } else {
-        format!("{}/", fake_sysroot_path.to_str().expect("expected str"))
+        format!("{}/", fake_sysroot_path.as_str())
     };
     *s = s.replace(&fake_sysroot_path, "$FAKESYSROOT$")
 }
 
-fn get_test_path(file: &str) -> PathBuf {
-    let base = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
+fn get_test_path(file: &str) -> Utf8PathBuf {
+    let base = Utf8PathBuf::from(env!("CARGO_MANIFEST_DIR"));
     base.join("test_data").join(file)
 }
 
@@ -139,7 +135,7 @@ fn get_fake_sysroot() -> Sysroot {
 fn rooted_project_json(data: ProjectJsonData) -> ProjectJson {
     let mut root = "$ROOT$".to_owned();
     replace_root(&mut root, true);
-    let path = Path::new(&root);
+    let path = Utf8Path::new(&root);
     let base = AbsPath::assert(path);
     ProjectJson::new(base, data)
 }
@@ -268,7 +264,7 @@ fn smoke_test_real_sysroot_cargo() {
 
     let cargo_workspace = CargoWorkspace::new(meta);
     let sysroot = Ok(Sysroot::discover(
-        AbsPath::assert(Path::new(env!("CARGO_MANIFEST_DIR"))),
+        AbsPath::assert(Utf8Path::new(env!("CARGO_MANIFEST_DIR"))),
         &Default::default(),
         true,
     )
diff --git a/crates/rust-analyzer/tests/crate_graph.rs b/crates/rust-analyzer/tests/crate_graph.rs
index efd42fadf7..cf38032b94 100644
--- a/crates/rust-analyzer/tests/crate_graph.rs
+++ b/crates/rust-analyzer/tests/crate_graph.rs
@@ -60,7 +60,7 @@ fn get_fake_sysroot() -> Sysroot {
     let sysroot_path = get_fake_sysroot_path();
     // there's no `libexec/` directory with a `proc-macro-srv` binary in that
     // fake sysroot, so we give them both the same path:
-    let sysroot_dir = AbsPathBuf::assert(sysroot_path);
+    let sysroot_dir = AbsPathBuf::assert_utf8(sysroot_path);
     let sysroot_src_dir = sysroot_dir.clone();
     Sysroot::load(sysroot_dir, Some(Ok(sysroot_src_dir)), false)
 }
diff --git a/crates/rust-analyzer/tests/slow-tests/main.rs b/crates/rust-analyzer/tests/slow-tests/main.rs
index 960f5b531d..cb43619262 100644
--- a/crates/rust-analyzer/tests/slow-tests/main.rs
+++ b/crates/rust-analyzer/tests/slow-tests/main.rs
@@ -917,7 +917,7 @@ fn resolve_proc_macro() {
     }
 
     let sysroot = project_model::Sysroot::discover_no_source(
-        &AbsPathBuf::assert(std::env::current_dir().unwrap()),
+        &AbsPathBuf::assert_utf8(std::env::current_dir().unwrap()),
         &Default::default(),
     )
     .unwrap();
@@ -1002,7 +1002,7 @@ pub fn foo(_input: TokenStream) -> TokenStream {
         },
         "procMacro": {
             "enable": true,
-            "server": proc_macro_server_path.as_path().as_ref(),
+            "server": proc_macro_server_path.as_path().as_str(),
         }
     }))
     .root("foo")
@@ -1039,7 +1039,7 @@ fn test_will_rename_files_same_level() {
 
     let tmp_dir = TestDir::new();
     let tmp_dir_path = tmp_dir.path().to_owned();
-    let tmp_dir_str = tmp_dir_path.to_str().unwrap();
+    let tmp_dir_str = tmp_dir_path.as_str();
     let base_path = PathBuf::from(format!("file://{tmp_dir_str}"));
 
     let code = r#"
@@ -1084,7 +1084,7 @@ use crate::old_folder::nested::foo as bar;
           "documentChanges": [
             {
               "textDocument": {
-                "uri": format!("file://{}", tmp_dir_path.join("src").join("lib.rs").to_str().unwrap().to_owned().replace("C:\\", "/c:/").replace('\\', "/")),
+                "uri": format!("file://{}", tmp_dir_path.join("src").join("lib.rs").as_str().to_owned().replace("C:\\", "/c:/").replace('\\', "/")),
                 "version": null
               },
               "edits": [
@@ -1141,7 +1141,7 @@ use crate::old_folder::nested::foo as bar;
           "documentChanges": [
             {
               "textDocument": {
-                "uri": format!("file://{}", tmp_dir_path.join("src").join("lib.rs").to_str().unwrap().to_owned().replace("C:\\", "/c:/").replace('\\', "/")),
+                "uri": format!("file://{}", tmp_dir_path.join("src").join("lib.rs").as_str().to_owned().replace("C:\\", "/c:/").replace('\\', "/")),
                 "version": null
               },
               "edits": [
@@ -1162,7 +1162,7 @@ use crate::old_folder::nested::foo as bar;
             },
             {
               "textDocument": {
-                "uri": format!("file://{}", tmp_dir_path.join("src").join("old_folder").join("nested.rs").to_str().unwrap().to_owned().replace("C:\\", "/c:/").replace('\\', "/")),
+                "uri": format!("file://{}", tmp_dir_path.join("src").join("old_folder").join("nested.rs").as_str().to_owned().replace("C:\\", "/c:/").replace('\\', "/")),
                 "version": null
               },
               "edits": [
diff --git a/crates/rust-analyzer/tests/slow-tests/support.rs b/crates/rust-analyzer/tests/slow-tests/support.rs
index 1d831b8b10..8bbe6ff372 100644
--- a/crates/rust-analyzer/tests/slow-tests/support.rs
+++ b/crates/rust-analyzer/tests/slow-tests/support.rs
@@ -1,7 +1,6 @@
 use std::{
     cell::{Cell, RefCell},
     fs,
-    path::{Path, PathBuf},
     sync::Once,
     time::Duration,
 };
@@ -9,6 +8,7 @@ use std::{
 use crossbeam_channel::{after, select, Receiver};
 use lsp_server::{Connection, Message, Notification, Request};
 use lsp_types::{notification::Exit, request::Shutdown, TextDocumentIdentifier, Url};
+use paths::{Utf8Path, Utf8PathBuf};
 use rust_analyzer::{config::Config, lsp, main_loop};
 use serde::Serialize;
 use serde_json::{json, to_string_pretty, Value};
@@ -21,7 +21,7 @@ use crate::testdir::TestDir;
 pub(crate) struct Project<'a> {
     fixture: &'a str,
     tmp_dir: Option<TestDir>,
-    roots: Vec<PathBuf>,
+    roots: Vec<Utf8PathBuf>,
     config: serde_json::Value,
     root_dir_contains_symlink: bool,
 }
@@ -359,7 +359,7 @@ impl Server {
         self.client.sender.send(Message::Notification(not)).unwrap();
     }
 
-    pub(crate) fn path(&self) -> &Path {
+    pub(crate) fn path(&self) -> &Utf8Path {
         self.dir.path()
     }
 }
diff --git a/crates/rust-analyzer/tests/slow-tests/testdir.rs b/crates/rust-analyzer/tests/slow-tests/testdir.rs
index b3ee7fa3d0..d113bd5127 100644
--- a/crates/rust-analyzer/tests/slow-tests/testdir.rs
+++ b/crates/rust-analyzer/tests/slow-tests/testdir.rs
@@ -1,11 +1,12 @@
 use std::{
     fs, io,
-    path::{Path, PathBuf},
     sync::atomic::{AtomicUsize, Ordering},
 };
 
+use paths::{Utf8Path, Utf8PathBuf};
+
 pub(crate) struct TestDir {
-    path: PathBuf,
+    path: Utf8PathBuf,
     keep: bool,
 }
 
@@ -51,10 +52,13 @@ impl TestDir {
                 #[cfg(target_os = "windows")]
                 std::os::windows::fs::symlink_dir(path, &symlink_path).unwrap();
 
-                return TestDir { path: symlink_path, keep: false };
+                return TestDir {
+                    path: Utf8PathBuf::from_path_buf(symlink_path).unwrap(),
+                    keep: false,
+                };
             }
 
-            return TestDir { path, keep: false };
+            return TestDir { path: Utf8PathBuf::from_path_buf(path).unwrap(), keep: false };
         }
         panic!("Failed to create a temporary directory")
     }
@@ -64,7 +68,7 @@ impl TestDir {
         self.keep = true;
         self
     }
-    pub(crate) fn path(&self) -> &Path {
+    pub(crate) fn path(&self) -> &Utf8Path {
         &self.path
     }
 }
@@ -79,7 +83,7 @@ impl Drop for TestDir {
         let actual_path = filetype.is_symlink().then(|| fs::read_link(&self.path).unwrap());
 
         if let Some(actual_path) = actual_path {
-            remove_dir_all(&actual_path).unwrap_or_else(|err| {
+            remove_dir_all(Utf8Path::from_path(&actual_path).unwrap()).unwrap_or_else(|err| {
                 panic!(
                     "failed to remove temporary link to directory {}: {err}",
                     actual_path.display()
@@ -88,18 +92,18 @@ impl Drop for TestDir {
         }
 
         remove_dir_all(&self.path).unwrap_or_else(|err| {
-            panic!("failed to remove temporary directory {}: {err}", self.path.display())
+            panic!("failed to remove temporary directory {}: {err}", self.path)
         });
     }
 }
 
 #[cfg(not(windows))]
-fn remove_dir_all(path: &Path) -> io::Result<()> {
+fn remove_dir_all(path: &Utf8Path) -> io::Result<()> {
     fs::remove_dir_all(path)
 }
 
 #[cfg(windows)]
-fn remove_dir_all(path: &Path) -> io::Result<()> {
+fn remove_dir_all(path: &Utf8Path) -> io::Result<()> {
     for _ in 0..99 {
         if fs::remove_dir_all(path).is_ok() {
             return Ok(());
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")