Какова связь между автоматическим разыменованием и разыменным принуждением? - PullRequest
0 голосов
/ 16 ноября 2018

После некоторого обсуждения , я теперь немного запутался по поводу связи между auto-dereferencing и deref coercion.

Кажется, что термин«Автоматическая разыменование» применяется только тогда, когда целью разыменования является приемник метода, тогда как кажется , что термин «приведение разыменования» применяется к аргументам функции и всем контекстам, в которых он нуждается.

Я думал, что разыменование не всегда подразумевает принудительное разыменование, но я не уверен: всегда ли разыменование использует некоторую реализацию Deref::deref trait?

Если да, встроен ли в компилятор разработчик T: Deref<Target = U> where T: &U?

Наконец, вполне естественно использовать термин «autoderef» во всех случаях, когда компилятор неявно преобразует &&&&x в &x:

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

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

Является ли это общим консенсусомобщество?

1 Ответ

0 голосов
/ 16 ноября 2018

Параллели между этими двумя случаями довольно поверхностны.

В выражении вызова метода сначала компилятору необходимо определить, какой метод вызывать. Это решение основано на типе получателя. Компилятор создает список возможных типов приемников, который включает все типы, полученные путем многократного разыменования приемника, а также &T и &mut T для всех встреченных типов T. По этой причине вы можете вызывать метод, получающий &mut self напрямую как x.foo() вместо необходимости писать (&mut x).foo(). Для каждого типа в списке кандидатов компилятор затем ищет присущие методы и методы на видимых чертах. Подробнее см. Справочник по языку .

Разбирательство довольно разное. Это происходит только на сайте приведения , где компилятор точно знает, какого типа ожидать. Если фактический встреченный тип отличается от ожидаемого типа, компилятор может использовать любое приведение, включая приведение к разыменованию, для преобразования действительного типа в ожидаемый тип. Список возможных приведениях включает в себя несимметричные приведения, ослабление указателя и приведения к разыменованию. Подробнее см. Главу о принуждениях в Nomicon .

Так что на самом деле это два совершенно разных механизма - один для нахождения правильного метода, а другой для преобразования типов, когда уже известно, какой тип ожидать. Первый механизм также автоматически ссылается на получателя, что никогда не может произойти при принуждении.

Я думал, что разыменование не всегда подразумевает принудительное разыменование, но я не уверен: всегда ли разыменование использует некоторую реализацию Deref::deref черты?

Не всякая разыменование является принуждением разыменования. Если вы пишете *x, вы явно разыменование x. Напротив, приведение приведение выполняется неявным образом компилятором и только в тех местах, где компилятор знает ожидаемый тип.

Семантика разыменования зависит от того, является ли тип x типом указателя , то есть указателем или необработанным указателем, или нет. Для типов указателей *x обозначает объект, на который указывает x, в то время как для других типов *x эквивалентно *Deref::deref(&x) (или изменчивому анлогу этого).

Если это так, встроен ли в компилятор разработчик T: Deref<Target = U> where T: &U?

Я не совсем уверен, что должен означать ваш синтаксис - это, безусловно, недопустимый синтаксис Rust - но я предполагаю, что вы спрашиваете, встроено ли в компилятор разыменование экземпляра от &T до T. Как упоминалось выше, разыменование типов указателей, включая ссылки, встроено в компилятор, но в стандартной библиотеке также имеется общая реализация для Deref для &T. Эта общая реализация полезна для универсального кода - ограничение черты T: Deref<Target = U> в противном случае не позволило бы T = &U.

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