Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing Nested Traits

Tags:

rust

traits

I have some traits which (after removing functions and some parameter bloat) look like:

trait Foo { }
trait Boo { }
trait Bar<T: Foo> { }
trait Baz { }

If U implements Bar<T> for some T implementing Foo and U implements Boo, then one is able to derive an implementation of Baz for U. However, I wasn't able to write valid Rust code doing this.

A few tries were:

impl<T: Foo, U: Bar<T> + Boo> Baz for U { }

which gives

error: the type parameter T is not constrained by the impl trait, self type, or predicates [E0207]

whereas

impl<U: Bar<T> + Boo> Baz for U { }

yields

error: type name T is undefined or not in scope [E0412]

Could one/how could one do this in (stable) Rust (hopefully without any dynamic dispatch)?

Edit: Some people hinted at some similar questions for which there were essentially two approaches (and I find both of them unsuitable for my situation):

  1. Using associated types. I don't want to do this because I want to keep track of T, e.g. I want to write some functions which have a signature like fn bla<T: Foo, U: Bar<T>, V: Bar<T>>() where I want to know that U and V implement Bar<T> for the same T. (Or is there way of doing this with associated types?)
  2. Using some kind of wrapping by putting U and T in a struct. I don't want to use this either because I have several levels of such "trait dependencies", so wrapping things in each level would bloat the code a lot.

So the updated question would be: Is there a solution to this problem without using associated types or wrappers?

like image 970
aclow Avatar asked Jul 19 '16 12:07

aclow


1 Answers

You can do it making T an associated type:

trait Foo { }
trait Boo { }
trait Bar {
    type T: Foo;
}
trait Baz { }

impl<U: Bar + Boo> Baz for U
    // this where clause is not necessary (this bound is already true)
    // where U::T: Foo
{ }

I don't want to do this because I want to keep track of T, e.g. I want to write some functions which have a signature like fn bla<T: Foo, U: Bar<T>, V: Bar<T>>() where I want to know that U and V implement Bar<T> for the same T. (Or is there way of doing this with associated types?)

Yes, you can do it with associated types:

fn bla<U: Bar, V: Bar<T = U::T>>() { }
like image 143
malbarbo Avatar answered Sep 19 '22 22:09

malbarbo