自动取消引用和强制取消引用之间有什么关系?

时间:2018-11-16 16:25:49

标签: rust

经过discussion之后,我对auto-dereferencingderef coercion之间的关系有些困惑。

It seems,术语“自动取消引用”仅在要取消引用的目标是方法接收者时适用, 而it seems中的“反强制”一词适用于函数自变量及其所需的所有上下文。

我认为取消引用并不总是涉及强制取消引用,但是我不确定:取消引用是否总是使用某些Deref::deref特性实现?

如果是,T: Deref<Target = U> where T: &U的实现者是否内置在编译器中?

最后,在编译器将&&&&x隐式转换为&x的所有情况下,使用术语“ autoderef”听起来很自然:

pub fn foo(_v: &str) -> bool {
    false
}

let x="hello world";
foo(&&&&x);

这是社区的普遍共识吗?

1 个答案:

答案 0 :(得分:7)

这两种情况之间的相似之处很肤浅。

在方法调用表达式中,编译器首先需要确定要调用的方法。该决定基于接收器的类型。编译器将构建候选接收器类型的列表,其中包括通过反复取消引用接收器而获得的所有类型,但还包括遇到的所有类型&T的{​​{1}}和&mut T。这就是为什么您可以调用直接将T接收为&mut self的方法而不必编写x.foo()的原因。对于候选列表中的每种类型,编译器随后会查找固有方法以及基于可见特征的方法。有关更多详细信息,请参见language reference

反强制具有很大的不同。它仅发生在胁迫站点上,在该站点上编译器完全知道期望的类型。如果遇到的实际类型与预期类型不同,则编译器可以使用任何强制(包括deref强制)将实际类型转换为预期类型。可能的强制列表包括未定大小的强制,指针减弱和反强制。有关更多详细信息,请参见chapter on coercions in the Nomicon

因此,实际上这是两种截然不同的机制–一种用于找到正确方法的机制,一种用于在已经知道确切期望哪种类型的情况下转换类型。第一种机制还会自动引用接收者,这种情况在强制转换中永远不会发生。

  

我认为取消引用并不总是涉及强制取消引用,但是我不确定:取消引用是否总是使用某些(&mut x).foo()特性实现?

并非每个取消引用都是取消引用强制。如果您写Deref::deref,则会明确地取消引用*x。相反,deref 强制由编译器隐式执行,并且仅在编译器知道预期类型的​​地方执行。

semantics of dereferencing取决于x的类型是指针类型,即引用还是原始指针。对于指针类型,x表示对象*x指向的对象,而对于其他类型,x等效于*x(或该变量的类似物)。

  

如果是,*Deref::deref(&x)的实现者是否内置在编译器中?

我不太确定您的语法是什么意思-这肯定不是有效的Rust语法-但我想您是在问是否将T: Deref<Target = U> where T: &U的实例取消引用到&T中编译器。如上所述,对指针类型(包括引用)的取消引用已内置到编译器中,但标准库中也有一个blanket implementation of Deref for &T。这种通用的实现对通用代码很有用-特质绑定T,否则将不允许T: Deref<Target = U>