kdy
kdy

Reputation: 480

How can I return specializable associated type from default method?

I'm implementing tuple flattening for Rust. It requires converting

((A,B), (C, (D, E)), F)

into

Cons[
    Cons[A, B, Nil],
    Cons[
        C, Cons[D, E, Nil], Nil
    ],
    F,
    Nil
]

I tried using specialization, but the compiler doesn't like it:

/// For non-tuple types.
impl<T> IntoCons for Val<T> {
    default type Out = Cons<T, Nil>;

    default fn into_cons(self) -> Cons<T, Nil> {
        Cons {
            head: self,
            tail: Nil,
        }
    }
}

How can I do this? Any alternative that doesn't use unsafe is ok.

Complete example:

#![feature(specialization)]
use std::fmt::{Debug, Display};

pub trait Tr {
    type It;
    fn it(self) -> Self::It;
}

impl<T> Tr for T
where
    T: Debug,
{
    default type It = u8;

    default fn it(self) -> Self::It {
        0
    }
}

impl<T> Tr for T
where
    T: Debug + Display,
{
    type It = u16;

    fn it(self) -> Self::It {
        0
    }
}

fn main() {}

playground

Compiler output:

error[E0308]: mismatched types
  --> src/main.rs:17:9
   |
16 |     default fn it(self) -> Self::It {
   |                            -------- expected `<T as Tr>::It` because of return type
17 |         0
   |         ^ expected associated type, found integral variable
   |
   = note: expected type `<T as Tr>::It`
              found type `{integer}`

Upvotes: 2

Views: 727

Answers (1)

Neikos
Neikos

Reputation: 1980

The problem here is that you are returning Self::It but give it a 0. What happens if someone were to implement this with It being String? Since there is no way to prove that this is always going to be a number, you either need a trait bound or to change the method signature.

A possible way of doing it is like this:

pub trait Tr {
    type It: Default;
    fn it(self) -> Self::It;
}

impl<T> Tr for T
where
    T: Debug,
{
    default type It = u8;

    default fn it(self) -> Self::It {
        Default::default()
    }
}

Playground Link

Upvotes: 2

Related Questions