为什么1 ==&2无法编译?

时间:2018-07-04 08:23:56

标签: rust

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

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
}

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

  1. T s的引用,对T s的引用的...是可比较的。
  2. 共享引用和可变引用可以混合使用。
  3. ==两侧的引用数量必须相同。

这些规则从何而来?规则1和2可以源自the semantics of comparison operators和反引用强制。考虑&1 == &mut 2

  1. 编译器将表达式解释为PartialEq::eq(&&1, &(&mut 2))
  2. 第一个自变量&&1通过反强制转换为&1,因为&T implements Deref<Target = T>
  3. 第二个参数&(&mut 2)通过反强制转换为&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),因为解引用强制被独立地应用于两个参数。

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

1 个答案:

答案 0 :(得分:1)

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

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

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

如果存在类型B和{{的A实现,则声明有PartialEq类型的借用实现和类型A的借用。 1}}。

鉴于此定义,可以使用B是因为&i32 == &i32实现了i32,并且鉴于以上暗示,这表明PartialEq是为PartialEq的借用而实现的。然后,这将导致递归的情况,即i32起作用,因为为&&i32 == &&i32实现了PartialEq,因此鉴于上述暗示,&i32也为PartialEq实现了。

由于此实现的定义,双方的借阅次数必须相同。