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?
The
Transaction::commit
method consumes the transaction:If you were able to call
commit
, then the value ofself
would be in some inconsistent state, because what would the value ofself.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 implementsDrop
, then you can never pull apart the struct because thenDrop
could not run! This even applies when you are inside theDrop
implementation itself.If you actually needed to do this, you'd have to have
transaction
be some type that you could easily replace. AnOption
is a good choice, as you can usetake
to replace it with aNone
.In the specific case of the
Transaction
, you don't have to do anything special. While aTransaction
normally rolls back on drop, you can callTransaction::set_commit
so that it commits on drop.