MIRI error, with `Drop`
⚓ Rust 📅 2025-11-17 👤 surdeus 👁️ 9I am not good at English. Sorry if there are any funny expressions.
My Rust code contains functions miri_ok and miri_ng. The only difference between two is the method of instance dropping. But, MIRI only outputs an error for the latter.
The reason for this is probably because on_drop is being called while the drop function's exit point still protects self (though I'm not fully understanding MIRI's Stacked Borrows model paper, so I'm not entirely sure...).
Putting the reasons aside, what troubles me is that drop causes an error in the Stacked Borrows model (Tree Borrows model does not cause error). There's no way we can stop API users from using drop, right? But since it's possible with an implicit drop, I wondered there might be some good approach.
Code
#![allow(unused)]
#[test]
fn miri_ok() {
let mut var = 0;
let mut twp = TwoWayPtr::new(&mut var);
twp.on_drop();
}
#[test]
fn miri_ng() {
let mut var = 0;
let mut twp = TwoWayPtr::new(&mut var);
drop(twp);
}
struct TwoWayPtr<'a> {
val_ptr: *mut i32,
val_ref: Option<&'a i32>,
}
impl<'a> TwoWayPtr<'a> {
fn new(val: &'a mut i32) -> Self {
let val_ptr = val as *mut _;
let val_ref = Some(unsafe { &*val_ptr });
Self { val_ptr, val_ref }
}
fn on_drop(&mut self) {
self.val_ref.take(); // For multiple alias avoiding.
let _ = unsafe { &mut *self.val_ptr };
}
}
impl Drop for TwoWayPtr<'_> {
fn drop(&mut self) {
self.on_drop();
}
}
Error excerpt
test miri_ng ... error: Undefined Behavior: not granting access to tag <146804> because that would remove [SharedReadOnly for <146817>] which is strongly protected
--> src\lib.rs:40:26
|
40 | let _ = unsafe { &mut *self.val_ptr };
| ^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
help: <146804> was created by a SharedReadWrite retag at offsets [0x0..0x4]
--> src\lib.rs:33:23
|
33 | let val_ptr = val as *mut _;
| ^^^
help: <146817> is this argument
--> src\lib.rs:23:5
|
23 | drop(twp);
| ^^^^^^^^^
= note: BACKTRACE (of the first span) on thread `miri_ng`:
= note: inside `TwoWayPtr::<'_>::on_drop` at src\lib.rs:40:26: 40:44
Note
val_ptr and val_ref are used for simplicity in explanation. In the actual code, they are a pointer to the map and a mutable reference to its iterator. This was done because I wanted to access the map after using the iterator.
5 posts - 3 participants
🏷️ Rust_feed