Skip to content
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

Rework only_used_in_recursion #8804

Merged
merged 2 commits into from
Aug 19, 2022
Merged

Rework only_used_in_recursion #8804

merged 2 commits into from
Aug 19, 2022

Conversation

Jarcho
Copy link
Contributor

@Jarcho Jarcho commented May 9, 2022

fixes #8782
fixes #8629
fixes #8560
fixes #8556

This is a complete rewrite of the lint. This loses some capabilities of the old implementation. Namely the ability to track through tuple and slice patterns, as well as the ability to trace through assignments.

The two reported bugs are fixed with this. One was caused by using the name of the method rather than resolving to the DefId of the called method. The second was cause by using the existence of a cycle in the dependency graph to determine whether the parameter was used in recursion even though there were other ways to create a cycle in the graph.

Implementation wise this switches from using a visitor to walking up the tree from every use of each parameter until it has been determined the parameter is used for something other than recursion. This is likely to perform better as it avoids walking the entire function a second time, and it is unlikely to walk up the HIR tree very much. Some cases would perform worse though.

cc @buttercrab

changelog: Scale back only_used_in_recursion to fix false positives
changelog: Move only_used_in_recursion back to complexity

@rust-highfive
Copy link

r? @Manishearth

(rust-highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties label May 9, 2022
@xFrednet
Copy link
Member

xFrednet commented May 9, 2022

r? @Alexendoo

Would you maybe like to review this PR? 🙃

@Alexendoo
Copy link
Member

Sure thing, I'll take a look at it

@xFrednet xFrednet self-assigned this May 9, 2022
@Jarcho Jarcho force-pushed the in_recursion branch 2 times, most recently from 44646b9 to 97a5177 Compare May 16, 2022 01:11
@bors
Copy link
Collaborator

bors commented May 20, 2022

☔ The latest upstream changes (presumably #8856) made this pull request unmergeable. Please resolve the merge conflicts.

@xFrednet
Copy link
Member

Hey @Alexendoo, was this PR done after your comment was fixed? 🙃

Copy link
Member

@Alexendoo Alexendoo left a comment

Choose a reason for hiding this comment

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

I wonder whether we want to mirror the unused behaviour of ignoring self entirely, I could see a preference for having method syntax even where it's not technically needed. It may also be surprising that adding a call would cause an unused style warning to appear

Other than that I have a few small bits of feedback, nothing major is jumping out at me but this is still a fairly complex lint

clippy_lints/src/only_used_in_recursion.rs Outdated Show resolved Hide resolved
clippy_lints/src/only_used_in_recursion.rs Outdated Show resolved Hide resolved
clippy_lints/src/only_used_in_recursion.rs Show resolved Hide resolved
@ghost
Copy link

ghost commented May 27, 2022

I tested this branch on bunch of crates and found a false positive.

---> lalrpop-0.19.8/src/normalize/lower/mod.rs:459:20                 
warning: parameter is only used in recursion                          
   --> src/normalize/lower/mod.rs:459:20
    |
459 |     fn symbol(&mut self, symbol: &pt::Symbol) -> r::Symbol {
    |                    ^^^^
    |
    = note: requested on the command line with `-W clippy::only-used-in-recursion`
note: parameter used here
   --> src/normalize/lower/mod.rs:463:79
    |
463 |             pt::SymbolKind::Choose(ref s) | pt::SymbolKind::Name(_, ref s) => self.symbol(s),
    |                                                                               ^^^^
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#only_used_in_recursion

This is what the function looks like. The lint misses the usage self.uses_error_recovery = true;.

    fn symbol(&mut self, symbol: &pt::Symbol) -> r::Symbol {
        match symbol.kind {
            pt::SymbolKind::Terminal(ref id) => r::Symbol::Terminal(id.clone()),
            pt::SymbolKind::Nonterminal(ref id) => r::Symbol::Nonterminal(id.clone()),
            pt::SymbolKind::Choose(ref s) | pt::SymbolKind::Name(_, ref s) => self.symbol(s),
            pt::SymbolKind::Error => {
                self.uses_error_recovery = true;
                r::Symbol::Terminal(TerminalString::Error)
            }

            pt::SymbolKind::Macro(..)
            | pt::SymbolKind::Repeat(..)
            | pt::SymbolKind::Expr(..)
            | pt::SymbolKind::AmbiguousId(_)
            | pt::SymbolKind::Lookahead
            | pt::SymbolKind::Lookbehind => unreachable!(
                "symbol `{}` should have been normalized away by now",
                symbol
            ),
        }
    }

@Jarcho
Copy link
Contributor Author

Jarcho commented May 27, 2022

Auto-deref makes linting not fun. Fixed.

@Jarcho
Copy link
Contributor Author

Jarcho commented May 27, 2022

I assume the reason for not linting self as unused is because it can't be renamed, so _self isn't an option.

The reasons for having an unused parameter in the first place are less applicable for this lint. Either the existence of the type has meaning, or API compatibility. The former is a pattern definitely used for self, but not really on recursive functions. The later is possible, but seems unlikely to occur outside of trait functions (for which self is already ignored).

@xFrednet
Copy link
Member

xFrednet commented Jun 1, 2022

I'll leave this PR to you @Alexendoo. Please don't hesitate to reach out if you need any assistance.

r? @Alexendoo

@Jarcho
Copy link
Contributor Author

Jarcho commented Jul 18, 2022

Should be fine now.

Comment on lines 173 to 180
/// Sets the `block_lint` flag on each parameter.
fn flag_for_linting(&mut self) {
// Stores the list of parameters currently being resolved. Needed to avoid cycles.
let mut eval_stack = Vec::new();
for param in &self.params {
self.try_block_lint_for_param(param, &mut eval_stack);
}
}
Copy link
Member

Choose a reason for hiding this comment

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

Thanks! Just one last thing, a couple references to block_lint remain

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@bors
Copy link
Collaborator

bors commented Aug 19, 2022

☔ The latest upstream changes (presumably #8957) made this pull request unmergeable. Please resolve the merge conflicts.

@Alexendoo
Copy link
Member

Thanks!

@bors r+

@bors
Copy link
Collaborator

bors commented Aug 19, 2022

📌 Commit 39f4bee has been approved by Alexendoo

It is now in the queue for this repository.

@bors
Copy link
Collaborator

bors commented Aug 19, 2022

⌛ Testing commit 39f4bee with merge 3a54117...

@bors
Copy link
Collaborator

bors commented Aug 19, 2022

☀️ Test successful - checks-action_dev_test, checks-action_remark_test, checks-action_test
Approved by: Alexendoo
Pushing 3a54117 to master...

@danieleades
Copy link

this PR doesn't resolve the false positive here - marshallpierce/rust-base64#188

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment