为什么我需要 "cover" T in `impl ForeignTrait<LocalType> for T` [E0210]
Why am I required to "cover" T in `impl ForeignTrait<LocalType> for T` [E0210]
今天我 运行 遇到了一个漂亮的 st运行ge 错误消息,我很难理解它。考虑这个简单的 map-entry-like 结构:
struct Entry<K, V> {
key: K,
value: V
}
现在,我想在 Entry<K, V>
和仅 K
之间实现所有 std::cmp
特征。现在让我们关注 PartialEq
。这两个实现工作得很好:
impl<K: PartialEq, V> PartialEq for Entry<K, V> { /* ... */ }
impl<K: PartialEq, V> PartialEq<K> for Entry<K, V> { /* ... */ }
但是最后一个让我很难受(Playground)
impl<K: PartialEq, V> PartialEq<Entry<K, V>> for K {
fn eq(&self, other: &Entry<K, V>) -> bool {
self.eq(&other.key)
}
}
据我所知,错误消息声称我将使用非本地类型作为外部特征的第一个参数。但是,Entry
是在同一文件中本地定义的。
error[E0210]: type parameter K
must be covered by another type when it appears before the first local type (Entry<K, V>
)
--> src/lib.rs:6:6
|
6 | impl<K: PartialEq, V> PartialEq<Entry<K, V>> for K {
| ^ type parameter `K` must be covered by another type when it appears before the first local type (`Entry<K, V>`)
|
note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local, and no uncovered type parameters appear before that first local type
note: in this case, 'before' refers to the following order: impl<..> ForeignTrait<T1, ..., Tn> for T0
, where T0
is the first and Tn
is the last
有人可以解释为什么我会收到此错误消息,错误尤其是 uncovered 的含义以及为什么不允许此实现吗?
我想你想反过来:
impl<K: PartialEq, V> PartialEq<K> for Entry<K, V> {
fn eq(&self, other: &K) -> bool {
self.key.eq(&other)
}
}
至于为什么你的方向不起作用:假设有人定义了一个 struct
可以与 anything:
进行比较
struct K;
impl<V> PartialEq<V> for K { // V could be anything (including your struct Entry)
fn eq(&self, other: &V) -> bool {
true
}
}
现在,K
和您的 Entry
会有冲突的 impl
。
错误信息非常糟糕,但仔细阅读 E0210 的完整描述至少给出了对发生的事情的解释:
Consider an impl:
impl<P1, ..., Pm> ForeignTrait<T1, ..., Tn> for T0 { ... }
where P1, ..., Pm
are the type parameters of the impl
and T0, ..., Tn
are types. One of the types T0, ..., Tn
must be a local type (this is another orphan rule, see the explanation for E0117).
Both of the following must be true:
- At least one of the types
T0..=Tn
must be a local type. Let Ti
be the first such type.
- No uncovered type parameters
P1..=Pm
may appear in T0..Ti
(excluding Ti
).
现在,回顾一下有问题的实现,它被声明为
impl<K: PartialEq, V> PartialEq<Entry<K, V>> for K // error
So 给出了 P1=K, P2=V
和 T0=K, T1=Entry<K, V>
的映射,Ti
是 T1
因此触发了错误消息。 覆盖就像把它放入一个单元素元组一样简单,所以这个语法完全没问题:
impl<K: PartialEq, V> PartialEq<Entry<K, V>> for (K,) // ok
通常,覆盖一个类型可以通过将其放入元组((K,)
)或将其用作类型参数(SomeType<K>
)来完成, 但 不 使用参考 (&K
) 或框 (Box<K>
).
然后仅在实施 RFC 2451 中给出对此的可理解且合理的解释,建议将此作为错误消息的一部分:
Rust's orphan rule always permits an impl if either the trait or the type being implemented are local to the current crate. Therefore, we can't allow impl<T> ForeignTrait<LocalTypeCrateA> for T
, because it might conflict with another crate writing impl<T> ForeignTrait<T> for LocalTypeCrateB
, which we will always permit.
我希望 rustc 会采用该错误消息,而不是吐出它目前所做的神秘消息。
今天我 运行 遇到了一个漂亮的 st运行ge 错误消息,我很难理解它。考虑这个简单的 map-entry-like 结构:
struct Entry<K, V> {
key: K,
value: V
}
现在,我想在 Entry<K, V>
和仅 K
之间实现所有 std::cmp
特征。现在让我们关注 PartialEq
。这两个实现工作得很好:
impl<K: PartialEq, V> PartialEq for Entry<K, V> { /* ... */ }
impl<K: PartialEq, V> PartialEq<K> for Entry<K, V> { /* ... */ }
但是最后一个让我很难受(Playground)
impl<K: PartialEq, V> PartialEq<Entry<K, V>> for K {
fn eq(&self, other: &Entry<K, V>) -> bool {
self.eq(&other.key)
}
}
据我所知,错误消息声称我将使用非本地类型作为外部特征的第一个参数。但是,Entry
是在同一文件中本地定义的。
error[E0210]: type parameter
K
must be covered by another type when it appears before the first local type (Entry<K, V>
)--> src/lib.rs:6:6 | 6 | impl<K: PartialEq, V> PartialEq<Entry<K, V>> for K { | ^ type parameter `K` must be covered by another type when it appears before the first local type (`Entry<K, V>`) |
note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local, and no uncovered type parameters appear before that first local type
note: in this case, 'before' refers to the following order:impl<..> ForeignTrait<T1, ..., Tn> for T0
, whereT0
is the first andTn
is the last
有人可以解释为什么我会收到此错误消息,错误尤其是 uncovered 的含义以及为什么不允许此实现吗?
我想你想反过来:
impl<K: PartialEq, V> PartialEq<K> for Entry<K, V> {
fn eq(&self, other: &K) -> bool {
self.key.eq(&other)
}
}
至于为什么你的方向不起作用:假设有人定义了一个 struct
可以与 anything:
struct K;
impl<V> PartialEq<V> for K { // V could be anything (including your struct Entry)
fn eq(&self, other: &V) -> bool {
true
}
}
现在,K
和您的 Entry
会有冲突的 impl
。
错误信息非常糟糕,但仔细阅读 E0210 的完整描述至少给出了对发生的事情的解释:
Consider an impl:
impl<P1, ..., Pm> ForeignTrait<T1, ..., Tn> for T0 { ... }
where
P1, ..., Pm
are the type parameters of theimpl
andT0, ..., Tn
are types. One of the typesT0, ..., Tn
must be a local type (this is another orphan rule, see the explanation for E0117).Both of the following must be true:
- At least one of the types
T0..=Tn
must be a local type. LetTi
be the first such type.- No uncovered type parameters
P1..=Pm
may appear inT0..Ti
(excludingTi
).
现在,回顾一下有问题的实现,它被声明为
impl<K: PartialEq, V> PartialEq<Entry<K, V>> for K // error
So 给出了 P1=K, P2=V
和 T0=K, T1=Entry<K, V>
的映射,Ti
是 T1
因此触发了错误消息。 覆盖就像把它放入一个单元素元组一样简单,所以这个语法完全没问题:
impl<K: PartialEq, V> PartialEq<Entry<K, V>> for (K,) // ok
通常,覆盖一个类型可以通过将其放入元组((K,)
)或将其用作类型参数(SomeType<K>
)来完成, 但 不 使用参考 (&K
) 或框 (Box<K>
).
然后仅在实施 RFC 2451 中给出对此的可理解且合理的解释,建议将此作为错误消息的一部分:
Rust's orphan rule always permits an impl if either the trait or the type being implemented are local to the current crate. Therefore, we can't allow
impl<T> ForeignTrait<LocalTypeCrateA> for T
, because it might conflict with another crate writingimpl<T> ForeignTrait<T> for LocalTypeCrateB
, which we will always permit.
我希望 rustc 会采用该错误消息,而不是吐出它目前所做的神秘消息。