【发布时间】:2016-02-24 18:25:26
【问题描述】:
关于这个问题,我正在寻找在该领域有更多知识的人的反馈。我绝不是专家。所以我不妨提前问我的问题:我的推理在这里正确吗?
问题
基于 SO 上的answer to a question,我很困惑地看到在 trait 方法的实现中省略了生命周期:
impl<'a, 'b, T> PartialEq<RefEquality<'b, T>> for RefEquality<'a, T> {
fn eq(&self, other: &RefEquality<T>) -> bool {
self.0 as *const T == other.0 as *const T
}
}
这里,在方法签名中,other 类型的生命周期 'b 被省略了。这有效并且是正确的。我希望它是 &RefEquality<'b, T> 类型是正确的。毕竟,这里的'b 是必不可少的:生命周期必须不同于'a。如果不是,那就太严格了:该实现只适用于另一个与Self 具有相同生命周期的RefEquality<T>。所以这些显然是不同的语义。编译器如何推断正确的生命周期?
终身省略处理它
函数签名的生命周期可以省略,但不能在 impl 块上省略。在那里,必须完全指定类型,包括命名生命周期。
另一方面,在 eq() 方法上,我可以在 other 的类型注释中省略生命周期。事实上,编译器随后会为其插入一个与'a 明显不同的任意生命周期。这就是为什么它在保持相同语义的同时有效的原因:
impl<'a, 'b, T> PartialEq<RefEquality<'b, T>> for RefEquality<'a, T> {
fn eq<'c>(&self, other: &RefEquality<'c, T>) -> bool {
self.0 as *const T == other.0 as *const T
}
}
在这里,我为该方法引入了一个任意的生命周期'c,这与编译器在生命周期省略的情况下所做的基本相同。
在我的 trait impl 中命名一生 'b 只是说它必须与 'a 不同(我也没有以任何方式将它们联系起来)。从逻辑上讲,这是行不通的:
impl<'a, 'b, T> PartialEq<RefEquality<'b, T>> for RefEquality<'a, T> {
fn eq(&self, other: &RefEquality<'a, T>) -> bool {
self.0 as *const T == other.0 as *const T
}
}
我在 impl 中说过类型会有所不同(基于它们的生命周期),但现在实际的 eq() 实现说它们是相同的。这会导致预期的类型错误。
如果我希望生命周期相等怎么办?在这种情况下我仍然可以使用生命周期省略,还是编译器会插入任意生命周期并报告类型错误? 事实证明,推理在这里也能正常工作:
impl<'a, T> PartialEq<RefEquality<'a, T>> for RefEquality<'a, T> {
fn eq(&self, other: &RefEquality<T>) -> bool {
self.0 as *const T == other.0 as *const T
}
}
省略的生命周期将被推断为 'a,同时保持 RefEquality<T> 类型必须具有相同生命周期的期望语义。
【问题讨论】: