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

New lint: needless_move #11759

Closed
wants to merge 5 commits into from
Closed

Conversation

dnbln
Copy link
Contributor

@dnbln dnbln commented Nov 4, 2023

A lint to check for uses of move on closures which aren't necessary. See #11721.

Fixes #11721.
Currently blocked on rust-lang/rust#117585, and an eventual sync.

changelog: [needless_move]: A lint for unnecessary moves on closures / async blocks.

@rustbot
Copy link
Collaborator

rustbot commented Nov 4, 2023

r? @Centri3

(rustbot has picked a reviewer for you, use r? to override)

@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties label Nov 4, 2023
@dnbln dnbln marked this pull request as ready for review November 7, 2023 11:21
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 drive-by comments, I noticed the pr is marked ready now :)

Comment on lines 49 to 60
// Collect moved & borrowed variables from the closure, which the closure *actually* needs.
let MovedVariablesCtxt {
moved_vars,
mut captured_vars,
} = {
Copy link
Member

Choose a reason for hiding this comment

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

Can this use the closure_captures query, or is there a reason that it isn't used? Reusing rustc's code seems like it would make it simpler and less error prone than reimplementing the capture rules in clippy

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I used that in the first commit (a66be9d), but it was kind of faulty because a move closure will always capture by value, e.g. have the captured_place.info.capture_kind == UpvarCapture::ByValue, regardless of whether that value is actually consumed in the body of the closure or not (unless the type is Copy?). What this would need in order to properly function is basically the closure_captures query applied on the same closure, but without the move keyword, because then we could use the inference results to tell whether a variable needs to be moved or if it is just referenced, but sadly getting that modified closure is a quest I failed.

Copy link
Member

Choose a reason for hiding this comment

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

oh right, that's unfortunate

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually I've found the file that does most of that analysis: https://github.com/rust-lang/rust/blob/master/compiler/rustc_hir_typeck/src/upvar.rs

Maybe exposing a few of those functions would be helpful for this lint, so I'm gonna look into it soon.

clippy_lints/src/needless_move.rs Outdated Show resolved Hide resolved
tests/ui/needless_move.rs Outdated Show resolved Hide resolved
@bors
Copy link
Collaborator

bors commented Nov 14, 2023

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

@dnbln dnbln force-pushed the feat/needless_move branch 4 times, most recently from 7a949c3 to fea8899 Compare November 18, 2023 17:39
@bors
Copy link
Collaborator

bors commented Nov 19, 2023

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

@dnbln dnbln force-pushed the feat/needless_move branch 6 times, most recently from fb343f3 to 14da14a Compare November 19, 2023 15:12
@dnbln dnbln force-pushed the feat/needless_move branch 3 times, most recently from 20b12fc to f3fcd2a Compare November 19, 2023 19:51
clippy_lints/src/needless_move.rs Show resolved Hide resolved
/// E.g. all the values are captured by value into the closure / `async` block.
///
/// ### Why is this bad?
/// Pedantry
Copy link
Member

Choose a reason for hiding this comment

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

This should be expanded upon


match lint_result {
LintResult::NothingCaptured => {
lint("there were no captured variables, so the `move` is unnecessary");
Copy link
Member

Choose a reason for hiding this comment

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

This could probably be a let note_msg = match lint_result ... instead, and early return on NeedMove.

Using a closure is a bit more complex, and imo harder to read

return;
}

let ExprKind::Closure(closure) = &expr.kind else {
Copy link
Member

Choose a reason for hiding this comment

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

This could be a let-chain instead. However since this is only ever called once, maybe you can inline it?

clippy_lints/src/needless_move.rs Outdated Show resolved Hide resolved
@bors
Copy link
Collaborator

bors commented Dec 1, 2023

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

@rustbot rustbot added has-merge-commits PR has merge commits, merge with caution. S-waiting-on-author Status: This is awaiting some action from the author. (Use `@rustbot ready` to update this status) labels Dec 3, 2023
@rustbot
Copy link
Collaborator

rustbot commented Dec 3, 2023

There are merge commits (commits with multiple parents) in your changes. We have a no merge policy so these commits will need to be removed for this pull request to be merged.

You can start a rebase with the following commands:

$ # rebase
$ git rebase -i master
$ # delete any merge commits in the editor that appears
$ git push --force-with-lease

The following commits are merge commits:

@bors
Copy link
Collaborator

bors commented Dec 11, 2023

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

Copy link
Member

@Centri3 Centri3 left a comment

Choose a reason for hiding this comment

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

Nya

clippy_lints/src/needless_move.rs Outdated Show resolved Hide resolved
Comment on lines 53 to 61
LL | let closure = assert_static(move || {
| ^----
| |
| _________________________________help: remove the `move`
| |
LL | | with_ref(&a);
LL | | with_owned(a);
LL | | });
| |_____^
Copy link
Member

Choose a reason for hiding this comment

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

I can see this getting out of hand quickly on larger closures. Can you make it so the span doesn't include the value (the block/expression)?

clippy_lints/src/needless_move.rs Outdated Show resolved Hide resolved
clippy_lints/src/needless_move.rs Outdated Show resolved Hide resolved
clippy_lints/src/needless_move.rs Outdated Show resolved Hide resolved
// rust/tests/ui/async-await/deep-futures-are-freeze.rs

fn _deep_futures_are_freeze() {
// no-prefer-dynamic
Copy link
Member

Choose a reason for hiding this comment

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

I would like to ensure x test won't read these, somehow, I dunno, very cautious 😅 I doubt it does when running tests in subtrees or when they aren't at the top of the file

Or just remove them

clippy_lints/src/needless_move.rs Outdated Show resolved Hide resolved
impl<'tcx> euv::Delegate<'tcx> for MovedVariablesCtxt<'tcx> {
fn consume(&mut self, cmt: &euv::PlaceWithHirId<'tcx>, hir_id: HirId) {
if let euv::PlaceBase::Upvar(_) = cmt.place.base {
self.moved.push((cmt.place.clone(), hir_id));
Copy link
Member

Choose a reason for hiding this comment

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

Is there any reason we can't store &'tcx Place<'tcx> to prevent cloning? This is cheap if projections is empty, tho you're cloning a Vec otherwise

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The cmt is not a &'tcx reference, so the lifetimes don't add up and the borrow checker is unhappy.

},
};

span_lint_and_then(
Copy link
Member

Choose a reason for hiding this comment

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

We should call is_from_proc_macro here. You can implement WithSearchPat for Closure by reusing the code for ExprKind::Closure in expr_search_pat

clippy_lints/src/needless_move.rs Show resolved Hide resolved
@Centri3 Centri3 removed S-waiting-on-author Status: This is awaiting some action from the author. (Use `@rustbot ready` to update this status) has-merge-commits PR has merge commits, merge with caution. labels Feb 2, 2024
@xFrednet
Copy link
Member

xFrednet commented Apr 1, 2024

Hey @dnbln, this is a ping from triage, since there hasn't been any activity in some time. Are you still planning to continue this implementation?

If you have any questions, you're always welcome to ask them in this PR or on Zulip.

@rustbot author


Also this PR needs a new reviewer since @Centri3 is currently busy.

r? @y21 would you mind taking this review? You can also ping @ARandomDev99 or @GuillaumeGomez for a pre-review if that helps :)

@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 Apr 1, 2024
@rustbot rustbot assigned y21 and unassigned Centri3 Apr 1, 2024
@dnbln
Copy link
Contributor Author

dnbln commented Apr 1, 2024

Hey @dnbln, this is a ping from triage, since there hasn't been any activity in some time. Are you still planning to continue this implementation?

If you have any questions, you're always welcome to ask them in this PR or on Zulip.

Hi @xFrednet. I've honestly really began to doubt the usefulness of this lint, so I don't think I'll be investing any more time into it.

@dnbln dnbln closed this Apr 1, 2024
@Centri3
Copy link
Member

Centri3 commented Apr 1, 2024

I do still quite like this as a restriction (very pedantic style) lint. I might get around to it eventually if nobody else picks it up :3

@xFrednet xFrednet added S-inactive-closed Status: Closed due to inactivity and removed S-waiting-on-author Status: This is awaiting some action from the author. (Use `@rustbot ready` to update this status) labels Apr 1, 2024
@dnbln
Copy link
Contributor Author

dnbln commented Apr 1, 2024

I'll just leave the script I used to extract the tests from the rust repo here, if anyone else is interested in continuing this and might find it useful:

https://gist.github.com/dnbln/6b03d98bf189d76236a51ae9e2082433

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-inactive-closed Status: Closed due to inactivity
Projects
None yet
Development

Successfully merging this pull request may close these issues.

lint suggestion: unnecessary_move
6 participants