I write a simple program in Rust. This program can compile.
use std::cell::{Ref, RefCell};
fn print_number(x: &i32) {
println!("x is {}", x);
}
fn main() {
let stack: i32 = 42;
let reference: &i32 = &stack;
let refcell: RefCell<&i32> = RefCell::new(reference);
let wrapped: Ref<'_, &i32> = refcell.borrow();
print_number(&wrapped);
print_number(*wrapped);
}
I can tell the reason why both work:
&works, because&wrappedis of type&Ref<&i32>, which can be deref-coerced to&&i32, which can be deref-coerced to&i32.*works, because*wrappedis equivalent to*Deref::deref(&wrapped). We knowDeref::deref(&Ref<&i32>)results to&&i32, so*Deref::deref(&Ref<&i32>)results to*&&i32, i.e.,&i32.
It seems that the 2nd approach (with *) is more straight-forward, however the Rust compiler suggests me using the 1st approach (with &). If I add one line:
print_number(wrapped);
This of course can't compile. But I'm interested with the compiler report:
error[E0308]: mismatched types
--> src/main.rs:16:18
|
16 | print_number(wrapped);
| ------------ ^^^^^^^ expected `&i32`, found `Ref<'_, &i32>`
| |
| arguments to this function are incorrect
|
= note: expected reference `&i32`
found struct `Ref<'_, &i32>`
note: function defined here
--> src/main.rs:3:4
|
3 | fn print_number(x: &i32) {
| ^^^^^^^^^^^^ -------
help: consider borrowing here
|
16 | print_number(&wrapped);
| +
For more information about this error, try `rustc --explain E0308`.
error: could not compile `testrust` (bin "testrust") due to 1 previous error
In the report's "help", it suggests me adding a &. I'm wondering why it doesn't suggest me adding a *.
Recommending
&fixes the code for any typeTinRef<'_, T>, while*only works if the contained type implementsCopyand is a reference.Copyis needed because else you couldn't "move" out of theRefand a reference because your function requires it's argument to be one. Special casing "Tis a shared reference" (that includes isCopyas shared references always are) doesn't seem all that useful if the other, and already necessary to implement for some cases, way of recommending&also works and produces the same assembly.In other words recommending
*over&here requires additional code (= more work) for no ergonomics or performance gain whatsoever.