#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
impl<T: ?Sized> const Deref for &T {
type Target = T;
#[rustc_diagnostic_item = "noop_method_deref"]
fn deref(&self) -> &T {
*self
}
}
没有Deref trait,编译器只能解引用 & 引用。deref方法使编译器能够获取任何实现Deref trait的类型的值,并调用deref方法以获取它知道如何解引用的 & 引用。
如果编译器知道如何解引用,为什么我们需要对 &T 类型进行 Deref trait 的全局实现呢?
Rust 的自动解引用规则是什么? 这个问题并没有回答我的问题,因为我的问题是这个全局实现的用途是什么。
为什么Deref::deref的返回类型本身是一个引用?这个问题也没有解决我的疑惑。在第一个答案中,作者没有解释为什么存在对&T类型的Deref trait的泛化实现。
我添加了第一个答案的作者的代码,并进行了自己的修改
Rust playground https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=25387e87ea7a7ef349df9e9b6671f6e7
我添加了一些注释,以确保我真正理解它
use std::ops::Deref;
use std::rc::Rc;
fn foo<T: Deref<Target = i32>>(t: T) {
println!("{}", *t);
print_type_of(&t);
print_type_of(&(*t));
println!("-----------------");
}
fn main() {
// Ok, because &i32 implements Deref<Target = i32>, so deref() return &i32 and the compiler can deref it again to get i32
// Thanks to the blanket implementation
foo(&100i32);
// No, because &&i32.deref() return &&i32, so the compiler can't deref it twice to get i32
foo(&&100i32);
// Ok, because Box<i32> implements Deref<Target = i32>, so deref() return &i32 and the compiler can deref it again to get i32
// But this has nothing to do with the blanket implementation of Deref for &T
// Because Box is not a reference type
foo(Box::new(42i32));
// Ok, because Rc<i32> implements Deref<Target = i32>, so deref() return &i32 and the compiler can deref it again to get i32
foo(Rc::new(5i32));
}
fn print_type_of<T>(_: &T) {
println!("{}", std::any::type_name::<T>())
}
我不确定我理解你的回答
rustc_diagnostic_item
是用于Clippy分析的注解。但是我找不到任何依赖它的Clippy规则。也许它们都被更具体的提示所替换(这个deref是不必要的,这个cast是不必要的...),现在这个无操作的注释本身就是一个无操作的注释;-)。 - rodrigo&T
或Box<T>
这样的内置类型的解引用,编译器知道如何在内部执行。出于凝聚力的原因,标准库定义了这些实现,以便特质解析按预期工作,但它们的主体实际上从未被执行。情况与1+1
类似,其中有一个std::ops::Add的实现,适用于所有以1+1
为基础定义的数字类型。 - user2722968