混淆特征边界而不指定具体的关联类型 [英] Aliasing trait bounds without specifying concrete associated types

查看:199
本文介绍了混淆特征边界而不指定具体的关联类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  pub fn foo< T>>我发现自己在同一界限下写了不同的函数, (mut self,path:T) - > Self其中
T:IntoIterator,
T :: Item:AsRef< str> ;,
{
// ...
}

pub fn bar< T>(mut self,path:T) - > Self其中
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其中
T:IntoIterator< Item = U> ;,
U:AsRef< str>,
{
type I = T;
type S = U;
}

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

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

但是当我尝试使用它时:

< T>(& [one,two]);<
}

我收到以下错误:

  src / lib.rs:104:19:104:34错误:不匹配的类型:
预计`< T as Path> :: I`,
找到了& [& str; 2]`
(期望的关联类型,
找到& -ptr)[b]
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

解决方案


如何前进?

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

  fn消耗< T:Path>(){
into_vec ::< T> ;(& [one,two]);





这表示对于任何类型的 Path ,用一段字符串调用 into_vec 。但是,您无法保证无论 T 是什么,它都会接受一段字符串。



从另一方面来看,很多类型可能接受一段字符串,所以它会使 T 含糊不清。



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



你可以通过明确指出哪些 T
$ p $ fn consume(){
into_vec ::<& [&'静态str]>(& [one,two]);
}

为了澄清,这与将特征组合到另一个特征中无关。这将是任何特质的问题。


I found myself writing different functions with an argument under the same bounds, like this:

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

Feeling this to be a bit of a chore, I tried to alias these bounds. But I didn’t find a way to. The closest I got, after checking a couple places[1],[2], is this:

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

Now, as an example, this compiles fine:

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

But when I try to use it:

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

I get the following error:

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"]);
                                 ^~~~~~~~~~~~~~~

So, no luck. How can I go forward?


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

解决方案

How can I go forward?

You can't directly. Let's look at your function:

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

This says "for any type that implements Path, call into_vec with a slice of strings". However, there's no way that you can guarantee that whatever the T is, it will accept a slice of strings.

Looking in another direction, many types might accept a slice of strings, so it would make T ambiguous.

Looking in a third direction, there's no way for type inference to decide what T should be, as it's not used as an argument or return value.

You can get it to work by explicitly stating which T you want:

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

To clarify, this has nothing to do with combining traits into another trait. This would be a problem with any trait.

这篇关于混淆特征边界而不指定具体的关联类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