Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trait implementation works when specifying types directly but not as power #208

Open
seftontycho opened this issue Mar 26, 2024 · 3 comments

Comments

@seftontycho
Copy link

The following code compiles correctly when the following types are defined as:

pub type MANTISSA_ONE = U8388608;
pub type MANTISSA_TWO = U16777216;

But not when they are defined as:

pub type MANTISSA_ONE = <U2 as Pow<U23>>::Output;
pub type MANTISSA_TWO = <U2 as Pow<U24>>::Output;

Any idea what is going on here?
Sorry for the spam and thank you for your time (this is my 3rd issue/question in the last week).

The following is as minimal as I could make it to still reproduce:

#![allow(dead_code)]

use std::ops::{Add, Div, Mul, Sub};

use private::IsLessPrivate;
use typenum::*;

pub type MANTISSA_ONE = <U2 as Pow<U23>>::Output;
pub type MANTISSA_TWO = <U2 as Pow<U24>>::Output;

pub struct MyStruct<T>(T);

pub trait TraitA<T> {
    type Output;
}

impl<M1, M2> TraitA<MyStruct<M2>> for MyStruct<M1>
where
    M1: Unsigned + Add<M2> + Mul<M2>,
    M2: Unsigned,
    Sum<M1, M2>: Unsigned
        + Cmp<MANTISSA_ONE>
        + Cmp<MANTISSA_TWO>
        + IsLessPrivate<MANTISSA_ONE, Compare<Sum<M1, M2>, MANTISSA_ONE>>,
    MyStruct<Prod<M1, M2>>: TraitB<Le<Sum<M1, M2>, MANTISSA_ONE>, True>,
{
    type Output = TraitBOut<MyStruct<Prod<M1, M2>>, Le<Sum<M1, M2>, MANTISSA_ONE>, True>;
}

pub trait TraitB<LHint: Bit, RHint: Bit> {
    type Output;
}

pub type TraitBOut<T, LHint, RHint> = <T as TraitB<LHint, RHint>>::Output;

impl<M> TraitB<True, False> for MyStruct<M>
where
    M: Unsigned + TraitBInner<op!(U1 + (MANTISSA_ONE / M)), False>,
    op!(U1 + (MANTISSA_ONE / M)): Unsigned,

    MANTISSA_ONE: Div<M>,
    U1: Add<Quot<MANTISSA_ONE, M>>,
{
    type Output = TraitBInnerOut<M, op!(U1 + (MANTISSA_ONE / M)), False>;
}

impl<M> TraitB<False, True> for MyStruct<M>
where
    M: Unsigned + Div<MANTISSA_TWO> + TraitBInner<op!(U1 + (M / MANTISSA_TWO)), True>,
    op!(U1 + (M / MANTISSA_TWO)): Unsigned,
    U1: Add<Quot<M, MANTISSA_TWO>>,
{
    type Output = TraitBInnerOut<M, op!(U1 + (M / MANTISSA_TWO)), True>;
}

// This has two different behaviours depending on the type of `Hint`
pub trait TraitBInner<U: Unsigned, Hint: Bit> {
    type Output;
}

pub type TraitBInnerOut<T, U, Hint> = <T as TraitBInner<U, Hint>>::Output;

impl<M, U> TraitBInner<U, True> for MyStruct<M>
where
    M: Unsigned + Add<U>,
    U: Unsigned,
{
    type Output = MyStruct<Sum<M, U>>;
}

impl<M, U> TraitBInner<U, False> for MyStruct<M>
where
    M: Unsigned + Sub<U>,
    U: Unsigned,
{
    type Output = MyStruct<Diff<M, U>>;
}

fn main() {
    type A = MyStruct<U1>;
    type B = MyStruct<U2>;
    type C = <A as TraitA<B>>::Output;
}
@seftontycho
Copy link
Author

I have also noticed that while cargo run produces errors during compilation, compilation never ends.
I believe I may have gotten stuck in unbounded recursion.
This would also explain why my editor kept crashing my pc.

I can't see where the issue is however.

@paholg
Copy link
Owner

paholg commented Mar 27, 2024

Strangely, cargo check succeeds, while cargo build fails and hangs. This definitely looks like a rust bug, I'd report there.

@seftontycho
Copy link
Author

Both seem to crash for me.
I will open an issue with rust anyway as I'm not sure it should hang.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants