什么是函数的正确 return 类型 returning 一个用闭包借用 self 生成的迭代器

What is the correct return type of a function returning an iterator produced with a closure borrowing self

考虑以下代码并强调 children_iter()

use std::collections::HashMap;

type NodeMap = HashMap<i32, Node>;

struct Node {
    id: i32,
    parent: Option<i32>,
    sibling: Option<i32>,
    children: Vec<i32>,
    content: String,
}

pub struct NodeIterator<'a> {
    nodes: &'a NodeMap,
    current: &'a Node,
}

impl<'a> NodeIterator<'a> {
    fn new(node: &'a Node, nodes: &'a NodeMap) -> NodeIterator<'a> {
        NodeIterator {
            nodes,
            current: node,
        }
    }

    pub fn children_iter(&self) -> impl Iterator<Item = NodeIterator> {
        self.current
            .children
            .iter()
            .map(|i| self.nodes.get(i).unwrap())
            .map(|n| Self::new(n, self.nodes))
    }
}

此代码的编译失败:

error[E0373]: closure may outlive the current function, but it borrows `self`, which is owned by the current function
  --> src/lib.rs:30:18
   |
30 |             .map(|i| self.nodes.get(i).unwrap())
   |                  ^^^ ---- `self` is borrowed here
   |                  |
   |                  may outlive borrowed value `self`
   |
note: closure is returned here
  --> src/lib.rs:26:36
   |
26 |     pub fn children_iter(&self) -> impl Iterator<Item = NodeIterator> {
   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: to force the closure to take ownership of `self` (and any other referenced variables), use the `move` keyword
   |
30 |             .map(move |i| self.nodes.get(i).unwrap())
   |                  ^^^^^^^^

error[E0373]: closure may outlive the current function, but it borrows `self`, which is owned by the current function
  --> src/lib.rs:31:18
   |
31 |             .map(|n| Self::new(n, self.nodes))
   |                  ^^^              ---- `self` is borrowed here
   |                  |
   |                  may outlive borrowed value `self`
   |
note: closure is returned here
  --> src/lib.rs:26:36
   |
26 |     pub fn children_iter(&self) -> impl Iterator<Item = NodeIterator> {
   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: to force the closure to take ownership of `self` (and any other referenced variables), use the `move` keyword
   |
31 |             .map(move |n| Self::new(n, self.nodes))
   |                  ^^^^^^^^

有没有办法正确指定生命周期,以便明确返回的迭代器仅在当前 NodeIterator 的生命周期内有效?

您收到此错误的原因是因为在 Rust 中,迭代器是 延迟求值的 。看起来您的闭包将在 children_iter 函数中执行,但实际上它们不会执行,直到调用者调用返回的迭代器上的 next 方法。

编译器建议使用 move 关键字将借用的引用移动到解决问题的闭包中。但是,您也可以通过 急切地评估 您的迭代器并将结果收集到 Vec<NodeIterator> 中来解决问题。这是固定和编译示例中的两种方法:

use std::collections::HashMap;

type NodeMap = HashMap<i32, Node>;

struct Node {
    id: i32,
    parent: Option<i32>,
    sibling: Option<i32>,
    children: Vec<i32>,
    content: String,
}

pub struct NodeIterator<'a> {
    nodes: &'a NodeMap,
    current: &'a Node,
}

impl<'a> NodeIterator<'a> {
    fn new(node: &'a Node, nodes: &'a NodeMap) -> NodeIterator<'a> {
        NodeIterator {
            nodes,
            current: node,
        }
    }

    pub fn children_iter(&self) -> impl Iterator<Item = NodeIterator> {
        self.current
            .children
            .iter()
            // lazily-evaluted closures
            // they run in the caller's scope
            .map(move |i| self.nodes.get(i).unwrap())
            .map(move |n| Self::new(n, self.nodes))
    }
    
    pub fn children_iter_vec(&self) -> Vec<NodeIterator> {
        self.current
            .children
            .iter()
            // eagerly-evaluted closures
            // we run them in the current scope
            .map(|i| self.nodes.get(i).unwrap())
            .map(|n| Self::new(n, self.nodes))
            .collect()
    }
}

playground