Skip to main content

supertrait/
lib.rs

1//! # Supertrait 🦹
2//!
3//! [![Crates.io](https://img.shields.io/crates/v/supertrait)](https://crates.io/crates/supertrait)
4//! [![docs.rs](https://img.shields.io/docsrs/supertrait?label=docs)](https://docs.rs/supertrait/latest/supertrait/)
5//! [![Build Status](https://img.shields.io/github/actions/workflow/status/sam0x17/supertrait/ci.yaml)](https://github.com/sam0x17/supertrait/actions/workflows/ci.yaml?query=branch%3Amain)
6//! [![MIT License](https://img.shields.io/github/license/sam0x17/supertrait)](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}