2

I am having a struct and respective impl (add_account) as well.

Struct

pub struct Departments {
    pub id: String,
    pub linked_accounts: Vec<Account>,
}

Impl

impl Departments {
    pub fn add_account(&mut self, acct: Account) -> Self {

        let mut vec: Vec<Account> = self.linked_accounts; //*Error here*
        vec.push(acct);

        Self {
            id: self.id, //*Error here*
            linked_accounts: vec,
        }
    }
}

Calling area

getting value from DB and adding account and update back to DB

match db.get::<Departments>(id).await? {
        None => bail!("No records found"),
        Some(departments) => {
            let mut departments = departments;

            //calling area
            departments.add_account(Account::Credit);

            let id = Id::new(Departments::KIND, &id);
            gh.update::<_, Departments>(
                id,
                departments.clone(),
            )
                .await?;
            
        }
    }

Error as 'Cannot move self' while assigning self values inside.

Arul
  • 23
  • 4

2 Answers2

2

There are a couple of ways to interpret your question. In all the cases, the answer starts with "Your function signature is wrong", but what exactly it should be, depends on your usecase.

But most certainly, it should be one of:

  • pub fn add_account(&mut self, acct: Account)
  • pub fn add_account(&mut self, acct: Account) -> &mut Self
  • pub fn add_account(mut self, acct: Account) -> Self

I think the biggest misconception you are having is that you think you need to return Self. The way you are using add_account, by simply calling it on departments.add_account(Account::Credit) does not require you to return Self. You can directly modify the self object:

pub struct Departments {
    pub id: String,
    pub linked_accounts: Vec<Account>,
}

impl Departments {
    pub fn add_account(&mut self, acct: Account) {
        self.linked_accounts.push(acct);
    }
}

Now, there is a usecase where you want to return some form of Self, and that is if you want to be able to chain those calls:

departments
    .add_account(Account::Credit)
    .add_account(Account::Debit)
    .add_account(Account::Savings);

This is usually done by returning &mut Self:

pub struct Departments {
    pub id: String,
    pub linked_accounts: Vec<Account>,
}

impl Departments {
    pub fn add_account(&mut self, acct: Account) -> &mut Self {
        self.linked_accounts.push(acct);
        self
    }
}

Note that this still doesn't require you to instantiate a new Self object, like you were doing in your code.


The actual error

In case you want to understand the original error:

  • The &mut self argument means that you only borrow self, and you have to give it back at some point. (happens automatically at the end of the function)
  • let mut vec: Vec<Account> = self.linked_accounts; moves the linked_accounts member out of self. This is only possible when we take ownership of self instead of borrowing it, because then, we can dismantle it to our pleasing. But as we need to give it back, we cannot just move members out of it.

I didn't talk about the actual error in more detail, because it was just an artifact of the incorrect function signature and didn't really contribute meaningfully to a solution.

Either way, I think there are a couple of misunderstandings of yours as to how ownership works, so I recommend reading the ownership chapter of the Rust book.

The reason why I think you have misunderstandings, is because it is literally impossible to return Self if your function signature contains &mut self. Self is owned, and you cannot create an owned object from a borrowed one without copying it.

Yes, you are trying to create a copy of it in your attempt to implement it, but the usage example you posted shows me that you don't actually want to create a copy.

Finomnis
  • 18,094
  • 1
  • 20
  • 27
0

In a meantime you can also Clone Self.

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=45c902d55a8f3e190893f82f720fdae2

Zhiburt
  • 65
  • 2
  • 6
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jan 24 '23 at 20:06