为什么 Borrow 和 AsRef 的实现方式不同?

Rem*_*i D 17 rust

BorrowRust 中的和特征AsRef非常相似。如果我理解正确的话,它们在同一类型上实现时具有完全相同的签名(方法名称除外),区别在于它们的使用方式。

但是,当您查看它们的实现时,例如,Vec<T>就会发现细微的差别:

切片.rs

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Borrow<[T]> for Vec<T> {
    fn borrow(&self) -> &[T] {
        &self[..]
    }
}
Run Code Online (Sandbox Code Playgroud)

向量.rs

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> AsRef<[T]> for Vec<T> {
    fn as_ref(&self) -> &[T] {
        self
    }
}
Run Code Online (Sandbox Code Playgroud)

我相信这里的实施AsRef得益于Deref强制。但不能使用相同的机制来Borrow实现吗?

kmd*_*eko 8

两种实现之间没有实际差异。

您对语义差异的评估是正确的:主体&self[..]使用具有开放范围的索引运算符来创建整个向量的切片,而基本self主体依赖于编译器自动Deref转换&Vec<T>&[T].

没有功能上的区别。正如您所注意到的,方法签名是相同的,因此与实现之外的借用检查器相同。上面的评论表明借用向量和借用该向量的切片之间存在内部差异,但事实并非如此;在这两个切片的生命周期中都源自self. 两种方法生成的程序集也是相同的;尽管他们使用不同的方法来获得相同的结果,并且优化有时很混乱,但如果在任何情况下存在任何代码生成差异,我都会感到惊讶。

所以唯一的区别就是风格。这两种实现在 Rust 1.0 发布之前就已经存在了。正如上面的评论所提到的,该Borrow实现较旧,虽然该Deref特征在撰写本文时确实存在Vec,但它只是在s 上(一个月前)新实现的,直到几个月后才最终确定。Borrow因此,最初的实现使用 pre-deref 语法也就不足为奇了。该AsRef实现直到最终确定之后才存在Deref,因此作者使用它并不奇怪。

因此,您看到的差异是无关紧要的,只是历史性的。