Live data from Hacker News

Several core problems with Rust

bykozy.me

251–260 of 341 posts

Re: Several core problems with Rust

#251
post #213

Earlier quoted context omitted.

>Do not misrepresent them and pretend that the Rust developers are incompetent or malicious. I'm sorry, but I sensirely think the Rust designer did a sloppy work by reimplementing C++ flaws with a new syntax. The history repeats itself, the same pathological mechanism once driving C++ development now drived Rust — I mean large enterprise wanting to change everything without changing nothing, the new tool that would f…

Rust certainly takes after C++, but it's not the same. It's more like C++ if it was made today. For instance, Rust's destructive move semantics are the better default. (However, Rust making everything moveable by default is a bit of a drawback.) I don't understand your point about std::shared_ptr, std::mutex, and the immutability/mutability model. These are not C++ constructs; they are general programming constructs…

> It's not "my take". https://www.pingcap.com/blog/rust-compilation-model-calamity... is a good resource on this.

I think one interesting thing that could be explored more is what aspects of Rust "inherently" result in slow compilation (i.e., if you changed said aspects to improve compilation speeds then you end up with a "different" language, assuming some hand-waviness with respect to equivalence here) and what aspects are practically and/or theoretically improvable.

For example, rustc's reliance on LLVM for optimization is a well-known source of sluggishness, but I wouldn't classify that as "inherent" since Rust could use a different backend that works faster (e.g., Cranelift) and/or be more efficient about the IR it emits. Something like monomorphization, on the other hand, is a more in a grey area since it's (as far as I know) essential for Rust to meet its performance goals, but IIRC it's not out of the question for the compiler to implement generics using a different strategy instead, which might be viable as an opt-in tradeoff.

Re: Several core problems with Rust

#252
post #206
post #49

Earlier quoted context omitted.

Unless I need close to 100% memory safety with no compromise in performance I'd rather write Zig, Odin or Go. Zig and Odin are much more enjoyable to write and provide enough safety for a lot of applications, and Go gets you 90% of the performance of Rust without the complexity.

>Unless I need close to 100% memory safety If you need that, you go Ada. Rust is practically the same as Zig, when compared to Ada.

I swear there are people who take a massive amount of pride in using languages or technology that are obscure. That thing use to be Rust, but now that it's become fairly mainstream they have to find something new to move to.

I wonder how long it will be before we start seeing "Ada is the new Rust" YouTube videos.

Re: Several core problems with Rust

#253
post #195

Earlier quoted context omitted.

It has potential to be the new thing, since several details synergize to make this incident more powerful: 1. Previous claims that Rust code often just works after compiling. 2. Previous claims that low-level error-handling idioms like matching, using Result, etc improve code reliability. 3. Previous claims that using unwrap in example code is ok for brevity. Also, Rust developers would know not to use it in producti…

.unwrap() was a huge mistake. It should be banned from release builds outright. It's the equivalent of dereferencing a null pointer in C or the NullPointerException in Java. All .unwraps() should be replaced by .expect("uniquely identifying message") immediately and preferably the compiler checks that the expect messages are unique within a crate and issues a warning. Debug builds should by default give .unwrap() and…

To my knowledge, the only difference between `unwrap()` and `expect()` is that the latter takes a custom error message, whereas the former generates a generic error message. In both cases the resulting error message includes the filename and line number of the panic. Both can also generate stack traces if you set `RUST_BACKTRACE=1`, unless this was explicitly disabled at compile time.

So if you want to ban `unwrap()`, then you should probably also ban `expect()`, and make sure to handle all possible cases of Err/None instead.

Re: Several core problems with Rust

#254

Regarding slow compilation... On the one hand, I don't regard it as a real "problem" because as the post says, it's by design and the design is that you pay the compilation cost but in return you get something valuable from it: fast safe code. So you pay a fixed cost to compile during development and it's your users and future you who get the benefit of future performance and stability. This is why Rust users are usu…

My understanding is Rust compiles each crate in the same way C++ compiles each .cpp file, so if you stick everything in a single crate you get horrible compile times. This does seem like a poor design decision by Rust to me, forcing people to break things into arbitrary crates just to get reasonable compile times. It also seems like a disaster for incremental compilation.

> This does seem like a poor design decision by Rust to me, forcing people to break things into arbitrary crates just to get reasonable compile times.

Not necessarily, since codegen units can introduce intra-crate parallelism during compilation.

But in any case, as with basically everything there are tradeoffs involved in choosing compilation unit size. Making your compilation unit crate-sized also means that you have some more flexibility in your code organization (e.g., stuff can mutually depend on each other, which is itself potentially useful and/or harmful) and you don't run into other potential issues like the orphan rule. There are also potential impacts on optimization, though LTO muddy the picture. Codegen units are just the cherry on top.

There's almost certainly other things I'm forgetting and/or not knowledgeable about as well.

Re: Several core problems with Rust

#255
post #195

Earlier quoted context omitted.

It has potential to be the new thing, since several details synergize to make this incident more powerful: 1. Previous claims that Rust code often just works after compiling. 2. Previous claims that low-level error-handling idioms like matching, using Result, etc improve code reliability. 3. Previous claims that using unwrap in example code is ok for brevity. Also, Rust developers would know not to use it in producti…

.unwrap() was a huge mistake. It should be banned from release builds outright. It's the equivalent of dereferencing a null pointer in C or the NullPointerException in Java. All .unwraps() should be replaced by .expect("uniquely identifying message") immediately and preferably the compiler checks that the expect messages are unique within a crate and issues a warning. Debug builds should by default give .unwrap() and…

