-
Notifications
You must be signed in to change notification settings - Fork 1.7k
vec_init_then_push should only trigger if there are no further pushes #7071
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
Comments
This isn't really a false positive. Could be let mut arg_strings: Vec<Box<str>> = vec![name.to_owned().into_boxed_str()];
for arg in args {
arg_strings.push(
arg.as_ref()
.to_os_string()
.into_string()
.unwrap()
.into_boxed_str(),
);
} |
What about if you have code of the form: let mut foo = Vec::new();
foo.push("bar".to_string());
for x in 0..9 {
foo.push(format!("baz {}", x));
}
foo.push("wibble".to_string());
..... The pattern here is clear as pushes, but if you move the first push into a The example in the lint shows the removal of |
Really In this case I guess if there's only one or two items being pushed before a loop pushing items (or extend, and maybe others) it might be better to leave it as is. |
I think the original request is reasonable. The lint is really only valuable if you can put all the elements in |
From a performance perspective it's always better to use the macro with the current |
That's not true (that it increases from a starting capacity of 1). I checked the source. It starts with zero, and then jumps to a capacity of 8 for So my original code creates an empty Vec, then allocates space for 4 items, and so on. Switching to I agree with the original request: Using |
Here's a playground link that demonstrates the problem. Assuming that the push of 2 occurs later, the clippy suggestion costs an extra malloc/free. |
@uazu Good point, that adds some nuance.
I don't think we should be dependent on the std implementation to that level of detail. |
Looks like I was looking at old sources. |
Here's an idea. We can split into two lints.
|
Yes, case 1 seems like a clear win. Also using Case 2 depends. Sometimes it's not possible to determine the required capacity in advance. Can clippy detect when the capacity could have been determined by the coder? That seems like quite an involved analysis. Sometimes Vec's behaviour is exactly what you want, i.e. optimised for short lists, but can still handle big lists if required, i.e. it scales smoothly. |
I think it is theoretically always possible to calculate the number of elements pushed within the function before
Very true. That means a lot of false positives for case 2. It would definitely not be warn-by-default. But I'm starting to think we should not lint those cases at all - which just goes back to the original request... |
@camsteffen only if the content is coming from a ExactSizeIterator or similarly capable source. For instance, an iterator over stdin lines() stopping at the first blank line isn't able to estimate the size at all without buffering (presumably in another vector, giving this issue again :P). |
Lint name: vec_init_then_push
I tried this code:
I expected to see this happen: The lint doesn't trigger, because using
vec![]
and then immediately pushing doesn't improve the code any, it uses two different styles of initializing the vector.Instead, this happened:
cc rust-lang/rustup#2718, @kinnison
Meta
cargo clippy -V
: clippy 0.1.53 (dae9d6a 2021-04-09)rustc -v
: rustc 1.53.0-nightly (dae9d6a 2021-04-09)The text was updated successfully, but these errors were encountered: