特质中 self 的显式生命周期似乎会导致循环中“E0499 无法一次多次借用`*emitter`作为可变对象”

问题描述 投票:0回答:1

我遇到了一个问题,该特征可以返回对

self
中数据的引用。这是一个最小的示例:

trait A<T> {
    fn emit_symbol(&mut self) -> T;
}

fn via_ans<'a>(emitter: &'a mut impl A<char>) -> String {
    let mut rval = String::new();
    for _ in 0..30 {
        let ch = emitter.emit_symbol();
        rval.push(ch)
    }
    rval
}

struct Hippo<T> {
    things: Vec<T>,
}

impl<T> A<&T> for Hippo<T> {
    fn emit_symbol(&mut self) -> &T {
        &self.things[2]
    }
}

出现错误

error: `impl` item signature doesn't match `trait` item signature
  --> src/b.rs:19:5
   |
2  |     fn emit_symbol(&mut self) -> T;
   |     ------------------------------- expected `fn(&'1 mut b::Hippo<T>) -> &'2 T`
...
19 |     fn emit_symbol(&mut self) -> &T {
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 mut b::Hippo<T>) -> &'1 T`
   |
   = note: expected signature `fn(&'1 mut b::Hippo<T>) -> &'2 T`
              found signature `fn(&'1 mut b::Hippo<T>) -> &'1 T`
help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
  --> src/b.rs:2:34
   |
2  |     fn emit_symbol(&mut self) -> T;
   |                                  ^ consider borrowing this type parameter in the trait

如果我为

&'s self
的特征添加生命周期,那么实现就可以工作,但我在使用该特征方法的循环中遇到了一个新错误。

trait A<'s, T> {
    fn emit_symbol(&'s mut self) -> T;
}

fn via_ans<'a: 'b, 'b>(emitter: &'a mut impl A<'b, char>) -> String {
    let mut rval = String::new();
    for _ in 0..30 {
        let ch = emitter.emit_symbol();
        rval.push(ch)
    }
    rval
}

struct Hippo<T> {
    things: Vec<T>,
}

impl<'s, T> A<'s, &'s T> for Hippo<T> {
    fn emit_symbol(&'s mut self) -> &'s T {
        &self.things[2]
    }
}

出现错误

error[E0499]: cannot borrow `*emitter` as mutable more than once at a time
  --> src/main.rs:10:18
   |
7  | fn via_ans<'a: 'b, 'b>(emitter: &'a mut impl A<'b, char>) -> String {
   |                    -- lifetime `'b` defined here
...
10 |         let ch = emitter.emit_symbol();
   |                  ^^^^^^^--------------
   |                  |
   |                  `*emitter` was mutably borrowed here in the previous iteration of the loop
   |                  argument requires that `*emitter` is borrowed for `'b`

这是 Rust 借用检查器的缺点,还是还有其他原因?

如何调整此特征以使其在我的应用程序中发挥作用?

rust lifetime
1个回答
0
投票

第二种方法的问题在于,因为

impl A<'b, char>
是函数的参数,编译器只能为 'b 选择
single
生命周期,并且由于它是从函数外部传入的,因此生命周期也持续整个函数。因此,当您在第一次调用
emitter
时借用
emit_symbol
时,借用直到函数结束后才会释放。

这是更高排名特质界限(HRTB)的典型应用:

fn via_ans<'a>(emitter: &'a mut impl for<'b> A<'b, char>) -> String {
    let mut rval = String::new();
    for _ in 0..30 {
        let ch = emitter.emit_symbol();
        rval.push(ch)
    }
    rval
}

现在意味着

emitter
必须是在
any
生命周期内实现 A 的类型,因此编译器可以为每次循环迭代选择不同的类型。

© www.soinside.com 2019 - 2024. All rights reserved.