* [PATCH v7 0/2] rust: take advantage of newer rust-analyzer features
@ 2026-05-07 14:47 Jesung Yang via B4 Relay
2026-05-07 14:47 ` [PATCH v7 1/2] scripts: generate_rust_analyzer.py: add versioning infrastructure Jesung Yang via B4 Relay
2026-05-07 14:47 ` [PATCH v7 2/2] scripts: generate_rust_analyzer.py: fix IDE support for primitive types Jesung Yang via B4 Relay
0 siblings, 2 replies; 7+ messages in thread
From: Jesung Yang via B4 Relay @ 2026-05-07 14:47 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, 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.
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.
----- [QUICK TEST INSTRUCTIONS] -----
[Example 1]
1) Apply this patch series.
2) Run `mypy --strict scripts/generate_rust_analyzer.py` against
different Python versions (e.g., `--python-version 3.9`,
`--python-version 3.11`)
3) Verify that there is no type errors.
[Example 2]
1) Make rust-analyzer>=v0.3.2727 (2025-12-22) available in `$PATH`.
2) Compile one of the crates under `driver/` or `samples/rust`.
3) Run `make LLVM=1 rust-analyzer`.
4) Check that autocompletion for inherent methods does not work for
primitive types (e.g., `0i32.rotate_left()`).
5) Apply this patch series.
6) Re-run `make LLVM=1 rust-analyzer`.
7) Verify that autocompletion works properly now.
8) Verify that no autocompletion is provided for `std`.
[Example 3]
1) Make rust-analyzer<v0.3.2727 (2025-12-22) available in `$PATH`.
2) Compile one of the crates under `driver/` or `samples/rust`.
3) Run `make LLVM=1 rust-analyzer`.
4) Run `mv rust-project.json rust-project.json.old`.
5) Apply this patch series.
6) Re-run `make LLVM=1 rust-analyzer`.
7) Run `diff -s rust-project.json rust-project.json.old` to verify that
they are identical.
[Example 4]
1) Apply this patch series.
2) Ensure `rust-analyzer` is not available in `$PATH`.
3) Run `make V=1 LLVM=1 rust-analyzer`.
4) Verify that the fallback warning message appears.
[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 v7:
- Streamline the bash script.
- Wrap `reversed(RaVersionInfo)` with `list()`.
- Link to v6: https://patch.msgid.link/20260504-ra-fix-primitive-v6-0-74cfc1e862d0@gmail.com
Changes in v6:
- Make bash script more portable.
- Aggregate fallback logs into one.
- Use `date` instead of `datetime`.
- Limit line length to 80 characters.
- Link to v5: https://patch.msgid.link/20260430-ra-fix-primitive-v5-0-6364d2258e14@gmail.com
Changes in v5:
- Document how to retrieve rust-analyzer version information.
- Rename `RaVersionInfo.DEFAULT` to `RaVersionInfo.MSRV`.
- Move the introduction of `RaVersionCtx` to the second patch.
- Embed `RaVersionCtx` into `RaVersionInfo`.
- Conditionally add `sysroot_src` field depending on
`manual_sysroot_crates`.
- Conditionally add `crate_attrs` field depending on `use_crate_attrs`.
- Conditionally define `RustProject` and `Crate` for stricter type
checking in newer Python versions.
- Move the dependency filtering logic to `build_crate`.
- Move `RustProject` closer to its point of use.
- Fix grammar.
- Link to v4: https://lore.kernel.org/r/20260317-ra-fix-primitive-v4-0-bc06709c8243@gmail.com
Changes in v4:
- Use `dataclass` for internal data structures.
- Change `RaVersionInfo` to an enum.
- Move `RaVersionInfo` closer to its point of use.
- Statically check if all `RaVersionInfo` variants are properly handled
(using mypy).
- Relocate `ctx.manual_sysroot_crates` check in `append_sysroot_crate`.
- Move `crate_attrs=["no_std"]` addition to `scripts:
generate_rust_analyzer.py: fix IDE support for primitive types`.
- Move `typing.NotRequired` closer to the relevant field.
- Link to v3: https://lore.kernel.org/r/20260308-ra-fix-primitive-v3-0-598017bcefd8@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 | 284 +++++++++++++++++++++++++++++++++++---
1 file changed, 264 insertions(+), 20 deletions(-)
---
base-commit: b4e07588e743c989499ca24d49e752c074924a9a
change-id: 20260101-ra-fix-primitive-78154fe8173f
Best regards,
--
Jesung Yang <y.j3ms.n@gmail.com>
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v7 1/2] scripts: generate_rust_analyzer.py: add versioning infrastructure
2026-05-07 14:47 [PATCH v7 0/2] rust: take advantage of newer rust-analyzer features Jesung Yang via B4 Relay
@ 2026-05-07 14:47 ` Jesung Yang via B4 Relay
2026-05-07 16:18 ` Tamir Duberstein
2026-05-07 14:47 ` [PATCH v7 2/2] scripts: generate_rust_analyzer.py: fix IDE support for primitive types Jesung Yang via B4 Relay
1 sibling, 1 reply; 7+ messages in thread
From: Jesung Yang via B4 Relay @ 2026-05-07 14:47 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, 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.
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 | 186 +++++++++++++++++++++++++++++++++++++-
1 file changed, 182 insertions(+), 4 deletions(-)
diff --git a/scripts/generate_rust_analyzer.py b/scripts/generate_rust_analyzer.py
index d5f9a0ca742c..79c69004aed1 100755
--- a/scripts/generate_rust_analyzer.py
+++ b/scripts/generate_rust_analyzer.py
@@ -4,6 +4,9 @@
"""
import argparse
+from datetime import date
+import enum
+import re
import json
import logging
import os
@@ -343,6 +346,161 @@ def generate_crates(
return crates
+
+Version = tuple[int, int, int]
+
+
+@enum.unique
+class RaVersionInfo(enum.Enum):
+ """
+ Represents rust-analyzer compatibility baselines. Concrete versions are
+ mapped to the most recent baseline they have reached. Must be in release
+ order.
+ """
+
+ # NOTE:
+ # This rust-analyzer release should be kept in sync with our MSRV (currently
+ # 1.85.0). When the MSRV is bumped, follow the steps below to retrieve the
+ # information needed to update this:
+ #
+ # 1) Clone both Rust and rust-analyzer repositories.
+ # ```console
+ # $ git clone https://github.com/rust-lang/rust.git
+ # $ git clone https://github.com/rust-lang/rust-analyzer.git
+ # ```
+ # 2) Run the following script, providing the new MSRV as an argument. It
+ # prints a link to the matching [1] rust-analyzer release page.
+ # ```bash
+ # #!/usr/bin/env bash
+ #
+ # set -euo pipefail
+ #
+ # RUST_VERSION=$1
+ #
+ # grep_args=()
+ # while IFS= read -r subject; do
+ # grep_args+=(--grep "$subject")
+ # done < <(git -C rust log \
+ # --fixed-strings \
+ # --format='%s' \
+ # --grep 'Merge pull request #' \
+ # --merges \
+ # --no-follow \
+ # -n 10 \
+ # "$RUST_VERSION" \
+ # -- src/tools/rust-analyzer
+ # )
+ #
+ # tag_predates=$(
+ # git -C rust-analyzer log \
+ # --fixed-strings \
+ # --format='%(describe:tags,abbrev=0)' \
+ # --merges \
+ # -n 1 \
+ # "${grep_args[@]}"
+ # )
+ #
+ # link_prefix="https://github.com/rust-lang/rust-analyzer/releases/tag"
+ # echo "$link_prefix/$tag_predates"
+ # ```
+ # 3) Grab the release date and the version string.
+ #
+ # [1] Note that rust-analyzer releases may not perfectly align with those
+ # shipped in upstream Rust. We take a conservative approach here: use
+ # the tag that directly predates the latest merge commit found upstream.
+ #
+ # v0.3.2228, released on 2024-12-23;
+ # shipped with the rustup 1.85.0 toolchain.
+ MSRV = (
+ date(2024, 12, 23),
+ (0, 3, 2228),
+ (1, 85, 0),
+ )
+
+ def __init__(
+ self,
+ release_date: date,
+ ra_version: Version,
+ rust_version: Version,
+ ) -> None:
+ self.release_date = release_date
+ self.ra_version = ra_version
+ self.rust_version = rust_version
+
+
+class RustProject(TypedDict):
+ crates: List[Crate]
+ sysroot: str
+
+
+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:
+ rust_project: RustProject = {
+ "crates": generate_crates(
+ srctree, objtree, sysroot_src, external_src, cfgs, core_edition
+ ),
+ "sysroot": str(sysroot),
+ }
+
+ return rust_project
+
+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:
+ return None
+
+def map_ra_version_baseline(ra_version_output: str) -> RaVersionInfo:
+ baselines = list(reversed(RaVersionInfo))
+
+ 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 a 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 = date.fromisoformat(date_match.group())
+ for info in baselines:
+ if found_date >= info.release_date:
+ return info
+
+ return RaVersionInfo.MSRV
+
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument('--verbose', '-v', action='store_true')
@@ -371,10 +529,30 @@ 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(
+ "Failed to find rust-analyzer in $PATH; " \
+ "falling back to `rust-project.json` for rust-analyzer " \
+ "%s, %s (shipped with Rust %s)",
+ ".".join(map(str, RaVersionInfo.MSRV.ra_version)),
+ RaVersionInfo.MSRV.release_date,
+ ".".join(map(str, RaVersionInfo.MSRV.rust_version)),
+ )
+ compatible_ra_version = RaVersionInfo.MSRV
+
+ 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.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v7 2/2] scripts: generate_rust_analyzer.py: fix IDE support for primitive types
2026-05-07 14:47 [PATCH v7 0/2] rust: take advantage of newer rust-analyzer features Jesung Yang via B4 Relay
2026-05-07 14:47 ` [PATCH v7 1/2] scripts: generate_rust_analyzer.py: add versioning infrastructure Jesung Yang via B4 Relay
@ 2026-05-07 14:47 ` Jesung Yang via B4 Relay
2026-05-07 16:19 ` Tamir Duberstein
2026-05-11 18:11 ` Tamir Duberstein
1 sibling, 2 replies; 7+ messages in thread
From: Jesung Yang via B4 Relay @ 2026-05-07 14:47 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, 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
Reviewed-by: Tamir Duberstein <tamird@kernel.org>
Signed-off-by: Jesung Yang <y.j3ms.n@gmail.com>
---
scripts/generate_rust_analyzer.py | 108 ++++++++++++++++++++++++++++++--------
1 file changed, 87 insertions(+), 21 deletions(-)
diff --git a/scripts/generate_rust_analyzer.py b/scripts/generate_rust_analyzer.py
index 79c69004aed1..8629dd186891 100755
--- a/scripts/generate_rust_analyzer.py
+++ b/scripts/generate_rust_analyzer.py
@@ -4,6 +4,7 @@
"""
import argparse
+from dataclasses import dataclass
from datetime import date
import enum
import re
@@ -39,14 +40,28 @@ class Source(TypedDict):
exclude_dirs: List[str]
-class Crate(TypedDict):
- display_name: str
- root_module: str
- is_workspace_member: bool
- deps: List[Dependency]
- cfg: List[str]
- edition: str
- env: Dict[str, str]
+# TODO: clean up once Python 3.11 is adopted.
+if sys.version_info < (3, 11):
+ class Crate(TypedDict, total=False):
+ display_name: str
+ root_module: str
+ is_workspace_member: bool
+ deps: List[Dependency]
+ cfg: List[str]
+ crate_attrs: List[str]
+ edition: str
+ env: Dict[str, str]
+else:
+ from typing import NotRequired
+ class Crate(TypedDict):
+ display_name: str
+ root_module: str
+ is_workspace_member: bool
+ deps: List[Dependency]
+ cfg: List[str]
+ crate_attrs: NotRequired[List[str]]
+ edition: str
+ env: Dict[str, str]
class ProcMacroCrate(Crate):
@@ -58,7 +73,14 @@ class CrateWithGenerated(Crate):
source: Source
+@dataclass(frozen=True)
+class RaVersionCtx:
+ manual_sysroot_crates: bool
+ use_crate_attrs: bool
+
+
def generate_crates(
+ ctx: RaVersionCtx,
srctree: pathlib.Path,
objtree: pathlib.Path,
sysroot_src: pathlib.Path,
@@ -84,22 +106,24 @@ def generate_crates(
def build_crate(
display_name: str,
root_module: pathlib.Path,
- deps: List[Dependency],
+ deps: List[Optional[Dependency]],
*,
cfg: Optional[List[str]],
+ crate_attrs: Optional[List[str]],
is_workspace_member: Optional[bool],
edition: Optional[str],
) -> Crate:
+ filtered_deps = [dep for dep in deps if dep is not None]
cfg = cfg if cfg is not None else crates_cfgs.get(display_name, [])
is_workspace_member = (
is_workspace_member if is_workspace_member is not None else True
)
edition = edition if edition is not None else "2021"
- return {
+ crate: Crate = {
"display_name": display_name,
"root_module": str(root_module),
"is_workspace_member": is_workspace_member,
- "deps": deps,
+ "deps": filtered_deps,
"cfg": cfg,
"edition": edition,
"env": {
@@ -107,10 +131,15 @@ def generate_crates(
}
}
+ if ctx.use_crate_attrs and crate_attrs is not None:
+ crate["crate_attrs"] = crate_attrs
+
+ return crate
+
def append_proc_macro_crate(
display_name: str,
root_module: pathlib.Path,
- deps: List[Dependency],
+ deps: List[Optional[Dependency]],
*,
cfg: Optional[List[str]] = None,
is_workspace_member: Optional[bool] = None,
@@ -121,6 +150,7 @@ def generate_crates(
root_module,
deps,
cfg=cfg,
+ crate_attrs=None,
is_workspace_member=is_workspace_member,
edition=edition,
)
@@ -148,9 +178,10 @@ def generate_crates(
def append_crate(
display_name: str,
root_module: pathlib.Path,
- deps: List[Dependency],
+ deps: List[Optional[Dependency]],
*,
cfg: Optional[List[str]] = None,
+ crate_attrs: Optional[List[str]] = None,
is_workspace_member: Optional[bool] = None,
edition: Optional[str] = None,
) -> Dependency:
@@ -160,6 +191,7 @@ def generate_crates(
root_module,
deps,
cfg=cfg,
+ crate_attrs=crate_attrs,
is_workspace_member=is_workspace_member,
edition=edition,
)
@@ -167,10 +199,12 @@ def generate_crates(
def append_sysroot_crate(
display_name: str,
- deps: List[Dependency],
+ deps: List[Optional[Dependency]],
*,
cfg: Optional[List[str]] = None,
- ) -> Dependency:
+ ) -> Optional[Dependency]:
+ if not ctx.manual_sysroot_crates:
+ return None
return append_crate(
display_name,
sysroot_src / display_name / "src" / "lib.rs",
@@ -269,13 +303,14 @@ def generate_crates(
def append_crate_with_generated(
display_name: str,
- deps: List[Dependency],
+ deps: List[Optional[Dependency]],
) -> Dependency:
crate = build_crate(
display_name,
srctree / "rust"/ display_name / "lib.rs",
deps,
cfg=generated_cfg,
+ crate_attrs=None,
is_workspace_member=True,
edition=None,
)
@@ -342,6 +377,7 @@ def generate_crates(
path,
[core, kernel, pin_init],
cfg=generated_cfg,
+ crate_attrs=["no_std"],
)
return crates
@@ -415,6 +451,21 @@ class RaVersionInfo(enum.Enum):
date(2024, 12, 23),
(0, 3, 2228),
(1, 85, 0),
+ RaVersionCtx(
+ use_crate_attrs=False,
+ manual_sysroot_crates=True,
+ ),
+ )
+ # v0.3.2727, released on 2025-12-22;
+ # v0.3.2743 is shipped with the rustup 1.94.0 toolchain.
+ SUPPROTS_CRATE_ATTRS = (
+ date(2025, 12, 22),
+ (0, 3, 2727),
+ (1, 94, 0),
+ RaVersionCtx(
+ use_crate_attrs=True,
+ manual_sysroot_crates=False,
+ ),
)
def __init__(
@@ -422,19 +473,30 @@ class RaVersionInfo(enum.Enum):
release_date: date,
ra_version: Version,
rust_version: Version,
+ ctx: RaVersionCtx,
) -> None:
self.release_date = release_date
self.ra_version = ra_version
self.rust_version = rust_version
+ self.ctx = ctx
-class RustProject(TypedDict):
- crates: List[Crate]
- sysroot: str
+# TODO: clean up once Python 3.11 is adopted.
+if sys.version_info < (3, 11):
+ class RustProject(TypedDict, total=False):
+ crates: List[Crate]
+ sysroot: str
+ sysroot_src: str
+else:
+ from typing import NotRequired
+ class RustProject(TypedDict):
+ crates: List[Crate]
+ sysroot: str
+ sysroot_src: NotRequired[str]
def generate_rust_project(
- _version_info: RaVersionInfo,
+ version_info: RaVersionInfo,
srctree: pathlib.Path,
objtree: pathlib.Path,
sysroot: pathlib.Path,
@@ -443,13 +505,17 @@ def generate_rust_project(
cfgs: List[str],
core_edition: str,
) -> RustProject:
+ ctx = version_info.ctx
rust_project: RustProject = {
"crates": generate_crates(
- srctree, objtree, sysroot_src, external_src, cfgs, core_edition
+ ctx, srctree, objtree, sysroot_src, external_src, cfgs, core_edition
),
"sysroot": str(sysroot),
}
+ if not ctx.manual_sysroot_crates:
+ rust_project["sysroot_src"] = str(sysroot_src)
+
return rust_project
def query_ra_version() -> Optional[str]:
--
2.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v7 1/2] scripts: generate_rust_analyzer.py: add versioning infrastructure
2026-05-07 14:47 ` [PATCH v7 1/2] scripts: generate_rust_analyzer.py: add versioning infrastructure Jesung Yang via B4 Relay
@ 2026-05-07 16:18 ` Tamir Duberstein
0 siblings, 0 replies; 7+ messages in thread
From: Tamir Duberstein @ 2026-05-07 16:18 UTC (permalink / raw)
To: Jesung Yang
Cc: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, Tamir Duberstein, Eliot Courtney,
rust-for-linux, linux-kernel
On Thu, 07 May 2026 23:47:24 +0900, Jesung Yang <y.j3ms.n@gmail.com> wrote:
> diff --git a/scripts/generate_rust_analyzer.py b/scripts/generate_rust_analyzer.py
> index d5f9a0ca742c..79c69004aed1 100755
> --- a/scripts/generate_rust_analyzer.py
> +++ b/scripts/generate_rust_analyzer.py
> @@ -343,6 +346,161 @@ def generate_crates(
> [ ... skip 117 lines ... ]
> + .decode("utf-8")
> + .strip()
> + )
> + return ra_version_output
> + except FileNotFoundError:
> + return None
This needs to also catch subprocess.CalledProcessError because rustup
may provide the `rust-analyzer` binstub even when the component is not
installed:
% rustup component remove rust-analyzer
% which rust-analyzer
/opt/homebrew/opt/rustup/bin/rust-analyzer
% rust-analyzer --version
I can fix this on apply; this diff fixed the problem for me (includes
more correct warning logging):
diff --git a/scripts/generate_rust_analyzer.py b/scripts/generate_rust_analyzer.py
index 8629dd186891..9dee5151cb45 100755
--- a/scripts/generate_rust_analyzer.py
+++ b/scripts/generate_rust_analyzer.py
@@ -531,7 +531,27 @@ def query_ra_version() -> Optional[str]:
)
return ra_version_output
except FileNotFoundError:
- return None
+ logging.warning(
+ "Failed to find rust-analyzer in $PATH; "
+ "falling back to `rust-project.json` for rust-analyzer "
+ "%s, %s (shipped with Rust %s)",
+ ".".join(map(str, RaVersionInfo.MSRV.ra_version)),
+ RaVersionInfo.MSRV.release_date,
+ ".".join(map(str, RaVersionInfo.MSRV.rust_version)),
+ )
+ except subprocess.CalledProcessError as exc:
+ logging.warning(
+ "Failed to query rust-analyzer version; "
+ "`rust-analyzer --version` exited with status %s; "
+ "falling back to `rust-project.json` for rust-analyzer "
+ "%s, %s (shipped with Rust %s)",
+ exc.returncode,
+ ".".join(map(str, RaVersionInfo.MSRV.ra_version)),
+ RaVersionInfo.MSRV.release_date,
+ ".".join(map(str, RaVersionInfo.MSRV.rust_version)),
+ )
+
+ return None
def map_ra_version_baseline(ra_version_output: str) -> RaVersionInfo:
baselines = list(reversed(RaVersionInfo))
@@ -596,18 +616,11 @@ def main() -> None:
)
ra_version_output = query_ra_version()
- if ra_version_output:
- compatible_ra_version = map_ra_version_baseline(ra_version_output)
- else:
- logging.warning(
- "Failed to find rust-analyzer in $PATH; " \
- "falling back to `rust-project.json` for rust-analyzer " \
- "%s, %s (shipped with Rust %s)",
- ".".join(map(str, RaVersionInfo.MSRV.ra_version)),
- RaVersionInfo.MSRV.release_date,
- ".".join(map(str, RaVersionInfo.MSRV.rust_version)),
- )
- compatible_ra_version = RaVersionInfo.MSRV
+ compatible_ra_version = (
+ map_ra_version_baseline(ra_version_output)
+ if ra_version_output is not None
+ else RaVersionInfo.MSRV
+ )
rust_project = generate_rust_project(
compatible_ra_version,
Reviewed-by: Tamir Duberstein <tamird@kernel.org>
--
Tamir Duberstein <tamird@kernel.org>
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v7 2/2] scripts: generate_rust_analyzer.py: fix IDE support for primitive types
2026-05-07 14:47 ` [PATCH v7 2/2] scripts: generate_rust_analyzer.py: fix IDE support for primitive types Jesung Yang via B4 Relay
@ 2026-05-07 16:19 ` Tamir Duberstein
2026-05-08 23:02 ` Jesung Yang
2026-05-11 18:11 ` Tamir Duberstein
1 sibling, 1 reply; 7+ messages in thread
From: Tamir Duberstein @ 2026-05-07 16:19 UTC (permalink / raw)
To: y.j3ms.n
Cc: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, Eliot Courtney, rust-for-linux, linux-kernel
On Thu, May 7, 2026 at 10:47 AM Jesung Yang via B4 Relay
<devnull+y.j3ms.n.gmail.com@kernel.org> wrote:
>
> 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
> Reviewed-by: Tamir Duberstein <tamird@kernel.org>
> Signed-off-by: Jesung Yang <y.j3ms.n@gmail.com>
> ---
> scripts/generate_rust_analyzer.py | 108 ++++++++++++++++++++++++++++++--------
> 1 file changed, 87 insertions(+), 21 deletions(-)
>
> diff --git a/scripts/generate_rust_analyzer.py b/scripts/generate_rust_analyzer.py
> index 79c69004aed1..8629dd186891 100755
> --- a/scripts/generate_rust_analyzer.py
> +++ b/scripts/generate_rust_analyzer.py
> @@ -4,6 +4,7 @@
> """
>
> import argparse
> +from dataclasses import dataclass
> from datetime import date
> import enum
> import re
> @@ -39,14 +40,28 @@ class Source(TypedDict):
> exclude_dirs: List[str]
>
>
> -class Crate(TypedDict):
> - display_name: str
> - root_module: str
> - is_workspace_member: bool
> - deps: List[Dependency]
> - cfg: List[str]
> - edition: str
> - env: Dict[str, str]
> +# TODO: clean up once Python 3.11 is adopted.
> +if sys.version_info < (3, 11):
> + class Crate(TypedDict, total=False):
> + display_name: str
> + root_module: str
> + is_workspace_member: bool
> + deps: List[Dependency]
> + cfg: List[str]
> + crate_attrs: List[str]
> + edition: str
> + env: Dict[str, str]
> +else:
> + from typing import NotRequired
> + class Crate(TypedDict):
> + display_name: str
> + root_module: str
> + is_workspace_member: bool
> + deps: List[Dependency]
> + cfg: List[str]
> + crate_attrs: NotRequired[List[str]]
> + edition: str
> + env: Dict[str, str]
>
>
> class ProcMacroCrate(Crate):
> @@ -58,7 +73,14 @@ class CrateWithGenerated(Crate):
> source: Source
>
>
> +@dataclass(frozen=True)
> +class RaVersionCtx:
> + manual_sysroot_crates: bool
> + use_crate_attrs: bool
> +
> +
> def generate_crates(
> + ctx: RaVersionCtx,
> srctree: pathlib.Path,
> objtree: pathlib.Path,
> sysroot_src: pathlib.Path,
> @@ -84,22 +106,24 @@ def generate_crates(
> def build_crate(
> display_name: str,
> root_module: pathlib.Path,
> - deps: List[Dependency],
> + deps: List[Optional[Dependency]],
> *,
> cfg: Optional[List[str]],
> + crate_attrs: Optional[List[str]],
> is_workspace_member: Optional[bool],
> edition: Optional[str],
> ) -> Crate:
> + filtered_deps = [dep for dep in deps if dep is not None]
> cfg = cfg if cfg is not None else crates_cfgs.get(display_name, [])
> is_workspace_member = (
> is_workspace_member if is_workspace_member is not None else True
> )
> edition = edition if edition is not None else "2021"
> - return {
> + crate: Crate = {
> "display_name": display_name,
> "root_module": str(root_module),
> "is_workspace_member": is_workspace_member,
> - "deps": deps,
> + "deps": filtered_deps,
> "cfg": cfg,
> "edition": edition,
> "env": {
> @@ -107,10 +131,15 @@ def generate_crates(
> }
> }
>
> + if ctx.use_crate_attrs and crate_attrs is not None:
> + crate["crate_attrs"] = crate_attrs
> +
> + return crate
> +
> def append_proc_macro_crate(
> display_name: str,
> root_module: pathlib.Path,
> - deps: List[Dependency],
> + deps: List[Optional[Dependency]],
> *,
> cfg: Optional[List[str]] = None,
> is_workspace_member: Optional[bool] = None,
> @@ -121,6 +150,7 @@ def generate_crates(
> root_module,
> deps,
> cfg=cfg,
> + crate_attrs=None,
> is_workspace_member=is_workspace_member,
> edition=edition,
> )
> @@ -148,9 +178,10 @@ def generate_crates(
> def append_crate(
> display_name: str,
> root_module: pathlib.Path,
> - deps: List[Dependency],
> + deps: List[Optional[Dependency]],
> *,
> cfg: Optional[List[str]] = None,
> + crate_attrs: Optional[List[str]] = None,
> is_workspace_member: Optional[bool] = None,
> edition: Optional[str] = None,
> ) -> Dependency:
> @@ -160,6 +191,7 @@ def generate_crates(
> root_module,
> deps,
> cfg=cfg,
> + crate_attrs=crate_attrs,
> is_workspace_member=is_workspace_member,
> edition=edition,
> )
> @@ -167,10 +199,12 @@ def generate_crates(
>
> def append_sysroot_crate(
> display_name: str,
> - deps: List[Dependency],
> + deps: List[Optional[Dependency]],
> *,
> cfg: Optional[List[str]] = None,
> - ) -> Dependency:
> + ) -> Optional[Dependency]:
> + if not ctx.manual_sysroot_crates:
> + return None
> return append_crate(
> display_name,
> sysroot_src / display_name / "src" / "lib.rs",
> @@ -269,13 +303,14 @@ def generate_crates(
>
> def append_crate_with_generated(
> display_name: str,
> - deps: List[Dependency],
> + deps: List[Optional[Dependency]],
> ) -> Dependency:
> crate = build_crate(
> display_name,
> srctree / "rust"/ display_name / "lib.rs",
> deps,
> cfg=generated_cfg,
> + crate_attrs=None,
> is_workspace_member=True,
> edition=None,
> )
> @@ -342,6 +377,7 @@ def generate_crates(
> path,
> [core, kernel, pin_init],
> cfg=generated_cfg,
> + crate_attrs=["no_std"],
> )
>
> return crates
> @@ -415,6 +451,21 @@ class RaVersionInfo(enum.Enum):
> date(2024, 12, 23),
> (0, 3, 2228),
> (1, 85, 0),
> + RaVersionCtx(
> + use_crate_attrs=False,
> + manual_sysroot_crates=True,
> + ),
> + )
> + # v0.3.2727, released on 2025-12-22;
> + # v0.3.2743 is shipped with the rustup 1.94.0 toolchain.
> + SUPPROTS_CRATE_ATTRS = (
Typo here. I can fix that on apply.
> + date(2025, 12, 22),
> + (0, 3, 2727),
> + (1, 94, 0),
> + RaVersionCtx(
> + use_crate_attrs=True,
> + manual_sysroot_crates=False,
> + ),
> )
>
> def __init__(
> @@ -422,19 +473,30 @@ class RaVersionInfo(enum.Enum):
> release_date: date,
> ra_version: Version,
> rust_version: Version,
> + ctx: RaVersionCtx,
> ) -> None:
> self.release_date = release_date
> self.ra_version = ra_version
> self.rust_version = rust_version
> + self.ctx = ctx
>
>
> -class RustProject(TypedDict):
> - crates: List[Crate]
> - sysroot: str
> +# TODO: clean up once Python 3.11 is adopted.
> +if sys.version_info < (3, 11):
> + class RustProject(TypedDict, total=False):
> + crates: List[Crate]
> + sysroot: str
> + sysroot_src: str
> +else:
> + from typing import NotRequired
> + class RustProject(TypedDict):
> + crates: List[Crate]
> + sysroot: str
> + sysroot_src: NotRequired[str]
>
>
> def generate_rust_project(
> - _version_info: RaVersionInfo,
> + version_info: RaVersionInfo,
> srctree: pathlib.Path,
> objtree: pathlib.Path,
> sysroot: pathlib.Path,
> @@ -443,13 +505,17 @@ def generate_rust_project(
> cfgs: List[str],
> core_edition: str,
> ) -> RustProject:
> + ctx = version_info.ctx
> rust_project: RustProject = {
> "crates": generate_crates(
> - srctree, objtree, sysroot_src, external_src, cfgs, core_edition
> + ctx, srctree, objtree, sysroot_src, external_src, cfgs, core_edition
> ),
> "sysroot": str(sysroot),
> }
>
> + if not ctx.manual_sysroot_crates:
> + rust_project["sysroot_src"] = str(sysroot_src)
> +
> return rust_project
>
> def query_ra_version() -> Optional[str]:
>
> --
> 2.53.0
>
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v7 2/2] scripts: generate_rust_analyzer.py: fix IDE support for primitive types
2026-05-07 16:19 ` Tamir Duberstein
@ 2026-05-08 23:02 ` Jesung Yang
0 siblings, 0 replies; 7+ messages in thread
From: Jesung Yang @ 2026-05-08 23:02 UTC (permalink / raw)
To: Tamir Duberstein
Cc: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, Eliot Courtney, rust-for-linux, linux-kernel
On Fri, May 8, 2026 at 1:20 AM Tamir Duberstein <tamird@kernel.org> wrote:
> On Thu, May 7, 2026 at 10:47 AM Jesung Yang via B4 Relay
> <devnull+y.j3ms.n.gmail.com@kernel.org> wrote:
> >
> > @@ -415,6 +451,21 @@ class RaVersionInfo(enum.Enum):
> > date(2024, 12, 23),
> > (0, 3, 2228),
> > (1, 85, 0),
> > + RaVersionCtx(
> > + use_crate_attrs=False,
> > + manual_sysroot_crates=True,
> > + ),
> > + )
> > + # v0.3.2727, released on 2025-12-22;
> > + # v0.3.2743 is shipped with the rustup 1.94.0 toolchain.
> > + SUPPROTS_CRATE_ATTRS = (
>
> Typo here. I can fix that on apply.
Thanks. I should refine my workflow so I don't repeat these trivial
mistakes ^_^;
Best regards,
Jesung
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v7 2/2] scripts: generate_rust_analyzer.py: fix IDE support for primitive types
2026-05-07 14:47 ` [PATCH v7 2/2] scripts: generate_rust_analyzer.py: fix IDE support for primitive types Jesung Yang via B4 Relay
2026-05-07 16:19 ` Tamir Duberstein
@ 2026-05-11 18:11 ` Tamir Duberstein
1 sibling, 0 replies; 7+ messages in thread
From: Tamir Duberstein @ 2026-05-11 18:11 UTC (permalink / raw)
To: y.j3ms.n
Cc: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, Eliot Courtney, rust-for-linux, linux-kernel
On Thu, May 7, 2026 at 10:47 AM Jesung Yang via B4 Relay
<devnull+y.j3ms.n.gmail.com@kernel.org> wrote:
>
> 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
> Reviewed-by: Tamir Duberstein <tamird@kernel.org>
> Signed-off-by: Jesung Yang <y.j3ms.n@gmail.com>
I think this loses the kernel's custom sysroot crate cfgs. In particular,
rust/Makefile passes --cfgs='core=$(core-cfgs)' today, which includes
no_fp_fmt_parse. Once we switch to sysroot_src and stop modeling core
explicitly, rust-analyzer discovers core by itself and no longer sees those
cfgs.
Would sysroot_project be needed here to keep the custom sysroot crate
configuration while still avoiding the primitive-method resolution issue?
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-05-11 18:11 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-07 14:47 [PATCH v7 0/2] rust: take advantage of newer rust-analyzer features Jesung Yang via B4 Relay
2026-05-07 14:47 ` [PATCH v7 1/2] scripts: generate_rust_analyzer.py: add versioning infrastructure Jesung Yang via B4 Relay
2026-05-07 16:18 ` Tamir Duberstein
2026-05-07 14:47 ` [PATCH v7 2/2] scripts: generate_rust_analyzer.py: fix IDE support for primitive types Jesung Yang via B4 Relay
2026-05-07 16:19 ` Tamir Duberstein
2026-05-08 23:02 ` Jesung Yang
2026-05-11 18:11 ` Tamir Duberstein
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox