I ran into a curious issue while debugging some async code in Rust. Mainly, I have the following async block which is part of a test:
let s = Signal::new(0);
let s_clone = s.clone();
assert_eq!(s_clone.clone().await, 0);
assert_eq!(s.clone().await, 0);
join![s.for_each(|_| async {}), async {
s_clone.set_and_wait(7).await;
println!("s_clone should drop here...");
drop(s_clone);
}];
The join![] code in this part doesn't matter too much, what matters is that the Signal I implemented is shared in such a way that only where there are no more unused signals do they stop and drop their values. Thus, if I omit the explicit drop(s_clone);, s_clone won't get dropped, causing join![] to never be able to complete.
The Question
In synchronous code, when a value reaches the end of the block, it just get's gropped, but why not in async? Why do I have to manually drop the value?
Additional Context
In case anyone is curious, I've implemented both Future and Stream for Signal. The future will only complete when all other pending signals cloned from the same source signal have finished reacting to any of their changes.