Rust for Linux List
 help / color / mirror / Atom feed
* [RFC PATCH] rust: doctest: add source map script
@ 2026-06-12 16:05 Gary Guo
  0 siblings, 0 replies; only message in thread
From: Gary Guo @ 2026-06-12 16:05 UTC (permalink / raw)
  To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
	Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich, Brendan Higgins, David Gow, Rae Moar
  Cc: linux-kernel, rust-for-linux, linux-kselftest, kunit-dev

From: Gary Guo <gary@garyguo.net>

Quite often when updating abstractions there will be some documentation
that needs updating, but the build process is not very developer friendly
as it just gives out something like
"rust/doctests_kernel_generated.rs:12345:42" and it is a hassle to find
where the documentation actually is.

Add a script as rustc wrapper, which translates the error message by
appending a "(generated from original_file:original_line:col)" message to
the original source info emitted by rustc.

Signed-off-by: Gary Guo <gary@garyguo.net>
---
I made this a rustc wrapper instead of trying to pipe rustc output to
it, as Kbuild is too complex for me to understand how to do it :)
---
 rust/Makefile                           |  4 ++
 scripts/rustdoc_test_build_sourcemap.py | 71 +++++++++++++++++++++++++
 2 files changed, 75 insertions(+)
 create mode 100644 scripts/rustdoc_test_build_sourcemap.py

diff --git a/rust/Makefile b/rust/Makefile
index 63b1e355321d..d133d4fe1f2d 100644
--- a/rust/Makefile
+++ b/rust/Makefile
@@ -393,6 +393,10 @@ quiet_cmd_rustdoc_test_kernel = RUSTDOC TK $<
     $(objtree)/scripts/rustdoc_test_gen FORCE
 	+$(call if_changed,rustdoc_test_kernel)
 
+ACTUAL_RUSTC := $(RUSTC_OR_CLIPPY)
+%/doctests_kernel_generated.o: private RUSTC_OR_CLIPPY = \
+	PYTHONDONTWRITEBYTECODE=1 ACTUAL_RUSTC=$(ACTUAL_RUSTC) $(PYTHON3) $(srctree)/scripts/rustdoc_test_build_sourcemap.py
+
 # We cannot use `-Zpanic-abort-tests` because some tests are dynamic,
 # so for the moment we skip `-Cpanic=abort`.
 quiet_cmd_rustc_test = $(RUSTC_OR_CLIPPY_QUIET) T  $<
diff --git a/scripts/rustdoc_test_build_sourcemap.py b/scripts/rustdoc_test_build_sourcemap.py
new file mode 100644
index 000000000000..afabcd061567
--- /dev/null
+++ b/scripts/rustdoc_test_build_sourcemap.py
@@ -0,0 +1,71 @@
+import sys
+import re
+import os
+import subprocess
+
+LOCATION_REGEX = re.compile(r"\.location: (.*):(\d+)")
+ANCHOR_REGEX = re.compile(r"static __DOCTEST_ANCHOR: i32 = .* \+ (\d+) \+ (\d+);")
+SOURCE_INFO_REGEX = re.compile(r"(rust/[\w/.-]+\.rs):(\d+):(\d+)")
+
+
+def transform(file, line):
+    with open(file, "r") as f:
+        lines = f.readlines()
+
+    line_idx = line - 1
+
+    # Find the last location and anchor before the erroring line
+    real_path = None
+    orig_line = None
+    anchor_line = None
+
+    for i in range(line_idx, -1, -1):
+        if real_path is None:
+            match = LOCATION_REGEX.search(lines[i])
+            if match:
+                real_path = match.group(1)
+                orig_line = int(match.group(2))
+
+        if anchor_line is None:
+            match = ANCHOR_REGEX.search(lines[i])
+            if match:
+                anchor_line = i + int(match.group(1)) + int(match.group(2))
+
+        if real_path is not None and anchor_line is not None:
+            break
+
+    new_line = orig_line + (line_idx - anchor_line)
+    return real_path, new_line
+
+
+def main():
+    actual_rustc = os.environ.get("ACTUAL_RUSTC")
+    args = sys.argv[1:]
+
+    # We redirected Rust output so it is not TTY anymore.
+    # Add `--color=always` back to preserve the color behaviour.
+    if sys.stdout.isatty() and not any(arg.startswith("--color") for arg in args):
+        args.append("--color=always")
+
+    result = subprocess.run([actual_rustc] + args, stderr=subprocess.PIPE, text=True)
+
+    def replacer(match):
+        orig = match.group(0)
+        file = match.group(1)
+        line = int(match.group(2))
+        col = int(match.group(3))
+
+        if file != "rust/doctests_kernel_generated.rs":
+            return orig
+
+        new_file, new_line = transform(file, line)
+        return f"{orig} (generated from {new_file}:{new_line}:{col})"
+
+    if result.stderr:
+        sys.stderr.write(SOURCE_INFO_REGEX.sub(replacer, result.stderr))
+
+    sys.exit(result.returncode)
+
+
+if __name__ == "__main__":
+    main()

base-commit: 3782319656f65f0bf020d4c058058c23c3e16679
-- 
2.54.0


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2026-06-12 16:05 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-12 16:05 [RFC PATCH] rust: doctest: add source map script Gary Guo

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