Live data from Hacker News

Why asynchronous Rust doesn't work

eta.st

271–280 of 305 posts

Re: Why asynchronous Rust doesn't work

#271

Earlier quoted context omitted.

I’d say both. The author of the post called Rust async/await a disaster, and the top commenter, who withoutboats replied to, agreed with the author’s criticism.

I don't think the author of a blog post is accountable in any way for the most inflammatory thing somebody that agrees with them says.

The original article is just as inflammatory as its top comment if you’ve read it:

> In 2017, I said that “asynchronous Rust programming is a disaster and a mess”. In 2021 a lot more of the Rust ecosystem has become asynchronous – such that it might be appropriate to just say that Rust programming is now a disaster and a mess. As someone who used to really love Rust, this makes me quite sad.

I imagine withoutboats read both and was pretty upset.

Re: Why asynchronous Rust doesn't work

#272

Earlier quoted context omitted.

> To be frank I find the point about developer speed in Rust to be a bit exaggerated, it's pretty high level and the tooling is pretty great. Rust has a long learning curve that most people won’t make it through. For them, they might feel the language is slow to developenin because they haven’t gotten to the point where they are “thinking” in Rust. As a Haskeller, you are well suited to learn Rust; due to their simil…

That's an interesting take on Rust. Given that I have written a lot of code in Standard ML, I might give Rust a try after all. GP's statement "If you care about security, correctness and performance but don't care about developer speed, use Rust." threw me a little off here. Because, Standard ML is very quick and easy to develop in. So should Rust not inherit that property?

Yes, I think Rust does get there. The thing of it is, I think people are measuring "time of development" differently. To some, the time developing a thing is the time spent writing it, and then getting it out the door. They often don't include things like fixing bugs that are discovered down the line and handled maybe by a completely different team. There's a difference between writing something and writing something right.

The Rust compiler and specifically the borrow checker help you write code that works the first time, which is a property Haskell famously exhibits. In order to get there, sometimes an involved conversation with the borrow checker or type checker is needed. What this means is sometimes you might spend a good long while figuring out a particular lifetime and ownership annotation in order to satisfy the borrow rules. Another implication is that sometimes the way you've architected your code is just plain wrong as far as the borrow checker is concerned. Sometimes it's hard to tell when you just need to add a particular annotation to your code to make it work, or if you actually need to rethink everything entirely. For example, if you go writing a doubly linked list in Rust thinking you'll use pointers, that's just the wrong way to go about it in Rust world, so rather than trying to force that style of code, doing things the Rust way (using Rc>>) will yield better results.

But once you get your code to compile, things generally work in a sense that the code will never fall victim to a whole class of bugs that frequent code written in other languages (segmentation faults, use after free, memory leaks, dangling pointers, etc.) You just won't see these things in safe, idiomatic Rust code.

And that leads me to developer speed. Once you and the borrow checker are on the same page, it's like night turned to day. Early when I first started writing Rust, I would spend most of my time dealing with borrow checker errors. Now that I know what the borrow checker expects, and I've internalized all the strange syntax and edge cases, the borrow checker fades into the background and I can code in Rust just about as fast as I can in TypeScript.

As a Haskeller, I expect you might approach writing Rust code in a functional style, and I think this would serve you well. The general approach that newbies take in Rust and which finds strong resistance by the Rust compiler is copious use of passing references for mutation, and creating a rat's nest of pointer references. This style of coding doesn't go over well in Rust, and unfortunately a lot of coders practice this because it's permitted by their native language.

Instead, it's better to lean into type checking and actually use the type checker to save you from having to write a lot of code. Take advantage of immutability and referentially transparent function. Make heavy use of pattern matching and Maybe monads cough I mean Option. We don't use that word in Rust. Haskellers get all of this.

Re: Why asynchronous Rust doesn't work

#273

Earlier quoted context omitted.

I don't think the author of a blog post is accountable in any way for the most inflammatory thing somebody that agrees with them says.

The original article is just as inflammatory as its top comment if you’ve read it: > In 2017, I said that “asynchronous Rust programming is a disaster and a mess”. In 2021 a lot more of the Rust ecosystem has become asynchronous – such that it might be appropriate to just say that Rust programming is now a disaster and a mess. As someone who used to really love Rust, this makes me quite sad. I imagine withoutboats re…

I'm less comfortable projecting my own opinions into the head of 'withoutboats than you are. The author of the comment they responded to and the author of this post are not the same person.

Re: Why asynchronous Rust doesn't work

#274

Earlier quoted context omitted.

Not possible for the same reasons why just adding a borrow checker to C++ isn't possible. Mostly this comes down to incompatibility with existing code. Zig is just not memory safe, and the only solution would be to add a GC.

This is a very bad take. By your argument there's no reason why sel3 should exist, which is written in C and safer than rust.

Assuming you mean seL4, that was formally verified by taking a manual specification of the L4 kernel and laboriously proving that the C code implements that specification. That is not at all what the compiler's lifetime/borrow check subsystems do for Rust. They know nothing about what the program is supposed to do; they only check that some relatively-simple rules are followed. That's why Rust requires so much less effort on the part of the programmer than formalisms that aim to prove programs correct.

Re: Why asynchronous Rust doesn't work

#275
post #261

Earlier quoted context omitted.

But this hypothetical "written without taking the proper care" code is buggy. Like I said it's just the same situation as a bad implementation of Index but more convoluted. Rust's standard library takes this very seriously. In many languages if I try to sort() things which refuse to abide by common sense rules like "Having a consistent sort order" the algorithm used may blow up arbitrarily. But Rust's sort() is robus…

Rust's npm like approach to crates and micro approach to standard library make it a real problem, regardless of the quality approach to the standard library. You would have a point if the standard library was batteries included. When a language sells safety it has to go all in.

Cargo-geiger and similar tools allow you to audit crates you depend on to discover whether they're definitely safe.

Of course just because some Rust is unsafe does not mean it's wrong, it just means that you're relying on it being correct as you have to with all code in unsafe languages.

Re: Why asynchronous Rust doesn't work

#276

Earlier quoted context omitted.

> let the crazy non-blocking folks write hand-crafted epoll() loops like they do in C++. > I think this is the most underappreciated part of this article. I think it's incredibly silly actually. Abandon all async for a difficult and error prone epoll model? > Since when did everything have to be async? It doesn't! No one is forcing anyone to use async. I'm not sure why the author implies that. But if you do want to u…

>It doesn't! No one is forcing anyone to use async. Well, hang on there... this isn't entirely fair. Rust does not force you to be async, but the community in some ways pushes you to be async even where it might not make sense for it to be the default. I can't say for certain (and this is all my opinion, to be clear) but it feels like this started happening when async-fervor hit its peak. My go-to example is reqwest,…

That is an absolutely fair distinction.

I think a blocking implementation being a `await(async impl)` is typically fine...

the problem with that is the lack of async interop in the current state of things, more than the async runtime which mostly gets compiled away.

Re: Why asynchronous Rust doesn't work

#277

Earlier quoted context omitted.

The original article is just as inflammatory as its top comment if you’ve read it: > In 2017, I said that “asynchronous Rust programming is a disaster and a mess”. In 2021 a lot more of the Rust ecosystem has become asynchronous – such that it might be appropriate to just say that Rust programming is now a disaster and a mess. As someone who used to really love Rust, this makes me quite sad. I imagine withoutboats re…

I'm less comfortable projecting my own opinions into the head of 'withoutboats than you are. The author of the comment they responded to and the author of this post are not the same person.

[deleted]

Re: Why asynchronous Rust doesn't work

#278

Earlier quoted context omitted.

The original article is just as inflammatory as its top comment if you’ve read it: > In 2017, I said that “asynchronous Rust programming is a disaster and a mess”. In 2021 a lot more of the Rust ecosystem has become asynchronous – such that it might be appropriate to just say that Rust programming is now a disaster and a mess. As someone who used to really love Rust, this makes me quite sad. I imagine withoutboats re…

I'm less comfortable projecting my own opinions into the head of 'withoutboats than you are. The author of the comment they responded to and the author of this post are not the same person.

[deleted]

Re: Why asynchronous Rust doesn't work

#279

Earlier quoted context omitted.

Why would the first example with the database be "shooting your own foot"? I'm not a Rust dev, but in other languages that code makes perfect sense to me.

What if you do: my_fn(|| { db.store(42); }); db.drop(); (Assuming you can just drop the database object, the semantics don’t really matter but the idea is the same.) The OP wants an easy way to do this but this is just not an easy thing to do. How can the closure guarantee that the database object will exist if my_fn decides to sleep for a couple seconds? Most languages do not have this problem because either: they u…

Ah, I see. So if there was a way to mark the DB as "ephemeral" or so, then it would be fine, but since the compiler can't know if the reference isn't deleted/freed, it doesn't compile? If I got it right, then that makes total sense.

Re: Why asynchronous Rust doesn't work

#280

Earlier quoted context omitted.

Why would the first example with the database be "shooting your own foot"? I'm not a Rust dev, but in other languages that code makes perfect sense to me.

For the same reason that keeping a shared excel file in a network disk is a bad idea. The closure can write to database, and after the call, there’s no way to know if it has already written, or even if it’s writing to it right now .

Well, without further ado that's true. But the callback could of course set a result type somewhere (so, behave similar to a future/promise) and then we could know if/when it is finished and if it was successfully, or if it's still running (or broke without an error). But that's not Rust specific, that's just plain language-independent logic no?
Post reply on HN