-
Notifications
You must be signed in to change notification settings - Fork 13.2k
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
Don't lint for self-recursion when the function can diverge #70822
Conversation
(rust_highfive has picked a reviewer for you, use r? to override) |
This comment has been minimized.
This comment has been minimized.
tcx: TyCtxt<'tcx>, | ||
body: &Body<'tcx>, | ||
def_id: DefId, | ||
) -> BitSet<BasicBlock> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could use more commentary in this function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried, but I'm not sure I fully understand it
I think this is more complex than it could be. To fix the first issue in #54444, you can suppress the lint if |
I think checking for cycles in the cfg is not enough - we do want to lint if there's a call before the cycle, but not if it comes after. |
Ah, that's right. In that case you would need to check for back-edges during the traversal, not as a separate step. There's a DFS framework with decent documentation that can differentiate between a cycle and a node with multiple predecessors. You could almost just use it directly, but you need to ignore successors of recursive Adding an
rust/src/librustc_data_structures/graph/iterate/mod.rs Lines 204 to 213 in b543afc
I do think it's worth implementing this using forward traversal since we can avoid computing the predecessor graph, but if you're happy with your approach, we could merge it with some more documentation. WDYT? |
Oh that's neat, didn't know there was an entire framework for that.
It was already getting computed anyways. I'm not sure what's using it though. |
I guess this makes sense since the query returns |
@ecstatic-morse okay, added some more comments. Let me know if there's anything else. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I asked for some clarification/changes in a few places that confused me initially, but I think this is good overall. I reserve the right to try rewriting this to use only forward traversal 😁.
r=me with comments (mine and @Centril's) addressed.
@bors r=ecstatic-morse |
📌 Commit b8f416d has been approved by |
⌛ Testing commit b8f416d with merge cc6ffab7291b3fb399bd30bd4b5a9fb25634bc6e... |
💔 Test failed - checks-azure |
@bors r=ecstatic-morse |
💡 This pull request was already approved, no need to approve it again.
|
📌 Commit b8f416d has been approved by |
🌲 The tree is currently closed for pull requests below priority 1000, this pull request will be tested once the tree is reopened |
Rollup of 7 pull requests Successful merges: - rust-lang#67705 (Use unrolled loop for searching NULL in [u16] on Windows) - rust-lang#70367 (save/restore `pessimistic_yield` when entering bodies) - rust-lang#70822 (Don't lint for self-recursion when the function can diverge) - rust-lang#70868 (rustc_codegen_ssa: Refactor construction of linker arguments) - rust-lang#70896 (Implement Chain with Option fuses) - rust-lang#70916 (Support `#[track_caller]` on functions in `extern "Rust" { ... }`) - rust-lang#70918 (rustc_session: forbid lints override regardless of position) Failed merges: r? @ghost
…nas-schievink Use forward traversal for unconditional recursion lint While reviewing rust-lang#70822, I noted that rust-lang#54444 could be solved without requiring the predecessor graph and without allocating a `Vec<Span>` for every basic block. The unconditional recursion lint is not a performance bottleneck however, so I approved rust-lang#70822 as it was. Nevertheless, I wanted to try implementing my idea using `TriColorDepthFirstSearch`, which is a DFS that can differentiate between [forward/tree edges and backward ones](https://en.wikipedia.org/wiki/Depth-first_search#Output_of_a_depth-first_search). I found this approach more straightforward than the existing one, so I'm opening this PR to see if it is desirable. The pass is now just a DFS across the control-flow graph. We ignore false edges and false unwinds, as well as the successors of recursive calls, just like existing pass does. If we see a back-edge (loop) or a terminator that would cause us to yield control-flow back to the caller (`Return`, `Resume`, etc.), we know that the function does not unconditionally recurse. r? @jonas-schievink
Fixes #54444