5 ms·
This is what I find most annoying about rust's async ecosystem; many functions depend on being called within a certain executor, but this is not documented in t
by lalaithion 4y ago
This is what I find most annoying about rust's async ecosystem; many functions depend on being called within a certain executor, but this is not documented in the type at all. You should not provide, and arguably not be able to provide, functions which look like they can be called in any context but which require shared mutable global state!
- ahepp 4y agoCan you give an example of what you're talking about? I'm pretty new to async and Rust in general but I'm having a hard time thinking of an example (almost certainly a deficiency on my end haha).
- paulgb 4y agoHere’s an example: https://docs.rs/tokio/latest/tokio/time/fn.sleep.html#panics https://docs.rs/tokio/latest/tokio/time/fn.sleep.html#panics > It can also panic whenever a timer is created outside of a Tokio runtime. Note that nothing in the signature tells you that, just the function documentation. In practice, this ends up not being a big deal, IMHO. The ecosystem has largely coalesced around tokio as an executor. The only times I've run into it are when running Actix, which has its own global state on top of tokio.
- ahepp 4y agoAh, that makes sense. In fact, I was trying to unit test some time based code in tokio a month or two back, and it was really painful. I couldn’t figure out how to inject a fake clock into the runtime to test my timers.
- lalaithion 4y agoIt’s not a big deal because the ecosystem has coalesced around tokio, but it’s coalesced around tokio partially because it’s a big deal.
- davidatbu 4y agoIf one is using a function from tokio itself, is it not a reasonable expectation that one should check the docs as to whether the function requires the tokio executor?
- ahepp 4y agoPart of me agrees with what you’re saying. I mean, tokio is right there in the namespace. But another part of me questions why it’s ok that calling a function in the wrong context is a runtime panic rather than a compilation error. Coming from a C background it seems pretty normal to just have a “tokio_context*” argument on tokio functions that would at least make the statefullness less obscure?
- davidatbu 4y agoIs what you're suggesting that one has to pass that `tokio_context` into every `.await()`? If so, I personally would be in strong opposition, cuz I don't think the verbosity cost is justified, in any of the use cases for async I've come across.
- ahepp 4y agoI don't think you'd have to pass the context into an await? Await is a Rust construct, not a tokio one. Unless I'm making a complete fool of myself... Maybe I'm just jaded from writing too much C, but it doesn't seem like a big deal to me to change sleep(duration) to sleep(ctx, duration). Three letters to be correct, transparent, and not have global state? Look at what a complete mess the C standard library is from where they used global state like that. I'm sure there are lots of other ways you could do it, like make the context it's own struct and call a sleep impl for the struct or something?
- davidatbu 4y agoYeah, I guess we're disagreeing about a very non-concrete proposal, so there isn't much point to our convo :)
- yazaddaruvala 4y ago+1 I don't have the time to shepherd this RFC (or something similar), but I really wish that the whole Async ecosystem was built on something less error prone / magic-y than ThreadLocalState. Its not ideal to ever have any "hidden" functionality like auto-propagation, but it would be way better than the current state of async Rust. https://github.com/rust-lang/rfcs/issues/2327 https://github.com/rust-lang/rfcs/issues/2327
- oconnor663 4y agoI could be wrong, but I don't think Rust futures/tasks rely on thread-local storage anymore. Some early iterations of the feature did, but I think that was replaced with an explicit argument to the poll() function before stabilization. That said, the typical async/await syntax makes that invisible, so it definitely does feel a lot like TLS.
- gpderetta 4y agoIf I understand correctly, Autopropagators are basically implicit parameters , a.k.a typed dynamic scoping, which is exactly what you need to solve this problem. In fact the equivalent Scala functionality is mentioned in the issue thread. They might be confusing but they are probably a million time better than actual mutable globals.
- msla 4y agoThis sounds like a job for monads, to be honest. "Shared mutable global state" is "IO monad" all over. (Ia! Ia! Ruskell fhtagn!)