Этот код определяет очень простой признак для представления двоичных деревьев и структуры, реализующей этот признак:
pub trait BTree<T> {
fn all(&self) -> Option<(&Self, &Self, &T)>;
fn left(&self) -> Option<&Self>;
fn right(&self) -> Option<&Self>;
fn value(&self) -> Option<&T>;
}
pub struct MyBTree<T> {
opt: Option<Box<(MyBTree<T>, MyBTree<T>, T)>>,
}
impl<T> BTree<T> for MyBTree<T> {
fn all(&self) -> Option<(&Self, &Self, &T)> {
match self.opt {
None => None,
Some(ref tuple) => Some((&tuple.0, &tuple.1, &tuple.2)),
}
}
fn left(&self) -> Option<&Self> {
match self.all() {
None => None,
Some((left, _, _)) => Some(left),
}
}
fn right(&self) -> Option<&Self> {
match self.all() {
None => None,
Some((right, _, _)) => Some(right),
}
}
fn value(&self) -> Option<&T> {
match self.all() {
None => None,
Some((_, _, value)) => Some(value),
}
}
}
Реализации left
, right
и value
могут перемещаться внутри признака, поскольку они зависят только от метода all
, определенного этим признаком, а не от деталей реализации.
Это отлично работает с value
, но не с left
и right
. Например, если я попытаюсь переместить реализацию left
в тело признака, я получаю следующую ошибку компиляции:
error[E0311]: the parameter type `T` may not live long enough
--> src/lib.rs:6:24
|
6 | match self.all() {
| ^^^
|
= help: consider adding an explicit lifetime bound for `T`
note: the parameter type `T` must be valid for the anonymous lifetime #1 defined on the method body at 5:9...
--> src/lib.rs:5:9
|
5 | / fn left(&self) -> Option<&Self> {
6 | | match self.all() {
7 | | None => None,
8 | | Some((left, _, _)) => Some(left),
9 | | }
10| | }
| |_________^
note: ...so that the reference type `&T` does not outlive the data it points at
--> src/lib.rs:6:24
|
6 | match self.all() {
|
Почему эта проблема возникает в признаке, но не в реализации для MyBTree
?
Почему компилятор жалуется на время жизни T
в методах, которые игнорируют значение T - в то время как он работает с методом value
, который упоминает T в его возвращаемом типе?