![](/img/trans.png)
[英]Issue with Rust using dynamic polymorphism on trait when specifying lifetime on self
[英]Rust - Specifying a Lifetime Parameter for the Borrow Trait
我有一個包含一些數據( &[u8]
)的結構( DataSource
)和一個迭代它的自定義迭代器。
struct DataSource<'a> {
data: &'a Vec<u8>,
}
struct MyIterator<'a> {
source: DataSource<'a>,
}
impl<'a> Iterator for MyIterator<'a> {
type Item = &'a u8;
fn next(&mut self) -> Option<Self::Item> {
let ret = &self.source.data[0];
Some(ret)
}
}
請注意這里的一些重要事項:
Item
有生命周期。 這僅是可能的,因為該結構的字段之一已經使用了生命周期 - source
Item
的生命周期是'a
,所以ret
的生命周期也必須是'a
。現在,由於我的用例,我想添加以下功能:
DataSource
也應該能夠擁有自己的data
。data
不是Clone
。 我最初的解決方案是將data: &'a [u8]
替換為data: D
where D: Borrow<[u8]>
:
struct DataHolder<D: Borrow<[u8]>> {
data: D,
}
struct MyIterator<D: Borrow<[u8]>> {
holder: DataHolder<D>,
}
impl<D: Borrow<[u8]>> Iterator for MyIterator<D> {
type Item = &u8;
fn next(&mut self) -> Option<Self::Item> {
Some(&self.holder.data.borrow()[0])
}
}
我認為這會起作用,因為&[u8]
和[u8]
都實現了Borrow<[u8]>
。 但是,這不會編譯。 迭代器的項目是&u8
所以它需要一個明確的生命周期。 MyIterator
沒有任何生命周期可以引用,因此編寫type Item = &'a u8
會導致未聲明的生命周期。
我的下一個解決方案是添加幻像數據並通過它引用生命周期:
struct DataHolder<'a, D: Borrow<[u8]>, T: 'a> {
data: D,
p: PhantomData<&'a T>,
}
struct MyIterator<'a, D: Borrow<[u8]>, T: 'a> {
holder: DataHolder<'a, D, T>,
}
impl<'a, D: Borrow<[u8]>, T> Iterator for MyIterator<'a, D, T> {
type Item = &'a u8;
fn next(&mut self) -> Option<Self::Item> {
Some(&self.holder.data.borrow()[0])
}
}
這會產生以下錯誤:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src\bin\main7c.rs:16:26
|
16 | Some(&self.holder.data.borrow()[0])
| ^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime defined here...
--> src\bin\main7c.rs:15:10
|
15 | fn next(&mut self) -> Option<Self::Item> {
| ^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src\bin\main7c.rs:16:9
|
16 | Some(&self.holder.data.borrow()[0])
| ^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined here...
--> src\bin\main7c.rs:12:6
|
12 | impl<'a, D: Borrow<[u8]>, T> Iterator for MyIterator<'a, D, T> {
| ^^
note: ...so that the types are compatible
--> src\bin\main7c.rs:15:43
|
15 | fn next(&mut self) -> Option<Self::Item> {
| ______________________________________________^
16 | | Some(&self.holder.data.borrow()[0])
17 | | }
| |_____^
= note: expected `<MyIterator<'a, D, T> as Iterator>`
found `<MyIterator<'_, D, T> as Iterator>`
編譯器無法推斷返回值的生命周期必須與第一個示例中'a
一樣。 我可以解決這個放棄實現Iterator
的問題,但這會破壞使用迭代器的全部意義。
impl<'a, D: Borrow<[u8]>, T> MyIterator<'a, D, T> {
fn next(&'a mut self) -> Option<&'a u8> {
Some(&self.holder.data.borrow()[0])
}
}
有沒有辦法在不放棄Iterator
特性的情況下解決這個問題?
有沒有辦法在不放棄
Iterator
特性的情況下解決這個問題?
不。假設D
是Vec<u8>
。 終生'a
什么?
當它已經是一個引用時,我們可以重用它的生命周期。 這是因為,假設data
是&'a T
, &self.data[0]
where self
is &'b mut self
可以看作(偽Rust):
let slice_data_pointer: &'a u8 = (*self.data);
slice_data_pointer
也就是說,我們只是復制引用。
但是當擁有data
時,就沒有要復制的引用了。 唯一的真實來源是self.data
本身 - 而self.data
僅在self
的生命周期內被借用。 所以你需要迭代器的產生值依賴於next()
的self
。 這是經典的借貸/流式迭代器,它:
self
借來。 換句話說,它不能實現像collect()
這樣的操作。 但是,我們可以從實際Vec
實現Iterator
的方式中學習。 具體來說,它不會 - 通常擁有值也是如此 - 它們實現IntoIterator
來代替對它們的引用,可能使用iter()
方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.