简体   繁体   English

包含在需要生命周期参数的结构中的返回引用

[英]Return reference wrapped in struct that requires lifetime parameters

How can I return a reference wrapped in a struct and what lifetime annotation is required?如何返回包装在结构中的引用以及需要什么生命周期注释? I am having a tough time formulating my exact question, but the following example illustrates what I am trying to do.我很难制定我的确切问题,但以下示例说明了我正在尝试做的事情。 I have a struct C that contains a reference to a struct B that requires lifetime parameters.我有一个结构C ,其中包含对需要生命周期参数的结构B的引用。 I want a function on C that returns the reference to B wrapped in another struct Borrower that functions as an interface.我想要一个C上的函数,该函数返回对B的引用,该B包含在另一个用作接口的 struct Borrower中。

When compiling this I get an error when returning Borrower : 'cannot infer an appropriate lifetime for lifetime parameter 'b due to conflicting requirements'.编译时,返回Borrower时出现错误:“由于需求冲突,无法推断生命周期参数'b的适当生命周期”。 How can I resolve this issue?我该如何解决这个问题? What lifetime parameters can I enter?我可以输入哪些生命周期参数? I feel like both 'a and 'b are not the right lifetimes.我觉得'a'b都不是正确的生命周期。

Playground 操场

struct C<'a, 'b> {
    ref2: &'a mut B<'b>,
}

impl<'a, 'b> C<'a, 'b> {
    fn get_borrower(&mut self) -> Borrower {
        Borrower { ref3: self.ref2 }
    }
}

struct Borrower<'a, 'b> {
    ref3: &'a mut B<'b>,
}

impl<'a, 'b> Borrower<'a, 'b> {
    fn print_and_add(&mut self) {
        println!("ref is {}", self.ref3.ref1.i);
        self.ref3.ref1.i += 1;
    }
}

struct B<'a> {
    ref1: &'a mut A,
}

struct A {
    i: u32,
}

fn main() {
    let mut a = A { i: 10 };
    let mut b = B { ref1: &mut a };
    let mut c = C { ref2: &mut b };

    for _ in 0..10 {
        let mut borrower = c.get_borrower();
        borrower.print_and_add();
    }
}

The issue is specifically in this method:问题特别在于这种方法:

impl<'a, 'b> C<'a, 'b> {
    fn get_borrower(&mut self) -> Borrower {
        Borrower { ref3: self.ref2 }
    }
}

We need to help the compiler understand which lifetime parameters are expected in the returned Borrower , because the inferred lifetimes here will be incorrect: The lifetime elision Borrower can be expanded to Borrower<'_, '_> where the anonymous lifetimes are both the lifetime of &mut self ;我们需要帮助编译器理解在返回的Borrower需要哪些生命周期参数,因为这里推断的生命周期是不正确的:生命周期省略Borrower可以扩展为Borrower<'_, '_>其中匿名生命周期都是生命周期&mut self ; If we call it 's , the equivalent signature would be:如果我们把它's ,等效签名是:

    fn get_borrower<'s>(&'s mut self) -> Borrower<'s, 's> {

This is clearly not right, because we know that the second lifetime is expected to be 'b , as directly described by field ref2 of type B<'b> .这显然是不对的,因为我们知道第二个生命周期应该是'b ,正如B<'b>类型的字段ref2直接描述的那样。 With the following signature (and after fixing unrelated errors), the code compiles successfully :使用以下签名(并在修复不相关的错误后), 代码编译成功

    fn get_borrower(&mut self) -> Borrower<'_, 'b> {

The fun part is in the first parameter.有趣的部分在第一个参数中。 One could be inclined to assume that we want it to be 'a instead of 's , but that would still lead to conflicting lifetimes:人们可能倾向于假设我们希望它是'a而不是's ,但这仍然会导致生命周期冲突:

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
 --> src/main.rs:7:9
  |
7 |         Borrower { ref3: self.ref2 }
  |         ^^^^^^^^
  |
note: first, the lifetime cannot outlive the lifetime `'s` as defined on the method body at 6:21...
 --> src/main.rs:6:21
  |
6 |     fn get_borrower<'s>(&'s mut self) -> Borrower<'a, 'b> {
  |                     ^^
note: ...so that reference does not outlive borrowed content
 --> src/main.rs:7:26
  |
7 |         Borrower { ref3: self.ref2 }
  |                          ^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 5:6...
 --> src/main.rs:5:6
  |
5 | impl<'a, 'b> C<'a, 'b> {
  |      ^^
note: ...so that the expression is assignable
 --> src/main.rs:7:9
  |
7 |         Borrower { ref3: self.ref2 }
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  = note: expected `Borrower<'a, 'b>`
             found `Borrower<'_, '_>`

This is because we are retrieving ref2 behind a mutable reference to self, and that one has its own lifetime.这是因为我们在对 self 的可变引用后面检索ref2 ,并且该引用有自己的生命周期。 We cannot just move it out of self by force to fulfill the lifetime 'a , nor can we pass a &'s mut &'a mut B<'b> instead.我们不能仅仅通过强制将它移出self来实现生命周期'a ,也不能传递 a &'s mut &'a mut B<'b> Therefore, returning a Borrower<'s, 'b> is the right thing to do: as it is implicit that 'a: 's ( 'a outlives 's ), the covariance in this lifetime will enable this method to narrow the mutable reference &'a mut B<'b> into its subtype &'s mut B<'b> .因此,返回一个Borrower<'s, 'b>是正确的做法:因为它隐含着'a: 's ( 'a outlives 's ),此生命周期中的协方差将使此方法能够缩小可变范围将&'a mut B<'b>引用到它的子类型&'s mut B<'b>

 ---------- 
| 'a       |
| ------   |
|| 's   | ---> Borrower<'s, 'b>
||      |  |
| ------   |
 ----------

See also:也可以看看:

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM