Same trait bounds for multiple type parameters

Hi there, I just came across this situation:

fn my_fn<
    'a,
    I,
    A: Really<Item=I> + ALot<'a, I> + ToType,
    B: Really<Item=I> + ALot<'a, I> + ToType,
>(a: A, b: B)
{ ... }

And was wondering if I there is a syntax (or an RFC for it) to define trait bounds on multiple type parameters, something like:

fn my_fn<
    'a,
    I,
    A & B: Really<Item=I> + ALot<'a, I> + ToType,
>(a: A, b: B)
{ ... }

The only way I would know to mitigate this is by implementing a utility trait:

trait ReallyALotToType<'a, I>: Really<Item=I> + ALot<'a, I> + ToType {}
impl<'a, I, T: Really<Item=I> + ALot<'a, I> + ToType> ReallyALotToType<'a, I> for T {}
fn my_fn<
    'a,
    I,
    A: ReallyALotToType<'a, I>,
    B: ReallyALotToType<'a, I>,
>(a: A, b: B)
{ ... }

But that doesn't scale as well as the first solution, especially when there are many type parameters involved in the trait. Also it introduces a lot of cognitive clutter, you have to think of a name for the trait, you have to implement it, all only really to tell the compiler something very simple: "These type parameters have the same trait bounds!"

The syntax could be debated, of course , would be the nicest to separate type parameter names before a trait bound, but that is already taken in this context. Other versions I could think of:

  • A : B: Trait,
  • A | B: Trait,
  • A B: Trait,
  • (A, B): Trait,

Maybe this could be taken even further and the type parameter context could allow for incremental definitions of trait bounds, i.e. type parameter names can be repeated to add new bounds, so that this would be possible:
<(A, B): Trait, A: Debug>

Apologies. But, to me it is not clear what could be preventing the use of a single type variable to represent both A & B ? Something like:

fn my_fn<'a, I, T: Really<Item=I> + ALot<'a, I> + ToType,>(a: T, b: T)

Oh, right. In my case A and B may be different types, because I am writing a function taking two closures which return these types. If both of these closures returned A, then I could not return different types in each closure.

fn my_fn<A: Trait, B: Trait>(af: impl Fn(u32) -> A, bf: impl Fn(u32) -> B) { ... }

Think something like iterators. If they were the same type, I could not return a Zip in one of the closures, and a Map in the other closure, for example.

Opened a thread on the rust internals forum: Same trait bounds for multiple type parameters - traits working group - Rust Internals