Description
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