为什么代码编译需要这些确切的生命周期?

Why are these exact lifetimes needed for the code to compile?

我正在编写一个解析器,需要从迭代器进行前瞻,但不想使用 Peekable 特征。相反,我为迭代器使用了一个包装器。我想出了这样的东西,省略了所有不必要的东西:

struct Wrapper<'a> {
    it: &'a mut Iterator<Item = &'a String>,
}

pub trait DoSomething {
    fn do_something(self);
}

impl<'a, T> DoSomething for T
where
    T: IntoIterator<Item = &'a String>,
{
    fn do_something(self) {
        let mut it = self.into_iter();
        let throwaway = Wrapper { it: &mut it };
    }
}

编译失败:

error[E0309]: the associated type `<T as std::iter::IntoIterator>::IntoIter` may not live long enough
  --> src/main.rs:15:39
   |
15 |         let throwaway = Wrapper { it: &mut it };
   |                                       ^^^^^^^
   |
   = help: consider adding an explicit lifetime bound `<T as std::iter::IntoIterator>::IntoIter: 'a`...
note: ...so that the type `<T as std::iter::IntoIterator>::IntoIter` is not borrowed for too long
  --> src/main.rs:15:39
   |
15 |         let throwaway = Wrapper { it: &mut it };
   |                                       ^^^^^^^

error[E0309]: the associated type `<T as std::iter::IntoIterator>::IntoIter` may not live long enough
  --> src/main.rs:15:39
   |
15 |         let throwaway = Wrapper { it: &mut it };
   |                                       ^^^^^^^
   |
   = help: consider adding an explicit lifetime bound `<T as std::iter::IntoIterator>::IntoIter: 'a`...
note: ...so that the type `<T as std::iter::IntoIterator>::IntoIter` will meet its required lifetime bounds
  --> src/main.rs:15:39
   |
15 |         let throwaway = Wrapper { it: &mut it };
   |                                       ^^^^^^^

虽然我不明白为什么这是必要的(问题1),但我在impl中的where子句中添加了T::IntoIter: 'a。这失败了:

error[E0597]: `it` does not live long enough
  --> src/main.rs:16:44
   |
16 |         let throwaway = Wrapper { it: &mut it };
   |                                            ^^ borrowed value does not live long enough
17 |     }
   |     - borrowed value only lives until here
   |
note: borrowed value must be valid for the lifetime 'a as defined on the impl at 9:1...
  --> src/main.rs:9:1
   |
9  | / impl<'a, T> DoSomething for T
10 | | where
11 | |     T: IntoIterator<Item = &'a String>,
12 | |     T::IntoIter: 'a,
...  |
17 | |     }
18 | | }
   | |_^

我也不明白为什么 it 的寿命不够长,因为释放顺序应该是 throwaway,然后是 it。使用第二个生命周期 'b 也不起作用,无论是 'a: 'b 还是 'b: 'a (我很沮丧,只是尝试了每一种组合)。

唯一有帮助的是将 Iterator 引用及其包含的引用的生命周期分开并将它们关联起来(无需指定 T::IntoIter 的生命周期):

struct Wrapper<'a, 'b: 'a> {
    it: &'a mut Iterator<Item = &'b String>,
}

为什么?

说 "The item references have to live at least as long as the iterator reference" 是有道理的,但我不明白为什么它们不能相同以及为什么错误消息暗示 Wrapper 构造而不是定义,其中改变生命周期根本没有帮助。

我发现有关生命周期的官方文档非常混乱。如果生命周期注解实际上改变了编译代码中关于释放的任何东西,或者它是否只是帮助静态分析而不实际改变一块内存的实际生命周期,它不会进入。

&'a mut Iterator<Item = &'a String>表示迭代器的引用和迭代器返回的引用的生命周期必须能够统一(到'a)。

声明迭代器和迭代器的引用具有不同的生命周期允许代码编译:

struct Wrapper<'i, 's: 'i> {
    it: &'i mut Iterator<Item = &'s String>,
}

不需要添加T::IntoIter: 'a

另请参阅: