特性问题:借用的数据在关联函数之外转义



我正在尝试实现一个二进制树。我希望节点数据是独立的,因为有很多不同的方法可以实现这一点,而树上的算法应该是通用的,并且与数据的存储方式无关。

但我遇到了一个奇怪的问题,借款检查。基本上,当我用impl<TValue> Display for TreeNode<TValue>切换impl<TValue> Display for dyn Tree<TValue>时,问题就消失了。但我不知道为什么。为什么Trait引起了这个问题?

我的代码是:

use std::fmt::{Display, Formatter};
struct TreeNode<TValue> {
value: TValue,
left: Option<Box<TreeNode<TValue>>>,
right: Option<Box<TreeNode<TValue>>>,
}
trait Tree<TValue> {
fn value(&self) -> &TValue;
fn left(&self) -> Option<&dyn Tree<TValue>>;
fn right(&self) -> Option<&dyn Tree<TValue>>;
}
impl<TValue> Display for dyn Tree<TValue>
where
TValue: Display,
{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str("(")?;
Display::fmt(self.value(), f)?;
f.write_str(", ")?;
match self.left() {
Some(ref x) => x.fmt(f)?,
None => f.write_str("None")?,
}
f.write_str(", ")?;
match self.right().as_ref() {
Some(x) => x.fmt(f)?,
None => f.write_str("None")?,
}
f.write_str(")")
}
}
impl<TValue> Tree<TValue> for TreeNode<TValue>
where
TValue: Display,
{
fn value(&self) -> &TValue {
&self.value
}
fn left(&self) -> Option<&dyn Tree<TValue>> {
self.left.as_ref().map(|x| &**x as &dyn Tree<TValue>)
}
fn right(&self) -> Option<&dyn Tree<TValue>> {
self.right.as_ref().map(|x| &**x as &dyn Tree<TValue>)
}
}
fn main() {
let tree = Box::new(TreeNode {
value: 1,
left: Some(Box::new(TreeNode {
value: 2,
left: None,
right: None,
})),
right: Some(Box::new(TreeNode {
value: 3,
left: None,
right: None,
})),
}) as Box<dyn Tree<i32>>;
println!("{}", tree);
}

编译器打印:

error[E0521]: borrowed data escapes outside of associated function
--> srcmain.rs:24:15
|
19 |     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|            -----
|            |
|            `self` declared here, outside of the associated function body
|            `self` is a reference that is only valid in the associated function body
|            let's call the lifetime of this reference `'1`
...
24 |         match self.left() {
|               ^^^^^^^^^^^
|               |
|               `self` escapes the associated function body here
|               argument requires that `'1` must outlive `'static`

对我来说,这毫无意义。函数体中没有捕获此值并试图将其保持在该函数的范围之外。这是借用检查器的限制吗?

编译器必须克服一些心理障碍才能对代码进行推理。剧透,原因是当您有dyn Tree<TValue>(在其中实现Display(时,约束类型的生存期默认为'static。因此,当您调用x.fmt(f)时,为了实现fmt方法,x的类型必须是'static,并且向后看意味着self.left()中用于获取xself也必须'static。但事实并非如此,因此出现了错误。

简单的修复方法是为任何生存期的dyn Tree<TValue>实现Display

impl<'a, TValue> Display for dyn Tree<TValue> + 'a

最新更新