rust - 具有生命周期和后续引用的可变方法

标签 rust lifetime borrow-checker

考虑以下代码:

struct Foo<'a> {
    borrowed: &'a u8,
    owned_one: Vec<u8>,
    owned_two: Vec<u8>,
    output: usize
}

impl<'a> Foo<'a> {
    fn do_stuff(&mut self) {
        self.output = self.owned_one.len();
        let zipped = self.owned_one.iter().zip(self.owned_two.iter());
        Self::subroutine(&zipped);
    }
    
    fn subroutine<Arg: Iterator<Item=(&'a u8, &'a u8)>>(_zipped: &Arg) {}
}

fn main() {
    let num = 0u8;
    let mut foo = Foo {
        borrowed: &num,
        owned_one: vec![0],
        owned_two: vec![1],
        output: 0
    };
    foo.do_stuff();
    let _out = &foo.output;
}

( playground link )

它无法编译,产生以下错误:

error: lifetime may not live long enough
  --> src/lib.rs:12:9
   |
8  | impl<'a> Foo<'a> {
   |      -- lifetime `'a` defined here
9  |     fn do_stuff(&mut self) {
   |                 - let's call the lifetime of this reference `'1`
...
12 |         Self::subroutine(&zipped);
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'a`

我不完全理解这个提示 - 当然self总是将生命周期分配给我们正在impl绑定(bind)的类? - 但我可以理解 zip() 的两个参数需要持续相同的时间。所以我将 do_stuff 更改为 &'a mut self

struct Foo<'a> {
    borrowed: &'a u8,
    owned_one: Vec<u8>,
    owned_two: Vec<u8>,
    output: usize
}

impl<'a> Foo<'a> {
    fn do_stuff(&'a mut self) {
        self.output = self.owned_one.len();
        let zipped = self.owned_one.iter().zip(self.owned_two.iter());
        Self::subroutine(&zipped);
    }
    
    fn subroutine<Arg: Iterator<Item=(&'a u8, &'a u8)>>(_zipped: &Arg) {}
}

fn main() {
    let num = 0u8;
    let mut foo = Foo {
        borrowed: &num,
        owned_one: vec![0],
        owned_two: vec![1],
        output: 0
    };
    foo.do_stuff();
    let _out = &foo.output;
}

但是,现在编译失败:

error[E0502]: cannot borrow `foo.output` as immutable because it is also borrowed as mutable
  --> src/lib.rs:27:16
   |
26 |     foo.do_stuff();
   |     -------------- mutable borrow occurs here
27 |     let _out = &foo.output;
   |                ^^^^^^^^^^^
   |                |
   |                immutable borrow occurs here
   |                mutable borrow later used here

为什么在 do_stuff 的参数列表中指定 self 的生命周期意味着我突然无法获取对 foo 的不可变引用之后;我能做些什么呢?

最佳答案

写作fn do_stuff(&'a mut self)在这种情况下,意味着这个借用的 self 的生命周期,必须与这个 self 借用的一样长borrowed 。这通常不是您想要的。

你的错误在这里fn subroutine<Arg: Iterator<Item=(&'a u8, &'a u8)>>(_zipped: &Arg) {} 。想想你的声明的词汇含义。您的方法什么都不返回,但需要“父级”生命周期?没有理由这样做。简单的解决方案就是为您的元素引入新的生命周期。喜欢fn subroutine<'i, Arg: Iterator<Item=(&'i u8, &'i u8)>>(_zipped: &Arg) {} 。除非你的函数返回一些链接到 'a , parent 的一生不应该在这里。

另外,最好接受 IntoIterator它更通用,没有理由通过引用来获取它,最后当你有如此复杂的通用时最好使用 where ,真的,如果你想迂腐,你需要两辈子:

fn subroutine<'i, 'j, Arg>(_zipped: Arg)
where
    Arg: IntoIterator<Item = (&'i u8, &'j u8)>,
{
}

关于rust - 具有生命周期和后续引用的可变方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75412434/

相关文章:

recursion - 在 Rust 中返回一个递归闭包

rust - 在 Rust 中使用引用和使用拥有的值有区别吗?

rust - 从结构 : cannot move out of borrowed content 中获取枚举字段

windows - 无法激活 rust 分析仪: bootstrap error

rust - 如何直接将有限字节从读取器复制到写入器

winapi - WinAPI OpenQuery产生错误

csv - 存储 csv::DecodedRecords 迭代器时变量的生命周期不够长

oop - 为什么 Rust 不支持特征对象向上转换?

rust - 如何表达闭包的生命周期限制以匹配特征有界生命周期?

rust - 在函数中返回由 serde_json 创建的结构