Trait method returns trait with different const generic param

Hello, is there a way to define trait method which returns same type but with another const generic params?

    struct A<const N: usize> {}
    
    impl<const N: usize> A<{N}> {
        pub fn minus_one(self) -> A<{N-1}> {
            A {}
        }
    }
    
    trait MinusOne<const N: usize> {
        fn minus_one(self) -> Self<{N - 1}>/* Doesn't work( */;
    }

I thought something like this might work, but it causes internal compiler errors in current nightly rustc:

#![feature(
    generic_associated_types,
    const_generics,
    const_evaluatable_checked,
)]

struct A<const N: usize> {}

trait MinusOne<const N: usize> where [u8; {N - 1}]: Sized {
    type Output<const M: usize>;
    fn minus_one(self) -> Self::Output<{N - 1}>;
}

impl<const N: usize> MinusOne<{N}> for A<{N}> where [u8; {N - 1}]: Sized {
    type Output<const M: usize> = A<{M}>;
    fn minus_one(self) -> A<{N - 1}> {
        A {}
    }
}

People are still working on implementing compiler support for code like this: Tracking Issue for complex generic constants (`const_evaluatable_checked`) · Issue #76560 · rust-lang/rust · GitHub

2 Likes

You can't use Self as generic type in trait method signatures, since trait is implemented for each substitution of generic parameters independently - i.e., if you implement MinusOne for A<N>, Self will be A<N>, not A.

This can be done, however, via associated types - almost as mbrubeck showed above, just without GATs:

#![feature(const_generics)]
#![feature(const_evaluatable_checked)]
#![allow(incomplete_features)]

struct A<const N: usize> {}

trait MinusOne<const N: usize> where [u8; N - 1]: Sized {
    type Minus;
    fn minus_one(self) -> Self::Minus;
}

impl<const N: usize> MinusOne<{N}> for A<{ N }>  where [u8; N - 1]: Sized {
    type Minus = A<{N - 1}>;
    fn minus_one(self) -> A<{ N - 1 }> {
        A {}
    }
}

Playground

4 Likes

Thanks, stumbled on this solution myself just now) Was ready to answer my own topic.

[u8; N - 1]: Sized is it only way to constraint const generics? Looks really strange IMO)

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.