Rust / rusqlite:无法移出共享引用

Rust / rusqlite: cannot move out of a shared reference

我将连接包裹在结构 属性 中的选项中,但在关闭连接时遇到问题。我已经在 Whosebug 上检查了很多关于一般问题的答案,但我无法让它适用于我的情况。

这是重现错误的最小示例:

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();
}

我得到以下输出,使用 Rust 1.61.0 (Arch Linux rust 1:1.61.0-1) 与 Cargo 和 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`.

输出引用的 rusqlite 库中的函数 close() 如下所示:

   /// 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))
    }

如何在不更改一般架构的情况下修复此错误,即将 Connection 包裹在结构的 属性 中的选项中并通过实现方法关闭它?

The Connection::close method 消耗 self,因此您必须将 self.c 中的包装值取出,以便在其上调用 closetakeing 后,c 变为 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