src/unsafe-deep-dive/safety-preconditions/references.md
# // Copyright 2026 Google LLC
# // SPDX-License-Identifier: Apache-2.0
#
fn main() {
let mut boxed = Box::new(123);
let a: *mut i32 = &mut *boxed as *mut i32;
let b: *mut i32 = std::ptr::null_mut();
println!("{:?}", *a);
println!("{:?}", b.as_mut());
}
Confirm understanding of the syntax
Box<i32> type is a reference to an integer on the heap that is owned by the
box.
*mut i32 type is a so-called raw pointer to an integer that the compiler
does not know the ownership of. Programmers need to ensure the rules are
enforced without assistance from the compiler.
&mut *boxed as *mut _ expression:
*boxed is ...&mut *boxed is ...as *mut i32 casts the reference to a pointer.References, such as &mut i32, "borrow" their referent. This is Rust's
ownership system.
Confirm understanding of ownership
Step through code:
123 by dereferencing the box, creating
a new reference and casting the new reference as a pointer..as_mut()Highlight that pointers are nullable in Rust (unlike references).
Compile to reveal the error messages.
Discuss
println!("{:?}", *a);
println!("{:?}", b.as_mut());
as_mut() is an unsafe function.Demonstrate: Fix the code (add unsafe blocks) and compile again to show the working program.
Demonstrate: Replace as *mut i32 with as *mut _, show that it compiles.
&mut i32. This reference type can only be
converted to one pointer type, *mut i32.Add safety comments:
Discuss: Whether to use one large unsafe block or two smaller ones:
Suggested Solution
# // Copyright 2026 Google LLC
# // SPDX-License-Identifier: Apache-2.0
#
fn main() {
let mut boxed = Box::new(123);
let a: *mut i32 = &mut *boxed as *mut i32;
let b: *mut i32 = std::ptr::null_mut();
// SAFETY: `a` is a non-null pointer to i32, it is initialized and still
// allocated.
println!("{:?}", unsafe { *a });
// SAFETY: `b` is a null pointer, which `as_mut()` converts to `None`.
println!("{:?}", unsafe { b.as_mut() });
}