Why loom is happy with this?

   use loom::sync::Arc;
   use loom::sync::atomic::{AtomicBool, AtomicUsize, Ordering};

   loom::model(|| {
        let ptr = Box::into_raw(Box::new(0));
        let flag = Arc::new(AtomicBool::new(false));
        let flag2 = flag.clone();

        loom::thread::spawn(move || {
            unsafe { *ptr = 1 };
            flag.store(true, Ordering::Relaxed);
        });
        
        loom::thread::spawn(move || {
            if flag2.load(Ordering::Relaxed) {
                assert!(unsafe { *ptr == 1 });
            }
        });
    });

this passes, could someone please explain why? thanks!
edit: oh, UB?

Yeah, UB.

How about using: UnsafeCell in loom::cell - Rust

Also looks like MutPtr would be useful.

If I rewrite it so that Loom can track the raw pointer use, I get:

use loom::sync::Arc;
use loom::sync::atomic::{AtomicBool, Ordering};

fn main() {
    loom::model(|| {
        let cell = loom::cell::UnsafeCell::new(0);
        let flag = Arc::new(AtomicBool::new(false));

        loom::thread::spawn({
            let ptr = cell.get_mut();
            let flag = flag.clone();
            move || {
                unsafe { *ptr.deref() = 1 };
                flag.store(true, Ordering::Relaxed);
            }
        });

        loom::thread::spawn({
            let ptr = cell.get_mut();
            let flag = flag.clone();
            move || {
                if flag.load(Ordering::Relaxed) {
                    assert!(unsafe { *ptr.deref() == 1 });
                }
            }
        });
    });
}

(which does fail)