如何使用impl函数声明枚举生存期?

时间:2019-10-11 17:21:13

标签: rust

我想用访问器函数声明一个枚举,该函数返回创建值时提供的值。下面是一个说明错误的人为示例:

use std::mem;

#[derive(Debug)]
enum SomeBytes<'a> {
  One([u8; 1]),
  Two([u8; 2]),
}

impl SomeBytes<'a> {

  pub fn get_bytes(&'a self) -> &'a[u8] {
    use SomeBytes::*;

    match *self {
      One(byte_array) => &byte_array,
      Two(byte_array) => &byte_array,
    }
  }
}

fn main() {
  let var1 = SomeBytes::One(*b"A");
  let var2 = SomeBytes::Two(*b"AB");

  println!("one byte = {:?}", var1);
  println!("sizeof one byte = {:?}", mem::size_of_val(&var1));
  println!("two bytes = {:?}", var2);
  println!("sizeof two bytes = {:?}", mem::size_of_val(&var2));
}

错误:

  Compiling playground v0.0.1 (/playground)
error[E0261]: use of undeclared lifetime name `'a`
 --> src/main.rs:9:16
  |
9 | impl SomeBytes<'a> {
  |                ^^ undeclared lifetime

error[E0261]: use of undeclared lifetime name `'a`
  --> src/main.rs:11:21
   |
11 |   pub fn get_bytes(&'a self) -> &'a[u8] {
   |                     ^^ undeclared lifetime

error[E0261]: use of undeclared lifetime name `'a`
  --> src/main.rs:11:34
   |
11 |   pub fn get_bytes(&'a self) -> &'a[u8] {
   |                                  ^^ undeclared lifetime

我如何编写此代码以便编译?

请参见Rust playground

如果我从代码中删除了所有生存期(不需要当前的注释/答案,那么该示例如下所示:

use std::mem;

#[derive(Debug)]
enum SomeBytes {
  One([u8; 1]),
  Two([u8; 2]),
}

impl SomeBytes {

  pub fn get_bytes(&self) -> &[u8] {
    use SomeBytes::*;

    match *self {
      One(byte_array) => &byte_array,
      Two(byte_array) => &byte_array,
    }
  }
}

fn main() {
  let var1 = SomeBytes::One(*b"A");
  let var2 = SomeBytes::Two(*b"AB");

  println!("one byte = {:?}", var1);
  println!("sizeof one byte = {:?}", mem::size_of_val(&var1));
  println!("two bytes = {:?}", var2);
  println!("sizeof two bytes = {:?}", mem::size_of_val(&var2));
}

这给了我以下错误:

Compiling playground v0.0.1 (/playground)
error[E0515]: cannot return value referencing local variable `byte_array`
  --> src/main.rs:14:5
   |
14 | /     match *self {
15 | |       One(byte_array) => &byte_array,
16 | |       Two(byte_array) => &byte_array,
   | |                          ----------- `byte_array` is borrowed here
17 | |     }
   | |_____^ returns a value referencing data owned by the current function

error[E0515]: cannot return value referencing local variable `byte_array`
  --> src/main.rs:14:5
   |
14 | /     match *self {
15 | |       One(byte_array) => &byte_array,
   | |                          ----------- `byte_array` is borrowed here
16 | |       Two(byte_array) => &byte_array,
17 | |     }
   | |_____^ returns a value referencing data owned by the current function

为了解决上述错误,我必须增加生命周期,但这不是解决方案。我试图告诉编译器我不想返回当前函数所拥有的东西……有人可以解释适当的解决方法吗?

1 个答案:

答案 0 :(得分:3)

Stargateur给出了没有解释的代码;让我们看看我是否可以填补空白。

您的代码无法正常工作的原因是,在struct上声明生存期将此生存期与struct 相关联。换句话说,在每种情况下,使用或返回'a的每种方法都将采用或返回相同的'a,而不论其放置位置和方式如何。如果您在struct中有一个引用,而您却没有,那么这是值得的。因此,这不是必需的。

如果您想全力以赴并指定生命周期,则可以这样做:

#[derive(Debug)]
enum SomeBytes {
  One([u8; 1]),
  Two([u8; 2]),
}

impl SomeBytes {

  pub fn get_bytes<'a>(&'a self) -> &'a [u8] {
    use SomeBytes::*;

    match self {
      One(ref byte_array) => byte_array,
      Two(ref byte_array) => byte_array,
    }
  }
}

生存期定义为方法的属性,而不是struct的属性。它的附加要求是显而易见的-&self的生命周期'a必须保证其返回参数也要遵守。

但是,这是修脚。实际上,此生存期要求不是强制性的,可以放弃使用更简单,更自动化的版本:

  pub fn get_bytes(&self) -> &[u8] {
    use SomeBytes::*;

    match self {
      One(ref byte_array) => byte_array,
      Two(ref byte_array) => byte_array,
    }
  }

注意:为了使示例生效,还需要在比赛右侧的&之前删除byte_array。由于您的方法采用&self,因此即使您匹配自身,模式匹配的内容也将是引用自身(因为您没有对象的所有权),因此,&将导致参考文献