Haru Atari
Haru Atari

Reputation: 1732

How can I set the lifetime for a reference which isn't an argument of the function?

I'm trying to compile this code. The function get_lines must generate a vector of Lines, push a new line to it and return this vector.

fn main() {
    let begin_point = Point{x:100, y:100};
    let end_point = Point{x:300, y:100};

    let lines = get_lines( &begin_point, &end_point);
}

fn get_lines<'a>(begin_point: &'a Point, end_point: &'a Point) -> Vec<Line<'a>>
{
    let mut lines: Vec<Line> = vec![];
    let middle_color = Color{r:0,g:0,b:0};

    let line = Line {
        begin_point: begin_point,
        end_point: end_point,
        color: &middle_color,
    };

    lines.push(line);
    lines
}

struct Color<> {r:i32, g:i32, b:i32}
struct Point {x:i32, y:i32}
struct Line<'a> {
    begin_point: &'a Point,
    end_point: &'a Point,
    color: &'a Color
}

Compilation fails with this error:

src\main.rs:16:17: 16:29 error: `middle_color` does not live long enough
src\main.rs:16         color: &middle_color,
                               ^~~~~~~~~~~~
src\main.rs:9:1: 21:2 note: reference must be valid for the lifetime 'a as defined on the block at 9:0...
src\main.rs: 9 {
src\main.rs:10     let mut lines: Vec<Line> = vec![];
src\main.rs:11     let middle_color = Color{r:0,g:0,b:0};
src\main.rs:12
src\main.rs:13     let line = Line {
src\main.rs:14         begin_point: begin_point,
               ...
src\main.rs:11:43: 21:2 note: ...but borrowed value is only valid for the block suffix following statement 1 at 11:42
src\main.rs:11     let middle_color = Color{r:0,g:0,b:0};
src\main.rs:12
src\main.rs:13     let line = Line {
src\main.rs:14         begin_point: begin_point,
src\main.rs:15         end_point: end_point,
src\main.rs:16         color: &middle_color,
               ...
error: aborting due to previous error

How can I set the lifetime for a reference which isn't an argument of the function? Or is the logic of code wrong?

Upvotes: 3

Views: 158

Answers (1)

Tibor Benke
Tibor Benke

Reputation: 1280

You get the error, because when get_lines() returns, middle_color goes out of scope and gets freed. You'd get a dangling pointer in the vector if this doesn't happen.

If you really want to use a reference in Line to color, you can instantiate it in the main function and pass a reference to it into get_lines(), e.g:

fn get_lines<'a>(begin_point: &'a Point, end_point: &'a Point, middle_color: &'a Color) -> Vec<Line<'a>>
{
...
}

But if you do this, you can even create your Line in main and move that into get_lines().

Upvotes: 3

Related Questions