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

Use ControlFlow in more places #12830

Merged
merged 1 commit into from
Jul 24, 2024
Merged

Conversation

blyxyas
Copy link
Member

@blyxyas blyxyas commented May 21, 2024

Now, instead of manually using variables in visitors to signify that a visit is "done" and that the visitor should stop traversing. We use the trait type "Result" to signify this (in relevant places).

I'll schedule a perf run, I don't think it will be much of a difference, but every bit of performance is welcomed :)

changelog: Improve performance, less memory use in visitors

Fixes #12829
r? @y21

@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties label May 21, 2024
@y21
Copy link
Member

y21 commented May 22, 2024

Looks like this broke some tests 😅

@blyxyas
Copy link
Member Author

blyxyas commented May 26, 2024

I've done some changes, it doesn't break any test files but it seems to not run .fixed rustfix tests.

EDIT: On CI it seems like there aren't any issues, could you test the patch on your PC to check? Maybe it's just my workflow

@blyxyas
Copy link
Member Author

blyxyas commented May 29, 2024

I've had this commit already finished for the last... 3 days? I'm not sure why I didn't commit it 😅

@y21
Copy link
Member

y21 commented May 29, 2024

EDIT: On CI it seems like there aren't any issues, could you test the patch on your PC to check? Maybe it's just my workflow

Oh sorry, didn't see this edit. Huh... yeah, I'm seeing something similar.
image

I don't think this is something caused by this PR though. It also seems to happen on master for me.

Anyway, I'll try taking a closer look at the changes in a bit

@blyxyas
Copy link
Member Author

blyxyas commented May 29, 2024

@oli-obk do you have some commentary on this weird behaviour

Copy link
Member

@y21 y21 left a comment

Choose a reason for hiding this comment

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

some possible improvements :)

clippy_lints/src/if_let_mutex.rs Outdated Show resolved Hide resolved
clippy_lints/src/loops/while_immutable_condition.rs Outdated Show resolved Hide resolved
clippy_lints/src/if_let_mutex.rs Outdated Show resolved Hide resolved
clippy_lints/src/unconditional_recursion.rs Outdated Show resolved Hide resolved
@y21
Copy link
Member

y21 commented May 29, 2024

btw didn't this also change for_each_expr? I could swear I looked at this PR for a very short time before and saw a change there

clippy_utils/src/visitors.rs Outdated Show resolved Hide resolved
@@ -109,30 +109,43 @@ pub fn for_each_expr<'tcx, B, C: Continue>(
res: Option<B>,
}
impl<'tcx, B, C: Continue, F: FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B, C>> Visitor<'tcx> for V<B, F> {
fn visit_expr(&mut self, e: &'tcx Expr<'tcx>) {
type Result = ControlFlow<()>;
Copy link
Member

Choose a reason for hiding this comment

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

wondering if this can also just be ControlFlow<B> like in some of the other visitors to get rid of the res field? tho this might require some more involved changes... 🤔

Copy link
Member Author

Choose a reason for hiding this comment

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

I've tried this, and the generic rules in the language doesn't permit us to do it because B in the internal impl and B in the external impl could be different (even if it's never actually different) :/

Copy link
Member

Choose a reason for hiding this comment

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

I feel like this should be possible, but fine, I can also look into- and try this in a followup, separately, and we can just keep this one as is

cx: &'a LateContext<'tcx>,
}

impl<'tcx> Visitor<'tcx> for OppVisitor<'_, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
type Result = ControlFlow<&'tcx Expr<'tcx>>;
Copy link
Member

Choose a reason for hiding this comment

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

side note, not caused by this pr: isn't this visitor doing exactly the same thing as the other ArmVisitor in this file? 😅

Copy link
Member

Choose a reason for hiding this comment

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

I think this comment could be worth to look at as a small cleanup. But it's optional.

Comment on lines 60 to 61
if found_mutex.is_none() {
found_mutex = arm_visit.visit_expr(if_else).break_value();
Copy link
Member

Choose a reason for hiding this comment

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

this is technically a semantic change, we're no longer overriding the mutex if we found one in the then branch, that is, this no longer emits a warning:

let x = Mutex::new(42);
let unrelated = Mutex::new(());
if let 42..=50 = *x.lock().unwrap() {
  drop(unrelated.lock()); // ... `arm_visit.found_mutex_if_same_as()` is false here
} else {
  drop(x.lock()); // never visited
};

on the other hand, the same argument can be made for the already existing logic, the current code already also has this bug if you swap the x.lock() and unrelated.lock() in the two branches, so.. 🤷 maybe we should just leave it and open an issue

Copy link
Member Author

Choose a reason for hiding this comment

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

I'll just keep the same behaviour, we can then talk about if the current behaviour should be like that :)

clippy_lints/src/redundant_closure_call.rs Outdated Show resolved Hide resolved
@@ -305,7 +304,9 @@ where
{
self.found_default_call = true;
Copy link
Member

Choose a reason for hiding this comment

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

same here, still has a found_* field

@@ -137,14 +135,15 @@ impl<'tcx> Visitor<'tcx> for PeekableVisitor<'_, 'tcx> {
&& func_did == into_iter_did
{
// Probably a for loop desugar, stop searching
return;
return ControlFlow::Continue(());
}

if args.iter().any(|arg| arg_is_mut_peekable(self.cx, arg)) {
self.found_peek_call = true;
Copy link
Member

Choose a reason for hiding this comment

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

also here

Copy link
Member 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
Contributor

bors commented Jun 13, 2024

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

@blyxyas blyxyas added the performance-project For issues and PRs related to the Clippy Performance Project label Jun 16, 2024
Copy link
Member

@y21 y21 left a comment

Choose a reason for hiding this comment

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

Two more small things (also CI is red, need to fix that too)

}
intravisit::walk_expr(self, expr)
Copy link
Member

Choose a reason for hiding this comment

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

This was previously inside of an else {} but isn't anymore with this change, so we descend into things when we don't need to right now

@@ -70,15 +71,22 @@ impl<'tcx> LateLintPass<'tcx> for UnusedPeekable {
return;
}

let mut found_peek_call = false;

for stmt in &block.stmts[idx..] {
Copy link
Member

Choose a reason for hiding this comment

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

Could simplify this for loop into let found_peek_call = block.stmts[idx..].iter().any(|stmt| vis.visit_stmt(stmt).is_break());

@bors
Copy link
Contributor

bors commented Jun 27, 2024

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

Copy link
Member

@y21 y21 left a comment

Choose a reason for hiding this comment

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

Alright, the changes look fine to me now. But I would like another person to quickly skim over the changes here and double check since some of these visitors are used by a lot of lints and a bug here can easily cause subtle bugs.

Maybe @xFrednet? Quick tldr/context: like the description says, this adds a type Result = ControlFlow and uses Break in some visitors to short circuit them (also makes it nicer since the final value that the lints are interested in are directly in the ControlFlow::Break and don't need their own field

@xFrednet xFrednet self-assigned this Jul 19, 2024
@xFrednet
Copy link
Member

Sure, I'll have a look at it tomorrow.

@xFrednet
Copy link
Member

If we rebase, we can also use our CI to check if there are any changed :3

Copy link
Member

@xFrednet xFrednet left a comment

Choose a reason for hiding this comment

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

Four smaller formatting nits. (As usual, probably a bit nitpicky ^^') The semantic changes all look good to me and I like the refactoring!

The CI is also happy and doesn't report any lint changes 👍

You can r=y21,xFrednet once you've addressed the last comments.

clippy_lints/src/loops/mut_range_bound.rs Outdated Show resolved Hide resolved
cx: &'a LateContext<'tcx>,
}

impl<'tcx> Visitor<'tcx> for OppVisitor<'_, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
type Result = ControlFlow<&'tcx Expr<'tcx>>;
Copy link
Member

Choose a reason for hiding this comment

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

I think this comment could be worth to look at as a small cleanup. But it's optional.

clippy_lints/src/methods/option_map_unwrap_or.rs Outdated Show resolved Hide resolved
clippy_utils/src/visitors.rs Outdated Show resolved Hide resolved
@bors
Copy link
Contributor

bors commented Jul 22, 2024

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

blyxyas added a commit to blyxyas/rust-clippy that referenced this pull request Jul 23, 2024
@xFrednet
Copy link
Member

LGTM, thanks!


Roses are red,
ControlFlow is used,
Timo approves,
And I have checked :D

@bors
Copy link
Contributor

bors commented Jul 24, 2024

📌 Commit b21a91a has been approved by y21,xFrednet

It is now in the queue for this repository.

@bors
Copy link
Contributor

bors commented Jul 24, 2024

⌛ Testing commit b21a91a with merge fcecf3f...

bors added a commit that referenced this pull request Jul 24, 2024
Use ControlFlow in more places

Now, instead of manually using variables in visitors to signify that a visit is "done" and that the visitor should stop traversing. We use the trait type "Result" to signify this (in relevant places).

I'll schedule a perf run, I don't think it will be much of a difference, but every bit of performance is welcomed :)

Fixes #12829
r? `@y21`
@bors
Copy link
Contributor

bors commented Jul 24, 2024

💔 Test failed - checks-action_test

@blyxyas
Copy link
Member Author

blyxyas commented Jul 24, 2024

@bors retry

@blyxyas
Copy link
Member Author

blyxyas commented Jul 24, 2024

@bors r=y21,xFredNet

@bors
Copy link
Contributor

bors commented Jul 24, 2024

💡 This pull request was already approved, no need to approve it again.

@bors
Copy link
Contributor

bors commented Jul 24, 2024

📌 Commit b21a91a has been approved by y21,xFredNet

It is now in the queue for this repository.

@bors
Copy link
Contributor

bors commented Jul 24, 2024

⌛ Testing commit b21a91a with merge 16953ce...

@bors
Copy link
Contributor

bors commented Jul 24, 2024

☀️ Test successful - checks-action_dev_test, checks-action_remark_test, checks-action_test
Approved by: y21,xFredNet
Pushing 16953ce to master...

@bors bors merged commit 16953ce into rust-lang:master Jul 24, 2024
8 checks passed
bors added a commit that referenced this pull request Jul 25, 2024
Remove unnecessary `res` field in `for_each_expr` visitors

Small refactor in the `for_each_expr*` visitors. This should not change anything functionally.

Instead of storing the final value `Option<B>` in the visitor and setting it to `Some` when we get a `ControlFlow::Break(B)` from the closure, we can just directly return it from the visitor itself now that visitors support that.

cc #12829 and #12830 (comment)

changelog: none
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
performance-project For issues and PRs related to the Clippy Performance Project 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.

Use ControlFlow in more visitors
5 participants