The std::cell::Ref
struct in Rust is defined as follows:
pub struct Ref<'b, T: ?Sized + 'b> {
// NB: we use a pointer instead of `&'b T` to avoid `noalias` violations, because a
// `Ref` argument doesn't hold immutability for its whole scope, only until it drops.
// `NonNull` is also covariant over `T`, just like we would have with `&T`.
value: NonNull<T>,
borrow: BorrowRef<'b>,
}
The // NB
comment (I assume Nota bene / Nasty Bug or something?) implies that the following definition would not work, because it would be a noalias
violation (do they mean the LLVM attributes in the backend?):
pub struct Ref2<'b, T: ?Sized + 'b> {
value: &'b T,
borrow: BorrowRef<'b>,
}
I don't understand this point, as I was under the impression that the non lexical lifetime semantics were properly preserved in code generation. Otherwise the following simple example (which of course compiles) would also be illegal, right?:
struct Foo<'a> {
v: &'a i32,
}
fn foo(x: &mut i32) {
let f = Foo { v: x };
*x = 5; // value modified while the `noalias` f.v pointer is still in scope
}
Could somebody with more knowledge about the internals shed some light on this for me? I fear that I am misunderstanding something critical here, leading to potential issues in my own unsafe code.
f
is no longer in scope when you modifyx
thanks to Non-Lexical Lifetimes. – PontefractRefCell
is that theRefCell
is still in scope while you access the mutable reference returned byborrow_mut
, so if theRefCell
held a mutable reference at the same time, that would violate Rust's aliasing rules (never mind LLVM). – Pontefract