Passing local reference to external functions and returning

Consider

use xcb_wm::ewmh;

pub struct App<'a> {
    conn: ewmh::Connection<'a>,
    // Other fields
}

The ewmh connection is basically just a wrapper over xcb::Connection but it takes a reference and I have no way to change this since it's an external library

impl<'a> App<'a> {
    pub fn new() -> App<'a> {
        let (conn, _) = xcb::Connection::connect(None).expect("Failed to connect to X server");
        
        // Can't change this since ewmh is an external library
        let ewmh_conn = ewmh::Connection::connect(&conn); 

        App {
            conn: ewmh_conn,
        }
    }
}

Now obviously the compiler complains cannot return value referencing local variable conn

My question is what's the best way to avoid this?

I want to avoid lazy_static type solutions because I know that the Application struct is the only one that needs access to the connection.

I need to store the wrapped ewmh connection because I will be calling the ewmh methods from the App methods.

The first option should always be “don't do that” — structure your code so that App takes an &'a xcb::Connection as a parameter rather than creating it.

Second, perhaps the library made an API design mistake that could be fixed. For example, if ewmh::Connection stored a Cow<'a, xcb::Connection> instead of &'a xcb::Connection (or was generic over AsRef<xcb::Connection>), then it could optionally own the connection. You would have to figure out if this is feasible, and contribute a patch.

As the last resort, if your use case requires it, you can create “self-referential” structs like this one using ouroboros. You should avoid this when possible because it is unergonomic, has some performance costs (additional memory allocation), and attempts in this space have often been discovered to be unsound.

1 Like

On further digging, xcb::Connection is not Clone so storing a Cow<'a, xcb::Connection> is not possible. Will have to think about AsRef or maybe restructuring my program.

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.