我从这个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()
中遇到的一个真实的问题的简化,但我更愿意从总体上理解它。
2条答案
按热度按时间gstyhher1#
当函数的参数和返回类型是泛型时,Rust编译器假设返回类型可能会借用参数。这就是为什么它假设
f()
返回一个引用局部变量i
的值。我不完全确定,但我认为这是需要的,因为有人可以为一个类型实现
Reply
,而这会有问题。编辑:这是因为一个bug。它已经在GitHub上发布了。
llmtgqce2#
四年后,我们有了深入的答案:Analysis of Rust issue #42940
我认为关键的部分是这样的:
test
返回的 value 不引用当前函数拥有的任何数据。错误消息只是错误的。然而,
test
* 返回的 type 引用了一个只在当前函数中有效的生存期。这才是真实的问题