[PATCH 0/3] rust: doctest: unify with other kunit tests

0 views
Skip to first unread message

Gary Guo

unread,
Jun 16, 2026, 11:24:58 AMJun 16
to Miguel Ojeda, Boqun Feng, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein, Alexandre Courbot, Onur Özkan, Brendan Higgins, David Gow, Rae Moar, rust-fo...@vger.kernel.org, linux-...@vger.kernel.org, linux-k...@vger.kernel.org, kuni...@googlegroups.com, Gary Guo
Currently in Rust, kunit tests are handled with `kunit_tests`, while the
doctests generate a lot `extern "C"` functions and invoke them through a
generated C wrapper.

This is currently needed because of the special treatment of file name and
line numbers from doctests. Convert them to override `file!()` and
`line!()` macro instead, and use them inside `kunit_assert!`.

With this it is possible to just generate `#[kunit_tests]` and `#[test]`
for doctests.

Signed-off-by: Gary Guo <ga...@garyguo.net>
---
Gary Guo (3):
rust: kunit: use `file!()` inside `kunit_assert!`
rust: kunit: use `line!()` inside `kunit_assert!`
rust: doctest: generate Rust kunit test suites

Documentation/rust/general-information.rst | 4 +-
init/Kconfig | 3 --
rust/Makefile | 4 +-
rust/kernel/device_id.rs | 2 +-
rust/kernel/kunit.rs | 11 +++--
rust/kernel/str.rs | 2 +-
rust/macros/helpers.rs | 16 -------
rust/macros/kunit.rs | 5 +-
rust/macros/lib.rs | 5 --
scripts/rustdoc_test_gen.rs | 73 ++++++++----------------------
10 files changed, 31 insertions(+), 94 deletions(-)
---
base-commit: c425609d6ac4012c8bbf01ec2e10e801b1923a7b
change-id: 20260616-kunit-348f2c029b1e

Best regards,
--
Gary Guo <ga...@garyguo.net>

Gary Guo

unread,
Jun 16, 2026, 11:24:59 AMJun 16
to Miguel Ojeda, Boqun Feng, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein, Alexandre Courbot, Onur Özkan, Brendan Higgins, David Gow, Rae Moar, rust-fo...@vger.kernel.org, linux-...@vger.kernel.org, linux-k...@vger.kernel.org, kuni...@googlegroups.com, Gary Guo
For doctest, instead of generating C FFI functions, generate a Rust test
suite with `#[kunit_tests]` and `#[test]` attributes. This makes the C glue
no longer needed.

Signed-off-by: Gary Guo <ga...@garyguo.net>
---
rust/Makefile | 4 +--
scripts/rustdoc_test_gen.rs | 69 ++++++---------------------------------------
2 files changed, 10 insertions(+), 63 deletions(-)

diff --git a/rust/Makefile b/rust/Makefile
index a870d1616c71..8c95dd4f6aee 100644
--- a/rust/Makefile
+++ b/rust/Makefile
@@ -36,10 +36,8 @@ obj-$(CONFIG_RUST) += exports.o
always-$(CONFIG_RUST) += libproc_macro2.rlib libquote.rlib libsyn.rlib

always-$(CONFIG_RUST_KERNEL_DOCTESTS) += doctests_kernel_generated.rs
-always-$(CONFIG_RUST_KERNEL_DOCTESTS) += doctests_kernel_generated_kunit.c

obj-$(CONFIG_RUST_KERNEL_DOCTESTS) += doctests_kernel_generated.o
-obj-$(CONFIG_RUST_KERNEL_DOCTESTS) += doctests_kernel_generated_kunit.o

always-$(subst y,$(CONFIG_RUST),$(CONFIG_JUMP_LABEL)) += kernel/generated_arch_static_branch_asm.rs
ifndef CONFIG_UML
@@ -387,7 +385,7 @@ quiet_cmd_rustdoc_test_kernel = RUSTDOC TK $<
$< $(rustdoc_test_kernel_quiet); \
$(objtree)/scripts/rustdoc_test_gen

