将对一个结构的一部分的引用返回为另一结构的字段

时间:2018-12-27 16:22:56

标签: struct rust lifetime borrow-checker

如果可能的话,我想将一个结构移到另一个结构中,并在不克隆或复制的情况下,将第一结构的一部分作为其他结构的一部分获得引用。如何以正确的方式做到这一点?

fn main() {
    let foo = Foo::new();
    let bar = Bar::new(foo);
    println!("{:?}", bar);
}

#[derive(Debug)]
struct Foo {
    v: String,
}

impl Foo {
    pub fn new() -> Self {
        Foo {
            v: String::from("a|b"),
        }
    }

    pub fn get_a(&self) -> &str {
        &self.v[0..1]
    }

    pub fn get_b(&self) -> &str {
        &self.v[2..3]
    }
}

#[derive(Debug)]
struct Bar<'a> {
    foo: Foo,
    a: &'a str,
    b: &'a str,
}

impl<'a> Bar<'a> {
    pub fn new(f: Foo) -> Self {
        Bar::parse(f)
    }

    fn parse(f: Foo) -> Self {
        let a = f.get_a();
        let b = f.get_b();

        Bar { foo: f, a, b }
    }
}

Rust Playground

我遇到一个错误:

error[E0515]: cannot return value referencing function parameter `f`
  --> src/main.rs:44:9
   |
41 |         let a = f.get_a();
   |                 - `f` is borrowed here
...
44 |         Bar { foo: f, a, b }
   |         ^^^^^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function

error[E0515]: cannot return value referencing function parameter `f`
  --> src/main.rs:44:9
   |
42 |         let b = f.get_b();
   |                 - `f` is borrowed here
43 | 
44 |         Bar { foo: f, a, b }
   |         ^^^^^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function

error[E0505]: cannot move out of `f` because it is borrowed
  --> src/main.rs:44:20
   |
35 | impl<'a> Bar<'a> {
   |      -- lifetime `'a` defined here
...
41 |         let a = f.get_a();
   |                 - borrow of `f` occurs here
...
44 |         Bar { foo: f, a, b }
   |         -----------^--------
   |         |          |
   |         |          move out of `f` occurs here
   |         returning this value requires that `f` is borrowed for `'a`

1 个答案:

答案 0 :(得分:1)

f返回时,参数parseparse的生存期结束。较旧的Rust编译器版本返回了一条错误消息,该消息可能更有用:

error[E0597]: `f` does not live long enough
  --> t.rs:41:17
   |
41 |         let a = f.get_a();
   |                 ^ borrowed value does not live long enough
...
45 |     }
   |     - borrowed value only lives until here
   |
note: borrowed value must be valid for the lifetime 'a as defined on the impl at 35:1...
  --> t.rs:35:1
   |
35 | / impl<'a> Bar<'a> {
36 | |     pub fn new(f: Foo) -> Self {
37 | |         Bar::parse(f)
38 | |     }
...  |
45 | |     }
46 | | }
   | |_^

我可以通过将Bar的定义更改为以下内容来编译您的示例:

#[derive(Debug)]
struct Bar<'a> {
    foo: &'a Foo,
    a: &'a str,
    b: &'a str,
}

,并将类型&'a Foo的引用传递到Bar::newBar::parse。但是,尚不清楚此解决方案是否可以解决您的原始问题。如果所有权结构过于复杂,也许您需要使用Rc