Have a Stream with references and need a 'static Stream (or mixing `Trait + 'a` and `Trait + 'static` in general)

Hey y'all, I'm looking for some input on the best way to deal with this situation. Basically, I have a Stream object from one library, I do some transformations, and then need to put that into a function from another library that requires Stream + 'static. So I don't have control over either of these lifetimes. E.g.:

fn outputs_borrowing_stream(input: &'a str) -> impl Stream + 'a { }

fn takes_static_stream(stream: impl Stream + 'static) { }

fn some_transformation(item: &str) -> String { }

fn main() {
     let input = String::from("dog");
     let stream = outputs_borrowing_stream(&input);
     let final_stream = stream.map(some_transformation);
     takes_static_stream(final_stream);
}

I do have ownership over the value that the borrowing stream is borrowing and don't mind cloning it. My current solution is to leak the memory:

let input = Box::leak(Box::new(input));

which is not ideal. This way the output of the function becomes impl Stream + 'static. I'm currently going through the codebase and replacing all the static references with Arcs wherever I can, but since I don't have control over this output I'm a little stumped. I know when it says Stream + 'static it doesn't mean it has to have 'static references, ideally it would just have owned values. Since I have the owned value, I'd really like to be able to tell it to just take the value!

Is there a better way to handle this? To state the question generically, is there a way to get a impl Trait + 'static from a function &'a T -> impl Stream + 'a if you have ownership of the T and/or it's wrapped in an Arc?

If that is the best way to deal with this, what does that mean for library creation best practices? The provided interface of &'a T -> impl Stream + 'a seems like the best for most situations. But if a user does need this 'static Stream, should the library expose two methods, one borrowed and one owned?

Other than leaking, you could collect all the owned outputs into something you can turn into a non-borrowing stream.

The fact that your transformation outputs owned items doesn't matter; it's the stream itself that's holding on to some borrow based on the input to outputs_borrowing_stream. The only way for the stream to be 'static is if that input is a &'static (so compiled into your binary or leaked). The collect-and-restream approach works around this by getting rid of the borrowing stream by consuming it. But at a cost you may or may not be able to tolerate.

If there's a sensible way to implement the owned version, it makes sense to provide both.

2 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.