I’m keeping a Connection wrapped in an Option in a property of a struct and I’m having trouble closing the Connection. I have checked a lot of answers here at stackoverflow for the general problem but I couldn´t get it working for my case.
Here’s a minimal example to reproduce the error:
use rusqlite::Connection;
struct Db {
c: Option<Connection>
}
impl Db {
pub fn new() -> Self {
return Db { c: None }
}
pub fn open(&mut self) {
self.c = Some(Connection::open("test.db").unwrap());
}
pub fn close(&mut self) {
self.c.as_ref().unwrap().close();
}
}
fn main() {
let mut d= Db::new();
d.open();
d.close();
}
I get the following output, using Rust 1.61.0 (Arch Linux rust 1:1.61.0-1) with Cargo and rusqlite (rusqlite = { version = "0.27.0", features = ["bundled"] })
error[E0507]: cannot move out of a shared reference
--> foo.rs:18:9
|
18 | self.c.as_ref().unwrap().close();
| ^^^^^^^^^^^^^^^^^^^^^^^^^-------
| | |
| | value moved due to this method call
| move occurs because value has type `Connection`, which does not implement the `Copy` trait
|
note: this function takes ownership of the receiver `self`, which moves value
--> ~.cargo/registry/src/github.com-1ecc6299db9ec823/rusqlite-0.27.0/src/lib.rs:725:18
|
725 | pub fn close(self) -> Result<(), (Connection, Error)> {
| ^^^^
For more information about this error, try `rustc --explain E0507`.
The function close() from the rusqlite library which the output refers to looks like this:
/// Close the SQLite connection.
///
/// This is functionally equivalent to the `Drop` implementation for
/// `Connection` except that on failure, it returns an error and the
/// connection itself (presumably so closing can be attempted again).
///
/// # Failure
///
/// Will return `Err` if the underlying SQLite call fails.
#[inline]
pub fn close(self) -> Result<(), (Connection, Error)> {
self.flush_prepared_statement_cache();
let r = self.db.borrow_mut().close();
r.map_err(move |err| (self, err))
}
How can I fix this error without changing the general architecture, that is keeping the Connection wrapped in an Option in a property of a struct and closing it via an implementation method?
>Solution :
The Connection::close method consumes self, so you have to take the wrapped value inside self.c out in order to call close on it. After takeing, the c becomes None.
use rusqlite::Connection;
struct Db {
c: Option<Connection>,
}
impl Db {
pub fn new() -> Self {
return Db { c: None };
}
pub fn open(&mut self) {
self.c = Some(Connection::open("test.db").unwrap());
}
pub fn close(&mut self) {
self.c.take().unwrap().close().unwrap();
}
}
fn main() {
let mut d = Db::new();
d.open();
d.close();
}
Documentation of std::option::Option::take