我正在尝试实现一个二叉树。我希望节点数据是独立的,因为有许多不同的实现方法,而树上的算法应该是通用的,并且与数据的存储方式无关。
但我遇到了一个奇怪的问题借用检查。基本上,当我用impl<TValue> Display for dyn Tree<TValue>
切换impl<TValue> Display for TreeNode<TValue>
时,问题就消失了。但我不知道为什么。为什么这个问题是由这种特质引起的呢?
我的代码是:
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
--> src\main.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`
对我来说,这毫无意义。函数体中没有任何内容捕获此值并试图将其保留在此函数的范围之外。这是借用检查器的限制吗?
发布于 2022-08-26 03:27:04
有一些心理循环,编译器必须跳过去对您的代码进行推理。原因是,当您有dyn Tree<TValue>
(在其中实现Display
)时,约束类型的生存期默认为'static
。因此,当您调用x.fmt(f)
时,x
类型必须是'static
才能实现fmt
方法,而回顾过去意味着self.left()
中用于获取x
的self
也必须是'static
。但事实并非如此,这就是错误。
简单的解决方法是为具有任意生存期的Display
实现dyn Tree<TValue>
:
impl<'a, TValue> Display for dyn Tree<TValue> + 'a
https://stackoverflow.com/questions/73495603
复制相似问题