* [PATCH v3 0/2] rust: take advantage of newer rust-analyzer features
@ 2026-03-07 23:30 Jesung Yang via B4 Relay
2026-03-07 23:30 ` [PATCH v3 1/2] scripts: generate_rust_analyzer.py: add versioning infrastructure Jesung Yang via B4 Relay
2026-03-07 23:30 ` [PATCH v3 2/2] scripts: generate_rust_analyzer.py: fix IDE support for primitive types Jesung Yang via B4 Relay
0 siblings, 2 replies; 8+ messages in thread
From: Jesung Yang via B4 Relay @ 2026-03-07 23:30 UTC (permalink / raw)
To: Miguel Ojeda, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
Boqun Feng, Tamir Duberstein, Boqun Feng, Tamir Duberstein
Cc: Eliot Courtney, rust-for-linux, linux-kernel, Jesung Yang
As discussed in [1], we need to support multiple versions of
rust-analyzer to take advantage of newer features without breaking
compatibility for users on older toolchains.
In this specific patch series addressing IDE support for inherent methods
of primitive types, the main compatibility issue arises from using
`sysroot_src`, which brings `std` as a dependency for crates in
`drivers/` and `samples/` (please see PATCH [2/2] for more details). This
causes rust-analyzer to incorrectly resolve symbols from `std` in those
crates.
It turns out that rust-analyzer v0.3.1877 (2024-03-11), which
corresponds to our current MSRV of 1.78, has the same `std` resolution
issue regardless of whether `sysroot_src` is used. However, as far as I
know, we're likely to bump the MSRV to 1.85, where the corresponding
rust-analyzer release indeed needs the versioning infrastructure to fix
the `std` issue.
Hence, this series revises the approach taken in [2] by first adding
multi-version support for rust-analyzer. Specifically, it enables
support for the v0.3.2727 (2025-12-22) release and newer, which is
required to resolve inherent method resolution issues for primitive
types found in recent versions of rust-analyzer.
As Eliot mentioned in [3], we might also want to do the `include_dirs`
trick on top of this series to support rust-analyzer releases older than
v0.3.2727, but it should be handled in a dedicated patch series.
[1] https://lore.kernel.org/rust-for-linux/20260101-rust-project-reduce-size-v1-1-4cd66e9e02d9@gmail.com/
[2] https://lore.kernel.org/r/20260101-ra-fix-primitive-v1-1-def809357b4e@gmail.com/
[3] https://lore.kernel.org/rust-for-linux/DFVQBFD54CJO.2D3VQ091URH2B@nvidia.com/
Signed-off-by: Jesung Yang <y.j3ms.n@gmail.com>
---
Changes in v3:
- Remove extra `crate_attrs=["no_std"]` for crates that specify
`#![no_std]` by themselves.
- Fix rust-analyzer version for Rust 1.78.
- Tweak `map_ra_version_baseline` to distinguish between Rust version
and rust-analyzer version.
- Simplify overall structure.
- Rebase on 6c02871d258 ("scripts: generate_rust_analyzer.py: reduce cfg
plumbing")
- Link to v2: https://lore.kernel.org/r/20260109-ra-fix-primitive-v2-0-249852a4145a@gmail.com
Changes in v2:
- Implement multiple rust-analyzer version support.
- Rebase on 9ace4753a520 (Linux 6.19-rc4).
- Remove an unnecessary new line between tags.
- Link to v1: https://lore.kernel.org/r/20260101-ra-fix-primitive-v1-1-def809357b4e@gmail.com
---
Jesung Yang (2):
scripts: generate_rust_analyzer.py: add versioning infrastructure
scripts: generate_rust_analyzer.py: fix IDE support for primitive types
scripts/generate_rust_analyzer.py | 221 +++++++++++++++++++++++++++++++++-----
1 file changed, 196 insertions(+), 25 deletions(-)
---
base-commit: 6c02871d2585bca9d43cea239f908c05ef55a89d
change-id: 20260101-ra-fix-primitive-78154fe8173f
Best regards,
--
Jesung Yang <y.j3ms.n@gmail.com>
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v3 1/2] scripts: generate_rust_analyzer.py: add versioning infrastructure
2026-03-07 23:30 [PATCH v3 0/2] rust: take advantage of newer rust-analyzer features Jesung Yang via B4 Relay
@ 2026-03-07 23:30 ` Jesung Yang via B4 Relay
2026-03-09 18:34 ` Tamir Duberstein
2026-03-07 23:30 ` [PATCH v3 2/2] scripts: generate_rust_analyzer.py: fix IDE support for primitive types Jesung Yang via B4 Relay
1 sibling, 1 reply; 8+ messages in thread
From: Jesung Yang via B4 Relay @ 2026-03-07 23:30 UTC (permalink / raw)
To: Miguel Ojeda, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
Boqun Feng, Tamir Duberstein, Boqun Feng, Tamir Duberstein
Cc: Eliot Courtney, rust-for-linux, linux-kernel, Jesung Yang
From: Jesung Yang <y.j3ms.n@gmail.com>
Introduce multi-version support for rust-analyzer. The script now
executes `rust-analyzer --version` to query the version string and
generates a `rust-project.json` file compatible with the detected
version.
This is a preparatory patch to address inherent method resolution
failures for primitive types occurring in rust-analyzer v0.3.2693
(2025-11-24) or later when used with our current `rust-project.json`
generation logic. Since the actual fix requires using the `sysroot_src`
field with a feature only available in rust-analyzer v0.3.2727
(2025-12-22) or later, this infrastructure is necessary to maintain
compatibility with older rust-analyzer releases.
Signed-off-by: Jesung Yang <y.j3ms.n@gmail.com>
---
scripts/generate_rust_analyzer.py | 201 +++++++++++++++++++++++++++++++++-----
1 file changed, 176 insertions(+), 25 deletions(-)
diff --git a/scripts/generate_rust_analyzer.py b/scripts/generate_rust_analyzer.py
index b4a55344688d..a4d25bb8b602 100755
--- a/scripts/generate_rust_analyzer.py
+++ b/scripts/generate_rust_analyzer.py
@@ -4,10 +4,12 @@
"""
import argparse
+from datetime import datetime, date
import json
import logging
import os
import pathlib
+import re
import subprocess
import sys
from typing import Dict, Iterable, List, Literal, Optional, TypedDict
@@ -36,6 +38,7 @@ class Crate(TypedDict):
is_workspace_member: bool
deps: List[Dependency]
cfg: List[str]
+ crate_attrs: List[str]
edition: str
env: Dict[str, str]
@@ -49,7 +52,41 @@ class CrateWithGenerated(Crate):
source: Source
+class RustProject(TypedDict):
+ crates: List[Crate]
+ sysroot: str
+
+
+Version = tuple[int, int, int]
+
+
+class RaVersionInfo(TypedDict):
+ release_date: date
+ ra_version: Version
+ rust_version: Version
+
+
+class RaVersionCtx(TypedDict):
+ manual_sysroot_crates: bool
+ use_crate_attrs: bool
+
+
+# Represents rust-analyzer compatibility baselines. Concrete versions are mapped to the most
+# recent baseline they have reached. Must be in release order.
+BASELINES: List[RaVersionInfo] = [
+ # v0.3.1877, released on 2024-03-11; shipped with the rustup 1.78 toolchain.
+ {
+ "release_date": datetime.strptime("2024-03-11", "%Y-%m-%d"),
+ "ra_version": (0, 3, 1877),
+ "rust_version": (1, 78, 0),
+ },
+]
+
+DEFAULT_BASELINE: RaVersionInfo = BASELINES[0]
+
+
def generate_crates(
+ ctx: RaVersionCtx,
srctree: pathlib.Path,
objtree: pathlib.Path,
sysroot_src: pathlib.Path,
@@ -75,10 +112,14 @@ def generate_crates(
deps: List[Dependency],
*,
cfg: Optional[List[str]],
+ crate_attrs: Optional[List[str]],
is_workspace_member: Optional[bool],
edition: Optional[str],
) -> Crate:
cfg = cfg if cfg is not None else crates_cfgs.get(display_name, [])
+ crate_attrs = (
+ crate_attrs if ctx["use_crate_attrs"] and crate_attrs is not None else []
+ )
is_workspace_member = (
is_workspace_member if is_workspace_member is not None else True
)
@@ -89,6 +130,7 @@ def generate_crates(
"is_workspace_member": is_workspace_member,
"deps": deps,
"cfg": cfg,
+ "crate_attrs": crate_attrs,
"edition": edition,
"env": {
"RUST_MODFILE": "This is only for rust-analyzer"
@@ -109,6 +151,7 @@ def generate_crates(
root_module,
deps,
cfg=cfg,
+ crate_attrs=None,
is_workspace_member=is_workspace_member,
edition=edition,
)
@@ -147,6 +190,7 @@ def generate_crates(
deps: List[Dependency],
*,
cfg: Optional[List[str]] = None,
+ crate_attrs: Optional[List[str]] = None,
is_workspace_member: Optional[bool] = None,
edition: Optional[str] = None,
) -> Dependency:
@@ -156,6 +200,7 @@ def generate_crates(
root_module,
deps,
cfg=cfg,
+ crate_attrs=crate_attrs,
is_workspace_member=is_workspace_member,
edition=edition,
)
@@ -200,67 +245,72 @@ def generate_crates(
edition=core_edition,
)
- # NB: sysroot crates reexport items from one another so setting up our transitive dependencies
- # here is important for ensuring that rust-analyzer can resolve symbols. The sources of truth
- # for this dependency graph are `(sysroot_src / crate / "Cargo.toml" for crate in crates)`.
- core = append_sysroot_crate("core", [])
- alloc = append_sysroot_crate("alloc", [core])
- std = append_sysroot_crate("std", [alloc, core])
- proc_macro = append_sysroot_crate("proc_macro", [core, std])
+ core = alloc = std = proc_macro = None
+ if ctx["manual_sysroot_crates"]:
+ # NB: sysroot crates reexport items from one another so setting up our transitive dependencies
+ # here is important for ensuring that rust-analyzer can resolve symbols. The sources of truth
+ # for this dependency graph are `(sysroot_src / crate / "Cargo.toml" for crate in crates)`.
+ core = append_sysroot_crate("core", [])
+ alloc = append_sysroot_crate("alloc", [core])
+ std = append_sysroot_crate("std", [alloc, core])
+ proc_macro = append_sysroot_crate("proc_macro", [core, std])
+
+ def sysroot_deps(*deps: Optional[Dependency]) -> List[Dependency]:
+ return [dep for dep in deps if dep is not None]
compiler_builtins = append_crate(
"compiler_builtins",
srctree / "rust" / "compiler_builtins.rs",
- [core],
+ sysroot_deps(core),
)
proc_macro2 = append_crate(
"proc_macro2",
srctree / "rust" / "proc-macro2" / "lib.rs",
- [core, alloc, std, proc_macro],
+ sysroot_deps(core, alloc, std, proc_macro),
)
quote = append_crate(
"quote",
srctree / "rust" / "quote" / "lib.rs",
- [core, alloc, std, proc_macro, proc_macro2],
+ sysroot_deps(core, alloc, std, proc_macro) + [proc_macro2],
edition="2018",
)
syn = append_crate(
"syn",
srctree / "rust" / "syn" / "lib.rs",
- [std, proc_macro, proc_macro2, quote],
+ sysroot_deps(std, proc_macro) + [proc_macro2, quote],
)
macros = append_proc_macro_crate(
"macros",
srctree / "rust" / "macros" / "lib.rs",
- [std, proc_macro, proc_macro2, quote, syn],
+ sysroot_deps(std, proc_macro) + [proc_macro2, quote, syn],
)
build_error = append_crate(
"build_error",
srctree / "rust" / "build_error.rs",
- [core, compiler_builtins],
+ sysroot_deps(core) + [compiler_builtins],
)
pin_init_internal = append_proc_macro_crate(
"pin_init_internal",
srctree / "rust" / "pin-init" / "internal" / "src" / "lib.rs",
- [std, proc_macro, proc_macro2, quote, syn],
+ sysroot_deps(std, proc_macro) + [proc_macro2, quote, syn],
)
pin_init = append_crate(
"pin_init",
srctree / "rust" / "pin-init" / "src" / "lib.rs",
- [core, compiler_builtins, pin_init_internal, macros],
+ sysroot_deps(core) + [compiler_builtins, pin_init_internal, macros],
)
ffi = append_crate(
"ffi",
srctree / "rust" / "ffi.rs",
- [core, compiler_builtins],
+ sysroot_deps(core) + [compiler_builtins],
)
def append_crate_with_generated(
@@ -272,6 +322,7 @@ def generate_crates(
srctree / "rust"/ display_name / "lib.rs",
deps,
cfg=generated_cfg,
+ crate_attrs=None,
is_workspace_member=True,
edition=None,
)
@@ -288,10 +339,14 @@ def generate_crates(
}
return register_crate(crate_with_generated)
- bindings = append_crate_with_generated("bindings", [core, ffi, pin_init])
- uapi = append_crate_with_generated("uapi", [core, ffi, pin_init])
+ bindings = append_crate_with_generated(
+ "bindings", sysroot_deps(core) + [ffi, pin_init]
+ )
+ uapi = append_crate_with_generated(
+ "uapi", sysroot_deps(core) + [ffi, pin_init]
+ )
kernel = append_crate_with_generated(
- "kernel", [core, macros, build_error, pin_init, ffi, bindings, uapi]
+ "kernel", sysroot_deps(core) + [macros, build_error, pin_init, ffi, bindings, uapi]
)
scripts = srctree / "scripts"
@@ -303,7 +358,7 @@ def generate_crates(
append_crate(
name,
path,
- [std],
+ sysroot_deps(std),
)
def is_root_crate(build_file: pathlib.Path, target: str) -> bool:
@@ -335,12 +390,90 @@ def generate_crates(
append_crate(
name,
path,
- [core, kernel, pin_init],
+ sysroot_deps(core) + [kernel, pin_init],
cfg=generated_cfg,
+ crate_attrs=["no_std"],
)
return crates
+def generate_rust_project(
+ version_info: RaVersionInfo,
+ srctree: pathlib.Path,
+ objtree: pathlib.Path,
+ sysroot: pathlib.Path,
+ sysroot_src: pathlib.Path,
+ external_src: Optional[pathlib.Path],
+ cfgs: List[str],
+ core_edition: str,
+) -> RustProject:
+ assert len(BASELINES) == 1, "Exhaustiveness check: update if branches!"
+
+ ctx: RaVersionCtx
+
+ if version_info["ra_version"] == (0, 3, 1877):
+ ctx = {
+ "use_crate_attrs": False,
+ "manual_sysroot_crates": True,
+ }
+ return {
+ "crates": generate_crates(
+ ctx, srctree, objtree, sysroot_src, external_src, cfgs, core_edition
+ ),
+ "sysroot": str(sysroot),
+ }
+ else:
+ assert False, "Unreachable!"
+
+def query_ra_version() -> Optional[str]:
+ try:
+ # Use the rust-analyzer binary found in $PATH.
+ ra_version_output = (
+ subprocess.check_output(
+ ["rust-analyzer", "--version"],
+ stdin=subprocess.DEVNULL,
+ )
+ .decode("utf-8")
+ .strip()
+ )
+ return ra_version_output
+ except FileNotFoundError:
+ logging.warning("Failed to find rust-analyzer in $PATH")
+ return None
+
+def map_ra_version_baseline(ra_version_output: str) -> RaVersionInfo:
+ baselines = reversed(BASELINES)
+
+ version_match = re.search(r"\d+\.\d+\.\d+", ra_version_output)
+ if version_match:
+ version_string = version_match.group()
+ found_version = tuple(map(int, version_string.split(".")))
+
+ # `rust-analyzer --version` shows different version string depending on how the binary
+ # is built: it may print either the Rust version or the rust-analyzer version itself.
+ # To distinguish between them, we leverage rust-analyzer's versioning convention.
+ #
+ # See:
+ # - https://github.com/rust-lang/rust-analyzer/blob/fad5c3d2d642/xtask/src/dist.rs#L19-L21
+ is_ra_version = version_string.startswith(("0.3", "0.4", "0.5"))
+ if is_ra_version:
+ for info in baselines:
+ if found_version >= info["ra_version"]:
+ return info
+ else:
+ for info in baselines:
+ if found_version >= info["rust_version"]:
+ return info
+
+ date_match = re.search(r"\d{4}-\d{2}-\d{2}", ra_version_output)
+ if date_match:
+ found_date = datetime.strptime(date_match.group(), "%Y-%m-%d")
+ for info in baselines:
+ if found_date >= info["release_date"]:
+ return info
+
+ return DEFAULT_BASELINE
+
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument('--verbose', '-v', action='store_true')
@@ -369,10 +502,28 @@ def main() -> None:
level=logging.INFO if args.verbose else logging.WARNING
)
- rust_project = {
- "crates": generate_crates(args.srctree, args.objtree, args.sysroot_src, args.exttree, args.cfgs, args.core_edition),
- "sysroot": str(args.sysroot),
- }
+ ra_version_output = query_ra_version()
+ if ra_version_output:
+ compatible_ra_version = map_ra_version_baseline(ra_version_output)
+ else:
+ logging.warning(
+ "Falling back to `rust-project.json` for rust-analyzer %s, %s (shipped with Rust %s)",
+ ".".join(map(str, DEFAULT_BASELINE["ra_version"])),
+ datetime.strftime(DEFAULT_BASELINE["release_date"], "%Y-%m-%d"),
+ ".".join(map(str, DEFAULT_BASELINE["rust_version"])),
+ )
+ compatible_ra_version = DEFAULT_BASELINE
+
+ rust_project = generate_rust_project(
+ compatible_ra_version,
+ args.srctree,
+ args.objtree,
+ args.sysroot,
+ args.sysroot_src,
+ args.exttree,
+ args.cfgs,
+ args.core_edition,
+ )
json.dump(rust_project, sys.stdout, sort_keys=True, indent=4)
--
2.52.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v3 2/2] scripts: generate_rust_analyzer.py: fix IDE support for primitive types
2026-03-07 23:30 [PATCH v3 0/2] rust: take advantage of newer rust-analyzer features Jesung Yang via B4 Relay
2026-03-07 23:30 ` [PATCH v3 1/2] scripts: generate_rust_analyzer.py: add versioning infrastructure Jesung Yang via B4 Relay
@ 2026-03-07 23:30 ` Jesung Yang via B4 Relay
2026-03-09 18:34 ` Tamir Duberstein
1 sibling, 1 reply; 8+ messages in thread
From: Jesung Yang via B4 Relay @ 2026-03-07 23:30 UTC (permalink / raw)
To: Miguel Ojeda, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
Boqun Feng, Tamir Duberstein, Boqun Feng, Tamir Duberstein
Cc: Eliot Courtney, rust-for-linux, linux-kernel, Jesung Yang
From: Jesung Yang <y.j3ms.n@gmail.com>
Update `generate_rust_analyzer.py` so that the generated
`rust-project.json` contains the `sysroot_src` field with
`"crate_attrs": ["no_std"]` specified for relevant crates. This ensures
that rust-analyzer provides proper IDE support for inherent methods of
primitive types.
Since commit 50384460c68f ("Rewrite method resolution to follow rustc
more closely") to rust-analyzer, it no longer provides language server
features like code completion and go-to-definition for inherent methods
of primitive types when sysroot crates (e.g., `core`, `std`) are inlined
in `rust-project.json` [1]. As `generate_rust_analyzer.py` currently
inlines these crates, our setup is affected by this change.
Specifying the `sysroot_src` field restores this functionality by
allowing rust-analyzer to locate sysroot crates by itself. However, this
causes `std` to be treated as a dependency for all local crates by
default. To align with our compilation settings, provide the `no_std`
attribute via the `crate_attrs` field, as the `-Zcrate-attr=no_std`
compiler flag is not visible to rust-analyzer. This combined approach
removes manual manipulation of sysroot dependencies while preventing
incorrect symbol resolution against the standard library.
Note that this configuration requires rust-analyzer release 2025-12-22
(v0.3.2727) or later, which introduced support for the `crate_attrs`
field.
Link: https://rust-lang.zulipchat.com/#narrow/channel/x/topic/x/near/561607963 [1]
Link: https://rust-for-linux.zulipchat.com/#narrow/channel/x/topic/x/near/561607753
Signed-off-by: Jesung Yang <y.j3ms.n@gmail.com>
---
scripts/generate_rust_analyzer.py | 24 ++++++++++++++++++++++--
1 file changed, 22 insertions(+), 2 deletions(-)
diff --git a/scripts/generate_rust_analyzer.py b/scripts/generate_rust_analyzer.py
index a4d25bb8b602..ab399f6044fa 100755
--- a/scripts/generate_rust_analyzer.py
+++ b/scripts/generate_rust_analyzer.py
@@ -52,9 +52,11 @@ class CrateWithGenerated(Crate):
source: Source
-class RustProject(TypedDict):
+# TODO: use `typing.NotRequired` when Python 3.11 is adopted.
+class RustProject(TypedDict, total=False):
crates: List[Crate]
sysroot: str
+ sysroot_src: str
Version = tuple[int, int, int]
@@ -80,6 +82,12 @@ BASELINES: List[RaVersionInfo] = [
"ra_version": (0, 3, 1877),
"rust_version": (1, 78, 0),
},
+ # v0.3.2727, released on 2025-12-22; v0.3.2743 is shipped with the rustup 1.94 toolchain.
+ {
+ "release_date": datetime.strptime("2025-12-22", "%Y-%m-%d"),
+ "ra_version": (0, 3, 2727),
+ "rust_version": (1, 94, 0),
+ },
]
DEFAULT_BASELINE: RaVersionInfo = BASELINES[0]
@@ -407,7 +415,7 @@ def generate_rust_project(
cfgs: List[str],
core_edition: str,
) -> RustProject:
- assert len(BASELINES) == 1, "Exhaustiveness check: update if branches!"
+ assert len(BASELINES) == 2, "Exhaustiveness check: update if branches!"
ctx: RaVersionCtx
@@ -422,6 +430,18 @@ def generate_rust_project(
),
"sysroot": str(sysroot),
}
+ elif version_info["ra_version"] == (0, 3, 2727):
+ ctx = {
+ "use_crate_attrs": True,
+ "manual_sysroot_crates": False,
+ }
+ return {
+ "crates": generate_crates(
+ ctx, srctree, objtree, sysroot_src, external_src, cfgs, core_edition
+ ),
+ "sysroot": str(sysroot),
+ "sysroot_src": str(sysroot_src),
+ }
else:
assert False, "Unreachable!"
--
2.52.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v3 1/2] scripts: generate_rust_analyzer.py: add versioning infrastructure
2026-03-07 23:30 ` [PATCH v3 1/2] scripts: generate_rust_analyzer.py: add versioning infrastructure Jesung Yang via B4 Relay
@ 2026-03-09 18:34 ` Tamir Duberstein
2026-03-15 7:01 ` Jesung Yang
0 siblings, 1 reply; 8+ messages in thread
From: Tamir Duberstein @ 2026-03-09 18:34 UTC (permalink / raw)
To: Jesung Yang
Cc: Miguel Ojeda, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
Boqun Feng, Tamir Duberstein, Eliot Courtney, rust-for-linux,
linux-kernel
On Sun, 08 Mar 2026 08:30:34 +0900, Jesung Yang <y.j3ms.n@gmail.com> wrote:
> diff --git a/scripts/generate_rust_analyzer.py b/scripts/generate_rust_analyzer.py
> index b4a55344688d..a4d25bb8b602 100755
> --- a/scripts/generate_rust_analyzer.py
> +++ b/scripts/generate_rust_analyzer.py
> @@ -49,7 +52,41 @@ class CrateWithGenerated(Crate):
> source: Source
>
>
> +class RustProject(TypedDict):
> + crates: List[Crate]
> + sysroot: str
> +
> +
> +Version = tuple[int, int, int]
> +
> +
> +class RaVersionInfo(TypedDict):
> + release_date: date
> + ra_version: Version
> + rust_version: Version
> +
Unlike other types that are intended to be serialized to JSON, this type is
strictly for internal use. Could we make it a `@dataclass` instead of a
`TypedDict`? That produces more pleasant syntax and clarifies the intended use.
> +
> +class RaVersionCtx(TypedDict):
> + manual_sysroot_crates: bool
> + use_crate_attrs: bool
> +
> +
> +# Represents rust-analyzer compatibility baselines. Concrete versions are mapped to the most
Same here.
> +# recent baseline they have reached. Must be in release order.
> +BASELINES: List[RaVersionInfo] = [
> + # v0.3.1877, released on 2024-03-11; shipped with the rustup 1.78 toolchain.
> + {
> + "release_date": datetime.strptime("2024-03-11", "%Y-%m-%d"),
> + "ra_version": (0, 3, 1877),
> + "rust_version": (1, 78, 0),
> + },
> +]
> +
> +DEFAULT_BASELINE: RaVersionInfo = BASELINES[0]
> +
> +
> def generate_crates(
> + ctx: RaVersionCtx,
> srctree: pathlib.Path,
Could we define these constants closer to their point of use? I understand the
custom of keeping these things near the top of the file but this 400-line
separation makes it hard to see that there is quite tight coupling between the
two sites.
> @@ -200,67 +245,72 @@ def generate_crates(
> edition=core_edition,
> )
>
> - # NB: sysroot crates reexport items from one another so setting up our transitive dependencies
> - # here is important for ensuring that rust-analyzer can resolve symbols. The sources of truth
> - # for this dependency graph are `(sysroot_src / crate / "Cargo.toml" for crate in crates)`.
> - core = append_sysroot_crate("core", [])
> - alloc = append_sysroot_crate("alloc", [core])
> - std = append_sysroot_crate("std", [alloc, core])
> - proc_macro = append_sysroot_crate("proc_macro", [core, std])
> + core = alloc = std = proc_macro = None
> + if ctx["manual_sysroot_crates"]:
> + # NB: sysroot crates reexport items from one another so setting up our transitive dependencies
> + # here is important for ensuring that rust-analyzer can resolve symbols. The sources of truth
> + # for this dependency graph are `(sysroot_src / crate / "Cargo.toml" for crate in crates)`.
> + core = append_sysroot_crate("core", [])
> + alloc = append_sysroot_crate("alloc", [core])
> + std = append_sysroot_crate("std", [alloc, core])
> + proc_macro = append_sysroot_crate("proc_macro", [core, std])
> +
Should this logic (inspecting `manual_sysroot_crates`) be in
`append_sysroot_crate`?
> @@ -335,12 +390,90 @@ def generate_crates(
> append_crate(
> name,
> path,
> - [core, kernel, pin_init],
> + sysroot_deps(core) + [kernel, pin_init],
> cfg=generated_cfg,
> + crate_attrs=["no_std"],
> )
Can you help me understand this addition? It's not mentioned except in the
cover letter as a diff from v2.
>
> return crates
>
> +def generate_rust_project(
> + version_info: RaVersionInfo,
> + srctree: pathlib.Path,
> + objtree: pathlib.Path,
> + sysroot: pathlib.Path,
> + sysroot_src: pathlib.Path,
> + external_src: Optional[pathlib.Path],
> + cfgs: List[str],
> + core_edition: str,
> +) -> RustProject:
> + assert len(BASELINES) == 1, "Exhaustiveness check: update if branches!"
> +
> + ctx: RaVersionCtx
> +
Could we make RaVersionInfo an enum? That would allow mypy to do this check
(using `match`) rather than relying on this.
--
Tamir Duberstein <tamird@kernel.org>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v3 2/2] scripts: generate_rust_analyzer.py: fix IDE support for primitive types
2026-03-07 23:30 ` [PATCH v3 2/2] scripts: generate_rust_analyzer.py: fix IDE support for primitive types Jesung Yang via B4 Relay
@ 2026-03-09 18:34 ` Tamir Duberstein
0 siblings, 0 replies; 8+ messages in thread
From: Tamir Duberstein @ 2026-03-09 18:34 UTC (permalink / raw)
To: Jesung Yang
Cc: Miguel Ojeda, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
Boqun Feng, Tamir Duberstein, Eliot Courtney, rust-for-linux,
linux-kernel
On Sun, 08 Mar 2026 08:30:35 +0900, Jesung Yang <y.j3ms.n@gmail.com> wrote:
> diff --git a/scripts/generate_rust_analyzer.py b/scripts/generate_rust_analyzer.py
> index a4d25bb8b602..ab399f6044fa 100755
> --- a/scripts/generate_rust_analyzer.py
> +++ b/scripts/generate_rust_analyzer.py
> @@ -52,9 +52,11 @@ class CrateWithGenerated(Crate):
> source: Source
>
>
> -class RustProject(TypedDict):
> +# TODO: use `typing.NotRequired` when Python 3.11 is adopted.
> +class RustProject(TypedDict, total=False):
This is good. Could you please indicate which fields would be `NotRequired`?
--
Tamir Duberstein <tamird@kernel.org>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v3 1/2] scripts: generate_rust_analyzer.py: add versioning infrastructure
2026-03-09 18:34 ` Tamir Duberstein
@ 2026-03-15 7:01 ` Jesung Yang
2026-03-16 14:37 ` Tamir Duberstein
0 siblings, 1 reply; 8+ messages in thread
From: Jesung Yang @ 2026-03-15 7:01 UTC (permalink / raw)
To: Tamir Duberstein, Jesung Yang
Cc: Miguel Ojeda, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
Boqun Feng, Eliot Courtney, rust-for-linux, linux-kernel
On Tue Mar 10, 2026 at 3:34 AM KST, Tamir Duberstein wrote:
> On Sun, 08 Mar 2026 08:30:34 +0900, Jesung Yang <y.j3ms.n@gmail.com> wrote:
[...]
>> @@ -335,12 +390,90 @@ def generate_crates(
>> append_crate(
>> name,
>> path,
>> - [core, kernel, pin_init],
>> + sysroot_deps(core) + [kernel, pin_init],
>> cfg=generated_cfg,
>> + crate_attrs=["no_std"],
>> )
>
> Can you help me understand this addition? It's not mentioned except in the
> cover letter as a diff from v2.
Assuming you're referring to `crate_attrs=["no_std"]`, this makes
rust-analyzer treat crates in `driver/` and `samples/` as if
`#![no_std]` were specified in their crate roots (they don't contain
`#![no_std]` themselves).
(Actually, I'm uncertain if this is the part you wanted me to elaborate
on. Please let me know if you need more context.)
>> +def generate_rust_project(
>> + version_info: RaVersionInfo,
>> + srctree: pathlib.Path,
>> + objtree: pathlib.Path,
>> + sysroot: pathlib.Path,
>> + sysroot_src: pathlib.Path,
>> + external_src: Optional[pathlib.Path],
>> + cfgs: List[str],
>> + core_edition: str,
>> +) -> RustProject:
>> + assert len(BASELINES) == 1, "Exhaustiveness check: update if branches!"
>> +
>> + ctx: RaVersionCtx
>> +
>
> Could we make RaVersionInfo an enum? That would allow mypy to do this check
> (using `match`) rather than relying on this.
I think you want something like the following?
@enum.unique
class RaVersionInfo(enum.Enum):
V20240311 = (
datetime.strptime("2024-03-11", "%Y-%m-%d"),
ra_version=(0, 3, 1877),
rust_version=(1, 78, 0),
)
V20251222 = ( ... )
def __init__(
self,
release_date: date,
ra_version: Version,
rust_version: Version,
) -> "RaVersionInfo":
self.release_date = release_date
self.ra_version = ra_version
self.rust_version = rust_version
@staticmethod
def default() -> "RaVersionInfo":
return RaVersionInfo.V20240311
At the call site, we can access each field via the dot operator. This
not only removes `BASELINES` and `DEFAULT_BASELINE` but also ensures
that we only match against valid variants, which helps reduce the chance
of human error. But unfortunately, `match` was introduced in Python
3.10, whereas the kernel only requires Python 3.9 [1]. This means we
cannot leverage mypy's exhaushtiveness check yet. Perhaps I could leave
a TODO to remove the assertion and switch to `match` once Python 3.10 is
adopted.
The rest of the feedback sounds reasonable to me.
[1] https://docs.kernel.org/process/changes.html#kernel-documentation
Best regards,
Jesung
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v3 1/2] scripts: generate_rust_analyzer.py: add versioning infrastructure
2026-03-15 7:01 ` Jesung Yang
@ 2026-03-16 14:37 ` Tamir Duberstein
2026-03-17 9:05 ` Jesung Yang
0 siblings, 1 reply; 8+ messages in thread
From: Tamir Duberstein @ 2026-03-16 14:37 UTC (permalink / raw)
To: Jesung Yang
Cc: Tamir Duberstein, Miguel Ojeda, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, Boqun Feng, Eliot Courtney, rust-for-linux,
linux-kernel
On 2026-03-15 16:01 +0900, Jesung Yang wrote:
> On Tue Mar 10, 2026 at 3:34 AM KST, Tamir Duberstein wrote:
> > On Sun, 08 Mar 2026 08:30:34 +0900, Jesung Yang <y.j3ms.n@gmail.com> wrote:
> [...]
> >> @@ -335,12 +390,90 @@ def generate_crates(
> >> append_crate(
> >> name,
> >> path,
> >> - [core, kernel, pin_init],
> >> + sysroot_deps(core) + [kernel, pin_init],
> >> cfg=generated_cfg,
> >> + crate_attrs=["no_std"],
> >> )
> >
> > Can you help me understand this addition? It's not mentioned except in the
> > cover letter as a diff from v2.
>
> Assuming you're referring to `crate_attrs=["no_std"]`, this makes
> rust-analyzer treat crates in `driver/` and `samples/` as if
> `#![no_std]` were specified in their crate roots (they don't contain
> `#![no_std]` themselves).
Yes, that's what I was referring to. Still, it's not clear to me why
that is part of this patch. Is it intentional, or incidental?
>
> (Actually, I'm uncertain if this is the part you wanted me to elaborate
> on. Please let me know if you need more context.)
Yes, sorry for the ambiguity.
>
> >> +def generate_rust_project(
> >> + version_info: RaVersionInfo,
> >> + srctree: pathlib.Path,
> >> + objtree: pathlib.Path,
> >> + sysroot: pathlib.Path,
> >> + sysroot_src: pathlib.Path,
> >> + external_src: Optional[pathlib.Path],
> >> + cfgs: List[str],
> >> + core_edition: str,
> >> +) -> RustProject:
> >> + assert len(BASELINES) == 1, "Exhaustiveness check: update if branches!"
> >> +
> >> + ctx: RaVersionCtx
> >> +
> >
> > Could we make RaVersionInfo an enum? That would allow mypy to do this check
> > (using `match`) rather than relying on this.
>
> I think you want something like the following?
>
> @enum.unique
> class RaVersionInfo(enum.Enum):
> V20240311 = (
> datetime.strptime("2024-03-11", "%Y-%m-%d"),
> ra_version=(0, 3, 1877),
> rust_version=(1, 78, 0),
> )
> V20251222 = ( ... )
>
> def __init__(
> self,
> release_date: date,
> ra_version: Version,
> rust_version: Version,
> ) -> "RaVersionInfo":
> self.release_date = release_date
> self.ra_version = ra_version
> self.rust_version = rust_version
>
> @staticmethod
> def default() -> "RaVersionInfo":
> return RaVersionInfo.V20240311
>
> At the call site, we can access each field via the dot operator. This
> not only removes `BASELINES` and `DEFAULT_BASELINE` but also ensures
> that we only match against valid variants, which helps reduce the chance
> of human error. But unfortunately, `match` was introduced in Python
> 3.10, whereas the kernel only requires Python 3.9 [1]. This means we
> cannot leverage mypy's exhaushtiveness check yet. Perhaps I could leave
> a TODO to remove the assertion and switch to `match` once Python 3.10 is
> adopted.
That sounds reasonable to me. You can also name the variants in a more
semantically meaningful way like DEFAULT, SUPPORTS_XXX, etc.
Finally, `__init__` should return None, not Self.
>
> The rest of the feedback sounds reasonable to me.
>
> [1] https://docs.kernel.org/process/changes.html#kernel-documentation
>
> Best regards,
> Jesung
>
Thanks for working on this!
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v3 1/2] scripts: generate_rust_analyzer.py: add versioning infrastructure
2026-03-16 14:37 ` Tamir Duberstein
@ 2026-03-17 9:05 ` Jesung Yang
0 siblings, 0 replies; 8+ messages in thread
From: Jesung Yang @ 2026-03-17 9:05 UTC (permalink / raw)
To: Tamir Duberstein, Jesung Yang
Cc: Miguel Ojeda, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
Boqun Feng, Eliot Courtney, rust-for-linux, linux-kernel
On Mon Mar 16, 2026 at 11:37 PM KST, Tamir Duberstein wrote:
> On 2026-03-15 16:01 +0900, Jesung Yang wrote:
>> On Tue Mar 10, 2026 at 3:34 AM KST, Tamir Duberstein wrote:
>> > On Sun, 08 Mar 2026 08:30:34 +0900, Jesung Yang <y.j3ms.n@gmail.com> wrote:
>> [...]
>> >> @@ -335,12 +390,90 @@ def generate_crates(
>> >> append_crate(
>> >> name,
>> >> path,
>> >> - [core, kernel, pin_init],
>> >> + sysroot_deps(core) + [kernel, pin_init],
>> >> cfg=generated_cfg,
>> >> + crate_attrs=["no_std"],
>> >> )
>> >
>> > Can you help me understand this addition? It's not mentioned except in the
>> > cover letter as a diff from v2.
>>
>> Assuming you're referring to `crate_attrs=["no_std"]`, this makes
>> rust-analyzer treat crates in `driver/` and `samples/` as if
>> `#![no_std]` were specified in their crate roots (they don't contain
>> `#![no_std]` themselves).
>
> Yes, that's what I was referring to. Still, it's not clear to me why
> that is part of this patch. Is it intentional, or incidental?
Ah, now I see your point. Yes, this should be in `scripts:
generate_rust_analyzer.py: fix IDE support for primitive types`
(PATCH [2/2]).
>> >> +def generate_rust_project(
>> >> + version_info: RaVersionInfo,
>> >> + srctree: pathlib.Path,
>> >> + objtree: pathlib.Path,
>> >> + sysroot: pathlib.Path,
>> >> + sysroot_src: pathlib.Path,
>> >> + external_src: Optional[pathlib.Path],
>> >> + cfgs: List[str],
>> >> + core_edition: str,
>> >> +) -> RustProject:
>> >> + assert len(BASELINES) == 1, "Exhaustiveness check: update if branches!"
>> >> +
>> >> + ctx: RaVersionCtx
>> >> +
>> >
>> > Could we make RaVersionInfo an enum? That would allow mypy to do this check
>> > (using `match`) rather than relying on this.
>>
>> I think you want something like the following?
>>
>> @enum.unique
>> class RaVersionInfo(enum.Enum):
>> V20240311 = (
>> datetime.strptime("2024-03-11", "%Y-%m-%d"),
>> ra_version=(0, 3, 1877),
>> rust_version=(1, 78, 0),
>> )
>> V20251222 = ( ... )
>>
>> def __init__(
>> self,
>> release_date: date,
>> ra_version: Version,
>> rust_version: Version,
>> ) -> "RaVersionInfo":
>> self.release_date = release_date
>> self.ra_version = ra_version
>> self.rust_version = rust_version
>>
>> @staticmethod
>> def default() -> "RaVersionInfo":
>> return RaVersionInfo.V20240311
>>
>> At the call site, we can access each field via the dot operator. This
>> not only removes `BASELINES` and `DEFAULT_BASELINE` but also ensures
>> that we only match against valid variants, which helps reduce the chance
>> of human error. But unfortunately, `match` was introduced in Python
>> 3.10, whereas the kernel only requires Python 3.9 [1]. This means we
>> cannot leverage mypy's exhaushtiveness check yet. Perhaps I could leave
>> a TODO to remove the assertion and switch to `match` once Python 3.10 is
>> adopted.
>
> That sounds reasonable to me. You can also name the variants in a more
> semantically meaningful way like DEFAULT, SUPPORTS_XXX, etc.
Sounds good to me.
On second thought, I think we can also take advantage of mypy's static
exhaustiveness check by introducing `assert_never`. I'll send v4 and
let's see if it works for you too.
> Finally, `__init__` should return None, not Self.
Absolutely, I'll make that change.
> Thanks for working on this!
My pleasure!
Best regards,
Jesung
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-03-17 9:05 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-07 23:30 [PATCH v3 0/2] rust: take advantage of newer rust-analyzer features Jesung Yang via B4 Relay
2026-03-07 23:30 ` [PATCH v3 1/2] scripts: generate_rust_analyzer.py: add versioning infrastructure Jesung Yang via B4 Relay
2026-03-09 18:34 ` Tamir Duberstein
2026-03-15 7:01 ` Jesung Yang
2026-03-16 14:37 ` Tamir Duberstein
2026-03-17 9:05 ` Jesung Yang
2026-03-07 23:30 ` [PATCH v3 2/2] scripts: generate_rust_analyzer.py: fix IDE support for primitive types Jesung Yang via B4 Relay
2026-03-09 18:34 ` Tamir Duberstein
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox