// Regression test for #52873. We used to ICE due to unexpected // overflows when checking for "blanket impl inclusion". use std::marker::PhantomData; use std::cmp::Ordering; use std::ops::{Add, Mul}; pub type True = B1; pub type False = B0; pub type U0 = UTerm; pub type U1 = UInt<UTerm, B1>; pub trait NonZero {} pub trait Bit { } pub trait Unsigned { } #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)] pub struct B0; impl B0 { #[inline] pub fn new() -> B0 { B0 } } #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)] pub struct B1; impl B1 { #[inline] pub fn new() -> B1 { B1 } } impl Bit for B0 { } impl Bit for B1 { } impl NonZero for B1 {} pub trait PrivatePow<Y, N> { type Output; } pub type PrivatePowOut<A, Y, N> = <A as PrivatePow<Y, N>>::Output; pub type Add1<A> = <A as Add<::B1>>::Output; pub type Prod<A, B> = <A as Mul<B>>::Output; pub type Square<A> = <A as Mul>::Output; pub type Sum<A, B> = <A as Add<B>>::Output; #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)] pub struct UTerm; impl UTerm { #[inline] pub fn new() -> UTerm { UTerm } } impl Unsigned for UTerm { } #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)] pub struct UInt<U, B> { _marker: PhantomData<(U, B)>, } impl<U: Unsigned, B: Bit> UInt<U, B> { #[inline] pub fn new() -> UInt<U, B> { UInt { _marker: PhantomData, } } } impl<U: Unsigned, B: Bit> Unsigned for UInt<U, B> { } impl<U: Unsigned, B: Bit> NonZero for UInt<U, B> {} impl Add<B0> for UTerm { type Output = UTerm; fn add(self, _: B0) -> Self::Output { UTerm } } impl<U: Unsigned, B: Bit> Add<B0> for UInt<U, B> { type Output = UInt<U, B>; fn add(self, _: B0) -> Self::Output { UInt::new() } } impl<U: Unsigned> Add<U> for UTerm { type Output = U; fn add(self, _: U) -> Self::Output { unimplemented!() } } impl<U: Unsigned, B: Bit> Mul<B0> for UInt<U, B> { type Output = UTerm; fn mul(self, _: B0) -> Self::Output { UTerm } } impl<U: Unsigned, B: Bit> Mul<B1> for UInt<U, B> { type Output = UInt<U, B>; fn mul(self, _: B1) -> Self::Output { UInt::new() } } impl<U: Unsigned> Mul<U> for UTerm { type Output = UTerm; fn mul(self, _: U) -> Self::Output { UTerm } } impl<Ul: Unsigned, B: Bit, Ur: Unsigned> Mul<UInt<Ur, B>> for UInt<Ul, B0> where Ul: Mul<UInt<Ur, B>>, { type Output = UInt<Prod<Ul, UInt<Ur, B>>, B0>; fn mul(self, _: UInt<Ur, B>) -> Self::Output { unimplemented!() } } pub trait Pow<Exp> { type Output; } impl<X: Unsigned, N: Unsigned> Pow<N> for X where X: PrivatePow<U1, N>, { type Output = PrivatePowOut<X, U1, N>; } impl<Y: Unsigned, X: Unsigned> PrivatePow<Y, U0> for X { type Output = Y; } impl<Y: Unsigned, X: Unsigned> PrivatePow<Y, U1> for X where X: Mul<Y>, { type Output = Prod<X, Y>; } impl<Y: Unsigned, U: Unsigned, B: Bit, X: Unsigned> PrivatePow<Y, UInt<UInt<U, B>, B0>> for X where X: Mul, Square<X>: PrivatePow<Y, UInt<U, B>>, { type Output = PrivatePowOut<Square<X>, Y, UInt<U, B>>; }