cargo test --test flatten -- --nocapture --test it_should_not_try_to_unsubscribe_from_completed_source_when_for_inner_errors
results in deadlock.
This is because the Nursery's need to be dropped:
Warning : If ever you wait on the stream to finish, remember it will only finish if there are no Nursery ’s alive anymore. You must drop the Nursery before awaiting the NurseryStream . If your program deadlocks, this should be the first place to look.
If I understand correctly, there is a Nursery owned by this closure here:
which is itself owned by:
Since everything has 'static lifetime, this basically means the Nursery in the closure is never dropped, so the .await never completes.
I haven't looked at your code in detail, but the usual solution would be to put an Option<...> somewhere in the ownership chain. When that gets set to None through something like Option::take(), any contents it previously held will be dropped.
If it makes no sense to library user then Option goes into your own code. Note that if you do something like:
fn Foo(bar: Bar) {
let holder = Some(bar);
…
}
And then later do holder.take() your bar would become “taken” and than, later, dropped (after use). If you would just do holder.take() (without assigning taken object to anything) it would be dropped immediately.
That's why 2e71828 says you need Option “somewhere in the ownership chain”, not necessarily as argument to your function or closure: question of where should you put an Option doesn't have a single answer, but “take from Option” is how you implement what's called “nullable pointer” in other languages (or just a simgle “pointer” because most languages don't have a “non-nullable pointer”).