> Debug builds should by default give .unwrap() and .expect() a tiny chance, like 0.1%, to trigger anyway, even when the Option is Some (opt out via configuration).

I'm trying to understand what you're proposing. Are you saying that normal debug builds should have artificial failures in them, or that there should be a special mode that tests these artificial failures?

Because some of these failures could cause errors to be shown to the user, that could be really confusing when testing a debug build.

Re: Several core problems with Rust

#256
> Rust is memory safe and unreliable. The price of memory safety was reliability

Uptime isn't reliability; it's producing predictable behavior. Allowing indeterminate ("malfunctioning") behavior is the opposite of reliability.

Re: Several core problems with Rust

#257
post #74

Earlier quoted context omitted.

> The cloudflare bug was not caused by rust Yeah. Rust’s Option::None as like null in C++. Unwrapping an option is like checking if something is null and crashing. This "crash from an unwrap" is just a null pointer exception / segfault in any other language. The same bug would be trivial to write in any other language, and with more or less the exact same result. Its just - weirdly news because it was rust code. What…

Rust makes it very, very easy to .unwrap() something, making panic-crashes the default error handling behavior for a lot of rust programmers. But it does this without, e.g., Erlang's reliability services that will auto-relaunch code that crashes. The end result is NOT a very good user experience. I say this as a Rust advocate and daily Rust programmer, btw.

When it comes to distributed services, unwrap is likely the behavior you do want, because the service is being run by a scheduler that detects failures, and a panic would be tied to a metric and page an sre. My read of the situation is that they were overwhelmed by their dashboards which made it harder to identify the root cause, but that is a common situation for these kind of events. I'm pretty sure that this exact sequence of events will never happen again to them because they will adjust their observability to be clearer, should this ever happen again.

For libraries and cli tools, you don't want panics except for things that are broken beyond any recovery. A cli tool should not panic directly, instead emitting human readable errors.

Re: Several core problems with Rust

#258

Earlier quoted context omitted.

Rust certainly takes after C++, but it's not the same. It's more like C++ if it was made today. For instance, Rust's destructive move semantics are the better default. (However, Rust making everything moveable by default is a bit of a drawback.) I don't understand your point about std::shared_ptr, std::mutex, and the immutability/mutability model. These are not C++ constructs; they are general programming constructs…

> It's not "my take". https://www.pingcap.com/blog/rust-compilation-model-calamity ... is a good resource on this. I think one interesting thing that could be explored more is what aspects of Rust "inherently" result in slow compilation (i.e., if you changed said aspects to improve compilation speeds then you end up with a "different" language, assuming some hand-waviness with respect to equivalence here) and what as…

There are at least three separate things that rustc and cargo could do to significantly improve compilation speed, but they are complex engineering efforts that require time and engineers being paid to work on full-time. They are: doing what zig does to compile only items that arr reachable, which requires making rustc reentrant to stop after name resolution and cargo more complex to pass used paths through subsequently, leveraging an incremental linker and have rustc only codegen the binary patch instead of the whole binary and have the linker calculate the patch, and caching proc-macros and treat them as idempotent (likely as opt-in). There are of course others, like pre-compiled distribution, better intra-rustc parallelism or feature cfg handling, but those have more open questions and require additional design work before I could claim they're attainable.

Re: Several core problems with Rust

#259
post #201
post #90

Earlier quoted context omitted.

>Eventually I rewrote my btree on top of Vecs. My node & leaf pointers are now array indices. The result? There is no longer any unsafe code. The code has become significantly simpler and it now runs ~10% faster than it did before, which is shocking to me. I guess bounds checks are cheaper than memory fragmentation on modern computers. Optimizations are very complex and potentially fragile in Rust, LLVM has to sort t…

>Do note that binary trees are mostly an obsolete legacy today — they are way too cache-unfriendly. I mean you could have written similar code in C++ using std::vector or std::dequeue and get the bounds checking too. This is simply not true, it's an ongoing thorn of mine that the Rust community seems to decide that anything which cannot be programmed in rust is obsolete legacy. This is a silly stance which is harming…

The person you're replying to is the author of the blog post, which I would not accuse of being a Rust proponent.

Re: Several core problems with Rust

#260

Earlier quoted context omitted.

Also the argument with `Arc >>>` boils down to "Rust makes it hard to work with automatic reference-counted shared mutable heap-allocated state." In which case... mission accomplished? Rust just made explicit all the problems that you still have to deal with in any other language, except dealing correctly with all that complexity is such a pain that you will do anything you can to avoid it. Again, mission f#*@ing acc…

Nit: it doesn't make it hard, it makes it ugly and explicit. `Arc >>>` is not hard to use, it's just annoyingly verbose and ugly. That's a low level construct, there are much nicer higher level sharing constructs, like channels. Mission accomplished.

Yeah, this pretty much summarizes my experience. In most situations, the actual information I need to share between different contexts is quite small, and using a channel ends up being pretty clean. There are still times I need an actual reference counted wrapper around a mutex, but they're the exception rather than the norm, and even then, there are often ways you can reduce the contention (e.g. if `T` is a type you can clone, and you only need a snapshot of the current state of the data rather than preventing changes while processing based on that snapshot, you can just clone it, drop the mutex guard, and then proceed without needing to worry about borrows).
Post reply on HN