1

I'm having trouble with lifetimes and borrowed points. I've read the manual and borrowed pointer tutorial, but... I'm still stuck.

Sketch of main.rs

fn main() {
  let (db_child, repo_child):(DuplexStream<~str, ~str>, DuplexStream<~str, ~str>) = DuplexStream();
    do spawn {
        slurp_repos(&repo_child);
    }
}

Sketch of repos.rs

fn slurp_repos(chan: &'static DuplexStream<~str, ~str>) {
    ...
    do request.begin |event| {
        ...
        chan.send(api_url);
    }
}

When I compile these modules, main.rs has the following error:

main.rs:21:20: 21:31 error: borrowed value does not live long enough
main.rs:21         slurp_repos(&repo_child);
                               ^~~~~~~~~~~
note: borrowed pointer must be valid for the static lifetime...
main.rs:13:10: 1:0 note: ...but borrowed value is only valid for the block at 13:10
error: aborting due to previous error

I can't quite figure out how to declare my DuplexStreams lifetime static. Or perhaps this was the wrong way to go in the function type for slurp_repos.

If you want to see the full context:

Community
  • 1
  • 1
Ozten
  • 188
  • 9
  • Shouldn't you define repo_child as managed (`@`)? – snf Jul 24 '13 at 06:52
  • I couldn't figure out how to declare @repo_child. Do you have an example that compiles? – Ozten Jul 24 '13 at 16:03
  • 1
    I guess one way of solving this is to have a state object which you update in the closure and then use the channel after you come back from `request.begin`. [This seems to work](https://github.com/ozten/learning_rust/commit/c002cc6881dd8bf3d39f653e6f52a7adcb987181). – Ozten Jul 24 '13 at 16:05
  • Cool you made it work. so it's solved? – snf Jul 24 '13 at 17:24
  • 1
    I haven't kept up to date with the latest changes to Rust's lifetime system, but I think only basically constant things can be static. Since you create the DuplexStream in main, I would think this couldn't be static. I might be wrong though. – Eric Holk Jul 24 '13 at 18:19
  • have to tried to remove the 'static? – Maik Klein Jul 24 '13 at 19:05
  • @MaikKlein He indeed did, check the diff in the third comment. – snf Jul 24 '13 at 19:45
  • try `let a= repo_child; slurp_repos(&a);` and remove the 'static and use `fn <'a> slerp_repos(&'a ...)`; – Maik Klein Jul 24 '13 at 19:54

1 Answers1

1

I'm unable to test, but I guess the solution is to move the repo_child stream into slurp_repos, that is:

fn main() {
  let (db_child, repo_child) = DuplexStream();
    do spawn {
        slurp_repos(repo_child);
    }
}

fn slurp_repos(chan: DuplexStream<~str, ~str>) {
    ...
    do request.begin |event| {
        ...
        chan.send(api_url);
    }
}

By moving the whole endpoint, it allows it to be transferred across tasks (because a DuplexStream is Sendable). Also, note that sharing (what the use of a references allows) the endpoint of a basic bidirectional stream (which is what DuplexStream is) doesn't really make sense: there can only be one person at each end of a telephone.

The error message about repo_child not living long enough is because the type of slurp_repos requires something that is 'static i.e. lasts for the whole lifetime of the program, but repo_child definitely doesn't: it is local to a function.

The reason the compiler tells you to put 'static on slurp_repos, is because the only Sendable reference is one with this lifetime. This restriction is required because you could have the owning task finish before the borrowing task does, and then destroy/deallocate the reference, leaving a dangling pointer; in diagrams:

start program/call main
  |
  v
allocate repo_child
  |
  v
spawn -----------------> slurp_repos(chan = &repo_child)
  |                          |
  v                          v
finish                   do things with the chan reference to repo_child
  |                          |
  v                          v
deallocate repo_child    general work ...
                             |
                             v
                         do more things with chan: 
                           oops, already freed; use-after-free bug
huon
  • 94,605
  • 21
  • 231
  • 225