type_const/lib.rs
1#![no_std]
2#![allow(rustdoc::redundant_explicit_links)]
3
4//! This crate provides simple utils for passing `const` values around through generics,
5//! in the form of types.
6//!
7//! The concept of a type const is expressed through the [`Const`](crate::Const) trait, which holds the type and
8//! the value of the constant.
9//!
10//! Passing values that are known at compile time through generics is different from passing
11//! them through arguments, for example:
12//! ```
13//! const fn array_of_const<C: type_const::Const, const N: usize>() -> [C::Type; N] {
14//! [C::VALUE; N] // no `Copy` needed!
15//! }
16//! assert_eq!(array_of_const::<type_const::DefaultOf<i32>, 3>(), [0; 3]);
17//! ```
18//!
19//! This may also be used to write `const` "functions" in traits without the nightly
20//! `const_trait` feature. Note that unlike `const fn`, these can only be evaluated at compile
21//! time.
22//! ```
23//! trait AddConst<Rhs=Self> {
24//! type Output;
25//! type Add<
26//! LhsC: type_const::Const<Type = Self>,
27//! RhsC: type_const::Const<Type = Rhs>,
28//! >: type_const::Const<Type = Self::Output>;
29//! }
30//! ```
31
32/// Describes a type that holds an associated const value.
33pub trait Const {
34 /// The value type of the const
35 type Type;
36 /// The implementation of the value. Prefer [`value_of`] for accessing this during const
37 /// evaluation.
38 const VALUE: Self::Type;
39}
40
41/// Alias for [`Const::Type`].
42pub type TypeOf<C> = <C as Const>::Type;
43
44/// Alias for [`Const::VALUE`]. Prefer this function over accessing the const directly.
45///
46/// Using the associated constant through this function rather than directly often causes it to only be
47/// evaluated when the branch that it is used in is actually executed.
48/// This means that it may improve compile times, avoid errors for recursive consts and avoid evaluating
49/// panics.
50///
51/// For example:
52/// ```compile_fail
53/// # use type_const::*;
54/// struct Fallible;
55/// impl Const for Fallible {
56/// type Type = ();
57/// const VALUE: Self::Type = panic!();
58/// }
59/// const _: () = if false { Fallible::VALUE }; // this gives a compile error
60/// ```
61/// ```
62/// # use type_const::*;
63/// # struct Fallible;
64/// # impl Const for Fallible {
65/// # type Type = ();
66/// # const VALUE: Self::Type = panic!();
67/// # }
68/// const _: () = if false { value_of::<Fallible>() }; // this compiles
69/// ```
70pub const fn value_of<C: Const + ?Sized>() -> C::Type {
71 C::VALUE
72}
73
74/// A const version of [`Default`].
75pub trait DefaultConst: Sized {
76 /// The default value for this type. Prefer accessing this by calling [`value_of`] on [`DefaultOf<Self>`].
77 const DEFAULT: Self;
78}
79/// A [`Const`] that evaluates to [`DefaultConst::DEFAULT`].
80pub struct DefaultOf<T>(#[allow(dead_code)] fn() -> T);
81impl<T: DefaultConst> Const for DefaultOf<T> {
82 type Type = T;
83 const VALUE: Self::Type = T::DEFAULT;
84}
85
86mod impls;
87
88pub mod consts;