当两者都有效时,为什么 Rust 编译器建议添加“&”而不是“*”?

Yan*_*Yan 2 dereference rust

我用 Rust 编写了一个简单的程序。这个程序可以编译。

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);
}
Run Code Online (Sandbox Code Playgroud)

我可以说出两者都有效的原因:

  1. &有效,因为&wrapped的类型为&Ref<&i32>,可以被解引用强制为&&i32,也可以被解引用强制为&i32
  2. *有效,因为*wrapped相当于*Deref::deref(&wrapped). 我们知道Deref::deref(&Ref<&i32>)结果为&&i32,因此*Deref::deref(&Ref<&i32>)结果为*&&i32,即&i32

似乎第二种方法(使用*)更直接,但是 Rust 编译器建议我使用第一种方法(使用&)。如果我添加一行:

print_number(wrapped);
Run Code Online (Sandbox Code Playgroud)

这当然不能编译。但我对编译器报告感兴趣:

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
Run Code Online (Sandbox Code Playgroud)

在报告的“帮助”中,它建议我添加一个&. 我想知道为什么它不建议我添加*.

caf*_*e25 5

推荐修复中&任何类型的代码,而仅当包含的类型实现并且是引用时才有效。是必需的,因为否则你无法“移出”和引用,因为你的函数要求它的参数为一。特殊大小写“是共享引用”(包括共享引用总是如此)似乎没有那么有用,如果另一个,并且已经有必要在某些情况下实现推荐的方式TRef<'_, T>*CopyCopyRefTCopy&也可以工作并生成相同的程序集。

换句话说,在这里推荐*需要&额外的代码(=更多的工作),而不会获得任何人体工程学或性能提升。