|
|
|
@ -127,13 +127,63 @@ fn random_empty_tile_2<'arr>(arr: &'arr mut [Tile]) -> &'arr mut Tile {
|
|
|
|
|
结果,编译器还是不给通过,报的错误几乎一样
|
|
|
|
|
|
|
|
|
|
## 深层原因
|
|
|
|
|
令人沮丧的是,我找遍了网上,也没有具体的原因,大家都说这是编译器太笨导致的问题,但是关于深层的原因,也没人能说出个
|
|
|
|
|
所有然。
|
|
|
|
|
令人沮丧的是,我找遍了网上,也没有具体的原因,大家都说这是编译器太笨导致的问题,但是关于深层的原因,也没人能说出个所有然。
|
|
|
|
|
|
|
|
|
|
因此,我无法在本文中给出为什么编译器会这么笨的真实原因,如果以后有结果,会在这里进行更新。
|
|
|
|
|
|
|
|
|
|
## 解决办法
|
|
|
|
|
虽然不能给出原因,但是我们可以看看解决办法,在上面,**移除中间变量**是一种办法,还有一种办法就是将部分引用移到循环外面.
|
|
|
|
|
------2022年1月13日更新-------
|
|
|
|
|
兄弟们,我带着挖掘出的一些内容回来了,再来看段错误代码先:
|
|
|
|
|
```rust
|
|
|
|
|
struct A {
|
|
|
|
|
a: i32
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl A {
|
|
|
|
|
fn one(&mut self) -> &i32{
|
|
|
|
|
self.a = 10;
|
|
|
|
|
&self.a
|
|
|
|
|
}
|
|
|
|
|
fn two(&mut self) -> &i32 {
|
|
|
|
|
loop {
|
|
|
|
|
let k = self.one();
|
|
|
|
|
if *k > 10i32 {
|
|
|
|
|
return k;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 可能存在的剩余代码
|
|
|
|
|
// ...
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
我们来逐步深入分析下:
|
|
|
|
|
|
|
|
|
|
1. 首先为`two`方法增加一下生命周期标识: `fn two<'a>(&'a mut self) -> &'a i32 { .. }`, 这里根据生命周期的[消除规则](../../advance/lifetime/basic.md#三条消除规则)添加的
|
|
|
|
|
2. 根据生命周期标识可知:`two`中返回的`k`的生命周期必须是`'a`
|
|
|
|
|
3. 根据第2条,又可知:`let k = self.one();`中对`self`的借用生命周期也是`'a`
|
|
|
|
|
4. 因为`k`的借用发生在`loop`循环内,因此它需要小于等于循环的生命周期,但是根据之前的推断,它又要大于等于函数的生命周期`'a`,而函数的生命周期又大于等于循环生命周期,
|
|
|
|
|
|
|
|
|
|
由上可以推出:`let k = self.one();`中`k`的生命周期要大于等于循环的生命周期,又要小于等于循环的生命周期, 唯一满足条件的就是:`k`的生命周期等于循环生命周期。
|
|
|
|
|
|
|
|
|
|
但是我们的`two`方法在循环中对`k`进行了提前返回,编译器自然会认为存在其它代码,这会导致`k`的生命周期小于循环的生命周期。
|
|
|
|
|
|
|
|
|
|
怎么办呢?很简单:
|
|
|
|
|
```rust
|
|
|
|
|
fn two(&mut self) -> &i32 {
|
|
|
|
|
loop {
|
|
|
|
|
let k = self.one();
|
|
|
|
|
return k;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
不要在`if`分支中返回`k`,而是直接返回,这样就让它们的生命周期相等了,最终可以顺利编译通过。
|
|
|
|
|
|
|
|
|
|
> 如果一个引用值从函数的某个路径提前返回了,那么该借用必须要在函数的所有返回路径都合法
|
|
|
|
|
|
|
|
|
|
## 解决方法
|
|
|
|
|
虽然不能给出原因,但是我们可以看看解决办法,在上面,**移除中间变量**和**消除代码分支**都是可行的方法,还有一种方法就是将部分引用移到循环外面.
|
|
|
|
|
|
|
|
|
|
#### 引用外移
|
|
|
|
|
```rust
|
|
|
|
|