Skip to content

Confusing error message with derived Traits #41825

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

Closed
stnma7e opened this issue May 8, 2017 · 1 comment
Closed

Confusing error message with derived Traits #41825

stnma7e opened this issue May 8, 2017 · 1 comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-enhancement Category: An issue proposing an enhancement or a PR with one. D-confusing Diagnostics: Confusing error or lint that should be reworked. D-newcomer-roadblock Diagnostics: Confusing error or lint; hard to understand for new users. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@stnma7e
Copy link

stnma7e commented May 8, 2017

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
@Mark-Simulacrum Mark-Simulacrum added the A-diagnostics Area: Messages for errors, warnings, and lints label Jun 22, 2017
@Mark-Simulacrum Mark-Simulacrum added the C-enhancement Category: An issue proposing an enhancement or a PR with one. label Jul 26, 2017
@crlf0710 crlf0710 added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Jun 11, 2020
@estebank estebank added D-confusing Diagnostics: Confusing error or lint that should be reworked. D-newcomer-roadblock Diagnostics: Confusing error or lint; hard to understand for new users. labels Aug 3, 2023
@estebank
Copy link
Contributor

This is the same case as #34629. Closing this one and moving the example to that ticket to consolidate.

estebank added a commit to estebank/rust that referenced this issue Nov 21, 2023
When encountering a case where `let x: T = (val: &T).clone();` and
`T: !Clone`, already mention that the reference is being cloned. We now
also suggest `#[derive(Clone)]` not only on `T` but also on type
parameters to satisfy blanket implementations.

```
error[E0308]: mismatched types
  --> $DIR/assignment-of-clone-call-on-ref-due-to-missing-bound.rs:17:39
   |
LL |             let mut x: HashSet<Day> = v.clone();
   |                        ------------   ^^^^^^^^^ expected `HashSet<Day>`, found `&HashSet<Day>`
   |                        |
   |                        expected due to this
   |
   = note: expected struct `HashSet<Day>`
           found reference `&HashSet<Day>`
note: `HashSet<Day>` does not implement `Clone`, so `&HashSet<Day>` was cloned instead
  --> $DIR/assignment-of-clone-call-on-ref-due-to-missing-bound.rs:17:39
   |
LL |             let mut x: HashSet<Day> = v.clone();
   |                                       ^
   = help: `Clone` is not implemented because the trait bound `Day: Clone` is not satisfied
help: consider annotating `Day` with `#[derive(Clone)]`
   |
LL + #[derive(Clone)]
LL | enum Day {
   |
```

Case taken from # rust-lang#41825.
estebank added a commit to estebank/rust that referenced this issue Dec 4, 2023
When encountering a case where `let x: T = (val: &T).clone();` and
`T: !Clone`, already mention that the reference is being cloned. We now
also suggest `#[derive(Clone)]` not only on `T` but also on type
parameters to satisfy blanket implementations.

```
error[E0308]: mismatched types
  --> $DIR/assignment-of-clone-call-on-ref-due-to-missing-bound.rs:17:39
   |
LL |             let mut x: HashSet<Day> = v.clone();
   |                        ------------   ^^^^^^^^^ expected `HashSet<Day>`, found `&HashSet<Day>`
   |                        |
   |                        expected due to this
   |
   = note: expected struct `HashSet<Day>`
           found reference `&HashSet<Day>`
note: `HashSet<Day>` does not implement `Clone`, so `&HashSet<Day>` was cloned instead
  --> $DIR/assignment-of-clone-call-on-ref-due-to-missing-bound.rs:17:39
   |
LL |             let mut x: HashSet<Day> = v.clone();
   |                                       ^
   = help: `Clone` is not implemented because the trait bound `Day: Clone` is not satisfied
help: consider annotating `Day` with `#[derive(Clone)]`
   |
LL + #[derive(Clone)]
LL | enum Day {
   |
```

Case taken from # rust-lang#41825.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-enhancement Category: An issue proposing an enhancement or a PR with one. D-confusing Diagnostics: Confusing error or lint that should be reworked. D-newcomer-roadblock Diagnostics: Confusing error or lint; hard to understand for new users. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

4 participants