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