public inbox for rust-for-linux@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/2] rust: take advantage of newer rust-analyzer features
@ 2026-01-09 22:08 Jesung Yang via B4 Relay
  2026-01-09 22:09 ` [PATCH v2 1/2] scripts: generate_rust_analyzer: add versioning infrastructure Jesung Yang via B4 Relay
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Jesung Yang via B4 Relay @ 2026-01-09 22:08 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: 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; we must maintain support
for rust-analyzer v0.3.1940 (2024-04-29), which corresponds to our
current MSRV of 1.78.

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.

Thanks to Gary Guo and Miguel Ojeda for their feedback and reviews.

[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/

Signed-off-by: Jesung Yang <y.j3ms.n@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: add versioning infrastructure
      scripts: generate_rust_analyzer: fix IDE support for primitive types

 scripts/generate_rust_analyzer.py | 196 +++++++++++++++++++++++++++++++++-----
 1 file changed, 172 insertions(+), 24 deletions(-)
---
base-commit: 9ace4753a5202b02191d54e9fdf7f9e3d02b85eb
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 v2 1/2] scripts: generate_rust_analyzer: add versioning infrastructure
  2026-01-09 22:08 [PATCH v2 0/2] rust: take advantage of newer rust-analyzer features Jesung Yang via B4 Relay
@ 2026-01-09 22:09 ` Jesung Yang via B4 Relay
  2026-01-09 23:07   ` Tamir Duberstein
  2026-01-09 22:09 ` [PATCH v2 2/2] scripts: generate_rust_analyzer: fix IDE support for primitive types Jesung Yang via B4 Relay
  2026-03-02 16:58 ` [PATCH v2 0/2] rust: take advantage of newer rust-analyzer features Tamir Duberstein
  2 siblings, 1 reply; 8+ messages in thread
From: Jesung Yang via B4 Relay @ 2026-01-09 22:09 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: 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 a feature only available
in rust-analyzer v0.3.2727 (2025-12-22) or later, this infrastructure is
necessary to avoid breaking compatibility with rust-analyzer v0.3.1940
(2024-04-29), which corresponds to our MSRV of 1.78.

Signed-off-by: Jesung Yang <y.j3ms.n@gmail.com>
---
 scripts/generate_rust_analyzer.py | 181 +++++++++++++++++++++++++++++++++-----
 1 file changed, 157 insertions(+), 24 deletions(-)

diff --git a/scripts/generate_rust_analyzer.py b/scripts/generate_rust_analyzer.py
index 147d0cc940681426771db865bc2462e7029a6d7d..32b0da99f17549ecc83e9a68911373310a2c9617 100755
--- a/scripts/generate_rust_analyzer.py
+++ b/scripts/generate_rust_analyzer.py
@@ -4,10 +4,13 @@
 """
 
 import argparse
+from datetime import datetime
+import enum
 import json
 import logging
 import os
 import pathlib
+import re
 import subprocess
 import sys
 
@@ -19,7 +22,7 @@ def args_crates_cfgs(cfgs):
 
     return crates_cfgs
 
-def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edition):
+def generate_crates(ctx, srctree, objtree, sysroot_src, external_src, cfgs, core_edition):
     # Generate the configuration list.
     cfg = []
     with open(objtree / "include" / "generated" / "rustc_cfg") as fd:
@@ -35,7 +38,7 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edit
     crates_indexes = {}
     crates_cfgs = args_crates_cfgs(cfgs)
 
-    def append_crate(display_name, root_module, deps, cfg=[], is_workspace_member=True, is_proc_macro=False, edition="2021"):
+    def append_crate(display_name, root_module, deps, cfg=[], crate_attrs=[], is_workspace_member=True, is_proc_macro=False, edition="2021"):
         crate = {
             "display_name": display_name,
             "root_module": str(root_module),
@@ -48,6 +51,8 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edit
                 "RUST_MODFILE": "This is only for rust-analyzer"
             }
         }
+        if ctx["use_crate_attrs"] and len(crate_attrs) > 0:
+            crate["crate_attrs"] = crate_attrs
         if is_proc_macro:
             proc_macro_dylib_name = subprocess.check_output(
                 [os.environ["RUSTC"], "--print", "file-names", "--crate-name", display_name, "--crate-type", "proc-macro", "-"],
@@ -72,52 +77,58 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edit
             edition=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)`.
