【问题标题】:Why does 1 == &2 not compile?为什么 1 == &2 不能编译?
【发布时间】:2018-07-04 08:23:56
【问题描述】:

我尝试编译以下代码以了解应用于引用的比较运算符的行为:

fn main() {
    &1 == &2;              // OK
    &&1 == &&2;            // OK
    &1 == &mut 2;          // OK
    &mut(&1) == &(&mut 2); // OK
    1 == &2;               // Compilation Error
    &1 == &&2;             // Compilation Error
}

根据这个结果,对于实现PartialEq的类型T,看来

  1. Ts 的引用,Ts 的引用的引用,...具有可比性。
  2. 可以混合使用共享引用和可变引用。
  3. == 两边的引用数量必须相同。

这些规则从何而来?规则 1 和 2 可以从 the semantics of comparison operators 和 deref 强制导出。考虑&1 == &mut 2

  1. 编译器将表达式解释为PartialEq::eq(&&1, &(&mut 2))
  2. 第一个参数 &&1 通过 deref 强制转换为 &1,因为 &T implements Deref<Target = T>
  3. 第二个参数 &(&mut 2) 通过 deref 强制转换为 &2,因为 &mut T implements Deref<Target = T>
  4. 现在两个参数的类型都与PartialEq::eq 的签名匹配,该签名由i32 实现。所以PartialEq::<i32>::eq(&1, &2) 被评估了。

但是,我不明白规则 3 的来源。我认为 PartialEq::eq(&1, &&2) 被强制转换为 PartialEq::eq(&1, &2) 因为 deref coercion 独立应用于两个参数。

规则 3 的基本原理是什么?请显示 Rust 的文档语义或编译器中的相应代码?

【问题讨论】:

  • 更令人好奇的是,“手工”PartialEq 实现实际上可以处理这种情况:playground

标签: rust


【解决方案1】:

似乎在使用运算符时没有发生 deref 强制(我不确定为什么会这样),但是由于 PartialEq 的实现,仍然可以使用借用。

PartialEq 的 Rust 文档中可以看到以下实现:

impl<'a, 'b, A, B> PartialEq<&'b B> for &'a A 
where
    A: PartialEq<B> + ?Sized,
    B: ?Sized, 

这表明存在类型为B 的借用和类型为A 的借用的实现,如果存在用于类型ABPartialEq 实现。

给定这个定义,&amp;i32 == &amp;i32 可以被使用,因为i32 实现了PartialEq,并且给定上面的 impl,这表明PartialEq 是为i32s 的借用实现的。这会导致&amp;&amp;i32 == &amp;&amp;i32 工作的递归情况,因为PartialEq 是为&amp;i32 实现的,所以上面的impl PartialEq 也为&amp;&amp;i32 实现。

由于此实现的定义,两边的借用次数必须相同。

【讨论】:

  • 似乎在使用运算符时没有发生 deref 强制 - 我不清楚您是基于什么声明的。
  • 我这样做的前提是,如果发生 deref 强制,问题中的示例都将起作用。当我有机会时,我会尝试找到更确凿的证据。
猜你喜欢
  • 1970-01-01
  • 2011-06-25
  • 1970-01-01
  • 2011-10-15
  • 1970-01-01
  • 1970-01-01
  • 2010-09-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多