Skip to content

[useless_vec]: lint vec! invocations when a slice or an array would do #10901

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

Merged
merged 3 commits into from
Jun 8, 2023

Conversation

y21
Copy link
Member

@y21 y21 commented Jun 6, 2023

First off, sorry for that large diff in tests. A lot of tests seem to trigger the lint with this new change, so I decided to #![allow()] the lint in the affected tests to make reviewing this easier, and also split the commits up so that the first commit is the actual logic of the lint and the second commit contains all the test changes. The stuff that changed in the tests is mostly just line numbers now. So, as large as the diff looks, it's not actually that bad. 😅
I manually went through all of these to find out about edge cases and decided to put them in tests/ui/vec.rs.

For more context, I wrote about the idea of this PR here: #2262 (comment) (that explains the logic)

Basically, it now also considers the case where a Vec is put in a local variable and the user only ever does things with it that one could also do with a slice or an array. This should catch a lot more cases, and (at least from looking at the tests) it does.

changelog: [useless_vec]: lint vec! invocations when a slice or an array would do (also considering local variables now)

@rustbot
Copy link
Collaborator

rustbot commented Jun 6, 2023

r? @Alexendoo

(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 Jun 6, 2023
@Manishearth
Copy link
Member

@Centri3 may also review this

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.

This looks good, thanks! Just one choice on ALLOWED_METHOD_NAMES I'm curious about.

/// that also exists on slices. If this returns true, it means that
/// this expression does not actually require a `Vec` and could just work with an array.
fn is_allowed_vec_method(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
const ALLOWED_METHOD_NAMES: &[&str] = &["len", "as_ptr", "is_empty"];
Copy link
Member

Choose a reason for hiding this comment

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

I'm a bit curious why len and is_empty are allowed.

Copy link
Member Author

@y21 y21 Jun 7, 2023

Choose a reason for hiding this comment

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

The method names that are checked for here exist on both slices and Vec<T>.
So, given a variable ve of type Vec<i32>, a call expression like ve.is_empty() does not actually call slice::is_empty, but Vec::is_empty, which also means that adjusts_to_slice(ve) would return false.

If we didn't have len and is_empty here, the lint would assume that those are Vec<T> methods that really do require a Vec<T> (like push and pop, for example).
For len and is_empty specifically, that isn't the case. These two methods also exist on slices, and we still want to lint for cases like these:

let ve = vec![1, 2];
dbg!(ve.is_empty()); // Vec::is_empty, but this would also work fine if ve was `[1, 2]`

Copy link
Member

Choose a reason for hiding this comment

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

Ah, I misunderstood then 😅 I thought those were exceptions. Yeah, that sounds fine then.

// Do lint
let mut x = vec![1, 2, 3];
x.fill(123);
dbg!(x[0]);
Copy link
Member Author

Choose a reason for hiding this comment

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

One interesting case I just thought of is that changing a vec to an array can sometimes lead to compile errors when indexing with a constant that is out of bounds, because the compiler checks index expressions for arrays but not vecs:

let ve = vec![1, 2];
ve[3]; // ok (no compile error)

let arr = [1, 2];
arr[3]; // compile error

Not really sure what to do here. Accept it as a "known issue"? I doubt this is something that people run into by accident?

Copy link
Member

Choose a reason for hiding this comment

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

"Known issue" is likely fine IMO, this would likely be helpful anyway

Copy link
Member

Choose a reason for hiding this comment

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

works for me

@Manishearth
Copy link
Member

@bors r=Manishearth,Centri3

@bors
Copy link
Contributor

bors commented Jun 8, 2023

📌 Commit 7af77f7 has been approved by Manishearth,Centri3

It is now in the queue for this repository.

@bors
Copy link
Contributor

bors commented Jun 8, 2023

⌛ Testing commit 7af77f7 with merge 177c6fe...

@bors
Copy link
Contributor

bors commented Jun 8, 2023

☀️ Test successful - checks-action_dev_test, checks-action_remark_test, checks-action_test
Approved by: Manishearth,Centri3
Pushing 177c6fe to master...

@bors bors merged commit 177c6fe into rust-lang:master Jun 8, 2023
bors added a commit that referenced this pull request Jun 12, 2023
[`useless_vec`]: lint on `vec![_]` invocations that adjust to a slice

Fixes #2262 (well, actually my PR over at #10901 did do most of the stuff, but this PR implements the one last other case mentioned in the comments that my PR didn't fix)

Before this change, it would lint `(&vec![1]).iter().sum::<i32>()`, but not `vec![1].iter().sum::<i32>()`. This PR handles this case.
This also refactors a few things that I wanted to do in my other PR but forgot about.

changelog: [`useless_vec`]: lint on `vec![_]` invocations that adjust to a slice
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.

6 participants