Can not move out of type which defines the `Drop`

2019-07-11 03:08发布

I have the following Rust code using rust-postgres with the intention of committing a transaction after my struct goes out of scope

struct SqlTransaction<'a> {
    connection: &'a Connection,
    transaction: Transaction<'a>,
}

impl<'a> Drop for SqlTransaction<'a> {
    fn drop(&mut self) {
        let result = self.transaction.commit();
        match result {
            Ok(_) => print!("herp"),
            Error => print!("lol"),

        }
    }
}

The compiler complains about the commit() line with the following message

cannot move out of type `SqlTransaction<'a>`, which defines the `Drop` trait [E0509]at line 12 col 22

What is happening and how can I fix that?

标签: rust
1条回答
神经病院院长
2楼-- · 2019-07-11 03:11

The Transaction::commit method consumes the transaction:

pub fn commit(self) -> Result<()> {
    self.set_commit();
    self.finish()
}

If you were able to call commit, then the value of self would be in some inconsistent state, because what would the value of self.transaction be? It's been moved out!

If the type didn't implement Drop, this wouldn't be a problem, as the compiler would just drop all the other pieces of the struct. However, since it implements Drop, then you can never pull apart the struct because then Drop could not run! This even applies when you are inside the Drop implementation itself.

If you actually needed to do this, you'd have to have transaction be some type that you could easily replace. An Option is a good choice, as you can use take to replace it with a None.


In the specific case of the Transaction, you don't have to do anything special. While a Transaction normally rolls back on drop, you can call Transaction::set_commit so that it commits on drop.

查看更多
登录 后发表回答