Did the bug in LLVM, where it completely removes empty infinite loops, because that is a valid optimization for C++, even though Rust is not C++, ever get fixed? Because that needs to get fixed first.
I can't think of any reason why we shouldn't start emitting a CPU-level "this thread has nothing useful to do" instruction into the body of all empty infinite loops, e.g. for x86
.infloop:
pause
jmp infloop
instead of just
.infloop:
jmp infloop
This would best be done by the compiler's back end, after all loop optimizations are complete, and is therefore a feature request for LLVM, Cranelift, etc. rather than for rustc.
Emitting a "park this thread" system call is harder, not because it's any harder to make the compiler do it (for example, on any x86-based Unix you would just replace the pause instruction above with call pause) but because introducing system calls where none exist in the source code is fraught with implications. Someone's got to actually provide the stub for the pause system call; normally this is the C library but in no-std configurations you can't assume that exists. People want to be able to enumerate all the system calls that might be invoked by a particular program by static analysis of its source code; this is an additional wrinkle for that analysis. Etc.
Yes, that was rust#28728 and llvm#1337, finally fixed by LLVM 12's explicit mustprogress attribute, which we avoid for Rust.
I agree, and I don't expect we'll ever do this implicitly. Maybe there could be some kind of "loop handler" akin to the existing panic handler, where you could choose to call an OS pause, but I think that would be a lot of effort for something that really shouldn't happen. While infinite loops definitely need to be safe, they don't need to be optimized IMO.
Can you say more about why you're writing such a loop in the first place?
Note that without an OS we can't really do any better than spin_loop in core::hint - Rust, which may reduce the CPU power usage by a bit but still keeps it at 100% usage.
Code size would be the most notable reason. If you expect to run the infinite loop, it makes sense to have a pause in it. If you're using the infinite loop as a placeholder, you might not want the extra two bytes.
More importantly, it's not obvious that we should do that by default for everyone, rather than encouraging people to use spin_loop in std::hint - Rust when they want it.
In particular, a loop that isn't empty still might need a spin loop hint. It would be bad if adding useful work to a spin loop implicitly made it less energy efficient.
Clippy already has an empty_loop lint, but its suggestions don't include spin_loop() (or thread::park()).
Sometimes you are forced to define a panic handler or have some other code you know for sure is unreachable but where rustc doesn't know about this. loop {} is a useful placeholder in that case. Especially as std::process::abort() can't be used on no_std, and core::intrinsics::abort() isn't exposed as a stable function.
And if it does happen, the hanged thread can be easier to debug than if it had aborted the process. Assuming it's the developer running it. One could even recover the process from that state in some cases.
I don't understand why this is appealing when there are options in the standard library with much clearer, explicit, semantics. If you want something they can't provide, then I think you should be asking for a new standard library function.