#Solved - Borrowed Data escapes outside associated function

7 messages · Page 1 of 1 (latest)

alpine quail
#

This is a Salvo web-server, all open source. I'm not a beginner programer, but I suppose a beginner at Rust still, since I don't think I'm doing anything particularly complex.

full main.rs: https://gist.github.com/Xevion/a1311c80568c6b4663e2c49fb3e7286a
It's a large file, but the main two functions are here:

#[handler]
async fn connect(req: &mut Request, res: &mut Response, depot: &Depot) -> Result<(), StatusError> {
    WebSocketUpgrade::new()
        .upgrade(req, res, |ws| async move {
            let session_id = get_session_id(req, depot).unwrap();
            handle_socket(session_id, ws).await;
        })
        .await
}

fn get_session_id(req: &Request, depot: &Depot) -> Option<usize> {
    match req.cookie("Session") {
        Some(cookie) => match cookie.value().parse::<usize>() {
            Ok(id) => Some(id),
            _ => None,
        },
        None => match depot.get::<usize>("session_id") {
            Ok(id) => Some(*id),
            _ => None,
        },
    }
}
#
   Compiling dynamic-preauth v0.1.0 (/home/xevion/projects/dynamic-preauth)
error[E0505]: cannot move out of `req` because it is borrowed
  --> src/main.rs:56:28
   |
54 | async fn connect(req: &mut Request, res: &mut Response, depot: &Depot) -> Result<(), StatusError> {
   |                  --- binding `req` declared here
55 |     WebSocketUpgrade::new()
56 |         .upgrade(req, res, |ws| async move {
   |          ------- ---       ^^^^ move out of `req` occurs here
   |          |       |
   |          |       borrow of `*req` occurs here
   |          borrow later used by call
57 |             let session_id = get_session_id(req, depot).unwrap();
   |                                             --- move occurs due to use in closure

error[E0373]: closure may outlive the current function, but it borrows `depot`, which is owned by the current function
  --> src/main.rs:56:28
   |
56 |         .upgrade(req, res, |ws| async move {
   |                            ^^^^ may outlive borrowed value `depot`
57 |             let session_id = get_session_id(req, depot).unwrap();
   |                                                  ----- `depot` is borrowed here
   |
note: function requires argument type to outlive `'static`
  --> src/main.rs:55:5
   |
55 | /     WebSocketUpgrade::new()
56 | |         .upgrade(req, res, |ws| async move {
57 | |             let session_id = get_session_id(req, depot).unwrap();
58 | |             handle_socket(session_id, ws).await;
59 | |         })
   | |__________^
help: to force the closure to take ownership of `depot` (and any other referenced variables), use the `move` keyword
   |
56 |         .upgrade(req, res, move |ws| async move {
   |                            ++++

error[E0521]: borrowed data escapes outside of associated function
  --> src/main.rs:55:5
   |
54 |   async fn connect(req: &mut Request, res: &mut Response, depot: &Depot) -> Result<(), StatusError> {
   |                    ---  - let's call the lifetime of this reference `'1`
   |                    |
   |                    `req` is a reference that is only valid in the associated function body
55 | /     WebSocketUpgrade::new()
56 | |         .upgrade(req, res, |ws| async move {
57 | |             let session_id = get_session_id(req, depot).unwrap();
58 | |             handle_socket(session_id, ws).await;
59 | |         })
   | |          ^
   | |          |
   | |__________`req` escapes the associated function body here
   |            argument requires that `'1` must outlive `'static`

error[E0521]: borrowed data escapes outside of associated function
  --> src/main.rs:55:5
   |
54 |   async fn connect(req: &mut Request, res: &mut Response, depot: &Depot) -> Result<(), StatusError> {
   |                                                           -----  - let's call the lifetime of this reference `'2`
   |                                                           |
   |                                                           `depot` is a reference that is only valid in the associated function body
55 | /     WebSocketUpgrade::new()
56 | |         .upgrade(req, res, |ws| async move {
57 | |             let session_id = get_session_id(req, depot).unwrap();
58 | |             handle_socket(session_id, ws).await;
59 | |         })
   | |          ^
   | |          |
   | |__________`depot` escapes the associated function body here
   |            argument requires that `'2` must outlive `'static`

Some errors have detailed explanations: E0373, E0505, E0521.
For more information about an error, try `rustc --explain E0373`.
error: could not compile `dynamic-preauth` (bin "dynamic-preauth") due to 4 previous errors
#

I apologize if my program is a bit indecipherable or poorly made at the moment; Rust is not my main language by any means.

#

Since there's no comments you should know

  • get_session_id is a helper method for acquiring the Session ID from either the request itself, or the depot (the Depot is like a context for passing between different handlers). While normally a request will always have a Cookie available (it's assigned immediately on the first request, even for static files like index.html or favicon.ico), I've had requests not acquire them, like for APIs). Thus, if a session ID is newly made, the request chain gets the session ID via the depot as a temporary alternative.
  • connect is a handler for the WebSocket connection at /ws, but not the handler for websockets itself. I'm still working on that part. I'm trying to use the helper method for it.
#

Oh, damnit. I literally solve it exactly 5 minutes after posting it.

#
#[handler]
async fn connect(req: &mut Request, res: &mut Response, depot: &Depot) -> Result<(), StatusError> {
    let session_id = get_session_id(req, depot).unwrap();
    WebSocketUpgrade::new()
        .upgrade(req, res, move |ws| async move {
            handle_socket(session_id, ws).await;
        })
        .await
}
```I move it two lines up and add `move` before the `|ws|` closure, done.
#

I think the incredible length of the compiler error tripped me up.