Live data from Hacker News

Why asynchronous Rust doesn't work

theta.eu.org

461–470 of 499 posts

Re: Why asynchronous Rust doesn't work

#461

I'm not totally sure what the author is asking for, apart from refcounting and heap allocations that happen behind your back. In my experience async Rust is heavily characterised by tasks (Futures) which own their data. They have to - when you spawn it, you're offloading ownership of its state to an executor that will keep it alive for some period of time that is out of the spawning code's control. That means all dat…

I'm a giant Rust fanboy and have been since about 2016. So, for context, this was literally before Futures existed in Rust. But, I only work on Rust code sporadically, so I definitely feel the pros and cons of it when I switch back and forth to/from Rust and other languages. The problem, IMO, isn't about allocations or ownership. In fact, I think that a lot of the complaints about async Rust aren't even about async R…

I wonder if most of the pain is actually caused by Rust async being an MVP, so things like async trait functions (which would be very nice) don't exist... yet.

I don't know if anybody has shown that they can't ever exist, it's just that they weren't considered necessary to get the initial async features out of the door. Rather like how you can't use impl Trait in trait method signatures either (there's definitely some generics-implications-complexity going on with that one).

Re: Why asynchronous Rust doesn't work

#462

Earlier quoted context omitted.

> First, Rust prefers unique ownership and acyclic data structures. You can make cyclic structures work if you use RefCell and Rc and Weak, but you're giving up the static guarantees that the borrow checker gives you in favor of a bunch of dynamic checks for 'is this in use' and 'is this still alive', One way to get around that is to instead of doing it like the very structureless async way actually impose lifetime r…

The structured parallelism movement predates structured concurrency by years and needs a similar push. It's from 2004 with the X10 parallel language and then Habanero in Java via their "async-finish" construct I wonder if your quote (structured XYZ or ABC considered harmful) is inspired by - https://conf.researchr.org/details/etaps-2019/places-2019-pa...

Well the link I posted is older than your link from 2019 so I doubt that. The other direction may be possible.

However, enither are definitely not the first having ideas along these lines - structures and logic like this can also be found in Erlang supervisors after all.

And as for the quote, it is quite explicitly referring to Dijkstra and structured programming constructs in nonconcurrent settings.

Re: Why asynchronous Rust doesn't work

#463
post #64

Earlier quoted context omitted.

Interesting! For comparison, Haskell went with the library approach but has the syntactic sugar of the equivalent of `and_then` built into the language. (I am talking about Monads and do-notation.) It's a bit like iterating in Python: for-loops are a convenient syntactic sugar to something that can be provided by a library.

It is a little old, but for the general gist of it, http://aturon.github.io/tech/2018/04/24/async-borrowing/ is an amazing description of the problem here. It is a PhD level research problem to know if monads and do notation would be able to work in Rust. The people who are most qualified to look into it (incidentally: a lot of the same crew was who was working on async) believe that it may literally be impossible.

[deleted]

Re: Why asynchronous Rust doesn't work

#464
post #185

I'll repeat this until my karma is zero: Erlang, Rust and Go have simple memory models and cannot do Joint (on the same memory) Parallelism efficiently. They are only fragmenting development. In my opinion there are only two programming languages worth mastering: C+ (C syntax compiled with cl/g++) on client and Java SE (8u181) on server. That said C++ (namespaces/string/stream) and JavaScript (HTML5) can be useful fo…

This is just plain wrong. There's nothing you can do in C/C++ (or C+, as you put it) that you can't in rust, when it comes to parallelism. There's always unsafe if you really need it.

Re: Why asynchronous Rust doesn't work

#465

Earlier quoted context omitted.

The structured parallelism movement predates structured concurrency by years and needs a similar push. It's from 2004 with the X10 parallel language and then Habanero in Java via their "async-finish" construct I wonder if your quote (structured XYZ or ABC considered harmful) is inspired by - https://conf.researchr.org/details/etaps-2019/places-2019-pa...

Well the link I posted is older than your link from 2019 so I doubt that. The other direction may be possible. However, enither are definitely not the first having ideas along these lines - structures and logic like this can also be found in Erlang supervisors after all. And as for the quote, it is quite explicitly referring to Dijkstra and structured programming constructs in nonconcurrent settings.

X10 Programming language is from 2004, http://x10-lang.org/x10-community/publications-using-x10.htm...

Habanero Java from 2011 https://www.cs.rice.edu/~vs3/PDF/hj-pppj11.pdf

Re: Why asynchronous Rust doesn't work

#466
post #443
post #433

Earlier quoted context omitted.

Wait so you're saying "|| async move {}" is equivalent to "|| move { async move {} }"? If so then mystery solved, but that is not obvious at all and should be documented somewhere more clearly. In that case all I'm doing vs. their example is explicitly writing the function that returns the promise instead of letting it be "inferred?"