-    append_sysroot_crate("core", [], cfg=crates_cfgs.get("core", []), edition=core_edition)
-    append_sysroot_crate("alloc", ["core"])
-    append_sysroot_crate("std", ["alloc", "core"])
-    append_sysroot_crate("proc_macro", ["core", "std"])
+    def sysroot_deps(*deps):
+        return list(deps) if ctx["add_sysroot_crates"] else []
+
+    if ctx["add_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)`.
+        append_sysroot_crate("core", [], cfg=crates_cfgs.get("core", []), edition=core_edition)
+        append_sysroot_crate("alloc", ["core"])
+        append_sysroot_crate("std", ["alloc", "core"])
+        append_sysroot_crate("proc_macro", ["core", "std"])
 
     append_crate(
         "compiler_builtins",
         srctree / "rust" / "compiler_builtins.rs",
         [],
+        crate_attrs=["no_std"],
     )
 
     append_crate(
         "proc_macro2",
         srctree / "rust" / "proc-macro2" / "lib.rs",
-        ["core", "alloc", "std", "proc_macro"],
+        sysroot_deps("core", "alloc", "std", "proc_macro"),
         cfg=crates_cfgs["proc_macro2"],
     )
 
     append_crate(
         "quote",
         srctree / "rust" / "quote" / "lib.rs",
-        ["alloc", "proc_macro", "proc_macro2"],
+        sysroot_deps("alloc", "proc_macro") + ["proc_macro2"],
         cfg=crates_cfgs["quote"],
     )
 
     append_crate(
         "syn",
         srctree / "rust" / "syn" / "lib.rs",
-        ["proc_macro", "proc_macro2", "quote"],
+        sysroot_deps("proc_macro") + ["proc_macro2", "quote"],
         cfg=crates_cfgs["syn"],
     )
 
     append_crate(
         "macros",
         srctree / "rust" / "macros" / "lib.rs",
-        ["std", "proc_macro", "proc_macro2", "quote", "syn"],
+        sysroot_deps("std", "proc_macro") + ["proc_macro2", "quote", "syn"],
         is_proc_macro=True,
     )
 
     append_crate(
         "build_error",
         srctree / "rust" / "build_error.rs",
-        ["core", "compiler_builtins"],
+        sysroot_deps("core") + ["compiler_builtins"],
+        crate_attrs=["no_std"],
     )
 
     append_crate(
@@ -125,31 +136,36 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edit
         srctree / "rust" / "pin-init" / "internal" / "src" / "lib.rs",
         [],
         cfg=["kernel"],
+        crate_attrs=["no_std"],
         is_proc_macro=True,
     )
 
     append_crate(
         "pin_init",
         srctree / "rust" / "pin-init" / "src" / "lib.rs",
-        ["core", "pin_init_internal", "macros"],
+        sysroot_deps("core") + ["pin_init_internal", "macros"],
         cfg=["kernel"],
+        crate_attrs=["no_std"],
     )
 
     append_crate(
         "ffi",
         srctree / "rust" / "ffi.rs",
-        ["core", "compiler_builtins"],
+        sysroot_deps("core") + ["compiler_builtins"],
+        crate_attrs=["no_std"],
     )
 
     def append_crate_with_generated(
         display_name,
         deps,
+        crate_attrs=[]
     ):
         append_crate(
             display_name,
             srctree / "rust"/ display_name / "lib.rs",
             deps,
             cfg=cfg,
+            crate_attrs=crate_attrs
         )
         crates[-1]["env"]["OBJTREE"] = str(objtree.resolve(True))
         crates[-1]["source"] = {
@@ -160,9 +176,21 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edit
             "exclude_dirs": [],
         }
 
-    append_crate_with_generated("bindings", ["core", "ffi", "pin_init"])
-    append_crate_with_generated("uapi", ["core", "ffi", "pin_init"])
-    append_crate_with_generated("kernel", ["core", "macros", "build_error", "pin_init", "ffi", "bindings", "uapi"])
+    append_crate_with_generated(
+        "bindings",
+        sysroot_deps("core") + ["ffi", "pin_init"],
+        crate_attrs=["no_std"],
+    )
+    append_crate_with_generated(
+        "uapi",
+        sysroot_deps("core") + ["ffi", "pin_init"],
+        crate_attrs=["no_std"],
+    )
+    append_crate_with_generated(
+        "kernel",
+        sysroot_deps("core") + ["macros", "build_error", "pin_init", "ffi", "bindings", "uapi"],
+        crate_attrs=["no_std"],
+    )
 
     def is_root_crate(build_file, target):
         try:
@@ -190,12 +218,103 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edit
             append_crate(
                 name,
                 path,
-                ["core", "kernel"],
+                sysroot_deps("core") + ["kernel"],
                 cfg=cfg,
+                crate_attrs=["no_std"]
             )
 
     return crates
 
+@enum.unique
+class RaVersion(enum.Enum):
+    """
+    Represents rust-analyzer compatibility baselines. Concrete versions are mapped to the most
+    recent baseline they have reached. Must be in release order.
+    """
+
+    # v0.3.1940, released on 2024-04-29; bundled with the rustup 1.78 toolchain.
+    V20240429 = 0
+
+    @staticmethod
+    def baselines():
+        assert len(RaVersion) == 1, "Exhaustiveness check: update baseline list!"
+
+        return [
+            (datetime.strptime("2024-04-29", "%Y-%m-%d"), (0, 3, 1940), RaVersion.V20240429),
+        ]
+
+    @staticmethod
+    def default():
+        # The default is the 2024-04-29 release, aligning with our MSRV policy.
+        return RaVersion.V20240429
+
+    def __str__(self):
+        assert len(RaVersion) == 1, "Exhaustiveness check: update if branches!"
+
+        if self == RaVersion.V20240429:
+            return "v0.3.1940 (2024-04-29)"
+        else:
+            assert False, "Unreachable"
+
+def generate_rust_project(
+    ra_version,
+    srctree,
+    objtree,
+    sysroot,
+    sysroot_src,
+    external_src,
+    cfgs,
+    core_edition
+):
+    assert len(RaVersion) == 1, "Exhaustiveness check: update if branches!"
+
+    if ra_version == RaVersion.V20240429:
+        ctx = {
+            "use_crate_attrs": False,
+            "add_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():
+    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):
+    checkpoints = reversed(RaVersion.baselines())
+
+    # First, attempt to resolve to our known checkpoint using the release date.
+    # This covers patterns like "rust-analyzer 1.78.0 (9b00956e 2024-04-29)".
+    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 date, ver, enum in checkpoints:
+            if found_date >= date:
+                return enum
+
+    # Otherwise, attempt to resolve to our known checkpoint using the rust-analyzer version.
+    # This covers patterns like "rust-analyzer 0.3.2743-standalone".
+    version_match = re.search(r"\d+\.\d+\.\d+", ra_version_output)
+    if version_match:
+        found_version = tuple(map(int, version_match.group().split(".")))
+        for date, ver, enum in checkpoints:
+            if found_version >= ver:
+                return enum
+
+    return RaVersion.default()
+
 def main():
     parser = argparse.ArgumentParser()
     parser.add_argument('--verbose', '-v', action='store_true')
@@ -216,10 +335,24 @@ def main():
     # Making sure that the `sysroot` and `sysroot_src` belong to the same toolchain.
     assert args.sysroot in args.sysroot_src.parents
 
-    rust_project = {
-        "crates": generate_crates(args.srctree, args.objtree, args.sysroot_src, args.exttree, args.cfgs, args.core_edition),
-        "sysroot": str(args.sysroot),
-    }
+    output = query_ra_version()
+    if output:
+        compatible_ra_version = map_ra_version_baseline(output)
+    else:
+        default = RaVersion.default()
+        logging.warning("Falling back to `rust-project.json` for rust-analyzer %s", default)
+        compatible_ra_version = default
+
+    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.47.3



^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 2/2] scripts: generate_rust_analyzer: fix IDE support for primitive types
  2026-01-09 22:08 [PATCH v2 0/2] rust: take advantage of newer rust-analyzer features Jesung Yang via B4 Relay
  2026-01-09 22:09 ` [PATCH v2 1/2] scripts: generate_rust_analyzer: add versioning infrastructure Jesung Yang via B4 Relay
@ 2026-01-09 22:09 ` Jesung Yang via B4 Relay
  2026-03-02 16:58 ` [PATCH v2 0/2] rust: take advantage of newer rust-analyzer features Tamir Duberstein
  2 siblings, 0 replies; 8+ messages in thread
From: Jesung Yang via B4 Relay @ 2026-01-09 22:09 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: 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 | 21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/scripts/generate_rust_analyzer.py b/scripts/generate_rust_analyzer.py
index 32b0da99f17549ecc83e9a68911373310a2c9617..6c3cb1d65d97e0ec414192f9fb867700a99c3d57 100755
--- a/scripts/generate_rust_analyzer.py
+++ b/scripts/generate_rust_analyzer.py
@@ -234,13 +234,16 @@ class RaVersion(enum.Enum):
 
     # v0.3.1940, released on 2024-04-29; bundled with the rustup 1.78 toolchain.
     V20240429 = 0
+    # v0.3.2727, released on 2025-12-22.
+    V20251222 = 1
 
     @staticmethod
     def baselines():
-        assert len(RaVersion) == 1, "Exhaustiveness check: update baseline list!"
+        assert len(RaVersion) == 2, "Exhaustiveness check: update checkpoint list!"
 
         return [
             (datetime.strptime("2024-04-29", "%Y-%m-%d"), (0, 3, 1940), RaVersion.V20240429),
+            (datetime.strptime("2025-12-22", "%Y-%m-%d"), (0, 3, 2727), RaVersion.V20251222),
         ]
 
     @staticmethod
@@ -249,10 +252,12 @@ class RaVersion(enum.Enum):
         return RaVersion.V20240429
 
     def __str__(self):
-        assert len(RaVersion) == 1, "Exhaustiveness check: update if branches!"
+        assert len(RaVersion) == 2, "Exhaustiveness check: update if branches!"
 
         if self == RaVersion.V20240429:
             return "v0.3.1940 (2024-04-29)"
+        elif self == RaVersion.V20251222:
+            return "v0.3.2727 (2025-12-22)"
         else:
             assert False, "Unreachable"
 
@@ -266,7 +271,7 @@ def generate_rust_project(
     cfgs,
     core_edition
 ):
-    assert len(RaVersion) == 1, "Exhaustiveness check: update if branches!"
+    assert len(RaVersion) == 2, "Exhaustiveness check: update if branches!"
 
     if ra_version == RaVersion.V20240429:
         ctx = {
@@ -277,6 +282,16 @@ def generate_rust_project(
             "crates": generate_crates(ctx, srctree, objtree, sysroot_src, external_src, cfgs, core_edition),
             "sysroot": str(sysroot),
         }
+    elif ra_version == RaVersion.V20251222:
+        ctx = {
+            "use_crate_attrs": True,
+            "add_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.47.3



^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 1/2] scripts: generate_rust_analyzer: add versioning infrastructure
  2026-01-09 22:09 ` [PATCH v2 1/2] scripts: generate_rust_analyzer: add versioning infrastructure Jesung Yang via B4 Relay
