为什么 Iterator<Item = T> 和 Iterator<Item = &T> 的实现有冲突?
Why are implementations of Iterator<Item = T> and Iterator<Item = &T> conflicting?
此代码无法编译:
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
只能有一个特定类型,因此它不能满足两种实现。
这是编译器的限制还是我的推理不正确?如果是这样,请提供一个满足这两个impls的例子。
粗略地说,具有 Item = &X
的迭代器将同时满足:
- 第一个
T == &X
=> 可能会导致 Vec<&X>
- 第二个
T == X
=> 可能导致 Vec<X>
也许专业化(每晚)会有帮助,但我不确定。
泛型类型参数 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 `&_`
我认为这是问题 #20400,Can't write non-overlapping blanket impls that involve associated type bindings. To summarize, the impl
s are in fact non-overlapping, but teaching the compiler to recognize that would introduce a form of negative reasoning, which is a major departure from how the trait solver currently works. An RFC 是为了解决这个问题而编写的,但由于对两种类型重叠的含义不明确而被推迟。
看来这个问题最终可能会被重新审视并解决,但这可能需要一些时间。
与此同时,您可以编写一个基于向 Trait
添加类型参数的解决方法,就像我对 Can I avoid eager ambiguity resolution for trait implementations with generics? 的回答一样(尽管在您的情况下,因为您的 impl
s 实际上从来没有重叠,你永远不必使用涡轮鱼来选择一个 impl
;编译器应该总是弄清楚它。)
此代码无法编译:
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
只能有一个特定类型,因此它不能满足两种实现。
这是编译器的限制还是我的推理不正确?如果是这样,请提供一个满足这两个impls的例子。
粗略地说,具有 Item = &X
的迭代器将同时满足:
- 第一个
T == &X
=> 可能会导致Vec<&X>
- 第二个
T == X
=> 可能导致Vec<X>
也许专业化(每晚)会有帮助,但我不确定。
泛型类型参数 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 `&_`
我认为这是问题 #20400,Can't write non-overlapping blanket impls that involve associated type bindings. To summarize, the impl
s are in fact non-overlapping, but teaching the compiler to recognize that would introduce a form of negative reasoning, which is a major departure from how the trait solver currently works. An RFC 是为了解决这个问题而编写的,但由于对两种类型重叠的含义不明确而被推迟。
看来这个问题最终可能会被重新审视并解决,但这可能需要一些时间。
与此同时,您可以编写一个基于向 Trait
添加类型参数的解决方法,就像我对 Can I avoid eager ambiguity resolution for trait implementations with generics? 的回答一样(尽管在您的情况下,因为您的 impl
s 实际上从来没有重叠,你永远不必使用涡轮鱼来选择一个 impl
;编译器应该总是弄清楚它。)