reference - Lifetimes' handling when returning inner reference from a reference passed as an argument to the function
问题描述
What is the reason the following code compiles fine, despite both the lifetimes 'a
and 'b
being independent of each other?
struct Foo<'a> {
i: &'a i32
}
fn func<'a, 'b>(x: &'a Foo<'b>) -> &'b i32 {
x.i
}
fn main() {}
If I make the reference i
in Foo
mutable, it gives the following error.
5 | fn func<'a, 'b>(x: &'a Foo<'b>) -> &'b i32 {
| ----------- -------
| |
| this parameter and the return type are declared with different lifetimes...
6 | x.i
| ^^^ ...but data from `x` is returned here
What is the reason it gives the above error?. Does it consider it's ownership over mutable reference and it sees that something (from Foo
) is being taken out (with an independent lifetime), which is not possible, hence the error ?
This code (which I thought would pass) fails too:
struct Foo<'a> {
i: &'a mut i32
}
fn func<'a, 'b: 'a>(x: &'a Foo<'b>) -> &'b i32 {
x.i
}
fn main() {}
fails with error:
error[E0623]: lifetime mismatch
--> src/main.rs:6:5
|
5 | fn func<'a, 'b: 'a>(x: &'a Foo<'b>) -> &'b i32 {
| -----------
| |
| these two types are declared with different lifetimes...
6 | x.i
| ^^^ ...but data from `x` flows into `x` here
But this one passes:
struct Foo<'a> {
i: &'a mut i32
}
fn func<'a: 'b, 'b>(x: &'a Foo<'b>) -> &'b i32 {
x.i
}
fn main() {}
This seems a bit counter-intuitive to me. Here, the outer lifetime ('a
) may outlive the inner lifetime ('b
). Why is this not an error?
解决方案
What is the reason the following code compiles fine, despite both the lifetimes
'a
and'b
being independent of each other?fn func<'a, 'b>(x: &'a Foo<'b>) -> &'b i32 { x.i }
The reason is that they are not independent of each other.
The type &'a Foo<'b>
would be impossible if 'a
outlived 'b
. So, implicitly the Rust borrow-checker is inferring that you must have intended that 'b: 'a
('b
outlives 'a
). So the code above is semantically the same as this:
fn func<'a, 'b: 'a>(x: &'a Foo<'b>) -> &'b i32 {
x.i
}
If I make the reference
i
inFoo
mutable, it gives the following error.5 | fn func<'a, 'b>(x: &'a Foo<'b>) -> &'b i32 { | ----------- ------- | | | this parameter and the return type are declared with different lifetimes... 6 | x.i | ^^^ ...but data from `x` is returned here
What is the reason it gives the above error?
When you pass around an immutable reference, it gets copied. In the above example, that means that the &'b i32
can be moved around by itself, and its liveness is not tied to where you got it from. This copied reference always points back to the original address of the data. And that's why the first example works - even if x
was dropped, the original reference would still be valid.
When you pass around a mutable reference, it gets moved. A consequence of that is this case is that the reference is still "through" the variable x
. If this wasn't the case, x
's mutable reference to the contents of Foo
could be live at the same time as this new immutable reference - which is not allowed. So, in this case the reference cannot outlive 'a
- or put another way: 'a: 'b
.
But didn't we already say 'b: 'a
? The only conclusion here is that 'a
and 'b
must be the same lifetime, which is what your previous error message was demanding.
推荐阅读
- r - 如何将未分类的条形图添加到同一个图表?
- c - Does the distance between read and write locations have an effect on cache performance?
- java - 使用 RxJava 对数组进行异步 forEach
- javascript - 如何获得动画下拉菜单?
- mysql - 如何从自动递增的主键切换到保留外键关系的 uuid
- python - 奇怪的日期时间格式 - Python
- c# - 邮递员 - 如何从列表中传递数据
,在内存中,进入 Newman 命令行的 -data 部分 - java - 使用 Homebrew 为 Mac 安装 OpenJDK 8 (subversion 1.8.0.119)?
- background-color - Android - 如何动态更改背景颜色或整个 TabLayout?
- python - PySpark 中的数据框未显示