rust “借来的值活得不够长”,返回impl trait的泛型函数

utugiqy6  于 2023-10-20  发布在  其他
关注(0)|答案(2)|浏览(110)

我从这个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)
}

Playground
错误是:

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

只有当同时存在类型参数和返回的trait对象时,编译器才会拒绝代码。
这是我们在warp::reply::json()中遇到的一个真实的问题的简化,但我更愿意从总体上理解它。

gstyhher

gstyhher1#

当函数的参数和返回类型是泛型时,Rust编译器假设返回类型可能会借用参数。这就是为什么它假设f()返回一个引用局部变量i的值。
我不完全确定,但我认为这是需要的,因为有人可以为一个类型实现Reply,而这会有问题。
编辑:这是因为一个bug。它已经在GitHub上发布了。

llmtgqce

llmtgqce2#

四年后,我们有了深入的答案:Analysis of Rust issue #42940
我认为关键的部分是这样的:
test返回的 value 不引用当前函数拥有的任何数据。错误消息只是错误的。
然而,test * 返回的 type 引用了一个只在当前函数中有效的生存期。这才是真实的问题

相关问题