Почему эти два примера не компилируются одинаково? Изменчивы
семантика ссылочного перемещения (т. е. {vref}
из E1), применяемая для
методы (т. е. split_at_mut
), но не функции (т. е. example2_inner
)?
Почему это так?
На самом деле речь идет не о методах против функций, а о синтаксисе вызова метода против синтаксиса вызова функции.
Каждый вызов метода может быть переведен в UFCS (универсальный синтаксис вызова функции), который обычно имеет такую форму:
<Type as Trait>::method(args);
Если мы предпримем наивную попытку перевести вызов { v_ref }.split_at_mut(len / 2)
в UFCS в версии 1, мы получим ту же ошибку, что и в версии 2:
<[_]>::split_at_mut({v_ref}, len / 2)
Причина в том, что вышесказанное эквивалентно чему-то, что опять же не приводит к перемещению v_ref
в блок:
<[_]>::split_at_mut({&mut *v_ref}, len / 2)
Синтаксис метода в действительности разрешает следующий рабочий вариант:
<[_]>::split_at_mut(&mut *{v_ref}, len / 2)
Для этого варианта компилятор делает вывод, что v_ref
действительно должен быть перемещен в блок, потому что компилятор понимает, что повторное заимствование, необходимое для вызова метода, уже должно произойти на {v_ref}
, поэтому он не ' t добавить лишнее повторное заимствование на v_ref
.
Теперь, когда мы знаем, как синтаксис метода решает вашу проблему неявно, у нас есть альтернативное решение для вашей проблемы в версии 2:
example2_inner(&mut *{ v_ref });