自动解除引用和解除引用强制之间有啥关系?
Posted
技术标签:
【中文标题】自动解除引用和解除引用强制之间有啥关系?【英文标题】:What is the relation between auto-dereferencing and deref coercion?自动解除引用和解除引用强制之间有什么关系? 【发布时间】:2019-04-19 21:01:25 【问题描述】:在discussion 之后,我现在对auto-dereferencing
和deref coercion
之间的关系有点困惑。
It seems 仅当要取消引用的目标是方法接收器时,术语“自动取消引用”才适用, 而it seems 术语“deref coercion”适用于函数参数及其需要的所有上下文。
我认为取消引用并不总是涉及强制取消引用,但我不确定:取消引用是否总是使用一些 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】:这两种情况之间的相似之处是相当肤浅的。
在方法调用表达式中,编译器首先需要确定调用哪个方法。该决定基于接收器的类型。编译器构建一个候选接收器类型列表,其中包括通过重复取消引用接收器获得的所有类型,还包括&T
和&mut T
遇到的所有类型T
。这就是为什么您可以将接收&mut self
的方法直接调用为x.foo()
而不必编写(&mut x).foo()
的原因。对于候选列表中的每种类型,编译器然后查找固有方法和可见特征上的方法。有关详细信息,请参阅language reference。
deref 强制是相当不同的。它只发生在编译器确切知道期望什么类型的强制站点。如果遇到的实际类型与预期类型不同,编译器可以使用任何强制(包括 deref 强制)将实际类型转换为预期类型。可能的强制列表包括未调整大小的强制、指针弱化和 deref 强制。详情请参阅chapter on coercions in the Nomicon。
所以这实际上是两种完全不同的机制——一种用于寻找正确的方法,另一种用于在已知确切期望的类型时转换类型。第一种机制还自动引用接收者,这在强制中永远不会发生。
我认为取消引用并不总是涉及强制取消引用,但我不确定:取消引用是否总是使用一些
Deref::deref
特征实现?
并非每次解除引用都是解除引用强制。如果你写*x
,你明确取消引用x
。相反,deref coercion 由编译器隐式执行,并且仅在编译器知道预期类型的地方执行。
semantics of dereferencing 取决于x
的类型是指针类型,即引用还是原始指针。对于指针类型,*x
表示 x
指向的对象,而对于其他类型,*x
等效于 *Deref::deref(&x)
(或 this 的可变类似物)。
如果是,
T: Deref<Target = U> where T: &U
的实现者是否内置在编译器中?
我不太确定你的语法应该是什么意思——它肯定不是有效的 Rust 语法——但我猜你问的是编译器中是否内置了将 &T
的实例取消引用到 T
的问题。如上所述,指针类型的解引用,包括引用,是编译器内置的,但标准库中也有一个blanket implementation of Deref
for &T
。这种一揽子实现对于通用代码很有用 - 特征绑定 T: Deref<Target = U>
否则将不允许 T = &U
。
【讨论】:
我认为重点在最后一句话。改写我的问题:编译器已知的解引用语义可以称为自动解引用?在强制站点,还有更多deref coercion
机制,因为正如您所指出的,延迟毯 impl fn deref(&self) -> &T *self
是幂等的,它不能解释 &&&&x -> &x。
@attdona 我跟不上。自动取消引用意味着隐式而不是显式取消引用。它与取消引用的语义无关。在这种情况下,我也无法理解“幂等”这个词。只有当范围是域的子集时,函数才能是幂等的,但这里不是这种情况 - 函数将 &&T
类型的值映射到 &T
类型的值。
我不恰当地使用术语幂等来表示 deref 覆盖实现将 &T 转换为 &T。显然,如果我们将deref()
应用于&&T
或&&&T
,我们得到了&T
,但在这种情况下,我看到的主要参与者是自动解除引用。在&&&x.deref()
接收器的自动取消引用之后,deref()
从&T
返回一个&T
:一种无操作操作(我假设deref
它被调用是因为文档声明deref
总是被调用,但对我来说,在这种情况下它似乎没用)。哪个术语最能描述正在发生的事情:auto-deref 或 deref coercion?
@attdona 对不起,我还是听不懂。一揽子 deref 实现的原型本质上是deref(&&T) -> &T
,而您似乎认为它是deref(&T) -> &T
。不过,我可能误读了您的评论。
非常感谢您的耐心等待!我错误地认为毯子 impl 为 deref(&T) -> &T
,这让我写了无意义的 cmets。以上是关于自动解除引用和解除引用强制之间有啥关系?的主要内容,如果未能解决你的问题,请参考以下文章