Is it possible to make a "constant" for where clauses?

I can't come up with decent search terms for this one.

What I'm looking to do is clean up my code so that I can remove identical where clauses from it. Using a couple well-known traits as placeholders, imagine:

enum Stuff<T, U> where T: Clone + Debug, U: Clone + Display {...}

struct Things<T, U>  where T: Clone + Debug, U: Clone + Display {...}

fn do_stuff_and_things<T, U>(t: T) -> u: U where T: Clone + Debug, U: Clone+Display {...}

Obviously, I'm getting a lot of duplicate Clone + Debug and Clone + Display in there. I'm looking for a way to reduce that, both for readability, and also because, maybe someday I'll want one of these to have the Read and Write traits as well.

I thought of creating a new trait with them as supertraits like so:

trait CloneDebug: Clone + Debug {};
trait CloneDisplay: Clone + Display{};

fn do_stuff_and_things<T: CloneDebug, U: CloneDisplay>(t: T) -> u: U  {...}

But I think this restricts what I can actually accept. The first version allowed do_stuff_and_things to operate on any traits that implement Clone and Debug, whereas the second version will only operate on traits that explicitly implement CloneDebug. So I wouldn't be able to pass String into it, even though it implements all three traits.

I tried type CloneDebug = Clone + Debug; but Rust found it offensive and I'm inclined to agree. :slight_smile: I've looked at the newType pattern, but for this particular usecase, that seems to be adding, not removing coding overhead.

Is there some other way to specify a "trait alias"?

You can add blanket implementations of your traits:

impl<T> CloneDebug for T where T: Clone + Debug {}
impl<T> CloneDisplay for T where T: Clone + Display {}
4 Likes

Whoah, awesome. Thanks.

1 Like

There's an unstable feature in the works called exactly that:

https://doc.rust-lang.org/nightly/unstable-book/language-features/trait-alias.html

cuviper's solution is probably the best you can do for now.

2 Likes