@ 2026-01-09 23:07   ` Tamir Duberstein
  2026-01-11  1:21     ` Jesung Yang
  0 siblings, 1 reply; 8+ messages in thread
From: Tamir Duberstein @ 2026-01-09 23:07 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, rust-for-linux, linux-kernel

On Fri, Jan 9, 2026 at 5:10 PM Jesung Yang via B4 Relay
<devnull+y.j3ms.n.gmail.com@kernel.org> wrote:
>
> 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 a feature only available
> in rust-analyzer v0.3.2727 (2025-12-22) or later, this infrastructure is
> necessary to avoid breaking compatibility with rust-analyzer v0.3.1940
> (2024-04-29), which corresponds to our MSRV of 1.78.
>
> Signed-off-by: Jesung Yang <y.j3ms.n@gmail.com>

I think we can get all the information we need about the compiler
without shelling out to RA here. In KConfig we already have options
like

config RUSTC_HAS_COERCE_POINTEE
  def_bool RUSTC_VERSION >= 108400

and those configs all flow through scripts/generate_rust_analyzer.py.
Could we add one to indicate the new version of RA, and then drive the
logic from it?

> ---
>  scripts/generate_rust_analyzer.py | 181 +++++++++++++++++++++++++++++++++-----
>  1 file changed, 157 insertions(+), 24 deletions(-)
>
> diff --git a/scripts/generate_rust_analyzer.py b/scripts/generate_rust_analyzer.py
> index 147d0cc940681426771db865bc2462e7029a6d7d..32b0da99f17549ecc83e9a68911373310a2c9617 100755
> --- a/scripts/generate_rust_analyzer.py
> +++ b/scripts/generate_rust_analyzer.py
> @@ -4,10 +4,13 @@
>  """
>
>  import argparse
> +from datetime import datetime
> +import enum
>  import json
>  import logging
>  import os
>  import pathlib
> +import re
>  import subprocess
>  import sys
>
> @@ -19,7 +22,7 @@ def args_crates_cfgs(cfgs):
>
>      return crates_cfgs
>
> -def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edition):
> +def generate_crates(ctx, srctree, objtree, sysroot_src, external_src, cfgs, core_edition):
>      # Generate the configuration list.
>      cfg = []
>      with open(objtree / "include" / "generated" / "rustc_cfg") as fd:
> @@ -35,7 +38,7 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edit
>      crates_indexes = {}
>      crates_cfgs = args_crates_cfgs(cfgs)
>
> -    def append_crate(display_name, root_module, deps, cfg=[], is_workspace_member=True, is_proc_macro=False, edition="2021"):
> +    def append_crate(display_name, root_module, deps, cfg=[], crate_attrs=[], is_workspace_member=True, is_proc_macro=False, edition="2021"):
>          crate = {
>              "display_name": display_name,
>              "root_module": str(root_module),
> @@ -48,6 +51,8 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edit
>                  "RUST_MODFILE": "This is only for rust-analyzer"
>              }
>          }
> +        if ctx["use_crate_attrs"] and len(crate_attrs) > 0:
> +            crate["crate_attrs"] = crate_attrs
>          if is_proc_macro:
>              proc_macro_dylib_name = subprocess.check_output(
>                  [os.environ["RUSTC"], "--print", "file-names", "--crate-name", display_name, "--crate-type", "proc-macro", "-"],
> @@ -72,52 +77,58 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edit
>              edition=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)`.
> -    append_sysroot_crate("core", [], cfg=crates_cfgs.get("core", []), edition=core_edition)
> -    append_sysroot_crate("alloc", ["core"])
> -    append_sysroot_crate("std", ["alloc", "core"])
> -    append_sysroot_crate("proc_macro", ["core", "std"])
> +    def sysroot_deps(*deps):
> +        return list(deps) if ctx["add_sysroot_crates"] else []
> +
> +    if ctx["add_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)`.
> +        append_sysroot_crate("core", [], cfg=crates_cfgs.get("core", []), edition=core_edition)
> +        append_sysroot_crate("alloc", ["core"])
> +        append_sysroot_crate("std", ["alloc", "core"])
> +        append_sysroot_crate("proc_macro", ["core", "std"])
>
>      append_crate(
>          "compiler_builtins",
>          srctree / "rust" / "compiler_builtins.rs",
>          [],
> +        crate_attrs=["no_std"],
>      )
>
>      append_crate(
>          "proc_macro2",
>          srctree / "rust" / "proc-macro2" / "lib.rs",
> -        ["core", "alloc", "std", "proc_macro"],
> +        sysroot_deps("core", "alloc", "std", "proc_macro"),
>          cfg=crates_cfgs["proc_macro2"],
>      )
>
>      append_crate(
>          "quote",
>          srctree / "rust" / "quote" / "lib.rs",
> -        ["alloc", "proc_macro", "proc_macro2"],
> +        sysroot_deps("alloc", "proc_macro") + ["proc_macro2"],
>          cfg=crates_cfgs["quote"],
>      )
>
>      append_crate(
>          "syn",
>          srctree / "rust" / "syn" / "lib.rs",
> -        ["proc_macro", "proc_macro2", "quote"],
> +        sysroot_deps("proc_macro") + ["proc_macro2", "quote"],
>          cfg=crates_cfgs["syn"],
>      )
>
>      append_crate(
>          "macros",
>          srctree / "rust" / "macros" / "lib.rs",
> -        ["std", "proc_macro", "proc_macro2", "quote", "syn"],
> +        sysroot_deps("std", "proc_macro") + ["proc_macro2", "quote", "syn"],
>          is_proc_macro=True,
>      )
>
>      append_crate(
>          "build_error",
>          srctree / "rust" / "build_error.rs",
> -        ["core", "compiler_builtins"],
> +        sysroot_deps("core") + ["compiler_builtins"],
> +        crate_attrs=["no_std"],
>      )
>
>      append_crate(
> @@ -125,31 +136,36 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edit
>          srctree / "rust" / "pin-init" / "internal" / "src" / "lib.rs",
>          [],
>          cfg=["kernel"],
> +        crate_attrs=["no_std"],
>          is_proc_macro=True,
>      )
>
>      append_crate(
>          "pin_init",
>          srctree / "rust" / "pin-init" / "src" / "lib.rs",
> -        ["core", "pin_init_internal", "macros"],
> +        sysroot_deps("core") + ["pin_init_internal", "macros"],
>          cfg=["kernel"],
> +        crate_attrs=["no_std"],
>      )
>
>      append_crate(
>          "ffi",
>          srctree / "rust" / "ffi.rs",
> -        ["core", "compiler_builtins"],
> +        sysroot_deps("core") + ["compiler_builtins"],
> +        crate_attrs=["no_std"],
>      )
>
>      def append_crate_with_generated(
>          display_name,
>          deps,
> +        crate_attrs=[]
>      ):
>          append_crate(
>              display_name,
>              srctree / "rust"/ display_name / "lib.rs",
>              deps,
>              cfg=cfg,
> +            crate_attrs=crate_attrs
>          )
>          crates[-1]["env"]["OBJTREE"] = str(objtree.resolve(True))
>          crates[-1]["source"] = {
> @@ -160,9 +176,21 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edit
>              "exclude_dirs": [],
>          }
>
> -    append_crate_with_generated("bindings", ["core", "ffi", "pin_init"])
> -    append_crate_with_generated("uapi", ["core", "ffi", "pin_init"])
> -    append_crate_with_generated("kernel", ["core", "macros", "build_error", "pin_init", "ffi", "bindings", "uapi"])
> +    append_crate_with_generated(
> +        "bindings",
> +        sysroot_deps("core") + ["ffi", "pin_init"],
> +        crate_attrs=["no_std"],
> +    )
> +    append_crate_with_generated(
> +        "uapi",
> +        sysroot_deps("core") + ["ffi", "pin_init"],
> +        crate_attrs=["no_std"],
> +    )
> +    append_crate_with_generated(
> +        "kernel",
> +        sysroot_deps("core") + ["macros", "build_error", "pin_init", "ffi", "bindings", "uapi"],
> +        crate_attrs=["no_std"],
> +    )
>
>      def is_root_crate(build_file, target):
>          try:
> @@ -190,12 +218,103 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edit
>              append_crate(
>                  name,
>                  path,
> -                ["core", "kernel"],
> +                sysroot_deps("core") + ["kernel"],
>                  cfg=cfg,
> +                crate_attrs=["no_std"]
>              )
>
>      return crates
>
> +@enum.unique
> +class RaVersion(enum.Enum):
> +    """
> +    Represents rust-analyzer compatibility baselines. Concrete versions are mapped to the most
> +    recent baseline they have reached. Must be in release order.
> +    """
> +
> +    # v0.3.1940, released on 2024-04-29; bundled with the rustup 1.78 toolchain.
> +    V20240429 = 0
> +
> +    @staticmethod
> +    def baselines():
> +        assert len(RaVersion) == 1, "Exhaustiveness check: update baseline list!"
> +
> +        return [
> +            (datetime.strptime("2024-04-29", "%Y-%m-%d"), (0, 3, 1940), RaVersion.V20240429),
> +        ]
> +
> +    @staticmethod
> +    def default():
> +        # The default is the 2024-04-29 release, aligning with our MSRV policy.
> +        return RaVersion.V20240429
> +
> +    def __str__(self):
> +        assert len(RaVersion) == 1, "Exhaustiveness check: update if branches!"
> +
> +        if self == RaVersion.V20240429:
> +            return "v0.3.1940 (2024-04-29)"
> +        else:
> +            assert False, "Unreachable"
> +
> +def generate_rust_project(
> +    ra_version,
> +    srctree,
> +    objtree,
> +    sysroot,
> +    sysroot_src,
> +    external_src,
> +    cfgs,
> +    core_edition
> +):
> +    assert len(RaVersion) == 1, "Exhaustiveness check: update if branches!"
> +
> +    if ra_version == RaVersion.V20240429:
> +        ctx = {
> +            "use_crate_attrs": False,
> +            "add_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():
> +    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):
> +    checkpoints = reversed(RaVersion.baselines())
> +
> +    # First, attempt to resolve to our known checkpoint using the release date.
> +    # This covers patterns like "rust-analyzer 1.78.0 (9b00956e 2024-04-29)".
> +    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 date, ver, enum in checkpoints:
> +            if found_date >= date:
> +                return enum
> +
> +    # Otherwise, attempt to resolve to our known checkpoint using the rust-analyzer version.
> +    # This covers patterns like "rust-analyzer 0.3.2743-standalone".
> +    version_match = re.search(r"\d+\.\d+\.\d+", ra_version_output)
> +    if version_match:
> +        found_version = tuple(map(int, version_match.group().split(".")))
> +        for date, ver, enum in checkpoints:
> +            if found_version >= ver:
> +                return enum
> +
> +    return RaVersion.default()
> +
>  def main():
>      parser = argparse.ArgumentParser()
>      parser.add_argument('--verbose', '-v', action='store_true')
> @@ -216,10 +335,24 @@ def main():
>      # Making sure that the `sysroot` and `sysroot_src` belong to the same toolchain.
>      assert args.sysroot in args.sysroot_src.parents
>
> -    rust_project = {
> -        "crates": generate_crates(args.srctree, args.objtree, args.sysroot_src, args.exttree, args.cfgs, args.core_edition),
> -        "sysroot": str(args.sysroot),
> -    }
> +    output = query_ra_version()
> +    if output:
> +        compatible_ra_version = map_ra_version_baseline(output)
> +    else:
> +        default = RaVersion.default()
> +        logging.warning("Falling back to `rust-project.json` for rust-analyzer %s", default)
> +        compatible_ra_version = default
> +
> +    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.47.3
>
>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 1/2] scripts: generate_rust_analyzer: add versioning infrastructure
  2026-01-09 23:07   ` Tamir Duberstein
@ 2026-01-11  1:21     ` Jesung Yang
  2026-01-11  2:24       ` Gary Guo
  0 siblings, 1 reply; 8+ messages in thread
From: Jesung Yang @ 2026-01-11  1:21 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, rust-for-linux, linux-kernel

On Sat, Jan 10, 2026 at 8:08 AM Tamir Duberstein <tamird@gmail.com> wrote:
>
> I think we can get all the information we need about the compiler
> without shelling out to RA here. In KConfig we already have options
> like
>
> config RUSTC_HAS_COERCE_POINTEE
>   def_bool RUSTC_VERSION >= 108400
>
> and those configs all flow through scripts/generate_rust_analyzer.py.
> Could we add one to indicate the new version of RA, and then drive the
> logic from it?

This could be an option, but I'm hesitant to use Kconfig soley for
tooling enhancements which don't affect the kernel binary. I'd like to
get a bit more input on whether this approach aligns with how we want
to use Kconfig.

Best regards,
Jesung

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 1/2] scripts: generate_rust_analyzer: add versioning infrastructure
  2026-01-11  1:21     ` Jesung Yang
@ 2026-01-11  2:24       ` Gary Guo
  0 siblings, 0 replies; 8+ messages in thread
From: Gary Guo @ 2026-01-11  2:24 UTC (permalink / raw)
  To: Jesung Yang, Tamir Duberstein
  Cc: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
	Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich, rust-for-linux, linux-kernel

On Sun Jan 11, 2026 at 1:21 AM GMT, Jesung Yang wrote:
> On Sat, Jan 10, 2026 at 8:08 AM Tamir Duberstein <tamird@gmail.com> wrote:
>>
>> I think we can get all the information we need about the compiler
>> without shelling out to RA here. In KConfig we already have options
>> like
>>
>> config RUSTC_HAS_COERCE_POINTEE
>>   def_bool RUSTC_VERSION >= 108400
>>
>> and those configs all flow through scripts/generate_rust_analyzer.py.
>> Could we add one to indicate the new version of RA, and then drive the
>> logic from it?
>
> This could be an option, but I'm hesitant to use Kconfig soley for
> tooling enhancements which don't affect the kernel binary. I'd like to
> get a bit more input on whether this approach aligns with how we want
> to use Kconfig.

Yes, we shouldn't have RA knobs in Kconfig just for this script (the script
is just a good-to-have utility but not a requirement to build or even develop
the kernel anyway).

Best,
Gary

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 0/2] rust: take advantage of newer rust-analyzer features
  2026-01-09 22:08 [PATCH v2 0/2] rust: take advantage of newer rust-analyzer features Jesung Yang via B4 Relay
  2026-01-09 22:09 ` [PATCH v2 1/2] scripts: generate_rust_analyzer: add versioning infrastructure Jesung Yang via B4 Relay
  2026-01-09 22:09 ` [PATCH v2 2/2] scripts: generate_rust_analyzer: fix IDE support for primitive types Jesung Yang via B4 Relay
@ 2026-03-02 16:58 ` Tamir Duberstein
  2026-03-04  9:52   ` Jesung Yang
  2 siblings, 1 reply; 8+ messages in thread
From: Tamir Duberstein @ 2026-03-02 16:58 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, rust-for-linux, linux-kernel

On Fri, Jan 9, 2026 at 5:10 PM Jesung Yang via B4 Relay
<devnull+y.j3ms.n.gmail.com@kernel.org> wrote:
>
> 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; we must maintain support
> for rust-analyzer v0.3.1940 (2024-04-29), which corresponds to our
> current MSRV of 1.78.
>
> 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.
>
> Thanks to Gary Guo and Miguel Ojeda for their feedback and reviews.
>
> [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/
>
> Signed-off-by: Jesung Yang <y.j3ms.n@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: add versioning infrastructure
>       scripts: generate_rust_analyzer: fix IDE support for primitive types
>
>  scripts/generate_rust_analyzer.py | 196 +++++++++++++++++++++++++++++++++-----
>  1 file changed, 172 insertions(+), 24 deletions(-)
> ---
> base-commit: 9ace4753a5202b02191d54e9fdf7f9e3d02b85eb
> change-id: 20260101-ra-fix-primitive-78154fe8173f
>
> Best regards,
> --
> Jesung Yang <y.j3ms.n@gmail.com>
>
>

Hi Jesung, is this something you'd be interested in updating now that
type hints have been staged in rust-analyzer-next?

Cheers.
Tamir

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 0/2] rust: take advantage of newer rust-analyzer features
  2026-03-02 16:58 ` [PATCH v2 0/2] rust: take advantage of newer rust-analyzer features Tamir Duberstein
@ 2026-03-04  9:52   ` Jesung Yang
  0 siblings, 0 replies; 8+ messages in thread
From: Jesung Yang @ 2026-03-04  9:52 UTC (permalink / raw)
  To: Tamir Duberstein, y.j3ms.n
  Cc: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
	Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich, rust-for-linux, linux-kernel

On Tue Mar 3, 2026 at 1:58 AM KST, Tamir Duberstein wrote:
[...]
>
> Hi Jesung, is this something you'd be interested in updating now that
> type hints have been staged in rust-analyzer-next?

Yeah, I'll send the next version within a few days.

Best regards,
Jesung

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2026-03-04  9:53 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-09 22:08 [PATCH v2 0/2] rust: take advantage of newer rust-analyzer features Jesung Yang via B4 Relay
2026-01-09 22:09 ` [PATCH v2 1/2] scripts: generate_rust_analyzer: add versioning infrastructure Jesung Yang via B4 Relay
2026-01-09 23:07   ` Tamir Duberstein
2026-01-11  1:21     ` Jesung Yang
2026-01-11  2:24       ` Gary Guo
2026-01-09 22:09 ` [PATCH v2 2/2] scripts: generate_rust_analyzer: fix IDE support for primitive types Jesung Yang via B4 Relay
2026-03-02 16:58 ` [PATCH v2 0/2] rust: take advantage of newer rust-analyzer features Tamir Duberstein
2026-03-04  9:52   ` Jesung Yang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox