“borrowed value does not live long enough” when using the builder pattern

后端 未结 1 1779
花落未央
花落未央 2020-11-27 08:22

I have the following code:

pub struct Canvas<\'a> {
    width: isize,
    height: isize,
    color: Color,
    surface: Surface,
    texture: Texture,
         


        
相关标签:
1条回答
  • 2020-11-27 08:51

    Here's a minimal reproduction:

    #[derive(Debug)]
    pub struct Canvas;
    
    impl Canvas {
        fn new() -> Self {
            Canvas
        }
    
        fn color(&self) -> &Canvas {
            self
        }
    }
    
    fn main() {
        let mut canvas = Canvas::new().color();
        //             1 ^~~~~~~~~~~~~
        //                           2 ^~~~~
        println!("{:?}", canvas);
    }
    

    Rust 2015

    error[E0597]: borrowed value does not live long enough
      --> src/main.rs:15:22
       |
    15 |     let mut canvas = Canvas::new().color();
       |                      ^^^^^^^^^^^^^        - temporary value dropped here while still borrowed
       |                      |
       |                      temporary value does not live long enough
    ...
    19 | }
       | - temporary value needs to live until here
       |
       = note: consider using a `let` binding to increase its lifetime
    

    Rust 2018

    error[E0716]: temporary value dropped while borrowed
      --> src/main.rs:15:22
       |
    15 |     let mut canvas = Canvas::new().color();
       |                      ^^^^^^^^^^^^^        - temporary value is freed at the end of this statement
       |                      |
       |                      creates a temporary which is freed while still in use
    ...
    18 |     println!("{:?}", canvas);
       |                      ------ borrow later used here
       |
       = note: consider using a `let` binding to create a longer lived value
    

    The problem arises because you create a temporary variable (1), then pass the reference to that variable to the method (2), which returns the reference. At the end of the method chain, you are trying to return the reference and store it in the variable, but the reference points to a temporary item that has nowhere to live! Rust doesn't let you have a reference to something that's invalid.

    Part of the problem is that this is not the Builder pattern, this is just a struct that modifies itself using chained method invocation. Some solutions:

    1. Store the "temporary" variable, in which case all the methods are just normal mutation methods that happen afterward.
    2. Take in self instead of a reference to self (&self, &mut self) and then ultimately return the full struct.
    3. Have a build method at the end of the chain that returns another standalone struct, not a reference.
    0 讨论(0)
提交回复
热议问题