-%/doctests_kernel_generated.rs %/doctests_kernel_generated_kunit.c: \
+%/doctests_kernel_generated.rs: \
$(src)/kernel/lib.rs $(obj)/kernel.o \
$(objtree)/scripts/rustdoc_test_builder \
$(objtree)/scripts/rustdoc_test_gen FORCE
diff --git a/scripts/rustdoc_test_gen.rs b/scripts/rustdoc_test_gen.rs
index acc4debe8592..601f7a5b3672 100644
--- a/scripts/rustdoc_test_gen.rs
+++ b/scripts/rustdoc_test_gen.rs
@@ -118,9 +118,7 @@ fn main() {
// Sort paths.
paths.sort();

- let mut rust_tests = String::new();
- let mut c_test_declarations = String::new();
- let mut c_test_cases = String::new();
+ let mut tests = String::new();
let mut body = String::new();
let mut last_file = String::new();
let mut number = 0;
@@ -165,10 +163,10 @@ fn main() {

use std::fmt::Write;
write!(
- rust_tests,
+ tests,
r#"/// Generated `{name}` KUnit test case from a Rust documentation test.
-#[no_mangle]
-pub extern "C" fn {kunit_name}(__kunit_test: *mut ::kernel::bindings::kunit) {{
+#[test]
+fn {kunit_name}() {{
// Overrides the usual [`file!`] macro with one that expands to the real path.
#[allow(unused)]
macro_rules! file {{
@@ -183,26 +181,6 @@ macro_rules! line {{
() => {{ const {{ ::core::line!() - __DOCTEST_ANCHOR + {line} }} }}
}}

- /// Overrides the usual [`assert!`] macro with one that calls KUnit instead.
- #[allow(unused)]
- macro_rules! assert {{
- ($cond:expr $(,)?) => {{{{
- ::kernel::kunit_assert!(
- "{kunit_name}", $cond
- );
- }}}}
- }}
-
- /// Overrides the usual [`assert_eq!`] macro with one that calls KUnit instead.
- #[allow(unused)]
- macro_rules! assert_eq {{
- ($left:expr, $right:expr $(,)?) => {{{{
- ::kernel::kunit_assert_eq!(
- "{kunit_name}", $left, $right
- );
- }}}}
- }}
-
// Many tests need the prelude, so provide it by default.
#[allow(unused)]
use ::kernel::prelude::*;
@@ -231,14 +209,9 @@ macro_rules! assert_eq {{
"#
)
.unwrap();
-
- write!(c_test_declarations, "void {kunit_name}(struct kunit *);\n").unwrap();
- write!(c_test_cases, " KUNIT_CASE({kunit_name}),\n").unwrap();
}

- let rust_tests = rust_tests.trim();
- let c_test_declarations = c_test_declarations.trim();
- let c_test_cases = c_test_cases.trim();
+ let tests = tests.trim();

write!(
BufWriter::new(File::create("rust/doctests_kernel_generated.rs").unwrap()),
@@ -246,34 +219,10 @@ macro_rules! assert_eq {{

const __LOG_PREFIX: &[u8] = b"rust_doctests_kernel\0";

-{rust_tests}
-"#
- )
- .unwrap();
-
- write!(
- BufWriter::new(File::create("rust/doctests_kernel_generated_kunit.c").unwrap()),
- r#"/*
- * `kernel` crate documentation tests.
- */
-
-#include <kunit/test.h>
-
-{c_test_declarations}
-
-static struct kunit_case test_cases[] = {{
- {c_test_cases}
- {{ }}
-}};
-
-static struct kunit_suite test_suite = {{
- .name = "rust_doctests_kernel",
- .test_cases = test_cases,
-}};
-
-kunit_test_suite(test_suite);
-
-MODULE_LICENSE("GPL");
+#[kernel::macros::kunit_tests(rust_doctests_kernel)]
+mod tests {{
+{tests}
+}}
"#
)
.unwrap();

--
2.54.0

Gary Guo

unread,
Jun 16, 2026, 11:24:59 AMJun 16
to Miguel Ojeda, Boqun Feng, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein, Alexandre Courbot, Onur Özkan, Brendan Higgins, David Gow, Rae Moar, rust-fo...@vger.kernel.org, linux-...@vger.kernel.org, linux-k...@vger.kernel.org, kuni...@googlegroups.com, Gary Guo
The `diff` parameter is needed currently because doctests want to override
the line number. Simplify it by changing it to use `line!()`. Have doctests
override `line!()` macro to achieve the current behavior.

A few current doctests (or their invoked macros) require `line!()` to
expand to literal; they're updated to use `::core::line!()` instead.

Signed-off-by: Gary Guo <ga...@garyguo.net>
---
rust/kernel/device_id.rs | 2 +-
rust/kernel/kunit.rs | 8 ++++----
rust/kernel/str.rs | 2 +-
rust/macros/kunit.rs | 4 ++--
scripts/rustdoc_test_gen.rs | 16 ++++++++++++----
5 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/rust/kernel/device_id.rs b/rust/kernel/device_id.rs
index 8e9721446014..20e2fe137202 100644
--- a/rust/kernel/device_id.rs
+++ b/rust/kernel/device_id.rs
@@ -195,7 +195,7 @@ macro_rules! module_device_table {
($table_type: literal, $module_table_name:ident, $table_name:ident) => {
#[rustfmt::skip]
#[export_name =
- concat!("__mod_device_table__", line!(),
+ concat!("__mod_device_table__", ::core::line!(),
"__kmod_", module_path!(),
"__", $table_type,
"__", stringify!($table_name))
diff --git a/rust/kernel/kunit.rs b/rust/kernel/kunit.rs
index 157fd0634708..58dfec66b4f6 100644
--- a/rust/kernel/kunit.rs
+++ b/rust/kernel/kunit.rs
@@ -58,7 +58,7 @@ pub fn info(args: fmt::Arguments<'_>) {
#[doc(hidden)]
#[macro_export]
macro_rules! kunit_assert {
- ($name:literal, $diff:expr, $condition:expr $(,)?) => {
+ ($name:literal, $condition:expr $(,)?) => {
'out: {
// Do nothing if the condition is `true`.
if $condition {
@@ -67,7 +67,7 @@ macro_rules! kunit_assert {

// Use `file!()` instead of `::core::file!()` here so it can be overridden.
static FILE: &'static $crate::str::CStr = $crate::c_str!(file!());
- static LINE: i32 = ::core::line!() as i32 - $diff;
+ static LINE: i32 = line!() as i32;
static CONDITION: &'static $crate::str::CStr = $crate::c_str!(stringify!($condition));

// SAFETY: FFI call without safety requirements.
@@ -165,10 +165,10 @@ unsafe impl Sync for UnaryAssert {}
#[doc(hidden)]
#[macro_export]
macro_rules! kunit_assert_eq {
- ($name:literal, $diff:expr, $left:expr, $right:expr $(,)?) => {{
+ ($name:literal, $left:expr, $right:expr $(,)?) => {{
// For the moment, we just forward to the expression assert because, for binary asserts,
// KUnit supports only a few types (e.g. integers).
- $crate::kunit_assert!($name, $diff, $left == $right);
+ $crate::kunit_assert!($name, $left == $right);
}};
}

diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs
index b3caa9a1c898..644b4279a116 100644
--- a/rust/kernel/str.rs
+++ b/rust/kernel/str.rs
@@ -411,7 +411,7 @@ fn as_ref(&self) -> &BStr {
/// const BAD: &CStr = c_str!("literal");
///
/// // `c_str!` is still needed for static non-literal C strings.
-/// const GOOD: &CStr = c_str!(concat!(file!(), ":", line!(), ": My CStr!"));
+/// const GOOD: &CStr = c_str!(concat!(file!(), ":", ::core::line!(), ": My CStr!"));
/// ```
#[macro_export]
macro_rules! c_str {
diff --git a/rust/macros/kunit.rs b/rust/macros/kunit.rs
index 936eff014870..e9152b9d51f9 100644
--- a/rust/macros/kunit.rs
+++ b/rust/macros/kunit.rs
@@ -113,7 +113,7 @@ pub(crate) fn kunit_tests(test_suite: Ident, mut module: ItemMod) -> Result<Toke
#[allow(unused)]
macro_rules! assert {
($cond:expr $(,)?) => {{
- kernel::kunit_assert!(#test_str, 0, $cond);
+ kernel::kunit_assert!(#test_str, $cond);
}}
}
});
@@ -121,7 +121,7 @@ macro_rules! assert {
#[allow(unused)]
macro_rules! assert_eq {
($left:expr, $right:expr $(,)?) => {{
- kernel::kunit_assert_eq!(#test_str, 0, $left, $right);
+ kernel::kunit_assert_eq!(#test_str, $left, $right);
}}
}
});
diff --git a/scripts/rustdoc_test_gen.rs b/scripts/rustdoc_test_gen.rs
index 37f4877f52e2..acc4debe8592 100644
--- a/scripts/rustdoc_test_gen.rs
+++ b/scripts/rustdoc_test_gen.rs
@@ -169,18 +169,26 @@ fn main() {
r#"/// Generated `{name}` KUnit test case from a Rust documentation test.
#[no_mangle]
pub extern "C" fn {kunit_name}(__kunit_test: *mut ::kernel::bindings::kunit) {{
- /// Overrides the usual [`file!`] macro with one that expands to the real path.
+ // Overrides the usual [`file!`] macro with one that expands to the real path.
#[allow(unused)]
macro_rules! file {{
() => {{ "{real_path}" }}
}}

+ // Overrides the usual [`line!`] macro with one that expands to the real line number.
+ #[allow(unused)]
+ macro_rules! line {{
+ // NOTE: This does not expand to a literal, but a constant expression.
+ // Therefore code that depends on `line!()` being overrideable needs special adjustment.
+ () => {{ const {{ ::core::line!() - __DOCTEST_ANCHOR + {line} }} }}
+ }}
+
/// Overrides the usual [`assert!`] macro with one that calls KUnit instead.
#[allow(unused)]
macro_rules! assert {{
($cond:expr $(,)?) => {{{{
::kernel::kunit_assert!(
- "{kunit_name}", __DOCTEST_ANCHOR - {line}, $cond
+ "{kunit_name}", $cond
);
}}}}
}}
@@ -190,7 +198,7 @@ macro_rules! assert {{
macro_rules! assert_eq {{
($left:expr, $right:expr $(,)?) => {{{{
::kernel::kunit_assert_eq!(
- "{kunit_name}", __DOCTEST_ANCHOR - {line}, $left, $right
+ "{kunit_name}", $left, $right
);
}}}}
}}
@@ -212,7 +220,7 @@ macro_rules! assert_eq {{

/// The anchor where the test code body starts.
#[allow(unused)]
- static __DOCTEST_ANCHOR: i32 = ::core::line!() as i32 + {body_offset} + 2;
+ static __DOCTEST_ANCHOR: u32 = ::core::line!() + {body_offset} + 2;
{{
#![allow(unreachable_pub, clippy::disallowed_names)]
{body}

--
2.54.0

Gary Guo

unread,
Jun 16, 2026, 11:24:59 AMJun 16
to Miguel Ojeda, Boqun Feng, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein, Alexandre Courbot, Onur Özkan, Brendan Higgins, David Gow, Rae Moar, rust-fo...@vger.kernel.org, linux-...@vger.kernel.org, linux-k...@vger.kernel.org, kuni...@googlegroups.com, Gary Guo
This parameter is needed currently because doctests want to override the
file. Simplify it by changing it to use `file!()`. Have doctests override
`file!()` macro to achieve the current behavior.

This allows us to remove the `file` helper and associated Kconfig options.

Signed-off-by: Gary Guo <ga...@garyguo.net>
---
Documentation/rust/general-information.rst | 4 ++--
init/Kconfig | 3 ---
rust/kernel/kunit.rs | 9 +++++----
rust/macros/helpers.rs | 16 ----------------
rust/macros/kunit.rs | 5 ++---
rust/macros/lib.rs | 5 -----
scripts/rustdoc_test_gen.rs | 10 ++++++++--
7 files changed, 17 insertions(+), 35 deletions(-)

diff --git a/Documentation/rust/general-information.rst b/Documentation/rust/general-information.rst
index 09234bed272c..20e3178ebfd4 100644
--- a/Documentation/rust/general-information.rst
+++ b/Documentation/rust/general-information.rst
@@ -157,5 +157,5 @@ numerical comparisons, one may define a new Kconfig symbol:

.. code-block:: kconfig

- config RUSTC_HAS_SPAN_FILE
- def_bool RUSTC_VERSION >= 108800
+ config RUSTC_HAS_FILE_AS_C_STR
+ def_bool RUSTC_VERSION >= 109100
diff --git a/init/Kconfig b/init/Kconfig
index 5230d4879b1c..e118fdb9df11 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -178,9 +178,6 @@ config LD_CAN_USE_KEEP_IN_OVERLAY
# https://github.com/llvm/llvm-project/pull/130661
def_bool LD_IS_BFD || LLD_VERSION >= 210000

-config RUSTC_HAS_SPAN_FILE
- def_bool RUSTC_VERSION >= 108800
-
config RUSTC_HAS_UNNECESSARY_TRANSMUTES
def_bool RUSTC_VERSION >= 108800

diff --git a/rust/kernel/kunit.rs b/rust/kernel/kunit.rs
index cdee5f27bd7f..157fd0634708 100644
--- a/rust/kernel/kunit.rs
+++ b/rust/kernel/kunit.rs
@@ -58,14 +58,15 @@ pub fn info(args: fmt::Arguments<'_>) {
#[doc(hidden)]
#[macro_export]
macro_rules! kunit_assert {
- ($name:literal, $file:literal, $diff:expr, $condition:expr $(,)?) => {
+ ($name:literal, $diff:expr, $condition:expr $(,)?) => {
'out: {
// Do nothing if the condition is `true`.
if $condition {
break 'out;
}

- static FILE: &'static $crate::str::CStr = $file;
+ // Use `file!()` instead of `::core::file!()` here so it can be overridden.
+ static FILE: &'static $crate::str::CStr = $crate::c_str!(file!());
static LINE: i32 = ::core::line!() as i32 - $diff;
static CONDITION: &'static $crate::str::CStr = $crate::c_str!(stringify!($condition));

@@ -164,10 +165,10 @@ unsafe impl Sync for UnaryAssert {}
#[doc(hidden)]
#[macro_export]
macro_rules! kunit_assert_eq {
- ($name:literal, $file:literal, $diff:expr, $left:expr, $right:expr $(,)?) => {{
+ ($name:literal, $diff:expr, $left:expr, $right:expr $(,)?) => {{
// For the moment, we just forward to the expression assert because, for binary asserts,
// KUnit supports only a few types (e.g. integers).
- $crate::kunit_assert!($name, $file, $diff, $left == $right);
+ $crate::kunit_assert!($name, $diff, $left == $right);
}};
}

diff --git a/rust/macros/helpers.rs b/rust/macros/helpers.rs
index d18fbf4daa0a..8cc9a20f470e 100644
--- a/rust/macros/helpers.rs
+++ b/rust/macros/helpers.rs
@@ -38,22 +38,6 @@ pub(crate) fn value(&self) -> String {
}
}

-pub(crate) fn file() -> String {
- #[cfg(not(CONFIG_RUSTC_HAS_SPAN_FILE))]
- {
- proc_macro::Span::call_site()
- .source_file()
- .path()
- .to_string_lossy()
- .into_owned()
- }
-
- #[cfg(CONFIG_RUSTC_HAS_SPAN_FILE)]
- {
- proc_macro::Span::call_site().file()
- }
-}
-
/// Obtain all `#[cfg]` attributes.
pub(crate) fn gather_cfg_attrs(attr: &[Attribute]) -> impl Iterator<Item = &Attribute> + '_ {
attr.iter().filter(|a| a.path().is_ident("cfg"))
diff --git a/rust/macros/kunit.rs b/rust/macros/kunit.rs
index ae20ed6768f1..936eff014870 100644
--- a/rust/macros/kunit.rs
+++ b/rust/macros/kunit.rs
@@ -109,12 +109,11 @@ pub(crate) fn kunit_tests(test_suite: Ident, mut module: ItemMod) -> Result<Toke
// Before the test, override usual `assert!` and `assert_eq!` macros with ones that call
// KUnit instead.
let test_str = test.to_string();
- let path = CString::new(crate::helpers::file()).expect("file path cannot contain NUL");
processed_items.push(parse_quote! {
#[allow(unused)]
macro_rules! assert {
($cond:expr $(,)?) => {{
- kernel::kunit_assert!(#test_str, #path, 0, $cond);
+ kernel::kunit_assert!(#test_str, 0, $cond);
}}
}
});
@@ -122,7 +121,7 @@ macro_rules! assert {
#[allow(unused)]
macro_rules! assert_eq {
($left:expr, $right:expr $(,)?) => {{
- kernel::kunit_assert_eq!(#test_str, #path, 0, $left, $right);
+ kernel::kunit_assert_eq!(#test_str, 0, $left, $right);
}}
}
});
diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs
index 4a48fabbc268..6b00f9789772 100644
--- a/rust/macros/lib.rs
+++ b/rust/macros/lib.rs
@@ -8,11 +8,6 @@

// Stable since Rust 1.87.0.
#![feature(extract_if)]
-//
-// Stable since Rust 1.88.0 under a different name, `proc_macro_span_file`,
-// which was added in Rust 1.88.0. This is why `cfg_attr` is used here, i.e.
-// to avoid depending on the full `proc_macro_span` on Rust >= 1.88.0.
-#![cfg_attr(not(CONFIG_RUSTC_HAS_SPAN_FILE), feature(proc_macro_span))]

mod concat_idents;
mod export;
diff --git a/scripts/rustdoc_test_gen.rs b/scripts/rustdoc_test_gen.rs
index d61a77219a8c..37f4877f52e2 100644
--- a/scripts/rustdoc_test_gen.rs
+++ b/scripts/rustdoc_test_gen.rs
@@ -169,12 +169,18 @@ fn main() {
r#"/// Generated `{name}` KUnit test case from a Rust documentation test.
#[no_mangle]
pub extern "C" fn {kunit_name}(__kunit_test: *mut ::kernel::bindings::kunit) {{
+ /// Overrides the usual [`file!`] macro with one that expands to the real path.
+ #[allow(unused)]
+ macro_rules! file {{
+ () => {{ "{real_path}" }}
+ }}
+
/// Overrides the usual [`assert!`] macro with one that calls KUnit instead.
#[allow(unused)]
macro_rules! assert {{
($cond:expr $(,)?) => {{{{
::kernel::kunit_assert!(
- "{kunit_name}", c"{real_path}", __DOCTEST_ANCHOR - {line}, $cond
+ "{kunit_name}", __DOCTEST_ANCHOR - {line}, $cond
);
}}}}
}}
@@ -184,7 +190,7 @@ macro_rules! assert {{
macro_rules! assert_eq {{
($left:expr, $right:expr $(,)?) => {{{{
::kernel::kunit_assert_eq!(
- "{kunit_name}", c"{real_path}", __DOCTEST_ANCHOR - {line}, $left, $right
+ "{kunit_name}", __DOCTEST_ANCHOR - {line}, $left, $right
);
}}}}
}}

--
2.54.0

David Gow

unread,
Jun 20, 2026, 7:07:42 AMJun 20
to Gary Guo, Miguel Ojeda, Boqun Feng, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein, Alexandre Courbot, Onur Özkan, Brendan Higgins, Rae Moar, rust-fo...@vger.kernel.org, linux-...@vger.kernel.org, linux-k...@vger.kernel.org, kuni...@googlegroups.com
Le 16/06/2026 à 11:24 PM, Gary Guo a écrit :
> This parameter is needed currently because doctests want to override the
> file. Simplify it by changing it to use `file!()`. Have doctests override
> `file!()` macro to achieve the current behavior.
>
> This allows us to remove the `file` helper and associated Kconfig options.
>
> Signed-off-by: Gary Guo <ga...@garyguo.net>
> ---

Looks good to me.

Reviewed-by: David Gow <da...@davidgow.net>

Cheers,
-- David

> Documentation/rust/general-information.rst | 4 ++--
> init/Kconfig | 3 ---
> rust/kernel/kunit.rs | 9 +++++----
> rust/macros/helpers.rs | 16 ----------------
> rust/macros/kunit.rs | 5 ++---
> rust/macros/lib.rs | 5 -----
> scripts/rustdoc_test_gen.rs | 10 ++++++++--
> 7 files changed, 17 insertions(+), 35 deletions(-)
>
> diff --git a/Documentation/rust/general-information.rst b/Documentation/rust/general-information.rst
> index 09234bed272c..20e3178ebfd4 100644
> --- a/Documentation/rust/general-information.rst
> +++ b/Documentation/rust/general-information.rst
> @@ -157,5 +157,5 @@ numerical comparisons, one may define a new Kconfig symbol:
>
> .. code-block:: kconfig
>
> - config RUSTC_HAS_SPAN_FILE
> - def_bool RUSTC_VERSION >= 108800
> + config RUSTC_HAS_FILE_AS_C_STR
> + def_bool RUSTC_VERSION >= 109100

Are we using RUSTC_FILE_AS_C_STR for this? I know it's used elsewhere,
and it makes sense to replace RUSTC_HAS_SPAN_FILE with something that's
used _somewhere_, but I do see a hardcoded c_str!(file!()) below. I'm
assuming that RUSTC_FILE_AS_C_STR isn't something useful there.

(This is just out of my own curiosity, rather than an actual suggestion.)

David Gow

unread,
Jun 20, 2026, 7:07:58 AMJun 20
to Gary Guo, Miguel Ojeda, Boqun Feng, Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein, Alexandre Courbot, Onur Özkan, Brendan Higgins, Rae Moar, rust-fo...@vger.kernel.org, linux-...@vger.kernel.org, linux-k...@vger.kernel.org, kuni...@googlegroups.com
Le 16/06/2026 à 11:24 PM, Gary Guo a écrit :
> For doctest, instead of generating C FFI functions, generate a Rust test
> suite with `#[kunit_tests]` and `#[test]` attributes. This makes the C glue
> no longer needed.
>
> Signed-off-by: Gary Guo <ga...@garyguo.net>
> ---

Thanks very much for this. It's been on the to-do list for a while, and
it's definitely much nicer than generating lots of C code.

Reviewed-by: David Gow <da...@davidgow.net>

My feeling is that this series should go via the rust-for-linux tree,
rather than the KUnit tree, as there's lots of poking around in common
rust files, and no change to the KUnit C code. But if you'd rather it go
in via kselftest/kunit, that's possible too.

Cheers,
-- David
Reply all
Reply to author
Forward
0 new messages