I'm new to Rust and trying to understand how reference works. Below is a simple function.

fn f1(x: &i32) -> &i32{
    x
}

Since x is of type &i32, return it directly matches the return type &i32. But I found that if I change the function to this, it also compiles without any problem:

fn f1(x: &i32) -> &i32{
    &x
}

Here x is of type &i32, &x is of type &&i32 and doesn't match the return type &i32. Why it compiles?

推荐答案

This is a result of type coercion.

To make the language more ergonomic, a certain set of coercions are allowed in specific situations. One of the situations is determining the return value of a function.

Among the allowed coercions is this:

&T or &mut T to &U if T implements Deref<Target = U>

In this particular case, there is an implementation of the deref trait in the std library:

impl<T: ?Sized> const Deref for &T {
    type Target = T;

    #[rustc_diagnostic_item = "noop_method_deref"]
    fn deref(&self) -> &T {
        *self
    }
}

In your case, the target T is i32, and the trait is implemented for &T (ie. &&i32) so the value can be coerced from &&i32 to &i32.

Rust相关问答推荐

用于读取文件块的迭代器

如何在 M1 Macbook 上安装 Cargo Generate

`T : 'static` 是什么意思?

每次在 VSCode 中启动 RLS 时出现“duplicated RLS configuration”

为什么trait object vtables包含大小和对齐?

如何使用std::hash::hash?

可以确定泛型类型的零值吗?

从同一个 HashMap 中borrow (Borrow)两个可变值

将JSON字符串或字符串数组反序列化为Vec

为什么 slice::from_raw_parts 的生命周期很重要?

在 struct 定义上指定'Fn'trait bound,而不修复其中一个'Fn'参数

如何将 struct 与指定的字节边界对齐?

在 Rust 中处理多个 `Option` 的惯用方法是什么?

是否有unwrap或continue循环的快捷方式?

如何将两个 u8 基元转换为 u16 基元?

使用 Emscripten 目标从 Rust 创建 Web Worker

泛型函数的不同实例是否有可能具有不同的静态变量?

如何flatten嵌套的结果?

从没有模式匹配的枚举中读取

在 Rust 中将 u8 缓冲区转换为 struct