简体   繁体   English

Rust 迭代器遍历 Rc 层次结构的生命周期

[英]Lifetime for Rust Iterator to Walk a Hierarchy of `Rc`s

I've got a Rust struct that represents a hierarchical data structure and each struct contains a Vec<Rc<Self>> that creates the hierarchical structure.我有一个表示分层数据结构的 Rust 结构,每个结构都包含一个创建分层结构的Vec<Rc<Self>> I want to create an iterator that iterates over Rc s to every member of the hierarchy, starting with a given node.我想创建一个迭代器,从给定节点开始,迭代Rc到层次结构的每个成员。 The Node struct has a lifetime parameter 'a because the entire hierarchy refers some &'a str s from a text document that the whole hierarchy is based on (contained inside NodeDetail<'a> ). Node结构有一个生命周期参数'a因为整个层次结构引用了整个层次结构所基于的文本文档中的一些&'a str s(包含在NodeDetail<'a>中)。

pub struct Node<'a> {
    pub detail: NodeDetail<'a>,
    pub children: Vec<Rc<Self>>,
}

impl<'a> Node<'a> {

    // Returns an iterator over `Rc`s to all the children
    pub fn iter(&self) -> Box<(dyn Iterator<Item=Rc<Self>> + 'static)> {
        let mut ans:Box<(dyn Iterator<Item=Rc<Self>> + 'static)> = Box::new(std::iter::empty());

        for c in self.children.iter() {
            ans = Box::new(ans.chain(std::iter::once(c.clone())));
            ans = Box::new(ans.chain(c.iter()));
        }

        ans
    }

}

With this attempt, I'm getting this error:通过这次尝试,我收到了这个错误:

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
  --> src/model/updm/impl_common.rs:23:40
   |
23 |             ans = Box::new(ans.chain(c.iter()));
   |                                        ^^^^
   |
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 5:6...
  --> src/model/updm/impl_common.rs:5:6
   |
5  | impl<'a> super::UpdmCommon<'a> {
   |      ^^
note: ...so that the types are compatible
  --> src/model/updm/impl_common.rs:23:40
   |
23 |             ans = Box::new(ans.chain(c.iter()));
   |                                        ^^^^
   = note: expected `&UpdmCommon<'_>`
              found `&UpdmCommon<'a>`
   = note: but, the lifetime must be valid for the static lifetime...
note: ...so that the expression is assignable
  --> src/model/updm/impl_common.rs:23:19
   |
23 |             ans = Box::new(ans.chain(c.iter()));
   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   = note: expected `Box<(dyn Iterator<Item = Rc<UpdmCommon<'a>>> + 'static)>`
              found `Box<dyn Iterator<Item = Rc<UpdmCommon<'a>>>>`

I think it's somehow confusing the lifetime that the Node struct is generic over with a lifetime specific to the iterator.我认为它以某种方式混淆了Node结构是通用的生命周期与特定于迭代器的生命周期。 I'm cloning the Rc s so the Item of the iterator is owned and has a 'static lifetime.我正在克隆Rc ,因此迭代器的Item是拥有的并且具有'static生命周期”。 I think the iterator itself should also be owned, which would make it 'static .我认为迭代器本身也应该被拥有,这将使它成为'static I first tried Box<dyn Iterator<Item=Rc<Self>>> , then added the 'static annotation to try to fix the first errors I got.我首先尝试了Box<dyn Iterator<Item=Rc<Self>>> ,然后添加了'static注释以尝试修复我遇到的第一个错误。 Anyone know how to fix this?有人知道怎么修这个东西吗? Thanks!谢谢!

I figured it out.我想到了。 I do my best troubleshooting immediately after I ask for help.在寻求帮助后,我会立即尽最大努力进行故障排除。 Kind of like how I do my best email proofreading after pressing send.有点像我在按下发送后如何尽最大努力进行 email 校对。

It turns out that I needed Box<(dyn Iterator<Item=Rc<Self>> + 'a)> which makes sense now that I think about it because the iterator can't outlive the original &'a str s that the whole hierarchy depends on.事实证明,我需要Box<(dyn Iterator<Item=Rc<Self>> + 'a)> ,现在我想到它是有道理的,因为迭代器不能比原来的&'a str层次结构取决于。

You need to tie the lifetime of the value you're returning from iter() to &self and you need to cast the boxed iterator to a trait object.您需要将从iter()返回的值的生命周期绑定到&self ,并且需要将装箱迭代器转换为特征 object。

use std::rc::Rc;

pub struct NodeDetail<'a>(&'a str);

pub struct Node<'a> {
    pub detail: NodeDetail<'a>,
    pub children: Vec<Rc<Self>>,
}

impl<'a> Node<'a> {

    // Returns an iterator over `Rc`s to all the children
    pub fn iter(&'a self) -> Box<(dyn Iterator<Item=Rc<Self>> + 'a)> {
        let mut ans = Box::new(std::iter::empty()) as Box<dyn Iterator<Item=Rc<Self>>>;

        for c in self.children.iter() {
            
            ans = Box::new(ans.chain(std::iter::once(c.clone())));
            ans = Box::new(ans.chain(c.iter()));
        }

        ans
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM