4 ms·
> the lifetime needs to be 'static only as the task starts to execute. It would seem the lifetime needs to be coerceable to the lifetime of the executor, but a
by couchand 7y ago
> the lifetime needs to be 'static only as the task starts to execute.
It would seem the lifetime needs to be coerceable to the lifetime of the executor, but as far as I can tell never really should need to be 'static.
> Most borrows are not exclusive.
Sorry, I meant, exclusive mutability.
> Rust's borrows have not been lexical since last year.
As I understand it, the borrows are not lexical in the classic sense of lasting until the end of the function, but they are still determined completely lexically, correct? Here the async/await syntax is provide lexical cues regarding the sequencing of asynchronous code, which is how it helps the borrow checker, right?
> But the team working on this has a ton of experience; multiple PhDs, etc, etc.
Of course. You've all done a great job producing a solid language! I'm not questioning the technical chops. And I don't think I said "just", I appreciate the scale of the problem. I'm just arguing about a tradeoff that I have not been able to find much discussion of.
It's great to improve the ergonomics of the language. We need more people to want to use it! Is it possible that this is going too far? It sounds like it introduces an awful lot of magic.
- steveklabnik 7y ago> I'm not questioning the technical chops. No worries then; a lot of people have made very similar statements in the past, and that's the place they're coming from. > I'm just arguing about a tradeoff that I have not been able to find much discussion of. I am still not 100% sure what exactly it is you're talking about, at this point, to be honest. I think it's "why do we need async/await and not just write manual futures". I've pointed out several things. Is there something else? > It would seem the lifetime needs to be coerceable to the lifetime of the executor, but as far as I can tell never really should need to be 'static. Some executors, like Tokio, are mult-threaded with work-stealing. A task (chain of futures) may start executing on one thread, be waiting, and then get moved to another thread before continuing execution. > the borrows are not lexical in the classic sense of lasting until the end of the function, but they are still determined completely lexically, correct? I am not totally sure what you mean by "completely lexically" here. It is true that NLL means that borrows can exist for only part of a lexical scope, but not more than a lexical scope. Or rather, the "more than" part is already taken care of by lifetimes anyway. > Is it possible that this is going too far? It sounds like it introduces an awful lot of magic. Most programmers don't really mind magic as much as you'd think. I mean, sure, in some sense, it's a lot of magic, but the result is that instead of writing use std::future::Future; use std::task::{Context, Poll}; use std::pin::Pin; struct Five; impl Future for Five { type Output = i32; fn poll(self: Pin<&mut Self>, _cx: &mut Context) -> Poll<Self::Output> { Poll::Ready(5) } } fn returns_five() -> impl Future<Output=i32> { Five } I write async fn returns_five() -> i32 { 5 } And, the intuition that "async fn returns an impl Future that I don't have to implement" is simple enough and accurate enough that it feels like even less magic. In practice, the people who have been writing tons of networking code don't see it as too much magic; they see it as a significantly nicer way to write the code they already have to write. The ergonomic difference is so large, that the delays in shipping have caused fairly significant community strife and pressure. It is possibly too hyped. Writing manual futures is so, so, so painful.