#[vtable]Expand description
Declares or implements a vtable trait.
Linux’s use of pure vtables is very close to Rust traits, but they differ
in how unimplemented functions are represented. In Rust, traits can provide
default implementation for all non-required methods (and the default
implementation could just return Error::EINVAL); Linux typically use C
NULL pointers to represent these functions.
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 for normal traits, it must have a default
implementation. However, for many users of #[vtable], 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. If
this is the case, #[optional] can be applied on the optional method.
Methods annotated as such do not need to be implemented nor need a default
implementation. Calling these methods on types that do not implement them
will fail to build using the build_error! mechanism.
This macro should not be used when all functions are required.
Additionally, this macro automatically handles the OwnerModule
associated type: on the trait side, type OwnerModule: ModuleMetadata;
is added as a required associated type if not already defined; on the
impl side, type OwnerModule = LocalModule; is automatically inserted
if not explicitly defined.
§Examples
use kernel::prelude::*;
// Declares a `#[vtable]` trait
#[vtable]
pub trait Operations: Send + Sync + Sized {
#[optional]
fn foo(&self) -> Result<()>;
#[optional]
fn bar(&self) -> Result<()>;
}
struct Foo;
// Implements the `#[vtable]` trait
#[vtable]
impl Operations for Foo {
fn foo(&self) -> Result<()> {
// ...
}
}
assert_eq!(<Foo as Operations>::HAS_FOO, true);
assert_eq!(<Foo as Operations>::HAS_BAR, false);