Typed and untyped Box references


Why do these references return different values?

fn main() {
  let x = Box::new(5);
  let p = &x;
  let pp : &i32 = &x;
  println!("&x: {:p}", &x);     //  &x: 0x7fff1ff19d08
  println!("p: {:p}",  p);      //  p:  0x7fff1ff19d08
  println!("pp: {:p}", pp);     //  pp: 0x7fec07c23008

It does not happen with stack variables.

fn main() {
  let x = 5;
  let p = &x;
  let pp : &i32 = &x;
  println!("&x: {:p}", &x);       // &x: 0x7fff67d996d4
  println!("p: {:p}",  p);        // p:  0x7fff67d996d4
  println!("pp: {:p}", pp);       // pp: 0x7fff67d996d4


It happens due to coercions you request by annotating a type:

 fn main() {
    let x: Box<i32> = Box::new(5);
    let p: &Box<i32> = &x;
    let pp: &i32 = &x;

You see, the third let binding ought to be a type error, but due to the way the & operator works in Rust, it may dereference the inner type an unspecified number of times until the type fits.


Ok, I see. Then I guess that the desired behavior would be to get a compilation error at ‘let pp’, right? I came across this situation while I was playing with this example:


There you have the following:

let boxed_int = Box::new(5);
// Take a reference to the data contained inside the box
let _ref_to_int: &i32 = &boxed_int;


Ah, ok, I get it. So it will only raise a compilation error if the data contained inside the box doesn’t fit the specified type. Thank you.


@alvalea The reason that the code compiles is due to deref coercions


Ok, thanks. This seems very convenient. Although at the beginning it can be a bit puzzling.


Shouldn’t either this be a &*boxed_int or there be a comment about deref coersions?


Maybe, yeah. I didn’t write Rust by Example, I just slowly give it updates when I can. There’s tons of little things like this that could be better.


Pull requests welcome :wink: