* [PATCH v2 0/3] rust: const_eval: add a mechanism to do const trait calls
@ 2026-09-03 15:21 Gary Guo
2026-09-03 15:21 ` [PATCH v2 1/3] rust: const_eval: add `#[const_eval_only]` attribute Gary Guo
` (3 more replies)
0 siblings, 4 replies; 6+ messages in thread
From: Gary Guo @ 2026-09-03 15:21 UTC (permalink / raw)
To: Eliot Courtney, 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
Cc: linux-kernel, rust-for-linux, Gary Guo
Add a mechanism to perform const trait method calls, with the same type
inference capabilities. This would only work for concrete types (not inside
generic functions).
As an example, convert `as_char_ptr_in_const_context`, so instead of
kernel::str::as_char_ptr_in_const_context(c_str)
one may write
const_call!(c_str.as_char_ptr())
instead.
Signed-off-by: Gary Guo <gary@garyguo.net>
---
Changes in v2:
- Split from `cv!()` alt series, and become a general infra instead.
- Link to v1: https://patch.msgid.link/20260828-cv-v1-0-694a695ff17f@garyguo.net
---
Gary Guo (3):
rust: const_eval: add `#[const_eval_only]` attribute
rust: const_eval: allow const trait method invocation in some contexts
rust: str: convert `as_char_ptr` to work with `const_call!`
rust/build_error.rs | 7 +++
rust/kernel/configfs.rs | 2 +-
rust/kernel/const_eval.rs | 115 ++++++++++++++++++++++++++++++++++++++++++++++
rust/kernel/device_id.rs | 4 ++
rust/kernel/drm/device.rs | 4 +-
rust/kernel/drm/ioctl.rs | 4 +-
rust/kernel/kunit.rs | 6 +--
rust/kernel/lib.rs | 1 +
rust/kernel/miscdevice.rs | 2 +-
rust/kernel/net/phy.rs | 2 +-
rust/kernel/prelude.rs | 1 +
rust/kernel/str.rs | 15 +++---
rust/macros/const_eval.rs | 51 ++++++++++++++++++++
rust/macros/lib.rs | 39 ++++++++++++++++
rust/macros/module.rs | 4 +-
15 files changed, 237 insertions(+), 20 deletions(-)
---
base-commit: 89c07d98716a13454ec3fd9f97689e812cc71bd4
change-id: 20260828-cv-acaf3400d16c
Best regards,
--
Gary Guo <gary@garyguo.net>
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2 1/3] rust: const_eval: add `#[const_eval_only]` attribute
2026-09-03 15:21 [PATCH v2 0/3] rust: const_eval: add a mechanism to do const trait calls Gary Guo
@ 2026-09-03 15:21 ` Gary Guo
2026-09-03 15:21 ` [PATCH v2 2/3] rust: const_eval: allow const trait method invocation in some contexts Gary Guo
` (2 subsequent siblings)
3 siblings, 0 replies; 6+ messages in thread
From: Gary Guo @ 2026-09-03 15:21 UTC (permalink / raw)
To: Eliot Courtney, 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
Cc: linux-kernel, rust-for-linux, Gary Guo
We have a lot of helper const functions which are intended to be used
during const evaluation only and runtime calls should not be generated. Add
a macro to denote this explicitly. This is similar to C++'s consteval
keyword.
Convert device_id.rs as an example.
Signed-off-by: Gary Guo <gary@garyguo.net>
---
rust/build_error.rs | 7 +++++++
rust/kernel/const_eval.rs | 9 +++++++++
rust/kernel/device_id.rs | 4 ++++
rust/kernel/lib.rs | 1 +
rust/macros/const_eval.rs | 24 ++++++++++++++++++++++++
rust/macros/lib.rs | 21 +++++++++++++++++++++
6 files changed, 66 insertions(+)
diff --git a/rust/build_error.rs b/rust/build_error.rs
index fa24eeef9929..b7ef80596f1f 100644
--- a/rust/build_error.rs
+++ b/rust/build_error.rs
@@ -29,3 +29,10 @@
pub const fn build_error(msg: &'static str) -> ! {
panic!("{}", msg);
}
+
+/// Assert that the code is in const evaluation.
+///
+/// Triggers a build error if called at runtime.
+#[inline(never)]
+#[export_name = "rust_const_eval_called_at_runtime"]
+pub const fn assert_in_const_eval() {}
diff --git a/rust/kernel/const_eval.rs b/rust/kernel/const_eval.rs
new file mode 100644
index 000000000000..f1b79d82549d
--- /dev/null
+++ b/rust/kernel/const_eval.rs
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Utilities for const evaluation.
+
+#[doc(inline)]
+pub use build_error::assert_in_const_eval;
+
+#[doc(inline)]
+pub use macros::const_eval_only;
diff --git a/rust/kernel/device_id.rs b/rust/kernel/device_id.rs
index c81fca5b4986..dad9cadaeb1b 100644
--- a/rust/kernel/device_id.rs
+++ b/rust/kernel/device_id.rs
@@ -10,6 +10,8 @@
mem::MaybeUninit, //
};
+use crate::const_eval::const_eval_only;
+
/// Marker trait to indicate a Rust device ID type represents a corresponding C device ID type.
///
/// This is meant to be implemented by buses/subsystems so that they can use [`IdTable`] to
@@ -108,6 +110,7 @@ impl<T: RawDeviceId + RawDeviceIdIndex, U: 'static, const N: usize> IdArray<T, U
/// Creates a new instance of the array.
///
/// The contents are derived from the given identifiers and context information.
+ #[const_eval_only]
pub const fn new(ids: [(T, &'static U); N]) -> Self {
let mut raw_ids = [const { MaybeUninit::<T::RawType>::uninit() }; N];
@@ -144,6 +147,7 @@ impl<T: RawDeviceId, const N: usize> IdArray<T, (), N> {
///
/// The contents are derived from the given identifiers and context information.
/// If the device implements [`RawDeviceIdIndex`], consider using [`IdArray::new`] instead.
+ #[const_eval_only]
pub const fn new_without_index(ids: [T; N]) -> Self {
// SAFETY: `T` is layout-wise compatible with `T::RawType`, so is the array of them.
let raw_ids: [MaybeUninit<T::RawType>; N] = unsafe { core::mem::transmute_copy(&ids) };
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index 4d5c96ddc49c..d9ed25e96ff3 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -57,6 +57,7 @@
pub mod clk;
#[cfg(CONFIG_CONFIGFS_FS)]
pub mod configfs;
+pub mod const_eval;
pub mod cpu;
#[cfg(CONFIG_CPU_FREQ)]
pub mod cpufreq;
diff --git a/rust/macros/const_eval.rs b/rust/macros/const_eval.rs
new file mode 100644
index 000000000000..0664888d3b38
--- /dev/null
+++ b/rust/macros/const_eval.rs
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0
+
+use proc_macro2::TokenStream;
+use quote::ToTokens;
+use syn::{
+ parse_quote,
+ ItemFn, //
+};
+
+pub(crate) fn const_eval_only(mut input: ItemFn) -> TokenStream {
+ // Prevent code generation as the function is for const evaluation only.
+ input.attrs.push(parse_quote!(
+ #[inline(always)]
+ ));
+
+ input.block.stmts.insert(
+ 0,
+ parse_quote!(
+ ::kernel::const_eval::assert_in_const_eval();
+ ),
+ );
+
+ input.into_token_stream()
+}
diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs
index 24f96feaeb34..e47a8c35ccff 100644
--- a/rust/macros/lib.rs
+++ b/rust/macros/lib.rs
@@ -15,6 +15,7 @@
#![cfg_attr(not(CONFIG_RUSTC_HAS_SPAN_FILE), feature(proc_macro_span))]
mod concat_idents;
+mod const_eval;
mod export;
mod fmt;
mod for_lt;
@@ -338,6 +339,26 @@ pub fn concat_idents(input: TokenStream) -> TokenStream {
concat_idents::concat_idents(parse_macro_input!(input)).into()
}
+/// Mark a function as usable from const evaluation only.
+///
+/// Build will fail if the function is used for runtime code.
+///
+/// # Examples
+///
+/// ```
+/// #[const_eval_only]
+/// const fn call_for_const_eval_only() {
+/// // This code will be executed only during const eval!
+/// }
+///
+/// const _: () = call_for_const_eval_only();
+/// ```
+#[proc_macro_attribute]
+pub fn const_eval_only(attr: TokenStream, input: TokenStream) -> TokenStream {
+ parse_macro_input!(attr as syn::parse::Nothing);
+ const_eval::const_eval_only(parse_macro_input!(input)).into()
+}
+
/// Paste identifiers together.
///
/// Within the `paste!` macro, identifiers inside `[<` and `>]` are concatenated together to form a
--
2.54.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v2 2/3] rust: const_eval: allow const trait method invocation in some contexts
2026-09-03 15:21 [PATCH v2 0/3] rust: const_eval: add a mechanism to do const trait calls Gary Guo
2026-09-03 15:21 ` [PATCH v2 1/3] rust: const_eval: add `#[const_eval_only]` attribute Gary Guo
@ 2026-09-03 15:21 ` Gary Guo
2026-09-03 15:21 ` [PATCH v2 3/3] rust: str: convert `as_char_ptr` to work with `const_call!` Gary Guo
2026-09-03 15:34 ` [PATCH v2 0/3] rust: const_eval: add a mechanism to do const trait calls Miguel Ojeda
3 siblings, 0 replies; 6+ messages in thread
From: Gary Guo @ 2026-09-03 15:21 UTC (permalink / raw)
To: Eliot Courtney, 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
Cc: linux-kernel, rust-for-linux, Gary Guo
Rust does not yet (as of 1.98) have stable const trait impl support; on
1.85 it does not have unstable support either. This leaves us having many
free functions that do the exact same as trait methods.
Create a `Const` wrapper type as the central place to put const trait
methods on as inherent methods, and a `const_call!` macro that dispatches
to these inherent methods as opposed to trait methods.
`const_call!` would check that the signature actually matches, and provides
some additional inference help. Once const trait impl is available, we can
also easily just convert the macro without having to touching all users at
once. Implement it as a proc macro, so it can accept the normal method
call syntax.
Signed-off-by: Gary Guo <gary@garyguo.net>
---
rust/kernel/const_eval.rs | 108 +++++++++++++++++++++++++++++++++++++++++++++-
rust/kernel/prelude.rs | 1 +
rust/macros/const_eval.rs | 31 ++++++++++++-
rust/macros/lib.rs | 9 ++++
4 files changed, 146 insertions(+), 3 deletions(-)
diff --git a/rust/kernel/const_eval.rs b/rust/kernel/const_eval.rs
index f1b79d82549d..2a6ea3f7b693 100644
--- a/rust/kernel/const_eval.rs
+++ b/rust/kernel/const_eval.rs
@@ -2,8 +2,114 @@
//! Utilities for const evaluation.
+use core::{
+ ops::Deref, //
+};
+
#[doc(inline)]
pub use build_error::assert_in_const_eval;
#[doc(inline)]
-pub use macros::const_eval_only;
+pub use macros::{
+ const_call,
+ const_eval_only, //
+};
+
+/// Constant wrapper type.
+///
+/// Rust does not yet (as of 1.98) have stable const trait impl support; on 1.85 it does not have
+/// unstable support either. Only inherent functions can be marked as const. There are a few const
+/// methods that we want to add on core types; and this mean that we cannot use extension trait on
+/// them.
+///
+/// This type serves as a middle layer. This type is local to the `kernel` crate, and thus we can
+/// define inherent methods on it. For core types, we will define it for `Const<Type>`. Other kernel
+/// crate types or even downstream types can also utilize it by defining inherent methods that
+/// *receive* `Const<Self>`.
+///
+/// Caller should use the `const_call!()` macro so it also checks that the type signature matches
+/// the trait.
+///
+/// # Examples
+///
+/// Say we want to define a extension method on u32. We can do
+/// ```no_run
+/// trait MyTrait {
+/// fn trait_method(self);
+/// }
+///
+/// impl MyTrait for u32 {
+/// fn trait_method(self) {
+/// /* impl */
+/// }
+/// }
+/// ```
+/// but we cannot mark it const.
+///
+/// Instead, we can do this
+/// ```ignore (doctest is outside kernel crate)
+/// trait MyTrait {
+/// fn trait_method(self);
+/// }
+///
+/// impl MyTrait for u32 {
+/// #[inline]
+/// fn trait_method(self) {
+/// // Forwarding impl
+/// Const(self).trait_method()
+/// }
+/// }
+///
+/// impl Const<u32> {
+/// pub const fn trait_method(self) {
+/// let Const(this) = self;
+/// /* impl */
+/// }
+/// }
+/// ```
+///
+/// For local or downstream types, implement it directly on the type with a different receiver:
+/// ```no_run
+/// # use kernel::const_eval::Const;
+/// trait MyTrait {
+/// fn trait_method(self);
+/// }
+///
+/// struct Foo;
+///
+/// impl MyTrait for Foo {
+/// #[inline]
+/// fn trait_method(self) {
+/// // Forwarding impl
+/// Const(self).trait_method()
+/// }
+/// }
+///
+/// impl Foo {
+/// pub const fn trait_method(self: Const<Self>) {
+/// let Const(this) = self;
+/// /* impl */
+/// }
+/// }
+/// ```
+///
+/// For caller of the method, one would simply replace `expr.method()` with `Const(expr).method()`;
+/// although the auto-ref coercion will be lost, so it a method expects `&self`, the caller would
+/// need to explicitly use the `Const(&expr).method()` syntax to call it.
+pub struct Const<T>(pub T);
+
+impl<T> Deref for Const<T> {
+ type Target = T;
+
+ #[inline]
+ fn deref(&self) -> &T {
+ &self.0
+ }
+}
+
+// Provide inference help only. Should never be code-generated.
+#[doc(hidden)]
+#[const_eval_only]
+pub const fn would_call<T, U, F: FnOnce(T) -> U>(_: T, _: F) -> U {
+ todo!()
+}
diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs
index ca396f1f78a6..8f4c8cd2d8a2 100644
--- a/rust/kernel/prelude.rs
+++ b/rust/kernel/prelude.rs
@@ -91,6 +91,7 @@
const_assert,
static_assert, //
},
+ const_eval::const_call,
current,
dev_alert,
dev_crit,
diff --git a/rust/macros/const_eval.rs b/rust/macros/const_eval.rs
index 0664888d3b38..10a4a93f905a 100644
--- a/rust/macros/const_eval.rs
+++ b/rust/macros/const_eval.rs
@@ -1,9 +1,17 @@
// SPDX-License-Identifier: GPL-2.0
-use proc_macro2::TokenStream;
-use quote::ToTokens;
+use proc_macro2::{
+ Span,
+ TokenStream, //
+};
+use quote::{
+ format_ident,
+ quote,
+ ToTokens, //
+};
use syn::{
parse_quote,
+ ExprMethodCall,
ItemFn, //
};
@@ -22,3 +30,22 @@ pub(crate) fn const_eval_only(mut input: ItemFn) -> TokenStream {
input.into_token_stream()
}
+
+pub(crate) fn const_call(mut input: ExprMethodCall) -> TokenStream {
+ let expr = input.receiver;
+
+ let expr_ident = format_ident!("expr", span = Span::mixed_site());
+ input.receiver = parse_quote!(#expr_ident);
+
+ let would_call = quote!(#input);
+ input.receiver = parse_quote!(::kernel::const_eval::Const(#expr_ident));
+
+ quote!({
+ let #expr_ident = #expr;
+ if false {
+ ::kernel::const_eval::would_call(#expr_ident, |#expr_ident| #would_call)
+ } else {
+ #input
+ }
+ })
+}
diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs
index e47a8c35ccff..262539cccf38 100644
--- a/rust/macros/lib.rs
+++ b/rust/macros/lib.rs
@@ -339,6 +339,15 @@ pub fn concat_idents(input: TokenStream) -> TokenStream {
concat_idents::concat_idents(parse_macro_input!(input)).into()
}
+/// Call a trait method in const context.
+///
+/// This is a polyfill for Rust's const trait impl feature. Only work for specific methods that have
+/// dedicated const implementation.
+#[proc_macro]
+pub fn const_call(input: TokenStream) -> TokenStream {
+ const_eval::const_call(parse_macro_input!(input)).into()
+}
+
/// Mark a function as usable from const evaluation only.
///
/// Build will fail if the function is used for runtime code.
--
2.54.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v2 3/3] rust: str: convert `as_char_ptr` to work with `const_call!`
2026-09-03 15:21 [PATCH v2 0/3] rust: const_eval: add a mechanism to do const trait calls Gary Guo
2026-09-03 15:21 ` [PATCH v2 1/3] rust: const_eval: add `#[const_eval_only]` attribute Gary Guo
2026-09-03 15:21 ` [PATCH v2 2/3] rust: const_eval: allow const trait method invocation in some contexts Gary Guo
@ 2026-09-03 15:21 ` Gary Guo
2026-09-03 15:34 ` [PATCH v2 0/3] rust: const_eval: add a mechanism to do const trait calls Miguel Ojeda
3 siblings, 0 replies; 6+ messages in thread
From: Gary Guo @ 2026-09-03 15:21 UTC (permalink / raw)
To: Eliot Courtney, 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
Cc: linux-kernel, rust-for-linux, Gary Guo
This allows `const_call!(foo.as_char_ptr())` to be used instead of
`kernel::str::as_char_ptr_in_const_context`.
`Const(foo).as_char_ptr()` is used directly in macros to avoid having to
import `CStrExt`.
Signed-off-by: Gary Guo <gary@garyguo.net>
---
rust/kernel/configfs.rs | 2 +-
rust/kernel/drm/device.rs | 4 ++--
rust/kernel/drm/ioctl.rs | 4 ++--
rust/kernel/kunit.rs | 6 +++---
rust/kernel/miscdevice.rs | 2 +-
rust/kernel/net/phy.rs | 2 +-
rust/kernel/str.rs | 15 +++++++--------
rust/macros/lib.rs | 9 +++++++++
rust/macros/module.rs | 4 ++--
9 files changed, 28 insertions(+), 20 deletions(-)
diff --git a/rust/kernel/configfs.rs b/rust/kernel/configfs.rs
index cd082b83e9e7..ece6cb31609f 100644
--- a/rust/kernel/configfs.rs
+++ b/rust/kernel/configfs.rs
@@ -612,7 +612,7 @@ impl<const ID: u64, O, Data> Attribute<ID, O, Data>
pub const fn new(name: &'static CStr) -> Self {
Self {
attribute: Opaque::new(bindings::configfs_attribute {
- ca_name: crate::str::as_char_ptr_in_const_context(name),
+ ca_name: const_call!(name.as_char_ptr()),
ca_owner: core::ptr::null_mut(),
ca_mode: 0o660,
show: Some(Self::show),
diff --git a/rust/kernel/drm/device.rs b/rust/kernel/drm/device.rs
index 6b88ade28e24..536a0e958c8b 100644
--- a/rust/kernel/drm/device.rs
+++ b/rust/kernel/drm/device.rs
@@ -186,8 +186,8 @@ const fn compute_features() -> u32 {
major: T::INFO.major,
minor: T::INFO.minor,
patchlevel: T::INFO.patchlevel,
- name: crate::str::as_char_ptr_in_const_context(T::INFO.name).cast_mut(),
- desc: crate::str::as_char_ptr_in_const_context(T::INFO.desc).cast_mut(),
+ name: const_call!(T::INFO.name.as_char_ptr()).cast_mut(),
+ desc: const_call!(T::INFO.desc.as_char_ptr()).cast_mut(),
driver_features: Self::compute_features(),
ioctls: T::IOCTLS.as_ptr(),
diff --git a/rust/kernel/drm/ioctl.rs b/rust/kernel/drm/ioctl.rs
index 64af9eacc306..5bba960504d6 100644
--- a/rust/kernel/drm/ioctl.rs
+++ b/rust/kernel/drm/ioctl.rs
@@ -206,9 +206,9 @@ macro_rules! declare_drm_ioctls {
Some($cmd)
},
flags: $flags,
- name: $crate::str::as_char_ptr_in_const_context(
+ name: $crate::const_eval::Const(
$crate::c_str!(::core::stringify!($cmd)),
- ),
+ ).as_char_ptr(),
}
),*];
ioctls
diff --git a/rust/kernel/kunit.rs b/rust/kernel/kunit.rs
index 91eaff8c186a..034df521b195 100644
--- a/rust/kernel/kunit.rs
+++ b/rust/kernel/kunit.rs
@@ -107,12 +107,12 @@ unsafe impl Sync for Location {}
unsafe impl Sync for UnaryAssert {}
static LOCATION: Location = Location($crate::bindings::kunit_loc {
- file: $crate::str::as_char_ptr_in_const_context(FILE),
+ file: $crate::const_eval::Const(FILE).as_char_ptr(),
line: LINE,
});
static ASSERTION: UnaryAssert = UnaryAssert($crate::bindings::kunit_unary_assert {
assert: $crate::bindings::kunit_assert {},
- condition: $crate::str::as_char_ptr_in_const_context(CONDITION),
+ condition: $crate::const_eval::Const(CONDITION).as_char_ptr(),
expected_true: true,
});
@@ -204,7 +204,7 @@ pub const fn kunit_case(
) -> kernel::bindings::kunit_case {
kernel::bindings::kunit_case {
run_case: Some(run_case),
- name: kernel::str::as_char_ptr_in_const_context(name),
+ name: const_call!(name.as_char_ptr()),
attr: kernel::bindings::kunit_attributes {
speed: kernel::bindings::kunit_speed_KUNIT_SPEED_NORMAL,
},
diff --git a/rust/kernel/miscdevice.rs b/rust/kernel/miscdevice.rs
index 8d4b719bd83f..02e115ec045d 100644
--- a/rust/kernel/miscdevice.rs
+++ b/rust/kernel/miscdevice.rs
@@ -46,7 +46,7 @@ impl MiscDeviceOptions {
pub const fn into_raw<T: MiscDevice>(self) -> bindings::miscdevice {
let mut result: bindings::miscdevice = pin_init::zeroed();
result.minor = bindings::MISC_DYNAMIC_MINOR as ffi::c_int;
- result.name = crate::str::as_char_ptr_in_const_context(self.name);
+ result.name = const_call!(self.name.as_char_ptr());
result.fops = MiscdeviceVTable::<T>::build();
result
}
diff --git a/rust/kernel/net/phy.rs b/rust/kernel/net/phy.rs
index 956cda573ddb..28047fc3a876 100644
--- a/rust/kernel/net/phy.rs
+++ b/rust/kernel/net/phy.rs
@@ -494,7 +494,7 @@ unsafe impl Sync for DriverVTable {}
pub const fn create_phy_driver<T: Driver>() -> DriverVTable {
// INVARIANT: All the fields of `struct phy_driver` are initialized properly.
DriverVTable(Opaque::new(bindings::phy_driver {
- name: crate::str::as_char_ptr_in_const_context(T::NAME).cast_mut(),
+ name: const_call!(T::NAME.as_char_ptr()).cast_mut(),
flags: T::FLAGS,
phy_id: T::PHY_DEVICE_ID.id(),
phy_id_mask: T::PHY_DEVICE_ID.mask_as_int(),
diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs
index b3caa9a1c898..93ae32b42e18 100644
--- a/rust/kernel/str.rs
+++ b/rust/kernel/str.rs
@@ -197,14 +197,13 @@ macro_rules! b_str {
}};
}
-/// Returns a C pointer to the string.
-// It is a free function rather than a method on an extension trait because:
-//
-// - error[E0379]: functions in trait impls cannot be declared const
-#[inline]
-#[expect(clippy::disallowed_methods, reason = "internal implementation")]
-pub const fn as_char_ptr_in_const_context(c_str: &CStr) -> *const c_char {
- c_str.as_ptr().cast()
+impl crate::const_eval::Const<&CStr> {
+ /// Returns a C pointer to the string.
+ #[inline]
+ #[expect(clippy::disallowed_methods, reason = "internal implementation")]
+ pub const fn as_char_ptr(self) -> *const c_char {
+ self.0.as_ptr().cast()
+ }
}
mod private {
diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs
index 262539cccf38..f5d8d0706e46 100644
--- a/rust/macros/lib.rs
+++ b/rust/macros/lib.rs
@@ -343,6 +343,15 @@ pub fn concat_idents(input: TokenStream) -> TokenStream {
///
/// This is a polyfill for Rust's const trait impl feature. Only work for specific methods that have
/// dedicated const implementation.
+///
+/// # Examples
+///
+/// ```
+/// const fn use_cstr(c: &CStr) {
+/// // This is an extension trait method that is not otherwise callable in const context.
+/// let char_ptr = const_call!((c).as_char_ptr());
+/// }
+/// ```
#[proc_macro]
pub fn const_call(input: TokenStream) -> TokenStream {
const_eval::const_call(parse_macro_input!(input)).into()
diff --git a/rust/macros/module.rs b/rust/macros/module.rs
index bc7027f8dbb2..b2c1f118c7e1 100644
--- a/rust/macros/module.rs
+++ b/rust/macros/module.rs
@@ -149,13 +149,13 @@ fn emit_params(&mut self, info: &ModuleInfo) {
::kernel::module_param::KernelParam =
::kernel::module_param::KernelParam::new(
::kernel::bindings::kernel_param {
- name: kernel::str::as_char_ptr_in_const_context(
+ name: ::kernel::const_eval::Const(
if ::core::cfg!(MODULE) {
#param_name_cstr
} else {
#param_name_cstr_with_module
}
- ),
+ ).as_char_ptr(),
// SAFETY: `__this_module` is constructed by the kernel at load
// time and will not be freed until the module is unloaded.
#[cfg(MODULE)]
--
2.54.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v2 0/3] rust: const_eval: add a mechanism to do const trait calls
2026-09-03 15:21 [PATCH v2 0/3] rust: const_eval: add a mechanism to do const trait calls Gary Guo
` (2 preceding siblings ...)
2026-09-03 15:21 ` [PATCH v2 3/3] rust: str: convert `as_char_ptr` to work with `const_call!` Gary Guo
@ 2026-09-03 15:34 ` Miguel Ojeda
2026-09-03 15:46 ` Gary Guo
3 siblings, 1 reply; 6+ messages in thread
From: Miguel Ojeda @ 2026-09-03 15:34 UTC (permalink / raw)
To: Gary Guo
Cc: Eliot Courtney, 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, linux-kernel, rust-for-linux
On Thu, Sep 3, 2026 at 5:21 PM Gary Guo <gary@garyguo.net> wrote:
>
> Add a mechanism to perform const trait method calls, with the same type
> inference capabilities. This would only work for concrete types (not inside
> generic functions).
>
> As an example, convert `as_char_ptr_in_const_context`, so instead of
>
> kernel::str::as_char_ptr_in_const_context(c_str)
>
> one may write
>
> const_call!(c_str.as_char_ptr())
>
> instead.
>
> Signed-off-by: Gary Guo <gary@garyguo.net>
Thanks for resending this!
So I definitely like having `#[const_eval_only]`, because we do want
to limit those calls sometimes and it is nice to have C++'s equivalent
to `consteval` (perhaps this could be called just `#[consteval]` to
match?); i.e. what we talked about in the call.
On `Const` and `const_call!`, i.e. the other two patches: I am not
sure if we care that much to introduce a macro for it, but it doesn't
look bad either. I guess perhaps it helps to have a consistent way to
do it and to easily remove it later when the actual feature lands in
Rust. I would like to hear some thoughts on it from others.
Cheers,
Miguel
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 0/3] rust: const_eval: add a mechanism to do const trait calls
2026-09-03 15:34 ` [PATCH v2 0/3] rust: const_eval: add a mechanism to do const trait calls Miguel Ojeda
@ 2026-09-03 15:46 ` Gary Guo
0 siblings, 0 replies; 6+ messages in thread
From: Gary Guo @ 2026-09-03 15:46 UTC (permalink / raw)
To: Miguel Ojeda, Gary Guo
Cc: Eliot Courtney, 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, linux-kernel, rust-for-linux
On Thu Sep 3, 2026 at 4:34 PM BST, Miguel Ojeda wrote:
> On Thu, Sep 3, 2026 at 5:21 PM Gary Guo <gary@garyguo.net> wrote:
>>
>> Add a mechanism to perform const trait method calls, with the same type
>> inference capabilities. This would only work for concrete types (not inside
>> generic functions).
>>
>> As an example, convert `as_char_ptr_in_const_context`, so instead of
>>
>> kernel::str::as_char_ptr_in_const_context(c_str)
>>
>> one may write
>>
>> const_call!(c_str.as_char_ptr())
>>
>> instead.
>>
>> Signed-off-by: Gary Guo <gary@garyguo.net>
>
> Thanks for resending this!
>
> So I definitely like having `#[const_eval_only]`, because we do want
> to limit those calls sometimes and it is nice to have C++'s equivalent
> to `consteval` (perhaps this could be called just `#[consteval]` to
> match?); i.e. what we talked about in the call.
>
> On `Const` and `const_call!`, i.e. the other two patches: I am not
> sure if we care that much to introduce a macro for it, but it doesn't
> look bad either. I guess perhaps it helps to have a consistent way to
> do it and to easily remove it later when the actual feature lands in
> Rust. I would like to hear some thoughts on it from others.
I think it's good to have such macro compared to our current approach; it can be
made into a identity macro once we have const trait impl.
FWIW, I even considered an extra macro that allow you to write
#[const_trait_impl] // #[const_trait_impl(foreign)] for core types
impl MyTrait for MyType {}
and generate the `impl Const` part too (and also add a line to the documentation
that the method is const-callable with `const_call!()`).
Best,
Gary
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-09-03 15:46 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-03 15:21 [PATCH v2 0/3] rust: const_eval: add a mechanism to do const trait calls Gary Guo
2026-09-03 15:21 ` [PATCH v2 1/3] rust: const_eval: add `#[const_eval_only]` attribute Gary Guo
2026-09-03 15:21 ` [PATCH v2 2/3] rust: const_eval: allow const trait method invocation in some contexts Gary Guo
2026-09-03 15:21 ` [PATCH v2 3/3] rust: str: convert `as_char_ptr` to work with `const_call!` Gary Guo
2026-09-03 15:34 ` [PATCH v2 0/3] rust: const_eval: add a mechanism to do const trait calls Miguel Ojeda
2026-09-03 15:46 ` Gary Guo
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox