在实现返回可变引用的迭代器时,如何解决“无法为autoref推断适当的生存期”?

我正在尝试为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所有Blocks要求(它们都借用了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 selfThreadIterator联系。因此,它无法保证&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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

从Iterator实现中调用方法时,无法为autoref推断适当的生存期

尝试更改返回迭代器的闭包内的状态时,Rust错误“无法为借用表达式推断适当的生存期”

使用闭包返回对枚举变量内容的引用时,“无法推断适当的生存期”

如何使用结构和impl的生存期为实现推断合适的生存期?

如何解决生存期错误以在Rust中进行可变引用?

无法为返回引用的闭包推断合适的生存期

无法为生存期参数克隆特征对象推断适当的生存期

为什么编译器为特征及其实现推断不同的生存期?

从函数返回的迭代器的生存期要求冲突

如何为引用自身但不会突变的迭代器的关联类型指定生存期?

如何返回具有多个生存期的impl迭代器?

如何将返回值的生存期设置为要移入的变量的生存期?

在Dialogflow的实现编辑器中是否存在可变生存期?

由于递归结构中的需求冲突,因此无法推断出适当的生存期

Rust:错误[E0495]:无法推断出适当的生存期,以自动关闭中相互矛盾的要求

调用返回引用的函数时了解非词汇生存期

具有多个生存期的迭代器

在迭代器特征中指定关联类型的生存期

如何指定一个带引用的闭包,并返回实现与该引用具有相同生存期的特征的任何类型?

如何在Fn特征绑定返回的引用上定义生存期?

SmtpClient-什么是适当的生存期?

如何设置不是函数自变量的引用的生存期?

如何告诉编译器我返回的枚举变量始终没有生存期?

Rust字符串生存期和迭代器适配器(生存期编译错误)

Symfony 2:如何设置登录时的会话生存期?

即使数组包含的值也具有静态生存期,也无法将静态引用返回给临时数组

无法返回对lazy_static HashMap中的元素的引用,因为该元素的生存期不够长

“由于需求冲突,无法为autoref推断适当的生存时间”,但由于特征定义约束,因此无法更改任何内容

C ++中指针引用的生存期