Flatten nested tuples


I want to achieve the following:

assert_eq!((1, 2).flatten(), (1, 2));
assert_eq!((1, (2, 3)).flatten(), (1, 2, 3));
assert_eq!((1, (2, (3, 4))).flatten(), (1, 2, 3, 4));
// ...

Due to conflicting trait implementations issues (stackoverflow) I tried to use #![feature(specialization)] and came up with this code (playground):


trait Flatten {
    type Output;
    fn flatten(self) -> Self::Output;

impl<T, U> Flatten for (T, U) {
    default type Output = (T, U);
    default fn flatten(self) -> Self::Output {

impl<A, B, T, U> Flatten for (A, B) where B: Flatten<Output = (T, U)> {
    type Output = (A, T, U);
    fn flatten(self) -> Self::Output {
        let (a, b) = self;
        let (t, u) = b.flatten();
        (a, t, u)

but then I get this error I’m not able to resolve:

expected associated type, found tuple

How could I make the tests run through?


Not a direct answer to your question but, could a macro do what you want?
I’m mostly curious to know if that’s possible.


I think so but I always try to avoid macros in favor of generic impls.


That’s because you can theoretically specialize Output and flatten independently so they can’t depend on each other (eventually, there needs to be a way to bind them together but we don’t have that yet). You can do this by doing a fancy associated type dance but it gets messy pretty quickly.

If you’re interested, take a look at the Zip implementation: https://doc.rust-lang.org/src/core/iter/mod.rs.html#714-720


By stupidly following the instructions of the compiler I came up with this piece of code:

impl<T, U> Flatten for (T, U) {
    default type Output = Self;
    default fn flatten(self) -> Self::Output {
        unsafe {
            ::std::mem::transmute::<Self, Self::Output>(self)

Still doesn’t compile…

transmute called with differently sized types:
(T, U) (size can vary because of T) to <(T, U) as Flatten>::Output (size can vary)

Why is Self another size then Self::Output when flattens Output is defined as Self? Am I heading in the right direction?