Hacker News new | ask | show | jobs
by tdbgamer 3043 days ago
You just have to intentionally use a method on integers called wrapping_add() to explicitly allow overflows. That said I believe overflows are only checked when you compile with the debug target. So when you compile to the release target it doesn't check them I believe.

I personally think it's a good thing to only allow overflows when explicitly allowed.

1 comments

The rules are:

1. overflow is a "program error"

2. If `debug_assertions` are enabled, then overflow must panic

3. If overflow does not panic, then it must two's compliment wrap

This leaves the door open to always requiring a panic someday in the future, if performance gets there.

> overflow is a "program error"

Can you expand on what that means to someone who hasn't used Rust yet? Does it mean a third thing distinct from (2) and (3)? Or is it that (2) and (3) are the things that might happen as a result of (1)?

Imagine if dereferencing a null pointer in C was defined to segfault. Currently, it's UB, which means the optimizer assumes it's not null, and when you break that assumption, weird things happen, the least scary of which is a segfault.

This is similar. "program error" means "You're not supposed to do this. But the compiler will not assume that you've not done this; it has your back. If you do this your program will exhibit defined behavior. Perhaps undesired behavior (panicking, or segfaulting), but the behavior will be defined."

How entirely sane and helpful! Thanks for the clarification.
It's cool, this is the only place where this kind of language is used. So even if you were familiar with Rust, you might not be familiar with this particular corner.

Mostly, it means "this is wrong but it is not undefined behavior".

> Or is it that (2) and (3) are the things that might happen as a result of (1)?

Yes, this.

> If `debug_assertions` are enabled, then overflow must panic

It is very risky to have different behavior on such things in test and production.

For what it's worth, you can still compile your code to panic on overflow in release builds today if that's worth it for your use case.
Yes, that's exactly the path I would choose. Not that I'm the target audience in my present day job but nothing is more irritating than having a production environment that subtly differs from the test environment at the language level.
I think it's more frustrating when production fails more often than the test environment than the other way around but I see your point. Main thing to consider obviously is that enabling the checks in the release code will degrade performance. Ultimately, overflow is a difficult problem to solve, I don't think there's a universal win that doesn't trade something off.
its fairly common to have a compiler produce different builds for release vs debug envs.
Rust cannot fix all bugs. This isn't a memory safety issue. Sometimes, you have to make tough calls.

Maybe Rust++ will fix this, someday :p

(Or, once people have the tolerance for the performance degradation and we can turn it on in rustc, exactly why we specified it the way we did.)

(Or, you can tweak it to include this behavior in release mode; always an option)

This is not about 'fixing all bugs', it is about re-visiting a specific class of bug that we already know about and have already seen many bad instances of in the wild.

Few things are harder to debug than things that pass the tests but fail in production and anything that inserts behavior like that should be avoided like the proverbial plague.

If you're already of a mindset to have a Rust++ then you are missing the point, Rust quite possibly has a window of opportunity to displace C but for that to work at a level where it succeeds rather than as an 'also ran' you will need to religiously avoid repeating the past.

> you will need to religiously avoid repeating the past.

Rust is not a religious language, regardless of what some people may think. It's even in the name, which evokes something practical, well used, and a bit worn.

> If you're already of a mindset to have a Rust++

Language design is about trade-offs. Do I think Rust is generally an excellent language? Yes. Does that mean that I believe we have solved programming languages, that there will never be a language better than Rust? No. Someday, Rust will be the old incumbent, and a new language will overtake it. That's how progress works.

In the end, as I said, this was a very tough call. In the end, we decided to be hardline[1] about one thing, and one thing only: memory safety. Does Rust care about program correctness? Absolutely! Does it care about it as much as memory safety? It does not. There's several PLT features that could help improve program correctness that are not in Rust. They're not in it because it's a balance. Including them would harm several of our other objectives for the language.

This RFC was one of the most discussed at its time. 160 comments! https://github.com/rust-lang/rfcs/pull/560

We would have loved to say that it's always on, but that's just life. Nothing is ever perfect. Rust certainly is not.

1: note that I said "hardline" and not "religious" here even; even Rust's most sacred principle, memory safety, has a keyword built into the language that lets you subvert it!

Sorry, but that just doesn't wash.

The reason C has the bad reputation it does is because it makes performance over correctness trade-offs that we have come to realize that are not just far from ideal, they are fundamentally wrong.

And now Rust, the supposed replacement of C is going to make different trade-offs some of which are rooted in exactly the same performance-over-correctness decisions that gave C its bad name.

I completely get why that RFC had as much input as it did, it's akin to the Python 'whitespace' decision, it's a fundamental thing and to get it wrong will turn off a lot of people from what you are building.

On another note, integer overflow has been the cause of the same kind of issues that unsafe use of memory is associated with:

http://www.kb.cert.org/vuls/id/945216

That makes it a problem in the same class and frankly I'm quite surprised that Rust would take performance over safety in this matter, in my opinion good slow code is always better than faster but possibly incorrect code.

My mental model of Rust's current overflow behaviour is that "integer overflow is wrapping overflow, but during development it also panics to push me to use explicit wrapping in the code." I'm failing to see how that can qualify as something that "pass[es] the tests but fail[s] in production".
A pretty reasonable test would be that some function panics on invalid input, in this case by way of integer overflow. This test would pass in a debug build, but could cause unintended, possibly even insecure, behavior in a release build.

Ideally you would run your tests in both debug and release modes, though. :)