2021年3月12日星期五

How should I implement this &Struct Default trait lifetime?

After reading the rust book many times I think I'm starting to get the gist of lifetimes, but for me, an additional problem is the syntax we need to use to declare them. I find it is really counterintuitive.

I've simplified a silly code of mine onto this pair of structs (which one referencing the other).

#[derive(Debug, Default)]  pub struct TestStructA  {      pub byte_1: u8,      pub byte_2: u8,      pub vector: Vec<u8>  }    impl<'a> Default for &'a TestStructA  {      fn default() -> &'a TestStructA      {          &TestStructA{byte_1:10, byte_2:20, vector:vec![1,2,3]}      }  }        #[derive(Debug, Default)]  pub struct TestStructB<'a>  {      pub test_array:&'a [u8],      pub t_a:&'a TestStructA,  }    fn main() {        println!("hi");    }  

If you copy and paste this isolated code onto a main.rs file and compile it, then you get the following error:

    Compiling report_rust v0.1.0 (/projects/report_rust)  error: expected `while`, `for`, `loop` or `{` after a label    --> src/main.rs:15:58     |  15 |             &TestStructA{byte_1:10, byte_2:20, vector:'a vec![1,2,3]}     |                                                          ^^^ expected `while`, `for`, `loop` or `{` after a label    error: labeled expression must be followed by `:`    --> src/main.rs:15:58     |  15 |             &TestStructA{byte_1:10, byte_2:20, vector:'a vec![1,2,3]}     |                                                       ---^^^^^^^^^^^     |                                                       | |     |                                                       | help: add `:` after the label     |                                                       the label     |     = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them    error: aborting due to 2 previous errors    error: could not compile `report_rust`    To learn more, run the command again with --verbose.  

If I don't anotate the vector parameter lifetime, I get the expected: "check your lifetimes boy" (which makes sense).

Compiling report_rust v0.1.0 (/projects/report_rust)  error[E0515]: cannot return reference to temporary value    --> src/main.rs:15:13     |  15 |             &TestStructA{byte_1:10, byte_2:20, vector:vec![1,2,3]}     |             ^-----------------------------------------------------     |             ||     |             |temporary value created here     |             returns a reference to data owned by the current function    error: aborting due to previous error    For more information about this error, try `rustc --explain E0515`.  error: could not compile `report_rust`    To learn more, run the command again with --verbose.  

Of course, if I choose a more drastic solution as removing the "vector" attribute from my struct, as all other attributes are scalars, the code compiles. But I need my struct to have non-scalar data structures of some kind. I suspect I need some kind of lifetime labeling for my vector inside the Default initializer, but I'm not sure what

By the way, I think my TestStructB is also properly lifetime annotated, but maybe not. Does it look correct?

Finally, I got here because the compiler said I needed to declare a Default initializer for the referenced (&) version of my original struct. This original struct was already happily used in my program, but never referenced. Whenever I started using it in a &referenced fashion, it was Rust claiming it needs its Default initializer. The thing is I still somewhat think I've done something wrong when using my referenced Struct, and that there is a proper way to use &referenced (and lifetime anotated) Structs without Rust complaining about their (non existing) default initializer.

EDIT: @JohnKugelman is more than right, I've come onto this "aberration" after the typical newbiee fight with rust compiler trying to overcome the mainly cryptic messages it yields.

My simplified original was this one:

#[derive(Debug, Default)]  pub struct TestStructA  {      pub byte_1: u8,      pub byte_2: u8,      pub vector: Vec<u8>  }    #[derive(Debug, Default)]  pub struct TestStructB<'a>  {      pub test_array:&'a [u8],      pub t_a:&'a TestStructA,  }    fn main() {        println!("hi");    }  

With this code, the error I get is:

pub t_a:&'a TestStructA,     |         ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `&TestStructA`  

Apparently Rustc misleaded me into thinking I need a &Struct Default initializer? Can't say...

https://stackoverflow.com/questions/66609014/how-should-i-implement-this-struct-default-trait-lifetime March 13, 2021 at 08:46AM

没有评论:

发表评论