В обоих случаях определенно UB.
Основная проблема здесь заключается в том, что любые изменения значения за общей ссылкой являются недопустимыми, за исключением UnsafeCell
внутренних значений. Компилятор может легко оптимизировать изменение в первом случае и просто подставить r
в println
вызов.
Второй случай немного сложнее, но основан на том же факте. Обратите внимание, что выражение &*r
, где r
имеет тип Rc<T>
, имеет тип & T ( детская площадка ):
use std::rc::Rc;
fn test<T>(r: Rc<T>) {
let _: () = &*r; // error: expected (), found &T
}
Хитрость в том, что Rc<T>
обращается к T
, поэтому *r
имеет тип T
.
Итак, это снова неизменяемая ссылка, которая рассматривается как изменяемая.