Closed
Description
The following library:
use std::cell::*;
pub fn break_it(rc: &RefCell<i32>, r: Ref<'_, i32>) {
// `r` has a shared reference, it is passed in as argument and hence
// a barrier is added that marks this memory as read-only for the entire
// duration of this function.
drop(r);
// *oops* here we can mutate that memory.
*rc.borrow_mut() = 2;
}
generates IR for break_it
that starts like
; playground::break_it
; Function Attrs: noinline nonlazybind uwtable
define void @_ZN10playground8break_it17hb8a9beeb2affda19E(
{ i64, i32 }* align 8 dereferenceable(16) %rc,
i32* noalias nocapture readonly align 4 dereferenceable(4) %r.0,
i64* nocapture align 8 dereferenceable(8) %r.1)
unnamed_addr #1 personality i32 (i32, i32, i64, %"unwind::libunwind::_Unwind_Exception"*, %"unwind::libunwind::_Unwind_Context"*)* @rust_eh_personality {
Note the noalias
. That is incorrect, this function violates the noalias assumptions by mutating the data r
points to through a pointer (rc
) not derived from c
. Here's a caller causing bad aliasing:
pub fn main() {
let rc = RefCell::new(0);
break_it(&rc, rc.borrow())
}
RefMut
has the same problem when -Zmutable-noalias
is set.