{
"$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"
}