Giovanni
Giovanni

Reputation: 4015

'move occurs because value has type' Rust error

I'm learning Rust and I don't udestrand what is the problem of the following code

pub enum BagEntryState {
    UNUSED, USED, REMOVED
}

impl PartialEq for BagEntryState {
    fn eq(&self, other: &Self) -> bool {
        self == other
    }
}

pub struct BagEntry< T: std::cmp::PartialEq + fmt::Display> {
    state : BagEntryState,
    value: T,
}

impl<'a, T: std::cmp::PartialEq + fmt::Display> BagEntry<T> {
    pub fn new(value: T) -> BagEntry< T> {
        BagEntry {
            value,
            state: BagEntryState::UNUSED,
        }
    }

    pub fn value(self)->T {
        self.value
    }
}

impl<'a, T: std::cmp::PartialEq + fmt::Display> PartialEq for BagEntry<T> {
    fn eq(&self, other: &Self) -> bool {
        self.value == other.value
    }
}

impl<T: std::cmp::PartialEq + fmt::Display> fmt::Display for BagEntry<T> {
    // This trait requires `fmt` with this exact signature.
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.value)
    }
}

use core::fmt;


fn main() {

    let my_bagentry = BagEntry::new(String::from("ciao"));
    //println!("{}", my_bagentry.value());
    let mut contVec : Vec<BagEntry<String>>=vec![];
    contVec.push(my_bagentry);
    println!("state ={}", contVec[0]);
    println!("state ={}", contVec[0].value());


}

The code is not compiling becaus of the error:

54 |     println!("state ={}", contVec[0].value());
   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ move occurs because value has type `BagEntry<std::string::String>`, which does not implement the `Copy` trait

My guess is that the problem is that with value()

I'm exposing the struct inner value, but I cannot really understand where the problem is and how to solve it.

My aim is that BagEntry owns the value but I want safely expose it outside the struct

Upvotes: 5

Views: 8601

Answers (1)

Leśny Rumcajs
Leśny Rumcajs

Reputation: 2526

Basically what is happening:

  pub fn value(self)->T {
      self.value
  }

Here -> T means that you are moving the struct field out of the struct. This is fine, but you cannot use your object anymore. You can verify this - you cannot call your println!("{}", my_bagentry.value()); twice in a row - after the first one the my_bagentry is invalidated.

If I understand correctly you want only to borrow the value out of the object. To do this you need change your method signature to borrowing one.

pub fn value(&self)-> &T {
    &self.value
}

Now the call will only borrow on the object and the the resulting reference will have the lifetime of that borrow.

Upvotes: 5

Related Questions