Mar*_*ara 6 rust borrow-checker
我正在尝试实现一个二叉树。我希望节点数据是分开的,因为有很多不同的方式可以实现这一点,而树上的算法应该是通用的并且独立于数据的存储方式。
但我在借用检查器方面遇到了一个奇怪的问题。基本上,当我切换时impl<TValue> Display for dyn Tree<TValue>,impl<TValue> Display for TreeNode<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
  --> 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`
对我来说,这毫无意义。函数体中没有任何内容捕获该值并尝试使其超出该函数的范围。这是借用检查器的限制吗?
编译器必须跳过一些心理障碍才能推理您的代码。剧透,原因是当你有dyn Tree<TValue>(在你实现的地方Display)时,限制类型的生命周期默认为'static。因此,当您调用 时x.fmt(f),x类型必须是'static为了实现该fmt方法,并且向后看意味着self用于self.left()get 的类型x 也必须是'static这样。但事实并非如此,因此出现了错误。
Display简单的解决方法是在任何生命周期内实现dyn Tree<TValue>:
impl<'a, TValue> Display for dyn Tree<TValue> + 'a
| 归档时间: | 
 | 
| 查看次数: | 5850 次 | 
| 最近记录: |