[PATCH v2 3/3] rust: str: convert `as_char_ptr` to work with `const_call!`

From: Gary Guo

Date: Thu Sep 03 2026 - 11:55:22 EST


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@xxxxxxxxxxx>
---
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