Параллели между этими двумя случаями довольно поверхностны.
В выражении вызова метода сначала компилятору необходимо определить, какой метод вызывать. Это решение основано на типе получателя. Компилятор создает список возможных типов приемников, который включает все типы, полученные путем многократного разыменования приемника, а также &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
.