1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/// For constructing types that implement [`Infer`], this includes `Is*` types.
///
/// This is best used when the constructed type can be inferred.
///
/// The type argument (`$ty`) is optional, inferred when not passed.
///
/// # Alternatives
///
/// `constmuck` types have their own macros for constructing them,
/// which are more concise with explicit type arguments,
/// and help type inference.
///
/// These are the macros:
///
/// - [`IsContiguous`](macro@crate::IsContiguous):
/// Constructs an [`IsContiguous`](struct@crate::IsContiguous) type.
///
/// - [`IsCopy`](macro@crate::IsCopy):
/// Constructs an [`IsCopy`](struct@crate::IsCopy) type.
///
/// - [`IsPod`](macro@crate::IsPod):
/// Constructs an [`IsPod`](struct@crate::IsPod) type.
///
/// - [`IsTW`](macro@crate::IsTW):
/// Constructs an [`IsTransparentWrapper`](struct@crate::IsTransparentWrapper) type.
///
/// - [`IsZeroable`](macro@crate::IsZeroable):
/// Constructs an [`IsZeroable`](struct@crate::IsZeroable) type.
///
/// - [`TypeSize`](macro@crate::TypeSize):
/// Constructs an [`TypeSize`](struct@crate::TypeSize) type.
///
///
/// # Example
///
/// ### Basic
///
/// ```rust
/// use constmuck::{infer, wrapper};
///
/// use std::num::Wrapping as W;
///
/// const FOO: &[W<u8>] = wrapper::wrap_slice(&[3, 2, 1, 0], infer!());
/// assert_eq!(FOO, [W(3), W(2), W(1), W(0)]);
///
/// let bar = wrapper::peel_slice::<W<u8>, u8>(FOO, infer!());
/// assert_eq!(bar, [3, 2, 1, 0]);
///
///
/// ```
///
/// ### Tuple
///
/// `infer` can contruct tuples of types that implement [`Infer`].
///
/// ```rust
/// use constmuck::infer;
/// use constmuck::{IsPod, IsTW, IsTransparentWrapper};
///
/// use std::num::Wrapping;
///
/// const fn requires_2_bounds<O, I>(_bounds: (IsPod<I>, IsTransparentWrapper<O, I>)) {}
///
/// requires_2_bounds::<Wrapping<u32>, u32>(infer!());
///
/// // the same as the above call
/// requires_2_bounds(infer!((IsPod<u32>, IsTransparentWrapper<Wrapping<u32>, u32>)));
///
/// // using more specific macros
/// requires_2_bounds((IsPod!(u32), IsTW!(Wrapping<u32>, u32)));
/// ```
#[macro_export]
macro_rules! infer {
    () => {
        $crate::Infer::INFER
    };
    ($ty:ty) => {
        <$ty as $crate::Infer>::INFER
    };
}

/// For constructing `Is*` types (values that represent trait bounds),
/// and tuples of them.
///
/// For a more concise way to write [`Infer::INFER`], there's the [`infer`] macro.
///
/// # Example
///
/// ### Basic
///
/// This example demonstrates how you can use the `INFER` associated constant
/// instead of using the [`infer`] macro.
///
/// ```rust
/// use constmuck::{cast, wrapper};
/// use constmuck::{Infer};
///
/// use std::num::Wrapping;
///
/// const FOO: [i8; 3] = cast([3u8, 5, u8::MAX - 1], Infer::INFER);
/// assert_eq!(FOO, [3, 5, -2]);
///  
/// const BAR: &[Wrapping<i8>] = wrapper::wrap_slice(&[13, 21, 34], Infer::INFER);
/// assert_eq!(BAR, &[Wrapping(13), Wrapping(21), Wrapping(34)]);
///  
/// ```
///  
pub trait Infer: Sized + Copy {
    /// Constructs this type.
    const INFER: Self;
}

macro_rules! impl_tuple {
    ($($ty:ident),*) => {
        impl<$($ty),*> Infer for ($($ty,)*)
        where $($ty: Infer,)*
        {
            const INFER: Self = ($($ty::INFER,)*);
        }
    };
}

impl_tuple! {}
impl_tuple! {A}
impl_tuple! {A,B}
impl_tuple! {A,B,C}
impl_tuple! {A,B,C,D}
impl_tuple! {A,B,C,D,E}
impl_tuple! {A,B,C,D,E,F}
impl_tuple! {A,B,C,D,E,F,G}
impl_tuple! {A,B,C,D,E,F,G,H}