Crate supertrait

Source
Expand description

§Supertrait 🦹

Crates.io docs.rs Build Status MIT License

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).