rust-lang / rust-lang/rust-clippy
Warn if 'nonstandard Clone' used in vec!
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 13.5k
- Forks
- 2.2k
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 32
Description
Background
Here is the essence of a bug that took me several hours to find in a larger code base. The code originally came from a much larger, multi-threaded function that fed data into a machine learning system. Instead of asserting, it just produced inputs that subtly changed other outputs.
use std::sync::{Arc, Mutex};
#[derive(Default, Clone)]
struct Entry<T> {
id: usize,
data: Arc<Mutex<T>>,
}
pub fn main() {
let mut entries = vec![Entry::default(); 10];
for (i, e) in entries.iter_mut().enumerate() {
e.id = i;
*e.data.lock().unwrap() = i;
}
let entry_0 = &entries[0];
assert_eq!(entry_0.id, *entry_0.data.lock().unwrap());
}
In our project we had the following lints and warning enabled:
#![forbid(unsafe_code)]
#![warn(clippy::all)]
#![warn(clippy::nursery)]
#![warn(clippy::pedantic)]
#![allow(clippy::inline_always)] // Globally allow "inline" because we do it too much.
#![allow(clippy::module_name_repetitions)] // We have too many of these
Analysis
The bug comes from combining a struct S {} that contains an Arc with the vec![T; N] macro. The official documentation even warns against this sort of behavior:
This will use clone to duplicate an expression, so one should be careful using this with types having a nonstandard Clone implementation. For example, vec![Rc::new(1); 5] will create a vector of five references to the same boxed integer value, not five references pointing to independently boxed integers.
However, my intuition is that most people are so used to vec![S; 10] meaning "give me 10 independent instances of S" that this 'nonstandard case' will be somewhat surprising.
Suggestion
This bug could have been avoided if Clippy warned against known 'nonstandard' Clone implementations used in vec!. For starters, that could be any call to vec![T; N], where T contains an Arc or Rc.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the vec![T; N] example and the documented behavior linked in the issue, focusing on types containing Arc or Rc and nonstandard Clone implementations. Determine the appropriate Clippy lint scope and how the warning should distinguish these cases. Done means the behavior is covered by tests and the requested warning is clearly specified.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- devtools
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100