我正在尝试为Thread
每个元素实现的链表编写一个可变的迭代器Block
。
trait Block<'a> {
fn next(&mut self) -> Option<&'a mut (dyn Block<'a> + 'a)> {
None
}
}
pub struct Thread<'a> {
head: Box<dyn Block<'a> + 'a>,
}
impl<'a> Thread<'a> {
fn iter_mut(&mut self) -> ThreadIterator<'a> {
ThreadIterator {
next: Some(self.head.as_mut()),
}
}
}
pub struct ThreadIterator<'a> {
next: Option<&'a mut (dyn Block<'a> + 'a)>,
}
impl<'a> Iterator for ThreadIterator<'a> {
type Item = &'a mut (dyn Block<'a> + 'a);
fn next(&mut self) -> Option<&'a mut (dyn Block<'a> + 'a)> {
self.next.take().map(|mut block| {
self.next = block.next();
block
})
}
}
编译将输出错误:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/lib.rs:14:34
|
14 | next: Some(self.head.as_mut()),
| ^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 12:5...
--> src/lib.rs:12:5
|
12 | / fn iter_mut(&mut self) -> ThreadIterator<'a> {
13 | | ThreadIterator {
14 | | next: Some(self.head.as_mut()),
15 | | }
16 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:14:24
|
14 | next: Some(self.head.as_mut()),
| ^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 11:6...
--> src/lib.rs:11:6
|
11 | impl<'a> Thread<'a> {
| ^^
note: ...so that the types are compatible
--> src/lib.rs:14:24
|
14 | next: Some(self.head.as_mut()),
| ^^^^^^^^^^^^^^^^^^
= note: expected `dyn Block<'_>`
found `dyn Block<'a>`
这就是为什么我需要'a
所有Block
s的要求(它们都借用了Runtime
):
struct Runtime {}
struct ExampleBlock<'a> {
runtime: &'a Runtime,
next: Box<dyn Block<'a> + 'a>,
}
impl<'a> Block<'a> for ExampleBlock<'a> {
fn next(&mut self) -> Option<&'a mut (dyn Block<'a> + 'a)> {
Some(self.next.as_mut())
}
}
我尝试的第一件事是从所有引用中删除可变需求。同样的错误。
我认为该错误告诉我该消息self.head.as_mut()
已过期self.head
,因此我必须确保该引用的生存期短于Thread<'a>
。我以为我的'a
生命达到了这一要求ThreadIterator<'a>
。换句话说,您不可能掉到Thread
之前ThreadIterator
,对吗?
编辑:
我改变Block
了结构以简化代码,尽管我最终需要将其作为特征。
struct Block {}
impl<'a> Block {
fn next(&mut self) -> Option<&'a mut Block> {
None
}
}
pub struct Thread {
head: Block,
}
impl<'a> Thread {
fn iter_mut(&mut self) -> ThreadIterator<'a> {
ThreadIterator {
next: Some(&mut self.head),
}
}
}
pub struct ThreadIterator<'a> {
next: Option<&'a mut Block>,
}
impl<'a> Iterator for ThreadIterator<'a> {
type Item = &'a mut Block;
fn next(&mut self) -> Option<&'a mut Block> {
self.next.take().map(|mut block| {
self.next = block.next();
block
})
}
}
它基于https://rust-unofficial.github.io/too-many-lists/second-iter-mut.html。
“由于需求冲突而无法为autoref推断合适的生存期”但由于特征定义约束而不能改变任何内容的答案是Option
为迭代器引入a ,我已经做到了。自定义迭代器中的可变参数上的生命周期参数问题以及LinkedList的重新实现:未编译的IterMut没有回答我的问题,尽管我很难将代码连接到他们的代码上。
我终于找到了行之有效的东西:
pub struct Block {}
impl<'a> Block {
fn next(&mut self) -> Option<&'a mut Block> {
None
}
}
pub struct Thread {
head: Block,
}
impl Thread {
fn iter_mut(&mut self) -> ThreadIterator<'_> { // The lifetime here is changed
ThreadIterator {
next: Some(&mut self.head),
}
}
}
pub struct ThreadIterator<'a> {
next: Option<&'a mut Block>,
}
impl<'a> Iterator for ThreadIterator<'a> {
type Item = &'a mut Block;
fn next(&mut self) -> Option<&'a mut Block> {
self.next.take().map(|mut block| {
self.next = block.next();
block
})
}
}
我很难将其应用于原始代码,因为可能有两个不同的生存期,一个用于迭代器,一个用于特征。
由u / quixotrykd /回答:
编译器似乎这里窒息,因为它不知道如何寿命&mut self
和ThreadIterator
联系。因此,它无法保证&mut self
生存至少与的潜在借贷时间一样长ThreadIterator
。在这里查看您的代码,即第12行(请注意,我已经在上面的链接中修复了您的错误)。
您需要告诉编译器输出的生存期与输入的生存期ThreadIterator
相同&mut self
(或者从技术上讲,它至少可以持续同样长的时间,尽管您很可能希望在此具有相同的生存期),否则编译器无法确保&mut self
只要坚持不懈地借来的“自我” ThreadIterator
。查看此处的生存期删除规则,我们可以发现这不适用于您的代码,因此,您需要手动指定生存期&mut self
(否则,它将生成另一个不相关的匿名生存期,如编译器的错误信息)。
固定代码:
pub trait Block<'a> { // Make public to resolve unrelated error
fn next(&mut self) -> Option<&'a mut (dyn Block<'a> + 'a)> {
None
}
}
pub struct Thread<'a> {
head: Box<dyn Block<'a> + 'a>,
}
impl<'a> Thread<'a> {
fn iter_mut(&'a mut self) -> ThreadIterator<'a> { // Add lifetime to &self
ThreadIterator {
next: Some(self.head.as_mut()),
}
}
}
pub struct ThreadIterator<'a> {
next: Option<&'a mut (dyn Block<'a> + 'a)>,
}
impl<'a> Iterator for ThreadIterator<'a> {
type Item = &'a mut (dyn Block<'a> + 'a);
fn next(&mut self) -> Option<&'a mut (dyn Block<'a> + 'a)> {
self.next.take().map(|mut block| {
self.next = block.next();
block
})
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句