Rust:错误[E0495]:由于需求冲突,无法为autoref推断适当的生存期

时间:2019-07-15 09:08:57

标签: rust lifetime

这是最小的代码:

struct Node<T> {
    item: T,
    next: Link<T>,
}

type Link<T> = Option<Box<Node<T>>>;

pub struct IterMut<'a, T>(&'a mut Link<T>);

impl<'a, T> Iterator for IterMut<'a, T> {
    type Item = &'a mut T;
    fn next(&mut self) -> Option<Self::Item> {
        self.0.as_mut().map(|boxed_node| {
            self.0 = &mut boxed_node.next;
            &mut boxed_node.item
        })
    }
}

据我了解,应该没有问题。我做了很多搜索,但是没有办法。

error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
  --> src/lib.rs:13:16
   |
13 |         self.0.as_mut().map(|boxed_node| {
   |                ^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 12:5...
  --> src/lib.rs:12:5
   |
12 | /     fn next(&mut self) -> Option<Self::Item> {
13 | |         self.0.as_mut().map(|boxed_node| {
14 | |             self.0 = &mut boxed_node.next;
15 | |             &mut boxed_node.item
16 | |         })
17 | |     }
   | |_____^
note: ...so that reference does not outlive borrowed content
  --> src/lib.rs:13:9
   |
13 |         self.0.as_mut().map(|boxed_node| {
   |         ^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 10:6...
  --> src/lib.rs:10:6
   |
10 | impl<'a, T> Iterator for IterMut<'a, T> {
   |      ^^
note: ...so that reference does not outlive borrowed content
  --> src/lib.rs:14:22
   |
14 |             self.0 = &mut boxed_node.next;
   |                      ^^^^^^^^^^^^^^^^^^^^

1 个答案:

答案 0 :(得分:2)

我们可以将您的代码重写为:

struct Node<T> {
    item: T,
    next: Link<T>,
}

type Link<T> = Option<Box<Node<T>>>;

pub struct IterMut<'a, T>(&'a mut Link<T>);

impl<'a, T> Iterator for IterMut<'a, T> {
    type Item = &'a mut T;
    fn next(&mut self) -> Option<Self::Item> {
        if let Some(boxed_node) = self.0 {
            self.0 = &mut boxed_node.next;
            Some(&mut boxed_node.item)
        }
        else {
            None
        }
    }
}

您可以看到boxed_node的生命在函数结尾处结束,因此您无法返回指向它的引用链接。

解决方案是引用该框而不是引用该选项:

struct Node<T> {
    item: T,
    next: Link<T>,
}

type Link<T> = Option<Box<Node<T>>>;

pub struct IterMut<'a, T>(Option<&'a mut Box<Node<T>>>);

impl<'a, T> Iterator for IterMut<'a, T> {
    type Item = &'a mut T;
    fn next(&mut self) -> Option<Self::Item> {
        if let Some(boxed_node) = self.0.take() {
            self.0 = boxed_node.next.as_mut();
            Some(&mut boxed_node.item)
        }
        else {
            None
        }
    }
}

您也可以删除Box

struct Node<T> {
    item: T,
    next: Link<T>,
}

type Link<T> = Option<Box<Node<T>>>;

pub struct IterMut<'a, T>(Option<&'a mut Node<T>>);

impl<'a, T> Iterator for IterMut<'a, T> {
    type Item = &'a mut T;
    fn next(&mut self) -> Option<Self::Item> {
        if let Some(boxed_node) = self.0.take() {
            self.0 = boxed_node.next.as_mut().map(AsMut::as_mut);
            Some(&mut boxed_node.item)
        }
        else {
            None
        }
    }
}