supertrait/lib.rs
1//! # Supertrait 🦹
2//!
3//! [](https://crates.io/crates/supertrait)
4//! [](https://docs.rs/supertrait/latest/supertrait/)
5//! [](https://github.com/sam0x17/supertrait/actions/workflows/ci.yaml?query=branch%3Amain)
6//! [](https://github.com/sam0x17/supertrait/blob/main/LICENSE)
7//!
8//! Supertrait is a revolutionary crate that enables _default associated types_ and _const fn trait
9//! items_ in stable Rust as of July 2023. Supertrait accomplishes this through a variety of
10//! macro-related techniques including the use of
11//! [macro_magic](https://crates.io/crates/macro_magic) as well as the "module wormhole"
12//! technique demonstrated in the docs for [`#[supertrait]`](`macro@supertrait`) and
13//! [`#[impl_supertrait]`](`macro@impl_supertrait`).
14//!
15//! Here is an end-to-end example:
16//!
17//! ```
18//! use supertrait::*;
19//!
20//! #[supertrait]
21//! pub trait Fizz<T: Copy>: Copy + Sized {
22//! type Foo = Option<T>;
23//! type Bar;
24//!
25//! const fn double_value(val: T) -> (T, T) {
26//! (val, val)
27//! }
28//!
29//! const fn triple_value(val: T) -> (T, T, T);
30//!
31//! fn double_self_plus(&self, plus: Self::Foo) -> (Self, Self, Self::Foo) {
32//! (*self, *self, plus)
33//! }
34//!
35//! const fn interleave<I>(&self, a: T, b: I) -> (I, Self::Foo, T);
36//! }
37//!
38//! #[derive(Copy, Clone, PartialEq, Eq, Debug)]
39//! struct Buzz;
40//!
41//! #[impl_supertrait]
42//! impl<T: Copy> Fizz<T> for Buzz {
43//! type Bar = usize;
44//!
45//! const fn triple_value(val: T) -> (T, T, T) {
46//! (val, val, val)
47//! }
48//!
49//! const fn interleave<I>(&self, a: T, b: I) -> (I, Self::Foo, T) {
50//! (b, Some(a), a)
51//! }
52//! }
53//!
54//! assert!(Buzz::triple_value(3).0 == 3);
55//! let buzz = Buzz {};
56//! match buzz.interleave('h', false).1 {
57//! Some(c) => assert!(c == 'h'),
58//! None => unreachable!(),
59//! }
60//! let buzz = Buzz {};
61//! assert_eq!(buzz.double_self_plus(Some(3)), (buzz, buzz, Some(3)));
62//! ```
63//!
64//! Supertraits are also sealed such that a trait created via [`supertrait`] can only be impled
65//! if `#[impl_supertrait]` is attached to the impl statement.
66//!
67//! Default associated types are implemented in a way that should be nearly identical with how
68//! default associated types will function when they are eventually added to stable rust.
69//!
70//! Const fn trait items are implemented as _inherents_ on the underlying type, however their
71//! presence is enforced by [`impl_supertrait`] and their type bounds are enforced by the
72//! requirement for shadow non-const implementations of each const fn trait item that are
73//! filled in by the expansion of [`impl_supertrait`]. These two mechanisms along with the
74//! trait sealing technique mentioned above collectively ensure that const fn trait items
75//! presence and correctness is enforced just as strongly as that of regular trait items.
76//!
77//! Using inherents as the vehicle for implementing const fn trait items has a few drawbacks due to
78//! the naming collisions that can occur with existing inherent items as well as the inability to
79//! blanket impl supertraits containing const fns (because it is impossible in stable Rust to
80//! blanket impl anything other than a real trait).
81//!
82//! That said, inherents are a convenient fallback when you find yourself reaching for const fn
83//! items in traits, and supertrait contains the most convenient implementation of this behavior
84//! currently possible in stable Rust.
85
86#![no_std]
87#![warn(missing_docs)]
88
89pub use supertrait_macros::*;
90pub mod traits;
91
92/// Contains hidden re-exports of [`macro_magic`] and other required types.
93#[doc(hidden)]
94pub mod __private {
95 pub use macro_magic;
96}