3 ms·
Panics in Rust do not currently time-travel like that (including panics from failed bounds checks), and that's a good thing. The reason is that panicking does n
by simonask 4mo ago
Panics in Rust do not currently time-travel like that (including panics from failed bounds checks), and that's a good thing. The reason is that panicking does not imply terminating the process - they can be caught and handled, just like exceptions in C++. In fact, they use the same stack unwinding mechanism by default.
What the compiler is allowed to do is to shorten the loop by one and unconditionally panic after the loop, but this falls under the purview of the LLVM optimizer.
- jojomodding 4mo agoOnce it shortens the loop, the compiler can also observe that `tab` is a local variable and therefore move the writes up "to the initializer." It can then see that the variable is unused and delete it, and also delete the loop.
- edevrk 4mo ago[flagged]
- kibwen 4mo agoC++'s experience has caused Rust to rightfully learn the lesson that you don't allow optimizations to change the semantics of the program like that. Rust's goal is to be fast enough that any performance difference between C or C++ is too negligible to bother considering, and it's achieved that. It's not going to sacrifice reliability on the altar just to make up a measly 3% gap. There are plenty of ways that Rust's stricter semantics allow it to produce faster code than C++ (no move constructors or implicit copy constructors, thorough reference aliasing information, automatic generic struct layout optimizations, safe non-atomic refcounting, safe concurrent stack references, less defensive copying, etc.), it does not need to "convince C++ language people" of anything.
- edevrk 4mo ago[flagged]
- nicoburns 4mo agoA little slower but safe is a pretty good default I think. Most of the time you're not in a hot loop and even a 5% slowdown would be negligable. And in the cases where you are in a hot loop you just have to put in a little extra effort to optimise it and gain the performance back, either by writing the code in a way that allows the compiler to prove correctness (e.g. using an iterator or assert), or by using the unsage keyword to "pinky-promise" to the compiler that your usage is correct. IME that extra effort in performance-critical places almost always ends up being a lot less than the effort needed to avoid correctness/safety issues in mundane boilerplate/glue/plumbing code in C++. Especially as Rust's package management system means that often you don't even have to do that optimisation work yourself: you can just pull in a crate that's done it for you (and Rust's safety guarantees make that a much less scary thing to do than it is in C++)
- zozbot234 4mo agoIf you can detect a case where a panic "time traveling" would meaningfully improve performance, you could simply let the compiler issue an optional warning that would allow for auto-fixing the code to have those different semantics.
- afdbcreid 4mo agoIt's true that panics (unlike UB) cannot automatically time-travel, but your justification is weak. Recovering from panics can only prevent this optimization if the loop have side effects, and LLVM knows when panic=abort is set.
- simonask 4mo agoI mean, sure, dead code elimination applies to all optimized code. The important thing to understand is that panicking in Rust does not get magic treatment by the Rust compiler. It’s just a function that is declared in the type system to never return.
- Animats 4mo agoThe post-panic situation is a problem in Rust. After a panic, you're in a somewhat abnormal state. Rust panics are not supposed to be a catchable exception system. If something other than program termination is in the near future, that's a problem. That does create a problem for early panics, panicking when panic becomes inevitable but has not happened yet. This deserves more thought.