You seem to have been misinformed. Rust panics on overflow in debug mode (or always if you toggle a compiler flag), and has a guaranteed wrap-around in release mode. In no case there is UB.

No, that's exactly what I'm aware of, and is exactly the wrong behavior I'm talking about. "Sometimes crashes, sometimes two's compliment" are extremely different behaviors, and not meaningfully different from just saying it's UB. It should always panic, with no way to disable it. The wrap around in release mode is simply bad behavior. It can't be relied upon (because it panics in debug), and it's not useful behavior for nearly anyone's logic (wrap around almost never is logically correct behavior)

It lets Rust claim to be UB free without delivering the actual value of being UB free. You still can't rely on a given behavior because it doesn't have one behavior, it has two, and the two behaviors are wildly incompatible with each other.

It's surprising and potentially buggy behavior, but that's very different from undefined behavior. To such a degree that I think you might not understand what it means, and what the risks are around undefined behavior, especially in the presence of an optimizing compiler.

As a starter / refresher perhaps, both of these are perfectly permissible and happen in practice with UB, but never with "wrap or panic" / "implementation defined" behavior: https://mohitmv.github.io/blog/Shocking-Undefined-Behaviour-... This kind of thing is an example of the "time travel" stevekablanik is referring to, stuff that is literally impossible as written, that absolutely no human would consider to be a reasonable execution of the code, but occurs regularly with UB.

> and not meaningfully different from just saying it's UB.

It is extremely meaningfully different, because the range of options of what can happen is bounded in one case (either two's compliment wrapping, or panic) and unbounded in the other case (literally anything is allowed to happen, including time travel).

This is "implementation defined behavior" in C and C++'s terms, not "undefined behavior."

If you want guaranteed wrapping or panic you can choose one and then rely on it just fine.

The default behavior helps you avoid wrapping without permanently bogging down your performance. It makes sense as an option.