如何从默认方法返回specializable关联类型?

时间:2017-11-24 00:51:51

标签: rust specialization

对于Rust,我是implementing tuple flattening。它需要转换

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

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

我尝试使用专门化,但编译器并不喜欢它:

/// 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,
        }
    }
}

我该怎么做?任何不使用unsafe的替代方案都可以。

完整示例:

#![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

编译器输出:

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}`

1 个答案:

答案 0 :(得分:1)

这里的问题是你要返回Self::It但是给它一个0.如果有人要It String来实现这一点会怎样?由于无法证明这总是一个数字,您需要一个特征限制或更改方法签名。

这样做的可行方法是这样的:

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