Is miri's mutable aliasing guard too conservative?

⚓ Rust    📅 2025-06-20    👤 surdeus    👁️ 4      

surdeus

Warning

This post was published 55 days ago. The information described in this article may have changed.

Hello. This question is the return of this other one, but unfortunately the brilliant work-around suggested by Quinedot can't be applied to this new case.

I have some code that exhibits the following pattern, and fails under miri.

use core::cell::UnsafeCell;

struct Database {
    state: UnsafeCell<Box<usize>>
}

struct Permission<'a> (&'a mut usize);

impl Permission<'_> {
    fn increment(&mut self) {
        *self.0 += 1;
    }
}

impl Database {
    fn new() -> Self {
        Self{ state: UnsafeCell::new(Box::new(0))}
    }
    fn get_permission(&self) -> Option<Permission<'_>> {
        //I know there needs to be other checks here so that multiple permissions aren't granted
        // to the same state.  That is elided because it's not relevant to this demonstration
        Some(Permission(unsafe{ &mut *self.state.get() }))
    }
    fn cleanup_permission(&self, perm: Permission<'_>) {
        drop(perm);

        let state = unsafe{ &mut *self.state.get() };
        **state += 1;
    }
}

fn main() {
    let db = Database::new();
    let mut perm = db.get_permission().unwrap();
    perm.increment();
    db.cleanup_permission(perm);
}

If I separate the cleanup_permission method into two, there is no problem. However, the point of the cleanup code is that it must run immediately after the permission object is destroyed. So separating the API, ironically, makes it unsound.

My questions are:

  1. is my code actually UB? i.e. could the compiler reorder the drop somehow? Or is miri just being too conservative?
  2. Is there a work-around, given the new constraints?

Thanks for any thoughts or ideas.

1 post - 1 participant

Read full topic

🏷️ rust_feed