Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> You can't have Foo<N> * Foo<M> -> Foo<N+M> or similar.

You can though, unless I totally misunderstand your syntax

    use std::{marker::PhantomData, ops::{Add, Mul}};

    pub struct Foo<T> {
        _p: PhantomData<T>,
    }

    impl<N, M> Mul<Foo<M>> for Foo<N> 
    where
        N: Add<M>
    {
        type Output = Foo<<N as Add<M>>::Output>;
        fn mul(self, rhs: Foo<M>) -> Self::Output {
            todo!()
        }
    }


You misunderstood. N, M are supposed to be integers (const generics); in your example code you've made them types. Also, your `type Output = Foo<<N as Add<M>>::Output>;` just means "multiplication has the same return type as addition". But desired is that multiplying a Foo<4> with a Foo<3> results in a Foo<7>.

Rust decided that it's important to not have instantiation-time compiler errors, but this makes computation with const generics complicated: you're not allowed to write Foo<{N+M}> because N+M might overflow, even if it never actually overflows for the generic arguments used in the program.


aiui this isn't inherently limited by instantiation-time error messages and is available on nightly today with the generic_const_exprs feature. It's in the pipeline.


I believe this kind of stuff is being worked on.


Instantiation time errors unlock so much metaprogramming potential that Rust is going to be forced to allow them sooner or later.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: