1

I found this answer: https://stackoverflow.com/a/56436053/5884503 and I'm intersted in this part:

struct SlowData;
impl SlowData {
    fn new(_initial: &str) -> SlowData {
        thread::sleep(Duration::from_secs(1));
        Self
    }

    fn next_block(&self) -> io::Result<&[u8]> {
        thread::sleep(Duration::from_secs(1));
        Ok(b"data")
    }
}

fn stream(pool: ThreadPool) -> impl Stream<Item = io::Result<Vec<u8>>> {
    let (mut tx, rx) = mpsc::channel(10);

    pool.spawn(async move {
        let sd = SlowData::new("dummy");

        for _ in 0..3 {
            let block = sd.next_block().map(|b| b.to_vec());
            tx.send(block).await.expect("Unable to send block");
        }
    })
    .expect("Unable to spawn thread");

    rx
}

How is it possible that we can return -> io::Result<&[u8]>? The reference is owned by the function next_block, in Ok(b"data). You can see that it's created inside the function. How can the result be used outside of it? As I understood, in Rust, a reference cannot be copied, it can only be referenced, so I don't see how Ok(b"data") could copy the reference to its inside.

Gatonito
  • 1,662
  • 5
  • 26
  • 55
  • 1
    String literals (`"data"`) and byte literals (`b"data"`) are **constants**, and this means a lot: their can be hard coded into the executable, which means that they live for the duration of the program (`&'static str` and `&'static [u8]`) – Aplet123 Mar 15 '21 at 23:52
  • 1
    Related: [Why can I return a reference to a local literal but not a variable?](https://stackoverflow.com/q/50345139/3650362) Rvalue static promotion doesn't actually come into play here, but the reason it works (stuff being placed in static memory) is the same – trent Mar 16 '21 at 00:44
  • Does this answer your question? [Why can I return a reference to a local literal but not a variable?](https://stackoverflow.com/questions/50345139/why-can-i-return-a-reference-to-a-local-literal-but-not-a-variable) – Jmb Mar 16 '21 at 08:19

2 Answers2

2

References are not owned, they point to owned data. However, constant strings are not owned by the the function they are in, they have 'static lifetime. As the function is just taking a self reference, the elided lifetime of the result borrow is implicitly that of the struct the function is called upon. And this is guaranteed to be less than or equal to 'static lifetime.

user1937198
  • 4,987
  • 4
  • 20
  • 31
1

I think the lifetime of self is inferred for the slice. Actually the slice could have a static lifetime, but it is legal to narrow down lifetimes, so the elided lifetimes should be inferred as the same.

sebpuetz
  • 2,430
  • 1
  • 7
  • 15