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

Compiler asks for already present bound #161

Open
newpavlov opened this issue Dec 3, 2020 · 1 comment
Open

Compiler asks for already present bound #161

newpavlov opened this issue Dec 3, 2020 · 1 comment
Labels
bug likely-rust-bug Likely a compiler bug

Comments

@newpavlov
Copy link

I think it's a compiler bug and I've reported it here. But I think it's wort to post it here as well. Feel free to close this issue if you think that it's indeed a compiler bug and not a typenum issue.

While working on RustCrypto/stream-ciphers#195. I got roughly the following code:

use generic_array::{GenericArray, ArrayLength, typenum::{Unsigned, Quot, U16}};
use core::ops::Div;

pub trait Foo: Copy + Default {
    type Size: Unsigned;

    fn load<N>(block: &GenericArray<u8, N>) -> GenericArray<Self, Quot<N, Self::Size>>
    where
        N: ArrayLength<u8> + Div<Self::Size>,
        Quot<N, Self::Size>: ArrayLength<Self>
    {
        Default::default()
    }
}

#[derive(Copy, Clone, Default)]
#[repr(transparent)]
struct Bar(u128);

impl Foo for Bar {
    type Size = U16;
}

It compiles without issues. The default method impl will not be present in the final code, I just use it to show that the bounds are correct.

But if we are to overwrite the load method in the Bar impl by simply copying the default impl:

impl Foo for Bar {
    type Size = U16;

    fn load<N>(block: &GenericArray<u8, N>) -> GenericArray<Self, Quot<N, Self::Size>>
    where
        N: ArrayLength<u8> + Div<Self::Size>,
        Quot<N, Self::Size>: ArrayLength<Self>
    {
        Default::default()
    }
}

Playground

Compiler will return the following compilation errors:

error[E0277]: cannot divide `N` by `UInt<UInt<UInt<UInt<UInt<UTerm, B1>, B0>, B0>, B0>, B0>`
  --> src/lib.rs:23:5
   |
23 | /     fn load<N>(block: &GenericArray<u8, N>) -> GenericArray<Self, Quot<N, Self::Size>>
24 | |     where
25 | |         N: ArrayLength<u8> + Div<Self::Size>,
26 | |         Quot<N, Self::Size>: ArrayLength<Self>
   | |______________________________________________^ no implementation for `N / UInt<UInt<UInt<UInt<UInt<UTerm, B1>, B0>, B0>, B0>, B0>`
   |
help: consider further restricting this bound
   |
25 |         N: ArrayLength<u8> + Div<Self::Size> + Div<UInt<UInt<UInt<UInt<UInt<UTerm, B1>, B0>, B0>, B0>, B0>>,
   |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0277]: cannot divide `N` by `UInt<UInt<UInt<UInt<UInt<UTerm, B1>, B0>, B0>, B0>, B0>`
  --> src/lib.rs:23:5
   |
23 | /     fn load<N>(block: &GenericArray<u8, N>) -> GenericArray<Self, Quot<N, Self::Size>>
24 | |     where
25 | |         N: ArrayLength<u8> + Div<Self::Size>,
26 | |         Quot<N, Self::Size>: ArrayLength<Self>
27 | |     {
28 | |         Default::default()
29 | |     }
   | |_____^ no implementation for `N / UInt<UInt<UInt<UInt<UInt<UTerm, B1>, B0>, B0>, B0>, B0>`
   |
help: consider further restricting this bound
   |
25 |         N: ArrayLength<u8> + Div<Self::Size> + Div<UInt<UInt<UInt<UInt<UInt<UTerm, B1>, B0>, B0>, B0>, B0>>,
   |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0277]: cannot divide `N` by `UInt<UInt<UInt<UInt<UInt<UTerm, B1>, B0>, B0>, B0>, B0>`
  --> src/lib.rs:23:8
   |
23 |     fn load<N>(block: &GenericArray<u8, N>) -> GenericArray<Self, Quot<N, Self::Size>>
   |        ^^^^ no implementation for `N / UInt<UInt<UInt<UInt<UInt<UTerm, B1>, B0>, B0>, B0>, B0>`
   |
help: consider further restricting this bound
   |
25 |         N: ArrayLength<u8> + Div<Self::Size> + Div<UInt<UInt<UInt<UInt<UInt<UTerm, B1>, B0>, B0>, B0>, B0>>,
   |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 3 previous errors

Replacing Div<Self::Size> with Div<U16> or even with explicit Div<Uint<..>> does not fix the error.

@paholg
Copy link
Owner

paholg commented Mar 12, 2021

Replacing Div<Self::Size> with Div<U16> or even with explicit Div<Uint<..>> does not fix the error.

Interestingly, having both bounds Div<Self::Size> + Div<U16> makes it compile for me. Though, you need them both in the trait definition as well, so that's not really helpful. But it does point to it being a compiler bug around associated types.

I can also get it to compile by having Size be a type parameter instead of an associated type, so that might be a workable workaround:

use core::ops::Div;
use generic_array::{
    typenum::{Quot, Unsigned, U16},
    ArrayLength, GenericArray,
};

pub trait Foo<Size>: Copy + Default {
    fn load<N>(block: &GenericArray<u8, N>) -> GenericArray<Self, Quot<N, Size>>
    where
        N: ArrayLength<u8> + Div<Size>,
        Quot<N, Size>: ArrayLength<Self>,
    {
        Default::default()
    }
}

#[derive(Copy, Clone, Default)]
#[repr(transparent)]
struct Bar(u128);

impl Foo<U16> for Bar {
    fn load<N>(block: &GenericArray<u8, N>) -> GenericArray<Self, Quot<N, U16>>
    where
        N: ArrayLength<u8> + Div<U16>,
        Quot<N, U16>: ArrayLength<Self>,
    {
        Default::default()
    }
}

@paholg paholg added bug likely-rust-bug Likely a compiler bug labels Mar 12, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug likely-rust-bug Likely a compiler bug
Projects
None yet
Development

No branches or pull requests

2 participants