我能否限制从结构寿命的污染?
一般地,如果你在你的任何结构的领域使用它们,然后你不能。由于很好的原因,它们被明确地表示出来(参见Why are explicit lifetimes needed in Rust?),并且一旦你有一个包含需要显式生存期的对象的结构,那么它们就必须被传播。
平时注意这不是消费者结构的问题,因为混凝土的寿命,然后由编译器施加:
struct NameRef<'a>(&'a str);
let name = NameRef("Jake"); // 'a is 'static
一个也小幅实施缓解了“噪音” next
通过使用Self::Item
的定义。
impl<'a> Iterator for LogReader<'a > {
type Item = (&'a str,&'a[ConvertedValue]);
fn next(&mut self) -> Option<Self::Item> {
(self.next_fn)(self)
}
}
然而,你的关心其实隐藏着一个更严重的问题:不像你所提到的,从next
返回的值是从结构不一定内部数据。实际上,它们的寿命只有通用寿命'a
,并且LogReader
中没有任何内容实际上受到该寿命的约束。
这意味着两件事情:
(1)我可以通过一个函数,提供完全不同的东西,它会工作得很好:
static NO_DATA: &[()] = &[()];
fn my_next_fn<'a>(reader: &mut LogReader<'a>) -> Option<(&'a str, &'a[ConvertedValue])> {
Some(("wat", NO_DATA))
}
(2)即使我想我的功能从日志阅读器的内部数据中返回一些内容,这是行不通的,因为生命周期根本不匹配。让我们来尝试一下呢,看看会发生什么:
static DATA: &[()] = &[()];
fn my_next_fn<'a>(reader: &mut LogReader<'a>) -> Option<(&'a str, &'a[ConvertedValue])> {
Some((&reader.data[0..4], DATA))
}
fn main() {
let mut a = LogReader {
data: "This is DATA!".to_owned(),
next_fn: my_next_fn
};
println!("{:?}", a.next());
}
,编译器将抛出你:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src/main.rs:26:12
|
26 | Some((&reader.data[0..4], DATA))
| ^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the body at 25:88...
--> src/main.rs:25:89
|
25 | fn my_next_fn<'a>(reader: &mut LogReader<'a>) -> Option<(&'a str, &'a[ConvertedValue])> {
| _________________________________________________________________________________________^ starting here...
26 | | Some((&reader.data[0..4], DATA))
27 | | }
| |_^ ...ending here
note: ...so that reference does not outlive borrowed content
--> src/main.rs:26:12
|
26 | Some((&reader.data[0..4], DATA))
| ^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the body at 25:88...
--> src/main.rs:25:89
|
25 | fn my_next_fn<'a>(reader: &mut LogReader<'a>) -> Option<(&'a str, &'a[ConvertedValue])> {
| _________________________________________________________________________________________^ starting here...
26 | | Some((&reader.data[0..4], DATA))
27 | | }
| |_^ ...ending here
note: ...so that expression is assignable (expected std::option::Option<(&'a str, &'a [()])>, found std::option::Option<(&str, &[()])>)
--> src/main.rs:26:5
|
26 | Some((&reader.data[0..4], DATA))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...其中匿名寿命#1是日志读取器的寿命。强制&mut LogReader
也有终身'a
(&'a mut LogReader<'a>
)将导致尝试实施Iterator
进一步生命期问题。这基本上缩小到'a
与提及LogReader
本身的值不相符的事实。
那么,我们该如何解决这个问题呢?
但这并不改变该返回类型的引用,因此寿命注解进入它
虽然这是不准确的(因为在某些情况下会出现一辈子省音),这一事实给解决方案提示:或者避免返回引用或将数据委托给单独的对象,以便'a
可以绑定到该对象的生命周期。对你的问题的答案的最后一部分是Iterator returning items by reference, lifetime issue。
“,并返回一个元组引用内部数据结构”你确定你不想要一个方法,而不是一个字段中的函数对象?现在,您正在使用'next_fn',就好像它是一种方法。 –
该字段仅包含一个指向该对象上方法的指针。这不是很好,但我正在移植python,所以有很多不好转换。 –
来自Python的方法很好地转换成[methods](https://doc.rust-lang.org/book/method-syntax.html)。 –