简体   繁体   English

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

[英]How can I fix “cannot infer an appropriate lifetime for autoref” when implementing an iterator that returns mutable references?

I'm trying to write a mutable iterator for a linked list called Thread where each element implements Block .我正在尝试为一个名为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
        })
    }
}

Compiling this will output the error:编译这个会 output 报错:

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>`

This is why I need the 'a requirement for all Block s (they are borrowing a Runtime ):这就是为什么我需要对所有Block 'a要求(他们正在借用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())
    }
}

The first thing I tried was removing the mutable requirement from all references.我尝试的第一件事是从所有引用中删除可变要求。 Same errors.同样的错误。

I think the error is telling me that self.head.as_mut() is outliving self.head , so I must ensure that the lifetime of that reference is shorter than Thread<'a> .我认为错误告诉我self.head.as_mut()的寿命超过self.head ,因此我必须确保该引用的生命周期短于Thread<'a> I thought I fulfilled this requirement with the 'a lifetime for ThreadIterator<'a> .我以为我用'a life for ThreadIterator<'a>满足了这个要求。 In other words, you can't possibly drop Thread before ThreadIterator , right?换句话说,您不可能在ThreadIterator之前删除Thread ,对吗?

Edit:编辑:

I changed Block to a struct to simplify the code, though I need it to be a trait in the end.我将Block更改为 struct 以简化代码,尽管我最终需要它成为一个 trait。

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
        })
    }
}

It is based off of https://rust-unofficial.github.io/too-many-lists/second-iter-mut.html .它基于https://rust-unofficial.github.io/too-many-lists/second-iter-mut.html

The answer to `cannot infer an appropriate lifetime for autoref due to conflicting requirements` but can't change anything due to trait definition constraints was to introduce a Option for the iterator, which I have done. `cannot infer a proper life for autoref due to conflicting requirements`但由于特征定义约束而无法更改任何内容的答案是为迭代器引入一个Option ,我已经这样做了。 Lifetime parameter problem in custom iterator over mutable references and Reimplementation of LinkedList: IterMut not compiling didn't answer my question, though I have a hard time connecting my code to theirs. 可变引用上的自定义迭代器中的生命周期参数问题LinkedList 的重新实现:IterMut 未编译并没有回答我的问题,尽管我很难将我的代码连接到他们的代码。

I finally found something that does work:我终于找到了一些有用的东西:

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
        })
    }
}

I'm having a hard time applying this to the original code, because there might be two different lifetimes, one for the iterator and one for the trait.我很难将其应用于原始代码,因为可能有两种不同的生命周期,一种用于迭代器,一种用于特征。

Answered by u/quixotrykd/ :u/quixotrykd/回答:

The compiler seems to be choking here because it doesn't know how the lifetime on &mut self and ThreadIterator relate.编译器似乎在这里窒息,因为它不知道&mut selfThreadIterator的生命周期是如何关联的。 As such, it has no way to guarantee that &mut self lives at least as long as the underlying borrow in ThreadIterator .因此,它无法保证&mut self至少与ThreadIterator中的底层借用一样长。 Looking at your code here , that would be line 12 (note I've fixed your mistake in the above link).这里查看您的代码,那将是第 12 行(请注意,我已在上面的链接中修正了您的错误)。

You need to tell the compiler that the lifetime on the output ThreadIterator is the same as the input &mut self (or technically that it lasts at least as long, though you very likely want the same lifetime here), otherwise the compiler has no way to ensure that the "self" that's borrowed by &mut self stick around as long as the ThreadIterator 's borrow.您需要告诉编译器 output ThreadIterator上的生命周期与输入&mut self相同(或者从技术上讲,它至少持续的时间至少一样长,尽管您很可能在这里想要相同的生命周期),否则编译器无法确保&mut self借用的“self”只要ThreadIterator的借用就一直存在。 Looking at the rules for lifetime elision here , we can see that this doesn't apply to your code, and as such, you need to manually specify the lifetime on &mut self (otherwise it generates another, unrelated, anonymous lifetime, as indicated in the compiler's error message).查看此处的生命周期省略规则,我们可以看到这不适用于您的代码,因此,您需要在&mut self上手动指定生命周期(否则它会生成另一个不相关的匿名生命周期,如编译器的错误信息)。

The fixed code:固定代码:

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
        })
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 从Iterator实现调用方法时,无法推断autoref的适当生命周期 - Cannot infer appropriate lifetime for autoref when calling a method from an Iterator implementation 从闭包调用可变方法时无法推断 autoref 的生命周期 - Cannot infer lifetime for autoref when calling mutable method from closure 为什么在使用嵌套的可变引用时,我会收到错误“无法推断泛型参数的适当生命周期”? - Why do I get the error “cannot infer an appropriate lifetime for lifetime parameter in generic type” when using nested mutable references? 尝试将具有生命周期的返回值设置为结构时,由于存在冲突的要求,无法推断出 autoref 的适当生命周期 - Cannot infer an appropriate lifetime for autoref due to conflicting requirements when tried to set a return value with lifetime to a struct 创建引用错误的递归列表“由于要求冲突,无法推断 autoref 的适当生命周期” - Creating a recursive list of references errors with "cannot infer an appropriate lifetime for autoref due to conflicting requirements" 由于需求冲突,无法为 autoref 推断适当的生命周期 - Cannot infer an appropriate lifetime for autoref due to conflicting requirements Rust:由于要求冲突,无法推断 autoref 的适当生命周期 - Rust: cannot infer an appropriate lifetime for autoref due to conflicting requirements `由于需求冲突,无法为 autoref 推断适当的生命周期`,但由于特征定义约束,无法更改任何内容 - `cannot infer an appropriate lifetime for autoref due to conflicting requirements` but can't change anything due to trait definition constraints 从迭代器返回切片时无法推断适当的生命周期 - Cannot infer an appropriate lifetime when returning a slice from an iterator 如何修复:无法推断自动强制的适当生命周期 - How to fix: cannot infer an appropriate lifetime for automatic coercion
相关标签
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM