Чем не является ограничение псевдонима
На самом деле обычно несколько существующих &mut T
псевдонимов одного и того же элемента.
Самый простой пример:
fn main() {
let mut i = 32;
let j = &mut i;
let k = &mut *j;
*k = 3;
println!("{}", i);
}
Обратите внимание, что из-за правил заимствования вы не можете получить доступ к другим псевдонимам одновременно.
Если вы посмотрите на реализацию ManuallyDrop::take
:
pub unsafe fn take(slot: &mut ManuallyDrop<T>) -> T {
ptr::read(&slot.value)
}
Вы заметите, что нет одновременно доступных &mut T
: вызов функции повторно заимствует ManuallyDrop
делает slot
единственная доступная изменяемая ссылка.
Почему алиасинг в Rust так плохо определен
Это действительно неоднозначно. Я хочу знать, в какой именно момент в Rust произошло неопределенное поведение &mut
noalias.
Не повезло, потому что, как указано в Nomicon :
К сожалению, Rust на самом деле не определил свою модель алиасинга.
Причина в том, что языковая группа хочет убедиться, что определение, которое они достигают, является как безопасным (очевидно, так), практическим , и все же не закрыть дверь до возможных доработок. Это сложная задача.
Рабочая группа Rust Unsafe Code Guidelines все еще работает над установлением точных границ, и, в частности, Ральф Юнг работает над операционной моделью псевдонима под названием Stacked Borrows .
Примечание. Модель Stacked Borrows реализована в MIRI, поэтому вы можете проверить свой код на соответствие модели Stacked Borrows, просто выполнив свой код в MIRI. Конечно, Stacked Borrows все еще экспериментальный, так что это ничего не гарантирует.
Что рекомендует предостережение
Я лично подписываюсь под предостережением. Поскольку точная модель не указана, правила постоянно меняются , и поэтому я рекомендую принять более строгую интерпретацию.
Таким образом, я интерпретирую правило без наложения имен из &mut T
как:
В любой точке кода в области не должно быть двух доступных ссылок, которые псевдонимы одной и той же памяти, если одна из них - &mut T
.
То есть, я считаю, что формирует a &mut T
в экземпляр T
, для которого другой &T
или &mut T
находится в области без аннулирования псевдонимов (через заимствование) неправильно сформирован.
Это вполне может быть излишне осторожным, но, по крайней мере, если модель псевдонимов окажется более консервативной, чем планировалось, мой код все равно будет действителен.