允许引用生命周期超过闭包

Allowing reference lifetime to outlive a closure

我正在通过尝试实现单链表来掌握 Rust。这是我的数据结构:

struct Linked<T> {
    head: Option<Box<Node<T>>>
}

struct Node<T> {
    data: T,
    next: Option<Box<Node<T>>>
}

现在,我想为此添加一个迭代器:

struct LinkedIter<'a, T: 'a> {
    node: Option<&'a Node<T>>,
}

我已经为 Linked<T> 编写了一个 .iter() 方法,它可以编译并且工作正常。

impl<T> Linked<T> {
    fn iter(&self) -> LinkedIter<T> {
        LinkedIter { node: match self.head {
                Some(ref node) => Some(&**node),
                None           => None
            }
        }
    }
}

现在,这个 match 块正在将 Option<Box<Linked<T>>> 转换为 Option<&Linked<T>>。这正是 Option::map() 方法的用途。所以我重新实现了这个方法,使用 head.as_ref() 而不是 head 来避免在闭包中获取 Option 内容的所有权。

impl<T> Linked<T> {
    fn iter(&self) -> LinkedIter<T> {
        LinkedIter { node:
            self.head.as_ref().map(|b: &Box<Node<T>>| &**b)
        }
    }
}

不幸的是,不能允许在闭包中创建的引用比闭包更有效,因为它引用了作为参数传递到闭包中的内容。编译器抱怨(解释一下):

error: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements:

first, the lifetime cannot outlive the anonymous lifetime #1 defined [in the closure]

but, the lifetime must be valid for [the lifetime of the iter function]

so that the [node:] expression is assignable

如何向编译器解释引用在闭包结束后仍然有效?

(Playground)

想法是通知编译器您在 map() 中获取的引用与迭代器一样长。我是这样工作的:

impl<T> Linked<T> {
    fn iter<'a>(&'a self) -> LinkedIter<T> {
        LinkedIter { node:
            self.head.as_ref().map(|b: &'a Box<Node<T>>| &**b)
        }
    }
}