此代码无法编译:
pub trait ToVec<T> {
fn to_vec(self) -> Vec<T>;
}
impl<I, T> ToVec<T> for I
where
I: Iterator<Item = T>,
{
fn to_vec(self) -> Vec<T> {
self.collect()
}
}
impl<'a, I, T> ToVec<T> for I
where
I: Iterator<Item = &'a T>,
T: Clone,
{
fn to_vec(self) -> Vec<T> {
self.cloned().collect()
}
}
错误:
error[E0119]: conflicting implementations of trait `ToVec<_>`:
--> src/lib.rs:14:1
|
5 | / impl<I, T> ToVec<T> for I
6 | | where
7 | | I: Iterator<Item = T>,
8 | | {
... |
11 | | }
12 | | }
| |_- first implementation here
13 |
14 | / impl<'a, I, T> ToVec<T> for I
15 | | where
16 | | I: Iterator<Item = &'a T>,
17 | | T: Clone,
... |
21 | | }
22 | | }
| |_^ conflicting implementation
据我了解,当给定类型
I
实现Iterator
时,I::Item
只能有一种特定类型,因此它不能满足两种实现。
这是编译器的限制还是我的推理不正确?如果是这样,请提供一个满足这两个实现的示例。
我相信这是问题#20400,无法编写涉及关联类型绑定的非重叠毯子实现。总而言之,
impl
实际上是不重叠的,但教导编译器认识到这会引入一种负面推理形式,这与特征求解器当前的工作方式有很大不同。 RFC 是为了解决该问题而编写的,但由于两种类型重叠的含义含糊不清而被推迟。
看来这个问题最终可能会被重新审视并解决,但这可能需要一些时间。
同时,您可以编写一个基于向
Trait
添加类型参数的解决方法,就像我对 Can I避免使用泛型对特征实现进行急切的歧义解析吗?(尽管在您的情况下,因为您的 impl
实际上永远不会重叠,你永远不必使用涡轮鱼来选择impl
;编译器应该总是弄清楚它。)
由泛型类型参数
T
表示的类型集 是由泛型类型参数 &T
表示的类型集的超集。它们并不是脱节的。
&T
中的所有内容也都在 T
中,因此会出现冲突的实现消息。
最小示例:
trait Trait {}
impl<T> Trait for T {}
impl<T> Trait for &T {} // compile error
投掷:
error[E0119]: conflicting implementations of trait `Trait` for type `&_`:
--> src/lib.rs:5:1
|
3 | impl<T> Trait for T {}
| ------------------- first implementation here
4 |
5 | impl<T> Trait for &T {} // compile error
| ^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_`
粗略地说,具有
Item = &X
的迭代器将满足以下两个要求:
T == &X
=> 可能会导致 Vec<&X>
T == X
=> 可能会导致 Vec<X>
也许专业化(每晚)可以有所帮助,但我不确定。
以下是如何在 disjoint_impls 宏的帮助下完成此操作:
use disjoint_impls::disjoint_impls;
disjoint_impls! {
pub trait ToVec<T> {
fn to_vec(self) -> Vec<T>;
}
impl<I, T> ToVec<T> for I
where
I: Iterator<Item = T>,
{
fn to_vec(self) -> Vec<T> {
self.collect()
}
}
impl<'a, I, T> ToVec<T> for I
where
I: Iterator<Item = &'a T>,
T: Clone + 'a,
{
fn to_vec(self) -> Vec<T> {
self.cloned().collect()
}
}
}
fn main() {
let a: Vec<u32> = vec![12, 14, 42];
let b: Vec<&u32> = vec![&12, &14, &42];
println!("{:?}", ToVec::<u32>::to_vec(a.iter()));
println!("{:?}", ToVec::<&u32>::to_vec(b.iter()));
}