Почему 1 == & 2 не компилируется? - PullRequest
0 голосов
/ 04 июля 2018

Я попытался скомпилировать следующий код, чтобы понять поведение операторов сравнения, применяемых к ссылкам:

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 с, ссылки ссылок T с, ... сопоставимы.
  2. Совместно используемые и изменяемые ссылки могут быть смешаны.
  3. Количество ссылок для обеих сторон == должно быть одинаковым.

Откуда берутся эти правила? Правило 1 и 2 могут быть выведены из семантики операторов сравнения и метода разыменования. Рассмотрим &1 == &mut 2:

  1. Выражение интерпретируется компилятором как PartialEq::eq(&&1, &(&mut 2)).
  2. Первый аргумент &&1 превращается в &1 путем принудительного применения, потому что &T реализует Deref<Target = T>.
  3. Второй аргумент &(&mut 2) превращается в &2 путем принудительного разглашения, поскольку &mut T реализует 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 голосов
/ 04 июля 2018

Похоже, что при использовании операторов (deref принуждение) не происходит (я не уверен, почему это так), однако заимствования могут все еще использоваться из-за реализации PartialEq.

Из документации по Rust PartialEq можно увидеть следующую реализацию:

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

Это означает, что существует реализация для заимствования типа B и заимствования для типа A, если существует реализация PartialEq для типа A и B.

С учетом этого определения можно использовать &i32 == &i32, поскольку i32 реализует PartialEq, а с учетом вышеизложенного подразумевается, что PartialEq реализовано для заимствований i32 с. Затем это приводит к рекурсивному случаю, когда &&i32 == &&i32 работает, потому что PartialEq реализован для &i32, поэтому, учитывая вышеизложенное, impl PartialEq также реализуется для &&i32.

Из-за определения этой реализации количество заимствований с обеих сторон должно быть одинаковым.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...