Why are where clauses on traits not inherited?


#1

Hi everyone !

Here is the code that arises my question :

pub trait TraitA<T> where i32: Into<T> {}

pub trait TraitB<T>: TraitA<T> where i32: Into<T> {
    fn do_something(x: i32) -> T;
}

Why would I need not rewrite where i32: Into<T> for TraitB (the code does not compile if it’s not there) ? Should’nt the fact that TraitB<T> inherits TraitA<T> make this clause always true ?


#2

It’s an annoying limitation indeed:

The gist is that you get “inheritance” for direct clauses. So with TraitB<T>: TraitA<T>, anything else that requires TraitB will implicitly get TraitA methods too. But it unfortunately does not transfer i32: Into<T>, even though that’s a mandatory part of the trait.


#3

Thanks for the answer.

I’m kinda surprised this issue isn’t getting more attention, this seems to make lots of things a pain.
Here for example, everytime I want to write a function that take a generic TraitA<T> as input, I have rewrite the where clause every time, even if I don’t want to use the fact that i32: Into<T>. Is there a way around that ? By that I mean is there a way to transform any where clause into a regular trait bound ?

Let’s say I want to create a Mat trait, I want this trait to be iterable by reference:

pub trait Mat: Index<(usize, usize), Output = < Self as Mat >::Item> where
        for<'a> &'a Self: IntoIterator<Item = &'a < Self as Mat >::Item>
{
    type Item: MatItem;
}

Doing it this way is clearly not a good idea since this fairly big where clause would have to be repeated often. What are my options here ?


#4

One possibility is to write a MatRef trait, and impl<'a, T: Mat> MatRef for &'a T. This probably needs tricky where clauses itself, but I think you might only need it in one place, not repeated everywhere. Then your only repeated clause will be something like for<'a> &'a Self: MatRef.

I played a little with this and couldn’t easily get it right. I think it may not end up any simpler compared to the single large clause in your example, but maybe it could be a reduction if you had more clauses to deal with.

The good news is that even though it’s annoying to repeat the clauses, the compiler still knows enough to validate that you actually wrote it correctly. I still hope someday it can just make this implicit.


#5

Perhaps the roadmap’s Trait system rewrite will make it possible to address this?


#6

I think doing something like this is blocked on the trait system rewrite. We do want to do something about the repetition of bounds, not only on traits but also on types.