{
  "$type": "site.standard.document",
  "bskyPostRef": {
    "cid": "bafyreifkqiftemvh2qtd4oyl4sr2oe2fji3enorlliuwfkzato7m55h5ca",
    "uri": "at://did:plc:ivbknywyskln22er3nkssdhl/app.bsky.feed.post/3mlynj6vfmae2"
  },
  "path": "/t/reducing-raw-pointer-footguns-preventing-reference-aliasing-violations-at-compile-time/24301#post_20",
  "publishedAt": "2026-05-16T08:36:29.000Z",
  "site": "https://internals.rust-lang.org",
  "textContent": "Here's how all your `AliasingGuardMut` can be written with simply a `&mut` reference without raw pointers! So while `AliasingGuardMut` may be safer than using raw pointers, it doesn't seem to enable anything that `&mut` references can do, So where is the actual benefit of using `AliasingGuardMut`? Note that in your examples there were even examples of unsoundness and reference aliasing violation where I left a comment on, so `AliasingGuardMut` seem to not even prevent them.\n\n\n    fn a(b: &mut Vec<i32>) {\n        *b = vec![1];\n    }\n\n    // some other code that must take pointer\n    // eg FFI code, low level code that takes pointer\n    // or 3rd party library code that takes pointer\n    fn b(b: *mut Vec<i32>) {\n        unsafe { *b = vec![1] }\n    }\n\n    fn main() {\n        let mut s = vec![1, 2, 3];\n\n        let reff = &mut s;\n        a(reff);\n        b(reff);\n    }\n\n\n\n        guard: &'a mut i32\n    }\n\n    impl<'a> Holder<'a> {\n        fn write(&mut self, val: i32) {\n            *self.guard = val;\n        }\n    }\n\n    fn main() {\n        let mut x = 5;\n\n        let mut h = Holder {\n            guard: &mut x,\n        };\n\n        let r = &mut *h.guard;\n\n        h.write(10);\n\n        *r += 1;\n    }\n\n\n\n    struct Arena<'a, T> {\n        guard: &'a mut T,\n    }\n\n    impl<'a, T> Arena<'a, T> {\n        fn get_mut(&self) -> &mut T {\n            // This is a compile time error.\n            // I hope the existing self.guard.mutable_reference() was a compile time error too\n            // or it would have been unsound (worse than a raw pointer because it didn't even require unsafe!)\n            &mut *self.guard\n        }\n    }\n\n    fn main() {\n        let mut value = String::from(\"hello\");\n\n        let mut arena = Arena {\n            guard: &mut value,\n        };\n\n        let a = arena.get_mut();\n\n        let b = arena.get_mut();\n\n        a.push_str(\" world\");\n        b.push_str(\" !!!\");\n    }\n\n\n\n    use std::ptr::NonNull;\n\n    struct Node {\n        next: Option<NonNull<Node>>,\n        value: i32,\n    }\n\n    struct List<'a> {\n        head: Option<NonNull<Node>>,\n        guard: Option<&'a mut Node>,\n    }\n\n    impl<'a> List<'a> {\n        fn new() -> Self {\n            Self {\n                head: None,\n                guard: None,\n            }\n        }\n\n        unsafe fn push_front(&mut self, node: &'a mut Node) {\n            node.next = self.head;\n            self.head = Some(NonNull::from(&mut *node));\n            // Note that both the new and the old code invalidate the pointer in `self.head`\n            // I'm not sure how you intended to use it, but it shows that AliasingGuardMut also has footguns\n            // self.guard = Some(AliasingGuardMut::from_reference(node));\n            self.guard = Some(node);\n        }\n\n        fn first_mut(&mut self) -> Option<&mut Node> {\n            self.guard.as_mut()\n        }\n    }\n\n    fn increment(node: &mut Node) {\n        node.value += 1;\n    }\n\n    fn main() {\n        let mut node = Box::new(Node {\n            next: None,\n            value: 10,\n        });\n\n        let mut list = List::new();\n\n        unsafe {\n            list.push_front(&mut *node);\n        }\n\n        let a = list.first_mut().unwrap();\n\n        increment(a);\n\n        let b = list.first_mut().unwrap();\n\n        b.value += 10;\n\n        println!(\"{}\", a.value);\n    }\n\n\n\n    struct Buffer<'a> {\n        guard: &'a mut Vec<i32>,\n    }\n\n    impl<'a> Buffer<'a> {\n        fn new(vec: &'a mut Vec<i32>) -> Self {\n            Self {\n                guard: vec,\n            }\n        }\n\n        fn get_mut(&mut self) -> &mut Vec<i32> {\n            &mut *self.guard\n        }\n    }\n\n    fn append_data(vec: &mut Vec<i32>) {\n        vec.push(100);\n    }\n\n    fn main() {\n        let mut data = vec![1, 2, 3];\n\n        let mut buffer = Buffer::new(&mut data);\n\n        let a = buffer.get_mut();\n\n        append_data(a);\n\n        let b = buffer.get_mut();\n\n        b.push(200);\n\n        a.push(300);\n\n        println!(\"{:?}\", a);\n    }\n\n\n\n    struct SlotMap<'a, T> {\n        slot: Option<&'a mut T>,\n    }\n\n    impl<'a, T> SlotMap<'a, T> {\n        fn new() -> Self {\n            Self {\n                slot: None,\n            }\n        }\n\n        fn insert(&mut self, value: &'a mut T) {\n            self.slot = Some(value);\n        }\n\n        fn get_mut(&mut self, _: usize) -> &mut T {\n            self.slot\n                .as_mut()\n                .unwrap()\n        }\n    }\n\n    fn update_user(user: &mut String) {\n        user.push_str(\" updated\");\n    }\n\n    fn main() {\n        let mut user = String::from(\"alice\");\n\n        let mut map = SlotMap::new();\n\n        map.insert(&mut user);\n\n        let current = map.get_mut(0);\n\n        update_user(current);\n\n        let another = map.get_mut(0);\n\n        another.push_str(\" !!!\");\n\n        println!(\"{}\", current);\n    }\n",
  "title": "Reducing Raw Pointer Footguns: Preventing Reference Aliasing Violations at Compile Time"
}