别名特征限制而不指定具体的关联类型

时间:2016-02-10 22:48:07

标签: generics rust associated-types

我发现自己用相同的边界下的参数编写不同的函数,如下所示:

pub fn foo<T>(mut self, path: T) -> Self where
    T: IntoIterator,
    T::Item: AsRef<str>,
{
    // ...
}

pub fn bar<T>(mut self, path: T) -> Self where
    T: IntoIterator,
    T::Item: AsRef<str>,
{
    // ...
}

感觉这是一件苦差事,我试着别名这些界限。但我找不到办法。在检查了几个地方 [1],[2] 之后,我得到的最接近的是:

trait Path {
    type I: IntoIterator<Item = Self::S>;
    type S: AsRef<str>;
}

impl<T, U> Path for T where
    T: IntoIterator<Item = U>,
    U: AsRef<str>,
{
    type I = T;
    type S = U;
}

现在,作为一个例子,这编译很好:

fn into_vec<T: Path>(it: T::I) -> Vec<String> {
    it.into_iter()
        .map::<String, _>(|x| x.as_ref().into())
        .collect()
}

但是当我尝试使用它时:

fn consume<T: Path>() {
    into_vec::<T>(&["one", "two"]);
}

我收到以下错误:

src/lib.rs:104:19: 104:34 error: mismatched types:
 expected `<T as Path>::I`,
    found `&[&str; 2]`
(expected associated type,
    found &-ptr) [E0308]
src/lib.rs:104     into_vec::<T>(&["one", "two"]);
                                 ^~~~~~~~~~~~~~~

所以,没有运气。我怎么能前进?

1 https://github.com/rust-lang/rust/issues/8634
2 https://stackoverflow.com/a/30424219/3957040

1 个答案:

答案 0 :(得分:2)

  

我怎样才能前进?

你不能直接。让我们来看看你的功能:

fn consume<T: Path>() {
    into_vec::<T>(&["one", "two"]);
}

这表示“对于实现Path任何类型,请使用一段字符串调用into_vec”。但是,你无法保证无论T是什么,它都会接受一片字符串。

从另一个方向看,许多类型可能会接受一段字符串,因此会使T不明确。

从第三个方向看,类型推断无法确定T应该是什么,因为它不用作参数或返回值。

您可以通过明确说明您想要的T来使其发挥作用:

fn consume() {
    into_vec::<&[&'static str]>(&["one", "two"]);
}

澄清一下,这与将特质结合到另一个特征无关。这可能是任何特质的问题。