I am trying to create a variable on the stack and one on the heap:
fn main() {
let mut x = 1;
let mut y = &x;
let mut z = Box::new(x);
let mut w = Box::new(2);
println!("&x = {:p}", &x);
println!("&y = {:p}", &y);
println!("&z = {:p}", &z);
println!("&w = {:p}", &w);
}
Another think that is worth pointing out, is that Rust is allowed to optimise-out heap allocation and put value on stack. So you can never rely on the fact that heap allocation was performed. This is explicitly stated in the documentation of std::alloc::GlobalAlloc.
You must not rely on allocations actually happening, even if there are explicit heap allocations in the source. The optimizer may detect unused allocations that it can either eliminate entirely or move to the stack and thus never invoke the allocator. The optimizer may further assume that allocation is infallible, so code that used to fail due to allocator failures may now suddenly work because the optimizer worked around the need for an allocation.
If you didn't observe the addresses by printing them, the compiler may have put some of those variables into registers or omitted them from your program altogether.
Examining pointer addresses is not an effective way to estimate what the compiler does, because it changes what the optimizer is allowed to do in significant ways.