Skip to content
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

Ownership error masks missing implementation of trait #27009

Closed
Leopard2A5 opened this issue Jul 13, 2015 · 5 comments
Closed

Ownership error masks missing implementation of trait #27009

Leopard2A5 opened this issue Jul 13, 2015 · 5 comments

Comments

@Leopard2A5
Copy link

I would expect the main function to not compile because clone() has not been implemented for struct Test. However this error is masked by:

src/main.rs:26:2: 26:7 error: cannot borrowtestsas mutable because it is also borrowed as immutable

The error here is the missing implementation though, because it solves the ownership issue. rustc doesn't complain about the missing implementation at all.

#[derive(Debug)]
struct Test {
    name: String
}

// impl std::clone::Clone for Test {
//  fn clone(&self) -> Test {
//      Test {
//          name: self.name.clone()
//      }
//  }
// }

fn main() {
    let mut tests = Vec::new();
    tests.push(Test{ name: "test1".to_string() });
    tests.push(Test{ name: "test2".to_string() });
    tests.push(Test{ name: "test3".to_string() });

    tests.sort_by(|a, b| a.name.cmp(&b.name));
    println!("{:?}", tests);

    let test = tests.last().unwrap().clone();
    println!("{:?}", test);

    tests.sort_by(|a, b| b.name.cmp(&a.name));
    println!("{:?}", tests);
}
@mitaa
Copy link
Contributor

mitaa commented Jul 13, 2015

This compiles because Copy and Clone (Make Copy a subtrait of Clone) are implemented for any &T. So in this situation just the pointer is copied, which retainins the borrow.

Maybe a lint which warns when this impl/method is invoked could help?
Because I don't think this is ever intended when someone explicitly uses .clone().

@Leopard2A5
Copy link
Author

(I have to point out that i've only just started with Rust.)

So if i get you right i should have dereferenced tests.last().unwrap() before calling clone and that would have been a compiler error because it doesn't use the Clone impl's for &T?

Maybe like so?
let test: &Test = tests.last().unwrap():
let test: Test = (*test).clone();

@mitaa
Copy link
Contributor

mitaa commented Jul 13, 2015

Well, yes, if you do that you will get the desired compiler error, but I don't think the error message is worth the additional verbosity in general.

<anon>:23:41: 23:48 error: no method named `clone` found for type `Test` in the current scope
<anon>:23     let test = (*tests.last().unwrap()).clone();
                                                  ^~~~~~~
<anon>:23:41: 23:48 help: items from traits can only be used if the trait is implemented and in scope; the following trait defines an item `clone`, perhaps you need to implement it:
<anon>:23:41: 23:48 help: candidate #1: `core::clone::Clone`

@Leopard2A5
Copy link
Author

So to wrap it up it was my bad, because i didn't know that references can be cloned by default... kinda hard to put my finger on the actual problem here 📦
Anyways, thanks!

@steveklabnik
Copy link
Member

Thanks for reporting! Always better to have too many reports than not enough.

Since this isn't a bug, I'm closing it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants