我能否限制從結構壽命的污染?
一般地,如果你在你的任何結構的領域使用它們,然後你不能。由於很好的原因,它們被明確地表示出來(參見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)。 –