Skip to content

Add direct-recursion Lint #15006

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

felix91gr
Copy link
Contributor

@felix91gr felix91gr commented Jun 6, 2025

Checklist:

  • Followed [lint naming conventions][lint_naming]
  • Added passing UI tests (including committed .stderr file)
  • cargo test passes locally
  • Executed cargo dev update_lints
  • Added lint documentation
  • Run cargo dev fmt

changelog: new lint: [direct_recursion]

Fixes #428

After we're done with this, I'll open a follow-up issue for the indirect recursion lint

@felix91gr
Copy link
Contributor Author

@PLeVasseur WIP.

I think the implementation is correct. I'll complete the documentation later, hopefully this weekend ^^

@PLeVasseur
Copy link
Contributor

Nice! Thanks for taking on the implementation.

Copy link
Contributor

@PLeVasseur PLeVasseur left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @felix91gr -- thanks for writing this up.
One thing I was unclear on: should this lint also check for recursion that's due to macros or only functions?

@felix91gr
Copy link
Contributor Author

Hey @felix91gr -- thanks for writing this up. One thing I was unclear on: should this lint also check for recursion that's due to macros or only functions?

Well... since it's a LateLintPass, then I believe it should already be linting macro-generated code by default. I wonder if there's a straightforward way of testing it 🤔 I'll give it a spin.

@felix91gr felix91gr force-pushed the direct_recursion branch 4 times, most recently from d955bfc to e06510b Compare June 9, 2025 00:37
@felix91gr
Copy link
Contributor Author

Sorry for the CI churn. It took me a while to understand why it was failing the changelog check.

@felix91gr felix91gr marked this pull request as ready for review June 9, 2025 00:53
@rustbot
Copy link
Collaborator

rustbot commented Jun 9, 2025

r? @samueltardieu

rustbot has assigned @samueltardieu.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties label Jun 9, 2025
@rustbot

This comment has been minimized.

changelog: new lint: [`direct_recursion`]
@felix91gr
Copy link
Contributor Author

⚠️ Warning ⚠️

* There are issue links (such as `#123`) in the commit messages of the following commits.
  _Please move them to the PR description, to avoid spamming the issues with references to the commit, and so this bot can automatically canonicalize them to avoid issues with subtree._
  
  * [30beb95](https://github.com/rust-lang/rust-clippy/commit/30beb9536f0d8a8c027e5ceecf207224522aa836)

I feel like this should be in the quick CI checks (like the changelog check), so that CI may do an early exit and avoid running the heavier test suites.

@felix91gr
Copy link
Contributor Author

Something that I'd like to add in a later PR, is a link to the Safety Critical Coding Guidelines where recursion is addressed.

Currently the functions section is empty, but I hope to get working on filling it as soon as I can https://coding-guidelines.arewesafetycriticalyet.org/coding-guidelines/functions.html

Copy link
Contributor

@PLeVasseur PLeVasseur left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice documentation addition, @felix91gr!

Copy link
Contributor

@samueltardieu samueltardieu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't flag all potentially direct recursive calls. For example, it doesn't trigger on this code path:

fn recurse_through_var(x: i32) -> i32 {
    let call = if x < 10 {
        std::convert::identity
    } else {
        recurse_through_var
    };
    call(x - 1)
}

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action from the author. (Use `@rustbot ready` to update this status) and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties labels Jun 10, 2025
@felix91gr
Copy link
Contributor Author

This doesn't flag all potentially direct recursive calls. For example, it doesn't trigger on this code path:

fn recurse_through_var(x: i32) -> i32 {
    let call = if x < 10 {
        std::convert::identity
    } else {
        recurse_through_var
    };
    call(x - 1)
}

Should I add this caveat to the documentation?

Context:

That kind of indirect call through a variable is ultimately undecidable (as a consequence of constprop being undecidable). That being said, one can attempt to detect as many of those cases as one can (as most lints that touch on undecidability do).

But still, this kind of detection requires MIR machinery that we don't have (in particular, it requires dataflow analysis capable of doing non-lexical constant propagation). I might implement it with the help of some friends in the future, but for now doing this properly in Clippy would require me to implement it in Clippy... which is outside of the scope of this lint.

See also: the transmute-null-ptr-to-ref lint. When I implemented it, I stopped at the base cases due to the same lack of dataflow machinery.

@felix91gr felix91gr requested a review from samueltardieu June 10, 2025 16:29
@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties and removed S-waiting-on-author Status: This is awaiting some action from the author. (Use `@rustbot ready` to update this status) labels Jun 10, 2025
@felix91gr
Copy link
Contributor Author

@samueltardieu does that make sense? I hope that makes sense.

Basically, I don't want to implement variable-bound-recursion-detection without the necessary dataflow machinery; it's going to be a pain and it's going to be a lot less complete than it would be otherwise.

It should probably be noted somewhere in the lint docs that this implementation only touches direct fn call expressions.

I could open up an issue as well noting down the code paths that a more sophisticated recursion analysis could catch, and write down exactly what such a lint is currently blocked on.

@felix91gr felix91gr requested a review from blyxyas June 10, 2025 19:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-review Status: Awaiting review from the assignee but also interested parties
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Recursion lint
5 participants