Value returned by to_owned doesn't always own the data

b2f8ea1
Opened by Jay at 2024-04-07 20:32:23

For example:

let a = vec![1, 2];
let s = Some(&a);
let r = vec![];
if let Some(ref v) = s {
    r = v.to_owned();
}

This doesn't compile:

error[E0308]: mismatched types
 --> src/main.rs:6:13
  |
6 |         r = v.to_owned();
  |             ^^^^^^^^^^^^ expected struct `std::vec::Vec`, found reference
  |
  = note: expected type `std::vec::Vec<_>`
             found type `&std::vec::Vec<{integer}>`

Relates to #43236.

  1. We now suggest using .to_vec() (without asking to remove to_owned()):

    error[E0308]: mismatched types
     --> src/main.rs:6:9
      |
    6 |     r = v.to_owned();
      |         ^^^^^^^^^^^^
      |         |
      |         expected struct `std::vec::Vec`, found reference
      |         help: try using a conversion method: `v.to_owned().to_vec()`
      |
      = note: expected type `std::vec::Vec<_>`
                 found type `&std::vec::Vec<{integer}>`
    

    Without the to_owned call, we also suggest the right thing:

    error[E0308]: mismatched types
     --> src/main.rs:6:9
      |
    6 |     r = v;
      |         ^
      |         |
      |         expected struct `std::vec::Vec`, found reference
      |         help: try using a conversion method: `v.to_vec()`
      |
      = note: expected type `std::vec::Vec<_>`
                 found type `&&std::vec::Vec<{integer}>`
    

    Esteban Kuber at 2019-05-29 17:19:24

  2. I may not express my concern correctly. It's not about the error messages, but the way to_owned works. When I calling to_owned, I'm expecting to get an owned data instead of another reference. This applies to other types other than Vec.

    Jay at 2019-05-31 06:24:55

  3. Hi, I have the exact same concern. In the example I provide, I struggled understanding how was to_owned() implemented when neither Copy or Clone is.

    //#[derive(Clone)] //Uncomment and it will suddenly works
    pub struct Example {
    	pub name : String
    }
    
    fn main() {
    	let ex = Example{name: "Name".to_string()};
    	let ex_ref = &ex;
    	let ex_owned : Example = ex_ref.to_owned();  // Error: expected struct `Example`, found &Example
    }
    

    As far as I understood, it is cloning the reference using the fact that &T implements Clone in

    #[stable(feature = "rust1", since = "1.0.0")]
    impl<T> ToOwned for T
    where
        T: Clone,
    {
        type Owned = T;
        fn to_owned(&self) -> T {
            self.clone()
        }
    
        fn clone_into(&self, target: &mut T) {
            target.clone_from(self);
        }
    }
    

    QDoussot at 2021-06-09 09:59:39

  4. close this?

    evbo at 2024-04-07 20:32:23