为什么代码示例1编译但示例2给出了编译错误?
示例1:
use std::ops::Index;
struct Bounded {
idx: usize,
}
impl<T> Index<Bounded> for [T; 4] {
type Output = T;
fn index(&self, b: Bounded) -> &T {
unsafe { self.get_unchecked(b.idx) }
}
}
示例2:
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g. `MyStruct<T>`)
--> src/main.rs:7:1
|
7 | impl<T> Index<Bounded> for [T; 4] {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
|
= note: only traits defined in the current crate can be implemented for a type parameter
import java.util.{Collections, WeakHashMap}
case class Memoized[T,R](f: T => R) extends Function1[T,R] {
val mem = Collections.synchronizedMap(new WeakHashMap[T,R])
def apply(t: T) = Option(mem.get(t)).getOrElse {
val r = f(t)
mem.put(t, r)
r
}
}
答案 0 :(得分:3)
归结为“这是一个很好的理由”,但好的理由并不是那么复杂。
这是问题所在。想象一下,我有一个图书馆箱子:
// library.rs
pub struct Dog;
pub trait Speak {
fn speak(&self);
}
使用该库箱的两个箱子。
// bark.rs
extern crate library;
impl library::Speak for library::Dog {
fn speak(&self) {
println!("woof");
}
}
// woof.rs
extern crate library;
impl library::Speak for library::Dog {
fn speak(&self) {
println!("bark");
}
}
现在,出于某种原因,我想使用这两个库:
// main.rs
extern crate library;
extern crate woof;
extern crate bark;
fn main() {
let rex = library::Dog;
rex.speak();
}
该程序应该输出什么?对于library::Speak
,library::Dog
有两个同等有效,无法区分的实现;没有正确的答案。更糟糕的是,如果我最初依赖woof
并稍后添加bark
,我的代码将停止编译,或者 - 更糟糕 - 开始透明地做错事。冲突的特质冲动是一件坏事。
添加泛型时会变得更糟。如果你有:
// barkgeneric.rs
extern crate library;
impl<T> library::Speak for T {
fn speak(&self) {
println!("woof");
}
}
// woofgeneric.rs
extern crate library;
impl<T> library::Speak for T {
fn speak(&self) {
println!("bark");
}
}
您现在有一个无限数量的冲突性特征。糟糕。
为了避免这个问题,我们有了孤儿规则。孤儿规则的想法是确保任何impl Trait for Type
都有一个,只有一个,它可以被放置。这样,我们就不用担心冲突了;如果正确设置了孤儿规则,它们应该是不可能的。
规则归结为:当你impl
类型的特征时,特征或类型必须来自当前的条件箱。这使得我所有相互矛盾的例子都行不通。 woof.rs
无法为library::speak
实施library::Dog
,因为它们都不是来自它的箱子。
同样,您不能impl<T> Index<Bounded> for [T; 4];
,因为[T; 4]
并非来自您的箱子,rustc
已确定Index<Bounded>
不算来自你的箱子。
然而,它允许您impl Index<Bounded> for [i32; 4]
通过,因为在这种情况下Index<Bounded>
确实来自您。这可能是一个错误,但它也可能只是预期的行为;孤儿规则比我在这里所说的稍微复杂一些,它们可能会以奇怪的方式进行交互。
有关更多细节,请参阅rustc --explain E0117
,rustc --explain E0210
。