aboutsummaryrefslogtreecommitdiff
path: root/rust/macros/lib.rs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2024-01-11 13:05:41 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2024-01-11 13:05:41 -0800
commitb6964fe2398cb8939c3d4fc6960a6be93687305d (patch)
treea27840783749295a28a32c8a9f43e254173e5324 /rust/macros/lib.rs
parent5bad490858c3ebdbb47e622e8f9049f828d2abba (diff)
parent711cbfc717650532624ca9f56fbaf191bed56e67 (diff)
Merge tag 'rust-6.8' of https://github.com/Rust-for-Linux/linux
Pull Rust updates from Miguel Ojeda: "Another routine one in terms of features. In terms of lines, this time the 'alloc' version upgrade is less prominent, given that it was fairly small (and we did not have two upgrades) Toolchain and infrastructure: - Upgrade to Rust 1.74.1 The patch release includes a fix for an ICE that the Apple AGX GPU driver was hitting - Support 'srctree'-relative links in Rust code documentation - Automate part of the manual constants handling (i.e. the ones not recognised by 'bindgen') - Suppress searching builtin sysroot to avoid confusion with installed sysroots, needed for the to-be-merged arm64 support which uses a builtin target - Ignore '__preserve_most' functions for 'bindgen' - Reduce header inclusion bloat in exports 'kernel' crate: - Implement 'Debug' for 'CString' - Make 'CondVar::wait()' an uninterruptible wait 'macros' crate: - Update 'paste!' to accept string literals - Improve '#[vtable]' documentation Documentation: - Add testing section (KUnit and 'rusttest' target) - Remove 'CC=clang' mentions - Clarify that 'rustup override' applies to build directory" * tag 'rust-6.8' of https://github.com/Rust-for-Linux/linux: docs: rust: Clarify that 'rustup override' applies to build directory docs: rust: Add rusttest info docs: rust: remove `CC=clang` mentions rust: support `srctree`-relative links rust: sync: Makes `CondVar::wait()` an uninterruptible wait rust: upgrade to Rust 1.74.1 rust: Suppress searching builtin sysroot rust: macros: improve `#[vtable]` documentation rust: macros: update 'paste!' macro to accept string literals rust: bindings: rename const binding using sed rust: Ignore preserve-most functions rust: replace <linux/module.h> with <linux/export.h> in rust/exports.c rust: kernel: str: Implement Debug for CString
Diffstat (limited to 'rust/macros/lib.rs')
-rw-r--r--rust/macros/lib.rs62
1 files changed, 52 insertions, 10 deletions
diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs
index c42105c2ff96..f489f3157383 100644
--- a/rust/macros/lib.rs
+++ b/rust/macros/lib.rs
@@ -20,7 +20,7 @@ use proc_macro::TokenStream;
/// The `type` argument should be a type which implements the [`Module`]
/// trait. Also accepts various forms of kernel metadata.
///
-/// C header: [`include/linux/moduleparam.h`](../../../include/linux/moduleparam.h)
+/// C header: [`include/linux/moduleparam.h`](srctree/include/linux/moduleparam.h)
///
/// [`Module`]: ../kernel/trait.Module.html
///
@@ -87,27 +87,49 @@ pub fn module(ts: TokenStream) -> TokenStream {
/// implementation could just return `Error::EINVAL`); Linux typically use C
/// `NULL` pointers to represent these functions.
///
-/// This attribute is intended to close the gap. Traits can be declared and
-/// implemented with the `#[vtable]` attribute, and a `HAS_*` associated constant
-/// will be generated for each method in the trait, indicating if the implementor
-/// has overridden a method.
+/// This attribute closes that gap. A trait can be annotated with the
+/// `#[vtable]` attribute. Implementers of the trait will then also have to
+/// annotate the trait with `#[vtable]`. This attribute generates a `HAS_*`
+/// associated constant bool for each method in the trait that is set to true if
+/// the implementer has overridden the associated method.
+///
+/// For a trait method to be optional, it must have a default implementation.
+/// This is also the case for traits annotated with `#[vtable]`, but in this
+/// case the default implementation will never be executed. The reason for this
+/// is that the functions will be called through function pointers installed in
+/// C side vtables. When an optional method is not implemented on a `#[vtable]`
+/// trait, a NULL entry is installed in the vtable. Thus the default
+/// implementation is never called. Since these traits are not designed to be
+/// used on the Rust side, it should not be possible to call the default
+/// implementation. This is done to ensure that we call the vtable methods
+/// through the C vtable, and not through the Rust vtable. Therefore, the
+/// default implementation should call `kernel::build_error`, which prevents
+/// calls to this function at compile time:
+///
+/// ```compile_fail
+/// # use kernel::error::VTABLE_DEFAULT_ERROR;
+/// kernel::build_error(VTABLE_DEFAULT_ERROR)
+/// ```
+///
+/// Note that you might need to import [`kernel::error::VTABLE_DEFAULT_ERROR`].
///
-/// This attribute is not needed if all methods are required.
+/// This macro should not be used when all functions are required.
///
/// # Examples
///
/// ```ignore
+/// use kernel::error::VTABLE_DEFAULT_ERROR;
/// use kernel::prelude::*;
///
/// // Declares a `#[vtable]` trait
/// #[vtable]
/// pub trait Operations: Send + Sync + Sized {
/// fn foo(&self) -> Result<()> {
-/// Err(EINVAL)
+/// kernel::build_error(VTABLE_DEFAULT_ERROR)
/// }
///
/// fn bar(&self) -> Result<()> {
-/// Err(EINVAL)
+/// kernel::build_error(VTABLE_DEFAULT_ERROR)
/// }
/// }
///
@@ -125,6 +147,8 @@ pub fn module(ts: TokenStream) -> TokenStream {
/// assert_eq!(<Foo as Operations>::HAS_FOO, true);
/// assert_eq!(<Foo as Operations>::HAS_BAR, false);
/// ```
+///
+/// [`kernel::error::VTABLE_DEFAULT_ERROR`]: ../kernel/error/constant.VTABLE_DEFAULT_ERROR.html
#[proc_macro_attribute]
pub fn vtable(attr: TokenStream, ts: TokenStream) -> TokenStream {
vtable::vtable(attr, ts)
@@ -254,8 +278,8 @@ pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream {
/// Within the `paste!` macro, identifiers inside `[<` and `>]` are concatenated together to form a
/// single identifier.
///
-/// This is similar to the [`paste`] crate, but with pasting feature limited to identifiers
-/// (literals, lifetimes and documentation strings are not supported). There is a difference in
+/// This is similar to the [`paste`] crate, but with pasting feature limited to identifiers and
+/// literals (lifetimes and documentation strings are not supported). There is a difference in
/// supported modifiers as well.
///
/// # Example
@@ -337,6 +361,24 @@ pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream {
/// assert_eq!(br_ok(), binder_driver_return_protocol_BR_OK);
/// ```
///
+/// # Literals
+///
+/// Literals can also be concatenated with other identifiers:
+///
+/// ```ignore
+/// macro_rules! create_numbered_fn {
+/// ($name:literal, $val:literal) => {
+/// kernel::macros::paste! {
+/// fn [<some_ $name _fn $val>]() -> u32 { $val }
+/// }
+/// };
+/// }
+///
+/// create_numbered_fn!("foo", 100);
+///
+/// assert_eq!(some_foo_fn100(), 100)
+/// ```
+///
/// [`paste`]: https://docs.rs/paste/
#[proc_macro]
pub fn paste(input: TokenStream) -> TokenStream {