直接回答:孤儿规则(trait coherence 的一部分)规定:为一个类型实现 trait 时,trait 和类型至少有一个必须是当前 crate 定义的,因此不能给 Vec<T>(外部类型)实现 Display(外部 trait)。目的是保证每个 trait+类型组合在全程序中至多一个实现,让编译器能做全局一致性检查,避免不同下游 crate 产生冲突实现。
展开解析:想给外部类型“加”外部 trait,标准解法是 newtype 包装:定义本地 tuple struct 包一层,为它实现目标 trait,再可选实现 Deref/From 降低包装成本;serde 的 #[serde(remote)] 是同一思路。blanket impl 同样受约束:impl<T: Display> MyTrait for T 允许(MyTrait 是本地的),反向则不允许。两个细节:Box、&T 是 fundamental 类型,Box<LocalType> 视作本地类型;把 impl 贡献给上游 crate 也是常见做法。
struct Pretty(Vec<i32>); // 本地 newtype
impl std::fmt::Display for Pretty {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self.0)
}
}
追问方向:为什么 fundamental 类型要特殊对待?取消孤儿规则会引发什么问题?newtype 包装如何减少样板代码? (约 590 字)