Expand description
§Supertrait š¦¹
Supertrait is a revolutionary crate that enables default associated types and const fn trait
items in stable Rust as of July 2023. Supertrait accomplishes this through a variety of
macro-related techniques including the use of
macro_magic as well as the āmodule wormholeā
technique demonstrated in the docs for #[supertrait]
and
#[impl_supertrait]
.
Here is an end-to-end example:
use supertrait::*;
#[supertrait]
pub trait Fizz<T: Copy>: Copy + Sized {
type Foo = Option<T>;
type Bar;
const fn double_value(val: T) -> (T, T) {
(val, val)
}
const fn triple_value(val: T) -> (T, T, T);
fn double_self_plus(&self, plus: Self::Foo) -> (Self, Self, Self::Foo) {
(*self, *self, plus)
}
const fn interleave<I>(&self, a: T, b: I) -> (I, Self::Foo, T);
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
struct Buzz;
#[impl_supertrait]
impl<T: Copy> Fizz<T> for Buzz {
type Bar = usize;
const fn triple_value(val: T) -> (T, T, T) {
(val, val, val)
}
const fn interleave<I>(&self, a: T, b: I) -> (I, Self::Foo, T) {
(b, Some(a), a)
}
}
assert!(Buzz::triple_value(3).0 == 3);
let buzz = Buzz {};
match buzz.interleave('h', false).1 {
Some(c) => assert!(c == 'h'),
None => unreachable!(),
}
let buzz = Buzz {};
assert_eq!(buzz.double_self_plus(Some(3)), (buzz, buzz, Some(3)));
Supertraits are also sealed such that a trait created via supertrait
can only be impled
if #[impl_supertrait]
is attached to the impl statement.
Default associated types are implemented in a way that should be nearly identical with how default associated types will function when they are eventually added to stable rust.
Const fn trait items are implemented as inherents on the underlying type, however their
presence is enforced by impl_supertrait
and their type bounds are enforced by the
requirement for shadow non-const implementations of each const fn trait item that are
filled in by the expansion of impl_supertrait
. These two mechanisms along with the
trait sealing technique mentioned above collectively ensure that const fn trait items
presence and correctness is enforced just as strongly as that of regular trait items.
Using inherents as the vehicle for implementing const fn trait items has a few drawbacks due to the naming collisions that can occur with existing inherent items as well as the inability to blanket impl supertraits containing const fns (because it is impossible in stable Rust to blanket impl anything other than a real trait).
That said, inherents are a convenient fallback when you find yourself reaching for const fn items in traits, and supertrait contains the most convenient implementation of this behavior currently possible in stable Rust.
Modules§
- traits
- Contains various commonly-needed supertraits and supporting types.
Macros§
- impl_
custom_ type_ id - Implements
CustomTypeId
for the specified type and sets its type id to the specified literal u64 value., e.g.impl_custom_type_id!(bool, 10681234549081409806);
. - set_
supertrait_ path - Allows you to override the module path where supertraitās macros will look for necessary
re-exports (such as
macro_magic
).
Attribute Macros§
- impl_
supertrait - Must be attached to any impl statement involving a supertrait.
- supertrait
- Attach this attribute to a trait definition to transform it into a supertrait, able to make use of default associated types and const fn trait items (the latter with some limitations).