gpt4 book ai didi

rust - 在实现返回可变引用的迭代器时,如何修复 “cannot infer an appropriate lifetime for autoref”?

转载 作者:行者123 更新时间:2023-12-03 11:39:24 26 4
gpt4 key购买 nike

我正在尝试为名为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>`
这就是为什么我需要所有 'aBlock要求(它们都借用了 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>。我以为 'aThreadIterator<'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
`cannot infer an appropriate lifetime for autoref due to conflicting requirements` but can't change anything due to trait definition constraints的答案是为迭代器引入一个 Option,我已经完成了。 Lifetime parameter problem in custom iterator over mutable referencesReimplementation of LinkedList: IterMut not compiling没有回答我的问题,尽管我很难将我的代码连接到他们的代码上。
我终于找到了行之有效的东西:
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 selfThreadIterator的生存期如何关联。因此,它无法保证&mut self的生存时间至少与ThreadIterator中的基础借用时间一样长。查看您的代码here,这将是第12行(请注意,我已经在上面的链接中修复了您的错误)。
您需要告诉编译器输出ThreadIterator上的生存期与输入&mut self上的生存期相同(或者,从技术上讲,它的生存期至少与之一样长,尽管您很可能希望在此处具有相同的生存期),否则编译器无法确保只要&mut self借用,ThreadIterator借用的“自我”就会一直存在。查看生存期省略规则here的规则,我们可以发现这不适用于您的代码,因此,您需要手动指定&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
})
}
}

关于rust - 在实现返回可变引用的迭代器时,如何修复 “cannot infer an appropriate lifetime for autoref”?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63121490/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com