Cannot return a value referencing a local variable, but the variable is being returned as well

Hello, I'm a beginner at Rust and I'm experimenting with the xcb library to connect to X11. I had some simple boilerplate code in my main function that I tried to extract into a function:

fn init() -> (xcb::Connection, i32, x::Window, x::Gcontext, &'static x::Setup) {
    let (connection, screen_num) = xcb::Connection::connect(None).unwrap();
    let window: x::Window = connection.generate_id();
    let gc: x::Gcontext = connection.generate_id();

    let setup = connection.get_setup();

    return(connection, screen_num, window, gc, setup);
}

This, however, yields the error:

error[E0515]: cannot return value referencing local variable `connection`
  --> src/main.rs:14:11
   |
12 |     let setup = connection.get_setup();
   |                 ---------- `connection` is borrowed here
13 |
14 |     return(connection, screen_num, window, gc, setup);
   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function

Why does this happen, if the value that's being referenced is also returned by the function? How do I fix this error, or what are some better solutions to this problem?

The problem is that the local variable connection is not the same as the return value. The connection is being moved to the return value, the references to connection are left hanging to a nonexistent connection.

I think you have to create the connection outside of the function and pass it by reference into the function.

1 Like

Thank you! That seems to have worked while still keeping the main function compact and focused.

fn init(connection: &xcb::Connection, screen_num: i32) -> (x::Window, x::Gcontext, &x::Setup, &x::Screen) {
    // Fetch the screen and setup
    let setup = connection.get_setup();
    let screen = setup.roots().nth(screen_num as usize).unwrap();
    
    // Get window ID
    let window: x::Window = connection.generate_id();
    let gcontext: x::Gcontext = connection.generate_id();
    

    return(window, gcontext, setup, screen);
}
1 Like

Rust does not support returning or storing a value and a reference to the same value together. This is called self-referential type, and it is completely forbidden in safe code, and it's very difficult to hack around it in unsafe code.

The usual solution is to split the function into two parts — one that gets the owned value, and returns only the owned value, and a second function call that gets the value by reference, and can return one or more references to the input arguments it got (it will never be possible to return a reference to data stored in a local variable).

3 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.