Skip to content

Trying to clone references to non-cloneable types gives a confusing error messages. #52095

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Closed
moxian opened this issue Jul 6, 2018 · 3 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints

Comments

@moxian
Copy link
Contributor

moxian commented Jul 6, 2018

When trying to compile this piece of code (playground link):

#[derive(Clone)]
struct Wrapper<T>
{
    inner: T,
}

fn dewrap<T>(d: &Wrapper<T>) -> Wrapper<T>
//where T: Clone
{
    d.clone()
}

I get the following error message:

error[E0308]: mismatched types
  --> src/main.rs:11:4
   |
8  | fn dewrap<T>(d: &Wrapper<T>) -> Wrapper<T>
   |                                 ---------- expected `Wrapper<T>` because of return type
...
11 |    d.clone()
   |    ^^^^^^^^^^^ expected struct `Wrapper`, found &Wrapper<T>
   |
   = note: expected type `Wrapper<T>`
              found type `&Wrapper<T>`

which is super weird, because the signature of .clone() is clone(&T)->T.

I'm not fully certain what exactly is happening here (I guess, d is getting auto-referenced, and the function body is equivalent to (&d).clone()), but regardless the error message is super confusing.

I would appreciate if some kind of did you mean to add trait bounds T: Clone? diagnostic was added.

Relatedly (but may be more suitable for a separate bugreport?), the struct declaration has #[derive(Clone)] but the derive fails silently, since T does not have : Clone bounds. It still may be what the author intended (the derive will work when the struct is instantiated with a cloneable type), but I'm afraid it usually isn't.

Also relatedly: clippy does catch the error:

error: using `clone` on a double-reference; this will copy the reference instead of cloning the inner type
  --> src/main.rs:11:4
   |
11 |    (d.clone())
   |    ^^^^^^^^^^^
   |
   = note: #[deny(clone_double_ref)] on by default
   = help: for further information visit https://rust-lang-nursery.github.io/rust-clippy/v0.0.211/index.html#clone_double_ref
help: try dereferencing it
   |
11 |    &(*d).clone()
   |
help: or try being explicit about what type to clone
   |
11 |    &Wrapper<T>::clone(d)

Unfortunately this is displayed only after the error is pseudo-fixed by declaring the function return type to be &Wrapper<T>, and not displayed at all when fixed for good by adding the : Clone trait bound.

It might be useful to uplift the diagnostics to rustc here (but I have zero understanding of the process or feasibility of this).

@csmoe csmoe added the A-diagnostics Area: Messages for errors, warnings, and lints label Jul 6, 2018
@abonander
Copy link
Contributor

This seems like it might be a regression. Maybe a bisect is in order?

@abonander
Copy link
Contributor

abonander commented Aug 17, 2018

Nevermind, this has been an issue for a while I guess: #34896, #48677

@moxian
Copy link
Contributor Author

moxian commented May 17, 2019

Closing in favour of #34896

@moxian moxian closed this as completed May 17, 2019
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints
Projects
None yet
Development

No branches or pull requests

3 participants