Well, no, that second one isn't valid rust, perhaps you mean: move || async move {} But this is not equivalent to: || async move {} crucially the closure is not going to take ownership of anything. This is kind of besides the point though, what I'm getting at is that both of the above are a closure which returns a future. i.e. you can also write them in this style: || { return async move {}; } Maybe that's more clear…

Ohhh.... I think I get it. The root of my confusion is that BRACES ARE OPTIONAL in Rust closures.

This is apparently valid Rust:

let func = || println!("foo!");

I didn't know that, which is why I thought "|| async move ..." was some weird form of pseudo-async-closure instead of what it is: a function that returns an async function.

Most of the code I see always uses braces in closures for clarity, but I now see that a lot of async code does not.

Re: Why asynchronous Rust doesn't work

#467
post #466
post #443

Earlier quoted context omitted.

Well, no, that second one isn't valid rust, perhaps you mean: move || async move {} But this is not equivalent to: || async move {} crucially the closure is not going to take ownership of anything. This is kind of besides the point though, what I'm getting at is that both of the above are a closure which returns a future. i.e. you can also write them in this style: || { return async move {}; } Maybe that's more clear…

Ohhh.... I think I get it. The root of my confusion is that BRACES ARE OPTIONAL in Rust closures. This is apparently valid Rust: let func = || println!("foo!"); I didn't know that, which is why I thought "|| async move ..." was some weird form of pseudo-async-closure instead of what it is: a function that returns an async function. Most of the code I see always uses braces in closures for clarity, but I now see that…

> I didn't know that, which is why I thought "|| async move ..." was some weird form of pseudo-async-closure instead of what it is: a function that returns an async function.

It does not return an async function, it is a closure that returns a future. Carefully read the function signature I had posted:

    fn foo(f: F) where F: Fn() -> Fut, Fut: Future
async move {} is just a future, there is no function call. || is a closure, put them both together and you have a closure that returns a future.

edit: I'm trying to think of how else to explain this. a future is just a state machine, an expression, there is no function call.

   let f = async move { };
Is a valid future, you can f.await just fine.

Re: Why asynchronous Rust doesn't work

#468
Being a developer of 30+ years I stick with C / C++. They give you the flexibility required for all use cases. They leverage the OS and hardware architecture by reflecting it appropriately. The desire to abstract away complexity is not possible given that the computing architecture is so fundamental to everything layered above it.

Re: Why asynchronous Rust doesn't work

#469
post #454

Earlier quoted context omitted.

> Wouldn't HKTs help us abstract over function/types more easily, including closures? In the sense that HKTs are a higher level abstraction, sure. More later. > Aren't GATs a special case of HKTs? My understanding is that GATs can get similar things done to HKTs for some stuff that Rust cares about, but that doesn't give them a subtyping relationship. Haskell has both higher kinded types and type families. That being…

> That is, even if Rust had a monad trait, that does not mean that Try and Future could both implement it. This is because, in Haskell, these things have the same signatures. In Rust, they do not have the same signature. For reference: This is nonsense; Try and Future are not the same thing in Haskell, there are plenty of functions you can only call with one or the other. The point of the monad abstraction is to abst…

Sorry, you're right! Ironically, I remembered the high level problem, but filled in the wrong concrete details. I also made the mistake of talking about Try/Future, and then switched to Iterator/Future.

> is a subtype of

Rust does not have subtyping. (except for lifetimes)

The point is, we don't actually have an existence proof that this is possible, and a lot of evidence to the contrary. It may be possible, but it's not a simple "just do x." There is a lot of handwaving in this post that would need to be hammered out, and details that would need to be fixed.

(Another point here is that "impl Trait in traits" isn't currently implemented in Rust either; this one is more feasible, though I am less sure about it when parameterized.)

Re: Why asynchronous Rust doesn't work

#470
post #243
post #26

I don't think any of this is actually a reason why async rust doesn't work. The function color problem is a bit overblown, it hasn't broken nodejs yet either. Most code is sync, sync can call async and vice versa, and the ecosystem hasn't come tumbling down yet (since most Rust isn't whichever async application runtime for web apps is currently in vogue - its a systems language after all). Either way there are bigger…

The issue is much more general. I also don't see a particular problem with Rust here, but I do see with Rust the same false hope I saw in the late eighties and early nineties with C++ (hell, I fell victim to it myself back then): the belief that with enough features, cleverness, and language complexity we could have the cake and eat it too -- have all the control of a low-level language with the same productivity as…

> Low-level languages... all suffer from low-abstraction, i.e. the inability to hide internal implementation details behind an API...

Do you have an example of Rust's inability to hide implementation details compared to, say, Java?

Post reply on HN