Do we really need undefined behavior?
FWIW, some of the biggest cases of undefined behavior are ones that, as far as I am concerned, are workarounds for legacy code: things like how older code uses &quot;int&quot; as the counter for every single for loop, despite this being an incredibly stupid type for this purpose... compilers are then competing on how fast they make the existing ecosystem of code and so add awkward detection cases like &quot;if it sort of looks like you only increment it I will decide you didn&#x27;t want overflow and that way I can avoid having to simulate it now that int is 32-bits but the CPU is 64-bits&quot;.<p>But once compilers start adding these special cases then new code has to be written to understand &quot;if I add a bounds check on some wrapping operation this compiler thinks I am insane and removes it as it assumes I am an idiot using the wrong type&quot;. And once compilers start doing that, particularly with incompatible heuristics, the concepts of what the language is even guaranteeing begin to erode and the standards adjust to define &quot;undefined&quot; behavior.<p>But the correct solution wasn&#x27;t to fix the compiler... it was to use the correct data type! Whether that feels like it should be size_t or uintptr_t I will refrain from providing an opinion on in this comment (to avoid bike-shedding), but the premise that the compiler is a billion little attempts to figure out how to make my code faster--rules that change constantly and see under-specified--when it is the code that is wrong is extremely frustrating.<p>If you want to avoid some aliasing use case, or make math operations faster, or avoid issues with the calling convention on &quot;this&quot; pointers, or whatever it is... we should agree on what the code <i>should</i> look like to make those semantics clear and then <i>forcibly deprecate as non-compliant</i> any implementation that uses strange quirks to auto-detect and &quot;improve&quot; old code.<p>Alternatively, we should have a special mode the compiler should support to &quot;just do what the code says even if it is slow&quot; and we should then guide developers in the direction that it is a &quot;code smell&quot; to stay in quirks mode: that if there is a way to make the &quot;strict&quot; compiler mode understand your code correctly and still be as fast as the one with tons of undefined behavior, it is your code that is at fault.<p>But like, the market incentives will never support this: people evaluating between two compilers are going to run benchmarks against projects that they have been using for decades and choose the compiler that &quot;works better&quot;; and meanwhile, convincing developers to stop using &quot;int&quot; or explicitly call out aliasing or whatever will never happen because people will benchmark the code against a compiler with all these bells and whistles and decide &quot;the risk of making these modifications to every single place in our code where it might matter is you great as we might break something in the process and the compiler seems to compile our code just as fast without it being explicit (due to UB)&quot; with a side of &quot;the explicit syntax for that is caught up in committee and isn&#x27;t supported on one of our key targets yet&quot;.<p>So, I personally consider this all a &quot;lost cause&quot;. But I also really want to point out that the root cause of all of this undefined behavior is due to an underlying incentive structure that your pet language isn&#x27;t immune to: you just got to start off clean without a ton of legacy baggage code. You don&#x27;t have a ridiculously large amount of code written with silly assumptions for 16-bit systems that has been carefully dragged through the ages into 64-bit, and you have a ton of explicit syntax already to prevent a lot of the other brutal cases in all new code... and there is also (probably) a single implementation of the compiler.<p>But, one day, 20 years from now, after a billion lines of code have been written in your language, there are four big implementations of the compiler (only one of which still supporting legacy ARM CPUs, as everyone has since moved on to KR7 or whatever is hip in 2040), and you&#x27;ve made a ton of sad choices in an attempt to hold your community together, someone is going to weigh a cost&#x2F;benefit analysis and decide &quot;keeping existing code working but making it faster is more important--and wins us more marketshare--than telling people how to port their code to the new era&quot;.<p>Now, I don&#x27;t know what these cases are going to be--maybe something super complex involving how massively parallel execution environments handle order of execution for old code designed to run on a classic computer core, or how to map explicit integer representations into prime-order field elements for zero-knowledge execution, or what to do with information leakage during homomorphic encryption--but it is going to happen, and we are going to repeat all of these &quot;quirks mode vs. strict mode&quot; discussions each generation for every actually-important piece of technology, just as we have for standards even so far afield to &quot;programming&quot; as HTML and TCP.