pub unsafe trait Deterministic {}
pub unsafe trait DeterministicOrDiverges {}
macro_rules! impl_deterministic {
(basic_or_diverges for $($ty:ty)+) => {
$(unsafe impl DeterministicOrDiverges for $ty {})+
};
(basic for $($ty:ty)+) => {
$(unsafe impl DeterministicOrDiverges for $ty {})+
$(unsafe impl Deterministic for $ty {})+
};
(wrapping for $($ty:ty)+) => {
$(unsafe impl DeterministicOrDiverges for Wrapping<$ty> {})+
$(unsafe impl Deterministic for Wrapping<$ty> {})+
};
(generic for $($tt:tt)+) => {
$(unsafe impl<T: DeterministicOrDiverges> DeterministicOrDiverges for $tt<T> {})+
$(unsafe impl<T: Deterministic> Deterministic for $tt<T> {})+
};
(array $($i:expr)+) => {
$(unsafe impl<T: DeterministicOrDiverges> DeterministicOrDiverges for [T; $i] {})+
$(unsafe impl<T: Deterministic> Deterministic for [T; $i] {})+
};
(tuple $($T:ident)+) => {
unsafe impl<$($T: DeterministicOrDiverges),*> DeterministicOrDiverges for ($($T,)+) {}
unsafe impl<$($T: Deterministic),*> Deterministic for ($($T,)+) {}
};
}
use ::std::num::Wrapping;
use ::std::ops::*;
use ::std::cmp::Ordering;
use ::std::any::TypeId;
use ::std::marker::PhantomData;
use ::std::sync::Arc;
use ::std::rc::Rc;
unsafe impl<T: Deterministic> Deterministic for [T] {}
unsafe impl<T: DeterministicOrDiverges> DeterministicOrDiverges for [T] {}
impl_deterministic!(array 0 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);
impl_deterministic!(tuple A);
impl_deterministic!(tuple A B);
impl_deterministic!(tuple A B C);
impl_deterministic!(tuple A B C D);
impl_deterministic!(tuple A B C D E);
impl_deterministic!(tuple A B C D E F);
impl_deterministic!(tuple A B C D E F G);
impl_deterministic!(tuple A B C D E F G H);
impl_deterministic!(tuple A B C D E F G H I);
impl_deterministic!(tuple A B C D E F G H I J);
impl_deterministic!(basic for () bool char str String);
impl_deterministic!(basic for RangeFull TypeId Ordering);
impl_deterministic!(wrapping for u8 i8 u16 i16 u32 i32 u64 i64 usize isize);
#[feature(i128_type)]
impl_deterministic!(wrapping for i128 u128);
impl_deterministic!(basic_or_diverges for u8 i8 u16 i16 u32 i32 u64 i64 usize isize);
#[feature(i128_type)]
impl_deterministic!(basic_or_diverges for i128 u128);
unsafe impl<T> Deterministic for *const T {}
unsafe impl<T> Deterministic for *mut T {}
impl_deterministic!(generic for Box Rc Arc Vec);
impl_deterministic!(generic for Range RangeFrom RangeTo);
#[feature(inclusive_range)]
impl_deterministic!(generic for RangeInclusive RangeToInclusive);
unsafe impl<T: ?Sized + Deterministic> Deterministic for PhantomData<T> {}
unsafe impl<T: Deterministic> Deterministic for Option<T> {}
unsafe impl<T: DeterministicOrDiverges> DeterministicOrDiverges for Option<T> {}
unsafe impl<T,E> Deterministic for Result<T,E> where T: Deterministic, E: Deterministic {}
unsafe impl<T,E> DeterministicOrDiverges for Result<T,E> where T: DeterministicOrDiverges, E: DeterministicOrDiverges {}
#[cfg(test)]
mod tests {
use super::Deterministic;
use ::std::num::Wrapping as Wp;
struct Well<T>(T);
unsafe impl<T: Deterministic> Deterministic for Well<T> {}
fn require_deterministic<T>(_: &T) where T: Deterministic {}
#[test]
fn should_not_accept_deterministic() {
}
#[test]
fn should_accept_deterministic() {
require_deterministic(&Wp(42));
require_deterministic(&vec![Wp(42), Wp(13)]);
require_deterministic(&Well(Wp(42)));
}
}