All of lore.kernel.org
 help / color / mirror / Atom feed
From: Gary Guo <gary@garyguo.net>
To: "Eliot Courtney" <ecourtney@nvidia.com>,
	"Miguel Ojeda" <ojeda@kernel.org>,
	"Boqun Feng" <boqun@kernel.org>,
	"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
	"Benno Lossin" <lossin@kernel.org>,
	"Andreas Hindborg" <a.hindborg@kernel.org>,
	"Alice Ryhl" <aliceryhl@google.com>,
	"Trevor Gross" <tmgross@umich.edu>,
	"Danilo Krummrich" <dakr@kernel.org>,
	"Daniel Almeida" <daniel.almeida@collabora.com>,
	"Tamir Duberstein" <tamird@kernel.org>,
	"Alexandre Courbot" <acourbot@nvidia.com>,
	"Onur Özkan" <work@onurozkan.dev>
Cc: linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org,
	 Gary Guo <gary@garyguo.net>
Subject: [PATCH v2 1/3] rust: const_eval: add `#[const_eval_only]` attribute
Date: Thu, 03 Sep 2026 16:21:44 +0100	[thread overview]
Message-ID: <20260903-cv-v2-1-e93b1613e40c@garyguo.net> (raw)
In-Reply-To: <20260903-cv-v2-0-e93b1613e40c@garyguo.net>

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


  reply	other threads:[~2026-09-03 15:22 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 [this message]
2026-09-07  8:45   ` [PATCH v2 1/3] rust: const_eval: add `#[const_eval_only]` attribute Eliot Courtney
2026-09-09 14:36     ` 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
2026-09-07  9:21     ` Eliot Courtney
2026-09-09 14:32       ` Gary Guo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260903-cv-v2-1-e93b1613e40c@garyguo.net \
    --to=gary@garyguo.net \
    --cc=a.hindborg@kernel.org \
    --cc=acourbot@nvidia.com \
    --cc=aliceryhl@google.com \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun@kernel.org \
    --cc=dakr@kernel.org \
    --cc=daniel.almeida@collabora.com \
    --cc=ecourtney@nvidia.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lossin@kernel.org \
    --cc=ojeda@kernel.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=tamird@kernel.org \
    --cc=tmgross@umich.edu \
    --cc=work@onurozkan.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.