@KentaNakajima Да, довольно. Я немного удивлен, что это не более известная проблема, учитывая, насколько полезны принуждения. Хотя, честно говоря, я никогда особо не думал об этом; Я думаю, что это правда для большинства пользователей.

аюКаковы точные правила автоматической разыменования в Rust? от начала до конца, но у меня все еще есть вопрос о приведении массива к срезу.

Давайте подумаем о следующем коде:

let arr: &[i32; 5] = &&&[1, 2, 3, 4, 5];
// let arr: &[i32] = &&&[1, 2, 3, 4, 5]; // Error; expected slice, found reference

Я ожидаю, что&&&[1, 2, 3, 4, 5] имеет тип,&&&[i32; 5] и ссылки на&&[i32; 5] =>&[i32; 5] =>&[i32; 5] =>&[i32], но результат отличается от того, что я ожидал.

Я попытался запустить следующий код:

let arr: &&&[i32; 5] = &&&[1, 2, 3, 4, 5];
let n = arr.first().unwrap(); // 1

Это правильный код. Типarr принужден к&&&[i32; 5] =>&&[i32; 5] =>&[i32; 5] =>&[i32] и соответствует первому аргументуfirst в срез,&self.

В каком состоянии приводятся массивы к ломтикам? Я не понимаю разницу между первым и вторым кодом.

Я тоже проверилдокументация в исходном кодеи предположите, что приведенный выше вопрос имеет отношение к приведенному ниже предложению;

Однако мы иногда делаем другие корректировки и принуждения на этом пути, в частности, изменение размера (например, преобразование из [T; n] в [T]). `

 Kenta Nakajima12 нояб. 2017 г., 05:33
Это немного отличается тем, что мой вопрос кажется о транзитивных принуждениях, тогда как ссылка @Shepmaster на вопросы о самом принуждении к DST.
 Shepmaster11 нояб. 2017 г., 16:38
Есть лиstackoverflow.com/a/43346583/155423 ответь на свой вопрос?

Ответы на вопрос(1)

Решение Вопроса

Массивы не реализовыватьDerefтак что принуждение&[T; n] -> &[T] не является принудительным применением и не работает так же, как один. Вместо этого это называется «нерегулируемое принуждение», потому что оно превращает размерный тип ([T; n]) в нестандартный ([T]).

Тем не менее,ссылка на язык (который не является нормативным и может быть устаревшим, но терпите меня) перечисляет возможные принуждения, включая следующие (выделение добавлено):

T_1 вT_3 гдеT_1 принуждает кT_2 а такжеT_2 принуждает кT_3 (переходный случай)

Обратите внимание, что это еще не полностью поддерживается

&T в&U еслиT инвентарьDeref<Target = U>.

TyCtor (T) к TyCtor (U), где TyCtor (T) один из

&T&mut T*const T*mut TBox<T>

и гдеT можно получить изU понепринужденное принуждение.

Последняя пуля, нестандартное принуждение, это то, что позволяет&[T; n] принуждать к&[T], Примечательно, что это описывает только один уровень ссылок; это не покрывает&&[T; n] ->&[T] случай (для которого нам также нужноDeref принуждение).

Вернемся к вашему нерабочему примеру:

let arr: &[i32] = &&&[1, 2, 3, 4, 5];

Предполагаемое принуждение&&&[i32; 5] ->&[i32], Мы можем понять, как это принуждениедолжен работать:

&[i32; 5] принуждает к&[i32] по размеру;&&[i32; 5] принуждает к&[i32; 5] поDeref;следовательно,&&[i32; 5] принуждает к&[i32] транзитивностью&&&[i32; 5] принуждает к&&[i32; 5] поDeref;следовательно,&&&[i32; 5] принуждает к&[i32] транзитивностью

Но это не так. Приведенная выше цитата намекает на то, почему: в переходном случае говорится: «Обратите внимание, что это еще не полностью поддерживается». Насколько я могу судить, согласно№ 18602«не полностью поддерживается» - это хеджирование; было бы точнее сказать «не реализовано». Итак, на данный момент,принуждение через транзитивность вообще невозможно, Очевидно, эта проблема не является приоритетной, возможно, потому, что размерные массивы не очень распространены. (Я подозреваю, что это может стать более распространенной жалобой, когда константные дженерики приземляются, поскольку это может сделать массивы более полезными.)

Так почемуделает arr.first() работай? Ну, то«Правила авторазыменения» используется для поиска методов, вызываемых с. (точка) оператор являетсярасширение правил принуждения. Autoderef похож на разыменование вручную любое количество раз, пока вы не получите что-то (что может быть приведено к типу) с помощью данного метода. Это означает, что вам не нужна транзитивность для поиска вызовов методов через autoderef (который RFC 401 называет «принудительным приёмом»).

дальнейшее чтение

RFC № 401 описываетпредназначены семантика большинства принуждений. Этот RFC был объединен более 5 лет назад. С тех пор многое изменилось, но все еще не полностью реализовано (проблема отслеживания# 18469), поэтому RFC 401 не дает точного описания какой-либо прошлой, настоящей или будущей версии Rust. Тем не менее, RFC 401также позволит принуждение&&&[i32; 5] в&[i32] и почти по той же логике.

Rustonomicon также имеет главу о принуждении и, кажется, согласен с справочником.

 Kenta Nakajima12 нояб. 2017 г., 05:58
Понимаю. Принуждение в «правилах автоопределения» считается как один, тогда как приведения в кодеlet arr: &[i32] = &&&[1, 2, 3, 4, 5]; более одного раза. Различие между ними происходит потому, что переходные принуждения все еще не реализованы. Большое спасибо!
 trentcl12 нояб. 2017 г., 20:55
@KentaNakajima Да, довольно. Я немного удивлен, что это не более известная проблема, учитывая, насколько полезны принуждения. Хотя, честно говоря, я никогда особо не думал об этом; Я думаю, что это правда для большинства пользователей.

Ваш ответ на вопрос