This code defines a very simple trait for representing binary trees and a struct implementing that trait:
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),
}
}
}
The implementations of left
, right
and value
could be moved inside the trait as they only depend on the all
method defined by the trait, and not on implementation details.
This works fine with value
, but not with left
and right
. For example, if I try to move the implementation of left
in the body of the trait, I get the following compilation error:
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() {
|
Why does this problem occur in the trait but not in the implementation for MyBTree
?
Why does the compiler complain about the lifetime of T
in the methods who ignore the T value -- while it works with the method value
which does mention T in its return type?
#![feature(nll)]
– Tim Diekmannfn f<'a, 'b>() { let _: &'a &'b (); }
– dtolnayBTree
trait, I suggest you use the associated type version instead. This way, when you write generic functions usingBTree
, you won't need an additional type parameter forBTree
'sT
. – Francis Gagné