-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update empty_loop documentation/message. #6162
Conversation
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @phansch (or someone else) soon. If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes. Please see the contribution instructions for more information. |
Thanks for the PR! The implementation looks good to me but I'm not using no_std myself, so I've asked on Zulip for a second pair of eyes. |
Using Further, |
Yeah really what this needs is a |
You can. let x = 0;
unsafe { (&x as *const i32).read_volatile() }; All the "forward progress" you'd ever need. |
Nice, that looks about right. @josephlr either way, this should not have a |
The thing is that this lint is serving two purposes now: 1) don't burn CPU 2) don't risk hitting the case where LLVM changes the semantics of your code. In non- |
Sure, if you want to suggest
🤷 this is the situation we're in. It's better to have visible unsafe than invisible unsoundness. Right now |
I guess you're right. We can always suggest it as a last resort. |
no_std has no portable way to sleep. you can't suggest thread::sleep, because there's no such thing. It's maybe a drag, but as jyn514 said, this is the world we live in. |
You can also suggest compiling with |
How about making sure that The documentation clearly states its intended use:
If it cannot be used for an empty loop I'd consider that a bug in BTW: It works just fine for the majority of Rust supported embedded systems (running on ARM Cortex-M MCUs) by turning into a |
It's a hint. A hint never changes the correctness (or not) of a program. For example, I do my embedded work on the GBA, and |
The program is correct with or without the hint. However since empty loops are frowned upon and miscompiled by the compiler there should be a proper and official way to declare an intentionally empty loop.
Fair enough, but what would be the issue using a |
The fact that the codegen will miscompile the program means that the program is not correct with or without the hint. The intended semantics of The official, unstable, way to handle this problem is the The stable way to handle this is to volatile read a stack variable, like I said.
Well, because that's not a loop. |
You're sort of contraticting yourself. A program following the intended semantics is a correct program. Linting about difference actual vs intended semantics and telling the user how to bridge the gap is exactly the job of clippy.
Empty loops are an essential part of any embedded application (and quite a few other applications, too); telling a user to use a weird unrelated unsafe magic or go unstable is not a solution.
This is about preventing the loop from being turned into mush by creating a side effect that forces the compiler to keep it. Of course the |
Anything else is UB. And volatile isn't "weird unrelated unsafe magic", every embedded developer needs to understand when to use volatile. |
It's not supposed/documented to be. And at the moment there's also no lint for it which is what this issue is all about. People are regularly running into problems with miscompilations due to this.
The matter of fact is a lot of people don't know it and they shouldn't have to (if we did our job right and abstracted all of that away which we do!). Requiring people to know things like that is a substantial hazard to Rust adoption and requiring such a magic block of unsafe code in every application is just ridiculous. |
Looking at all the comments it seems like we will need to cover multiple use-cases including Here would be my plan:
|
This is exactly why I think this should not treat this as if the LLVM bug does not exist. Linting on |
That makes sense. Are you suggesting changing the lint category from "Style" to "Correctness"? |
But it is how things are. There's an open bug about it. No amount of "it shouldn't be that way" will change the facts. Sometimes Rust just isn't good yet and you have to wait for it to improve. If you want this fixed, help patch LLVM to allow side-effect free loops, or help move Clippy should give accurate information about the current state of the compiler. If the compiler improves later then the lint can be updated later to match the improvement.
Is there even an issue about this ever happening? Because I don't think this will otherwise happen. |
I'm working on a patch for |
Not sure where you got this notion from. We're having this discussion on the clippy repository because we want to tell people about the facts and how to remedy them (in a sane way).
I am not convinced that this is a solution, at best it's a workaround that has the potential to pessimize generated code even further.
I fully agree. |
Yes, I am. |
After reading all the comments in this thread and most of the comments in rust-lang/rust#28728 I conclude:
3.a. seems to be too much (useless) information in the lint message.
may work for So I would go with 3.c. What workarounds should we suggest? (please add to the list, if I forgot something)
|
These won't work on any platform, they don't involve forward progress or side effects. @josephlr suggested changing them so that they emit some sort of intrinsic to LLVM, but there's no guarentee that change is going to be accepted; personally, it seems like solving this in the wrong place to me. |
I'm also dubious this will work, precisely because the bug is in LLVM and not the platform. I think suggesting |
@bors retry |
Enable empty_loop for no_std crates. Fixes #6161 This change: - Makes it so the `empty_loop` lint will fire for `no_std` crates, but with a `no_std`-specific message (mentioning [`spin_loop_hint`](https://doc.rust-lang.org/core/sync/atomic/fn..html)). - Updates the `std` message to also mention [`std::thread::yield_now`](https://doc.rust-lang.org/std/thread/fn.yield_now.html). - Updates the docs to also mention the [LLVM infinite loop bug](rust-lang/rust#28728) - Updates the tests/stderr files to test this change. changelog: Update `empty_loop` lint to work with `no_std` crates
💔 Test failed - checks-action_test |
@bors retry (please?) |
Enable empty_loop for no_std crates. Fixes #6161 This change: - Makes it so the `empty_loop` lint will fire for `no_std` crates, but with a `no_std`-specific message (mentioning [`spin_loop_hint`](https://doc.rust-lang.org/core/sync/atomic/fn..html)). - Updates the `std` message to also mention [`std::thread::yield_now`](https://doc.rust-lang.org/std/thread/fn.yield_now.html). - Updates the docs to also mention the [LLVM infinite loop bug](rust-lang/rust#28728) - Updates the tests/stderr files to test this change. changelog: Update `empty_loop` lint to work with `no_std` crates
💥 Test timed out |
So, after all that, rust-lang/rust#77972 just landed. Maybe we no longer need to sound the alarm on this? |
IMO we could keep the more detailed documentation regarding the case of burning CPU, but I think the lint should go back to warn-by-default and ignore |
Enable empty_loop for no_std crates. Fixes #6161 This change: - Makes it so the `empty_loop` lint will fire for `no_std` crates, but with a `no_std`-specific message (mentioning [`spin_loop_hint`](https://doc.rust-lang.org/core/sync/atomic/fn..html)). - Updates the `std` message to also mention [`std::thread::yield_now`](https://doc.rust-lang.org/std/thread/fn.yield_now.html). - Updates the docs to also mention the [LLVM infinite loop bug](rust-lang/rust#28728) - Updates the tests/stderr files to test this change. changelog: Update `empty_loop` lint to work with `no_std` crates
In that case someone should r- before bors merges 😆 |
💥 Test timed out |
@bors r- (Not sure what triggered that last build 🤔) |
We also update the documentation to note that the remediations are different for `std` and `no_std` crates. Signed-off-by: Joe Richey <[email protected]>
012413d
to
3807634
Compare
@ebroto @jyn514 I've updated this PR to do just this. But I've added a TODO to address #6161. I think we would ideally have this still trigger for But this sort of discussion can be continued in #6161. EDIT: It looks like adding this |
@bors r+ Thanks! |
📌 Commit 3807634 has been approved by |
☀️ Test successful - checks-action_dev_test, checks-action_remark_test, checks-action_test |
Originally part of #6161, but now this PR only deals with
std
cratesThis change:
std
message .no_std
targetschangelog: Update
empty_loop
lint documentation