Вы реализуете черту (Index
) для объекта черты (Stack<T>
).
Ссылка Rust сообщает:
Поскольку объект признака может содержать ссылки, время жизни этих ссылок должно быть выражено как часть объекта признака. Эта жизнь написана как Черта + 'a. Существуют значения по умолчанию, которые позволяют сделать вывод об этой жизни с разумным выбором.
Если Вы не определяете время жизни, компилятор принимает значение по умолчанию, в этом случае предполагается 'static
(подробное объяснение см. здесь )
Ваш код эквивалентен:
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>
, которое подразумевает 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()
в bad()
- нет?
Чтобы понять это, попробуйте прочитать комментарии, встроенные в MVCE ниже.
use std::ops::Index;
trait Stack<T> {
fn as_slice(&self) -> &[T];
}
// equivalent to: impl<T> Index<usize> for Stack<T>
// just to expose the conflicting requirements error
// the right declaration is:
// impl<'a, T> Index<usize> for Stack<T> + 'a
impl<T> Index<usize> for Stack<T> + 'static {
type Output = T;
fn index(&self, i: usize) -> &T {
&self.as_slice()[i]
}
}
trait Core {
fn stack(&self) -> &Stack<usize>;
fn bad<'a>(&'a mut self) -> usize {
//self.stack()[0] syntactic sugar for:
*self.stack().index(0)
// self.stack() returns a trait object with a lifetime bound != 'static
// but Stack impl for Index requires a 'static lifetime bound:
// COMPILE ERROR: cannot infer an appropriate lifetime for
// autoref due to conflicting requirements
}
fn good<'a>(&'a mut self) -> usize {
// self.stack() returns a trait object with 'a lifetime bound
// this is congruent with as_slice() lifetime requirements
// see Catasta::as_slice() impl below
// NO COMPILE ERROR
self.stack().as_slice()[0]
}
}
struct Catasta<T> {
pila: [T;4]
}
impl<T> Stack<T> for Catasta<T> {
fn as_slice<'a>(&'a self) -> &'a [T] {
&self.pila
}
}
struct RealCore {
stk: Catasta<usize>
}
impl Core for RealCore {
fn stack(&self) -> &Stack<usize> {
&self.stk
}
}
fn main() {
let mut core = RealCore {stk: Catasta {pila: [100, 2, 3, 4]} };
println!("pos [0] item: {}", core.good());
}