使用refs实现迭代器时的生命周期推断问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用refs实现迭代器时的生命周期推断问题相关的知识,希望对你有一定的参考价值。
我正在为包含ref的结构实现一个简单的Iterator:
extern crate zip;
extern crate quick_xml;
extern crate chrono;
use std::io::{Seek, Write, Read, Error};
use std::fs::File;
use xlsx_read::zip::read::ZipFile;
use xlsx_read::zip::result::ZipResult;
use xlsx_read::zip::ZipArchive;
use xlsx_read::zip::write::{FileOptions, ZipWriter};
use xlsx_read::quick_xml::Reader as XmlReader;
use xlsx_read::quick_xml::events::Event;
use std::io::BufReader;
use xlsx_read::chrono::prelude::*;
pub struct XlsxFile<'a> {
path: &'a str,
archive: ZipArchive<File>,
sheet_count: usize,
curr: usize,
}
impl<'a> XlsxFile<'a> {
pub fn from(path: &'a str) -> Result<XlsxFile, Error> {
let file = File::open(path)?;
let archive = ZipArchive::new(file)?;
let sheet_count = archive.len();
Ok(XlsxFile {
path: path,
archive: archive,
sheet_count,
curr: 0,
})
}
}
pub struct XlsxSheet<'a> {
pub name: &'a str,
pub index: usize,
}
impl<'a> Iterator for XlsxFile<'a> {
type Item = XlsxSheet<'a>;
fn next(&mut self) -> Option<XlsxSheet<'a>> {
loop {
if self.sheet_count > 0 &&
self.sheet_count > self.curr {
let zip_file = self.archive.by_index(self.curr).unwrap();
let file_name = zip_file.name();
if file_name.contains("xl/worksheets/sheet") {
let sheet = XlsxSheet {
name: file_name, // works fine if String::from(file_name) is used
index: self.curr,
};
self.curr += 1;
return Some(sheet);
}
self.curr += 1;
continue;
} else {
break;
}
}
return None;
}
}
static XLSX_FILE: &'static str = "<location_to_xlsx_file>";
fn main() {
let mut file = xlsx_read::XlsxFile::from(XLSX_FILE).unwrap();
file.for_each(|s| println!("idx: {:?}", s.name));
}
但是我收到以下错误:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/xlsx_read.rs:50:45
|
50 | let zip_file = self.archive.by_index(self.curr).unwrap();
| ^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 46:5...
--> src/xlsx_read.rs:46:5
|
46 | / fn next(&mut self) -> Option<XlsxSheet<'a>> {
47 | | loop {
48 | | if self.sheet_count > 0 &&
49 | | self.sheet_count > self.curr {
... |
66 | | return None;
67 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/xlsx_read.rs:50:32
|
50 | let zip_file = self.archive.by_index(self.curr).unwrap();
| ^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 43:1...
--> src/xlsx_read.rs:43:1
|
43 | impl<'a> Iterator for XlsxFile<'a> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: ...so that the expression is assignable:
expected std::option::Option<xlsx_read::XlsxSheet<'a>>
found std::option::Option<xlsx_read::XlsxSheet<'_>>
error: aborting due to previous error
For more information about this error, try `rustc --explain E0495`.
我的问题是,如何告诉Rust编译器在这里使用适当的生命周期?即使我已经使用生命周期修饰符定义了XlsxSheet <'a>,并希望将名称绑定到&'a str,但不知何故这不会转换为有效的Rust代码。
答案
简单的解决方案:使用String
而不是&'a str
可以轻松解决此问题。
说明:
我不知道by_index
的定义,这似乎对这个问题非常重要。以下推理纯粹是猜测而且不可靠。它仅供参考。
self.archive
借用self
(在整个范围内有效,假设生命周期被命名为'me
),并且有生命的'me
。- 因此,
by_index
的返回值具有终身'me
。 - 哎呀,
XlsxSheet<'me>
与XlsxSheet<'a>
不兼容(预计会有)!
我们在这里想要的是XlsxSheet<'me>
是XlsxSheet<'a>
的一个子类型,如果'me
是协变的话,它反过来暗示'a
是XlsxSheet
的一个子类型。因此,您可以明确说明它们
fn next(&mut self) -> Option<XlsxSheet<'a>> where Self: 'a
// or
impl<'a> Iterator for XlsxFile<'a> + 'a
以上是关于使用refs实现迭代器时的生命周期推断问题的主要内容,如果未能解决你的问题,请参考以下文章