返回对内部集合的引用时的迭代器生命周期问题
Iterator lifetime issue when returning references to inner collection
我有一个将数据延迟加载到内部向量中的结构(但对于示例,这是省略的)。然后我为 IntoIterator 类型实现 IntoIterator
和 Iterator
:
struct EntryOwned(u32);
struct Entry<'a>(&'a u32);
impl<'a> EntryOwned {
fn to_entry(&'a self) -> Entry<'a> {
Entry(&self.0)
}
}
struct LazyStruct {
cache: Vec<EntryOwned>,
}
impl<'a> LazyStruct {
fn new(data: Vec<EntryOwned>) -> LazyStruct {
Self {
cache: data,
}
}
fn get_entry(&'a self, index: usize) -> Option<Entry<'a>> {
match self.cache.get(index) {
Some(entry_owned) => Some(entry_owned.to_entry()),
None => None,
}
}
}
impl<'a> IntoIterator for &'a mut LazyStruct {
type Item = Entry<'a>;
type IntoIter = LazyStructIter<'a>;
fn into_iter(self) -> Self::IntoIter {
LazyStructIter {
inner: self,
current_index: 0,
}
}
}
struct LazyStructIter<'a> {
inner: &'a mut LazyStruct,
current_index: usize,
}
impl<'a> LazyStructIter<'a> {
fn next_item(&'a mut self) -> Option<Entry<'a>> {
if self.current_index > self.inner.cache.len() {
return None;
}
let ret = self.inner.get_entry(self.current_index);
self.current_index += 1;
ret
}
}
impl<'a> Iterator for LazyStructIter<'a> {
type Item = Entry<'a>;
fn next(&mut self) -> Option<Self::Item> {
self.next_item()
}
}
这让我遇到了一生的问题:
Compiling playground v0.0.1 (/playground)
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/main.rs:64:14
|
64 | self.next_item()
| ^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 63:5...
--> src/main.rs:63:5
|
63 | / fn next(&mut self) -> Option<Self::Item> {
64 | | self.next_item()
65 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:64:9
|
64 | self.next_item()
| ^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 60:6...
--> src/main.rs:60:6
|
60 | impl<'a> Iterator for LazyStructIter<'a> {
| ^^
note: ...so that the types are compatible
--> src/main.rs:64:14
|
64 | self.next_item()
| ^^^^^^^^^
= note: expected `&mut LazyStructIter<'_>`
found `&mut LazyStructIter<'a>`
引用的生命周期应该绑定到 LazyStruct
,但我无法更改 Iter 特性,不接受任何生命周期说明符。
我已经检查了类似问题的一些答案:
Iterator returning items by reference, lifetime issue
编辑:Entry
是一个更复杂的数据结构,无法复制。我必须将它绑定到特定的生命周期,因为它包含对事物的引用。
其中一个指出迭代器应该持有对原始集合的引用而不是拥有它,因为它不允许 return 具有自身生命周期的引用。但我无法让它发挥作用。
那么,这里的参考应该怎么玩呢?
非常欢迎任何帮助,提前谢谢大家!
通常您不需要在 Rust 中指定生命周期,除非两件事中的其中之一为真,引用绑定到未知的所有者,或者引用是静态的。 Rust 表示它期望 '_
生命周期,这意味着它了解所有权并自行借用。
struct EntryOwned(u32);
struct Entry(u32);
impl EntryOwned {
fn to_entry(&self) -> Entry {
Entry(self.0)
}
}
struct LazyStruct {
cache: Vec<EntryOwned>,
}
impl LazyStruct {
fn new(data: Vec<EntryOwned>) -> LazyStruct {
Self {
cache: data,
}
}
fn get_entry(&self, index: usize) -> Option<Entry> {
match self.cache.get(index) {
Some(entry_owned) => Some(entry_owned.to_entry()),
None => None,
}
}
}
impl IntoIterator for LazyStruct {
type Item = Entry;
type IntoIter = LazyStructIter;
fn into_iter(self) -> Self::IntoIter {
LazyStructIter {
inner: self,
current_index: 0,
}
}
}
struct LazyStructIter {
inner: LazyStruct,
current_index: usize,
}
impl LazyStructIter {
fn next_item(&mut self) -> Option<Entry> {
if self.current_index > self.inner.cache.len() {
return None;
}
let ret = self.inner.get_entry(self.current_index);
self.current_index += 1;
ret
}
}
impl Iterator for LazyStructIter {
type Item = Entry;
fn next(&mut self) -> Option<Self::Item> {
self.next_item()
}
}
fn main() {
// let json_data = r#"{"item_1" : 10, "item_2" : 100, "item_3" : 1000}"#;
// if let Ok(data) = serde_json::from_str::<A>(json_data) {
// println!("{:?}", data);
// }
// else if let Ok(data) = serde_json::from_str::<B>(json_data) {
// println!("{:?}", data);
// }
for _ in 0..0 {
println!("foo");
}
}
删除生命周期规范后,它可以正常编译并运行。
你不能。
您要求 next()
返回的每个项目都有一个生命周期与
LazyStructIter
迭代器的存在。
Iterator
界面无法做到这一点:
pub trait Iterator {
type Item;
fn next(&mut self) -> Option<Self::Item>;
但是可以使用定义为的特征:
trait FakeIterator<'a> {
type Item;
fn next(&'a mut self) -> std::option::Option<Self::Item>;
}
impl<'a> FakeIterator<'a> for LazyStructIter<'a> {
type Item = Entry<'a>;
fn next(&'a mut self) -> Option<Self::Item> {
self.next_item()
}
}
目标是拥有一种迭代器,其中 returns 项从自身借用
RFC 1598 - GAT.
另请参阅此 article,了解有关此主题的一系列解决方法。
我有一个将数据延迟加载到内部向量中的结构(但对于示例,这是省略的)。然后我为 IntoIterator 类型实现 IntoIterator
和 Iterator
:
struct EntryOwned(u32);
struct Entry<'a>(&'a u32);
impl<'a> EntryOwned {
fn to_entry(&'a self) -> Entry<'a> {
Entry(&self.0)
}
}
struct LazyStruct {
cache: Vec<EntryOwned>,
}
impl<'a> LazyStruct {
fn new(data: Vec<EntryOwned>) -> LazyStruct {
Self {
cache: data,
}
}
fn get_entry(&'a self, index: usize) -> Option<Entry<'a>> {
match self.cache.get(index) {
Some(entry_owned) => Some(entry_owned.to_entry()),
None => None,
}
}
}
impl<'a> IntoIterator for &'a mut LazyStruct {
type Item = Entry<'a>;
type IntoIter = LazyStructIter<'a>;
fn into_iter(self) -> Self::IntoIter {
LazyStructIter {
inner: self,
current_index: 0,
}
}
}
struct LazyStructIter<'a> {
inner: &'a mut LazyStruct,
current_index: usize,
}
impl<'a> LazyStructIter<'a> {
fn next_item(&'a mut self) -> Option<Entry<'a>> {
if self.current_index > self.inner.cache.len() {
return None;
}
let ret = self.inner.get_entry(self.current_index);
self.current_index += 1;
ret
}
}
impl<'a> Iterator for LazyStructIter<'a> {
type Item = Entry<'a>;
fn next(&mut self) -> Option<Self::Item> {
self.next_item()
}
}
这让我遇到了一生的问题:
Compiling playground v0.0.1 (/playground)
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/main.rs:64:14
|
64 | self.next_item()
| ^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 63:5...
--> src/main.rs:63:5
|
63 | / fn next(&mut self) -> Option<Self::Item> {
64 | | self.next_item()
65 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:64:9
|
64 | self.next_item()
| ^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 60:6...
--> src/main.rs:60:6
|
60 | impl<'a> Iterator for LazyStructIter<'a> {
| ^^
note: ...so that the types are compatible
--> src/main.rs:64:14
|
64 | self.next_item()
| ^^^^^^^^^
= note: expected `&mut LazyStructIter<'_>`
found `&mut LazyStructIter<'a>`
引用的生命周期应该绑定到 LazyStruct
,但我无法更改 Iter 特性,不接受任何生命周期说明符。
我已经检查了类似问题的一些答案:
Iterator returning items by reference, lifetime issue
编辑:Entry
是一个更复杂的数据结构,无法复制。我必须将它绑定到特定的生命周期,因为它包含对事物的引用。
其中一个指出迭代器应该持有对原始集合的引用而不是拥有它,因为它不允许 return 具有自身生命周期的引用。但我无法让它发挥作用。 那么,这里的参考应该怎么玩呢?
非常欢迎任何帮助,提前谢谢大家!
通常您不需要在 Rust 中指定生命周期,除非两件事中的其中之一为真,引用绑定到未知的所有者,或者引用是静态的。 Rust 表示它期望 '_
生命周期,这意味着它了解所有权并自行借用。
struct EntryOwned(u32);
struct Entry(u32);
impl EntryOwned {
fn to_entry(&self) -> Entry {
Entry(self.0)
}
}
struct LazyStruct {
cache: Vec<EntryOwned>,
}
impl LazyStruct {
fn new(data: Vec<EntryOwned>) -> LazyStruct {
Self {
cache: data,
}
}
fn get_entry(&self, index: usize) -> Option<Entry> {
match self.cache.get(index) {
Some(entry_owned) => Some(entry_owned.to_entry()),
None => None,
}
}
}
impl IntoIterator for LazyStruct {
type Item = Entry;
type IntoIter = LazyStructIter;
fn into_iter(self) -> Self::IntoIter {
LazyStructIter {
inner: self,
current_index: 0,
}
}
}
struct LazyStructIter {
inner: LazyStruct,
current_index: usize,
}
impl LazyStructIter {
fn next_item(&mut self) -> Option<Entry> {
if self.current_index > self.inner.cache.len() {
return None;
}
let ret = self.inner.get_entry(self.current_index);
self.current_index += 1;
ret
}
}
impl Iterator for LazyStructIter {
type Item = Entry;
fn next(&mut self) -> Option<Self::Item> {
self.next_item()
}
}
fn main() {
// let json_data = r#"{"item_1" : 10, "item_2" : 100, "item_3" : 1000}"#;
// if let Ok(data) = serde_json::from_str::<A>(json_data) {
// println!("{:?}", data);
// }
// else if let Ok(data) = serde_json::from_str::<B>(json_data) {
// println!("{:?}", data);
// }
for _ in 0..0 {
println!("foo");
}
}
删除生命周期规范后,它可以正常编译并运行。
你不能。
您要求 next()
返回的每个项目都有一个生命周期与
LazyStructIter
迭代器的存在。
Iterator
界面无法做到这一点:
pub trait Iterator {
type Item;
fn next(&mut self) -> Option<Self::Item>;
但是可以使用定义为的特征:
trait FakeIterator<'a> {
type Item;
fn next(&'a mut self) -> std::option::Option<Self::Item>;
}
impl<'a> FakeIterator<'a> for LazyStructIter<'a> {
type Item = Entry<'a>;
fn next(&'a mut self) -> Option<Self::Item> {
self.next_item()
}
}
目标是拥有一种迭代器,其中 returns 项从自身借用 RFC 1598 - GAT.
另请参阅此 article,了解有关此主题的一系列解决方法。