Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dereferencing Box<T> gives back value instead of reference

Tags:

rust

I can't seem to figure out why:

let a = Box::new(5i32);
let _:() = *a;

tells me that the assigned type on the second line is i32 and not &i32 since Deref.deref() (which I assume is being called at *a), returns &T.

Also, if I were to call deref() myself:

let _:() = <Box<i32> as Deref>::deref(&a);

I get the expected &i32.

like image 941
Mansour Avatar asked Nov 11 '15 15:11

Mansour


People also ask

Does Rust automatically dereference?

Rust will also insert automatic dereferencing as part of deref coercion. This is a special coercion that can only convert from one reference type to another. For example, this is what lets you convert from String to &str by writing &x instead of &*x .

What is Deref trait Rust?

Trait std::ops::DerefUsed for immutable dereferencing operations, like *v . In addition to being used for explicit dereferencing operations with the (unary) * operator in immutable contexts, Deref is also used implicitly by the compiler in many circumstances. This mechanism is called ' Deref coercion'.

What is dereferencing in Rust?

The dereference operator is also known as the indirection operator. Simply put, the dereferencing operator allows us to get the value stored in the memory address of a pointer. In Rust, we use the Deref trait to customize the behaviour of the dereferencing operator.

What does &* do in Rust?

In general, &* means to first dereference ( * ) and then reference ( & ) a value. In many cases, this would be silly, as we'd end up at the same thing. However, Rust has deref coercions. Combined with the Deref and DerefMut traits, a type can dereference to a different type!


1 Answers

Dereferencing doesn't necessarily produce an (intermediate) value. Consider

let b = Box::new(1);
(*b).clone();

The method i32::clone() is called with a &self argument where the reference points to the value inside the box, not to a temporary value that could be produced by (*b).

The trait Deref is part of implementing dereferencing (just like DerefMut).

There is no corresponding trait to what * can additionally do on a box: Move the inner value out and discard the box; this is colloquially called DerefMove but remains a compiler-hardcoded box speciality at this point.

When the compiler sees (*a), it has to infer whether to use Deref, DerefMut or “DerefMove”; it is inferred from how the expression is used: if you call a &self method on the result, Deref is used, for example.

Edited: Inherently copyable types (trait Copy), use Deref followed by copy instead of “DerefMove”; this is then no longer resticted to Box, but works with all smart pointers.

like image 148
bluss Avatar answered Oct 21 '22 18:10

bluss