Skip to content

Confusing error message with derived Traits #41825

Closed
@stnma7e

Description

@stnma7e

I was trying to drain a referenced HashSet into a Vec to sort it before another operation,

fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for (k, v) in &self.class_times {
            let mut days_clone = v.clone();
            let mut days: Vec<DayOfWeek> = days_clone.drain().collect();
            days.sort();

but when I tried to clone the HashSet so that I could mutate it, this error appeared.

error: cannot borrow immutable borrowed content `*days_clone` as mutable
  --> src/models.rs:99:44
   |
99 |             let mut days: Vec<DayOfWeek> = days_clone.drain().collect();
   |                                            ^^^^^^^^^^ cannot borrow as mutable

error: aborting due to previous error

After cloning the HashSet I assumed that I should be able to use it in a moved, mutable context, so I tried to foce the type of the variable in the declaration, which gave me this error:

error[E0308]: mismatched types
  --> src/models.rs:98:48
   |
98 |             let mut days_clone: HashSet<DayOfWeek> = v.clone();
   |                                                ^^^^^^^^^ expected struct `std::collections::HashSet`, found reference
   |
   = note: expected type `std::collections::HashSet<models::DayOfWeek>`
              found type `&std::collections::HashSet<models::DayOfWeek>`

error: aborting due to previous error

The issue with the borrowing for cloning and reference vs non-reference in the return type of the clone() threw me off the track. Eventually, the solution I found was that I'd forgotten to derive Clone on the enum called DayOfWeek that the HashSet works over, and adding that derivation fixed the problem. The error message seems misleading because I thought I had referencing error somewhere, and the error message didn't reference a Clone trait at all, but the problem only had to do with the derivation.

An example set up could look like this:

use std::collections::BTreeMap;
use std::collections::HashSet;

#[derive(Debug,Eq,PartialEq,Hash)]
enum Day {
    Mon,
}

struct Class {
    days: BTreeMap<u32, HashSet<Day>>
}

impl Class {
    fn do_stuff(&self) {
        for (_, v) in &self.days {
            let mut x = v.clone();
            let y: Vec<Day> = x.drain().collect();
            println!("{:?}", x);
        }
    }
}

fn fail() {
    let c = Class { days: BTreeMap::new() };
    c.do_stuff();
}

And this will compile only if the Day enum derives Clone.

Rust version:

rustc 1.16.0 (30cf806ef 2017-03-10)
binary: rustc
commit-hash: 30cf806ef8881c41821fbd43e5cf3699c5290c16
commit-date: 2017-03-10
host: x86_64-unknown-linux-gnu
release: 1.16.0
LLVM version: 3.9

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsC-enhancementCategory: An issue proposing an enhancement or a PR with one.D-confusingDiagnostics: Confusing error or lint that should be reworked.D-newcomer-roadblockDiagnostics: Confusing error or lint; hard to understand for new users.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions