4

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

ESCoder
  • 15,431
  • 2
  • 19
  • 42
Giovanni
  • 3,951
  • 2
  • 24
  • 30

1 Answers1

4

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.

Leśny Rumcajs
  • 2,259
  • 2
  • 17
  • 33
  • What if you want to change the struct field from inside the function? Is it possible to do this when only passing a reference, or how would one achieve this? – pfincent Aug 16 '21 at 12:15
  • @pfincent if you want to modify member field from a method you need to use mutable reference e.g. `fn modification(&mut self)` – Leśny Rumcajs Aug 16 '21 at 14:25