rust-lang / rust-lang/rust-clippy

Warn if 'nonstandard Clone' used in vec!

Open
#4,288 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-lint L-correctness
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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.