“借用的值活得不够长”,带有返回 impl 特征的通用函数

问题描述 投票:0回答:2

我从这个 Rust 代码中得到了一个意外的错误:

struct Container<'a> {
    x: &'a i32,
}

trait Reply {}
impl Reply for i32 {}

fn json<T>(_val: &T) -> impl Reply {
    3
}

fn f() -> impl Reply {
    let i = 123;
    let a = Container { x: &i };
    json(&a)
}

游乐场

错误是:

error[E0597]: `i` does not live long enough
  --> src/lib.rs:14:28
   |
12 | fn f() -> impl Reply {
   |           ---------- opaque type requires that `i` is borrowed for `'static`
13 |     let i = 123;
14 |     let a = Container { x: &i };
   |                            ^^ borrowed value does not live long enough
15 |     json(&a)
16 | }
   | - `i` dropped here while still borrowed

为什么?

如果我将

json()
的声明更改为以下任一版本,代码将编译:

fn json(val: &Container) -> impl Reply
fn json<T>(val: &T) -> i32

只有当同时存在类型参数和返回的特征对象时,编译器才会拒绝该代码。

这是我们遇到的实际问题的减少

warp::reply::json()
,但我更愿意总体上理解它。

generics rust borrow-checker
2个回答
1
投票

当函数的参数和返回类型是泛型时,Rust 编译器假定返回类型可能会借用参数。这就是为什么它假设

f()
返回引用局部变量
i
的值。

我不完全确定,但我认为这是理想的,因为有人可以为可能出现问题的类型实现

Reply

编辑:由于错误,这不起作用。已经在 GitHub 上报道过。


0
投票

四年后,我们有了深入的答案:Rust 问题分析#42940

我认为关键部分是这样的:

test返回的

引用当前函数拥有的任何数据。错误消息是错误的。

但是, test

does
返回的 type 引用仅在当前函数内有效的生命周期。这才是真正的问题。

© www.soinside.com 2019 - 2024. All rights reserved.