0

I'm trying to use some xcb bindings while trying to learn Rust.

conn.get_setup() only borrows an immutable reference; doesn't that borrow end after the function call ends?

use std::error::Error; 
use std::convert::From;

pub struct State<'a> {
    conn: xcb::Connection,
    screen: xcb::Screen<'a>,
}

impl<'a> State<'a> {
    pub fn new() -> Result<State<'a>, Box<dyn Error>> {
        let (conn, _) = xcb::Connection::connect(None)?;
        let screen = conn.get_setup().roots().next().ok_or::<Box<dyn Error>>(From::from("Couldn't get screen"))?;
        Ok(State{conn: conn, screen:screen})
    }
}

The compiler gives me

error[E0515]: cannot return value referencing local variable `conn`
  --> /.../src/lib.rs:16:4
   |
15 |             let screen = conn.get_setup().roots().next().ok_or::<Box<dyn Error>>(From::from("Couldn't get screen"))?;
   |                          ---- `conn` is borrowed here
16 |             Ok(State{conn: conn, screen:screen})
   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function

error[E0505]: cannot move out of `conn` because it is borrowed
  --> /.../src/lib.rs:16:19
   |
12 |     impl<'a> State<'a> {
   |          -- lifetime `'a` defined here
...
15 |             let screen = conn.get_setup().roots().next().ok_or::<Box<dyn Error>>(From::from("Couldn't get screen"))?;
   |                          ---- borrow of `conn` occurs here
16 |             Ok(State{conn: conn, screen:screen})
   |             ---------------^^^^-----------------
   |             |              |
   |             |              move out of `conn` occurs here
   |             returning this value requires that `conn` is borrowed for `'a`

Is there any way to return both conn and state or am I just limited to conn?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366

1 Answers1

1

There would be a use after free error if you did this:

  1. conn is created, it has no attached lifetime
  2. We borrow conn for 'a, which in and of itself is impossible since I could say the following:
State::<'static>::new()
  1. We move conn out of the function, invalidating any references to it.

So therefore, unless if there's a different way to achieve this in the library you're working with, this won't work as-is. Another name for this is a self-referential struct, so you might want to do some looking into why that doesn't work in rust.

Optimistic Peach
  • 3,862
  • 2
  • 18
  • 29