生命周期必须对静态生命周期有效,以便类型兼容

时间:2018-09-05 14:31:22

标签: rust

我知道Where did the 'static lifetime come fromCannot infer an appropriate lifetime for autoref due to conflicting requirements

但是我仍然不明白我遇到的问题:

use std::ops::Index;

trait Stack<T> {
    fn as_slice(&self) -> &[T];
}

impl<T> Index<usize> for Stack<T> {
    type Output = T;
    fn index(&self, i: usize) -> &T {
        &self.as_slice()[i]
    }
}

trait Core {
    fn stack(&self) -> &Stack<usize>;
    fn bad(&mut self) -> usize {
       self.stack()[0]
    }
    fn good(&mut self) -> usize {
       self.stack().as_slice()[0]
    }
}

fn main() {}

在上面的代码中,good()没有给出错误,但是bad()抱怨:

error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/main.rs:18:14
|
18 |         self.stack()[0]
|              ^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 17:5...
--> src/main.rs:17:5
|
17 | /     fn bad(&mut self) -> usize {
18 | |         self.stack()[0]
19 | |     }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:18:9
|
18 |         self.stack()[0]
|         ^^^^
= note: but, the lifetime must be valid for the static lifetime...
= note: ...so that the types are compatible:
        expected std::ops::Index<usize>
            found std::ops::Index<usize>

此代码中没有Box,而且我不知道静态寿命来自何处。

编辑:通过尝试和错误,我发现编译器采用Stack +'static。以下代码进行编译。但为什么?请指出一些文件。

impl<'b, T> Index<usize> for Stack<T> + 'b {
    type Output = T;
    fn index<'a>(&'a self, i: usize) -> &'a T {
        &self.as_slice()[i]
    }
}

1 个答案:

答案 0 :(得分:4)

您正在为特性对象(Index)实现特性(Stack<T>)。

Rust reference指出:

  

由于特征对象可以包含引用,因此这些引用的生存期需要表示为特征对象的一部分。此寿命写为特质+'a。缺省情况下,通常可以通过明智的选择来推断此寿命。

如果您未定义生存期,则编译器将采用默认值,在这种情况下,将假定为'static(有关详细说明,请参见here

您的代码等同于:

impl<T> Index<usize> for Stack<T> + 'static {
    type Output = T;
    fn index(&self, i: usize) -> &T {
        &self.as_slice()[i]
    }
}

要解决cannot infer an appropriate lifetime for autoref due to conflicting requirements编译错误,只需声明stack()方法返回寿命为'static的特征对象。

trait Core {
    fn stack(&self) -> &'static Stack<usize>;
    fn bad(&mut self) -> usize {
       self.stack()[0]
    }
    fn good(&mut self) -> usize {
       self.stack().as_slice()[0]
    }
}

否则,声明Stack<T>的{​​{1}}特征对象的通用生存期:

Index

这时您应该问:为什么在impl<'a, T> Index<usize> for Stack<T> + 'a { type Output = T; fn index(&self, i: usize) -> &T { &self.as_slice()[i] } } trait Core { fn stack(&self) -> &Stack<usize>; fn bad(&mut self) -> usize { self.stack()[0] } fn good(&mut self) -> usize { self.stack().as_slice()[0] } } 中使用as_slice()而不在good()中使用index()是有效的?

要想具有相同的含义,请阅读下面的MVCE中嵌入的注释。

bad()