Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Sadly, this is only lexical scoping which means you can only borrow from the outer scope and not ad-hoc the normal way borrowing works in Rust.

In short, this means that thread pools and async runtimes cannot use this feature to provide borrowing across tasks. We're still stuck with Arc-ing everything that crosses task boundaries.

Prior to 1.0, there were "true" scoped threads (with a lifetime 'a on the join handle), which let you borrow from the parent thread. (This could have extended to tasks as well, had they been around.) unfortunately it wasn't safe together with the much more popular Arc/Rc, which wasn't 'static restricted, despite it's ability to cause cycles and leak. So those powerful scoped threads were removed and "destructors are not guaranteed to run in safe Rust" was formalized instead.

Seeing how popular async became, I wonder if this was the only and right way to move forward. I'm not against Arcs, they have their place. But if you can use normal RAII it's much preferable.



How is this different from the prior 1.0 scoped threads? I remember the whole "Leakpocalypse" event that lead to the deletion of the API, (and subsequently, to invention of this API, where the scope guard is represented as an additional closure) but those were entirely lexical too, right? Rust borrows in general are pretty much lexical in the sense that you only analyze the body local function, nothing more. Rustc can't reason about dynamic invariants, you need runtime checks for that.


Probably some sort of flexibility / infectivity e.g. let’s say you have a function a which calls a function b with some borrowed data, b wants to spawn and return a thread (possibly wrapped in some other structure).

In the original acception I think you could literally do that, a scoped thread would just be a normal RAII object with various lifetime bounds.

With the new scoped threads, I’d think you need to create the scope in a and pass the scope handle to b so it can spawn the thread correctly.


> async runtimes cannot use this feature to provide borrowing across tasks

They can't use this function, but with some duplicated unsafe code they can still provide similar APIs for their callers, right? Things like this: https://github.com/jaboatman/tokio-scoped


I just checked quickly so may be wrong, but it looks like they're pulling the same trick as with the new scoped threads, ie only lexical scoping. Note also that the scope function is blocking and called from within an async fn, which is normally not great for composability with other async code.

That said, taking a step back it has crossed my mind that bringing back true scoping with unsafe in the impl might be an acceptable way forward, despite how upsetting this is to a lot of rustaceans. I think that the failure modes (ie triggering UB) for this case can be simply enumerated in a short list of "DON'Ts" (such as putting a scoped join handle in an Arc).

OTOH, since leaking was formalized and explicitly allowed (heck, even borderline encouraged through mem::forget), god knows if people have exploited that for other cases in true Hyrum's law fashion, that breaks the abovementioned idea. They certainly had the right to.


the problem with this approaches like these that it requires blocking the runtime: https://github.com/jaboatman/tokio-scoped/blob/master/src/li....




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: