无法移动借用内容,没有借用的内容。

3

我正在使用 Rust 和 Rocket 构建 REST API。我有一个端点,用于创建新用户,定义如下:

/// View with which to create a user
#[post("/users", format = "application/json", data = "<user_data>")]
fn create_user(user_data: Json<UserData>, db: DB) -> Status<Json<Value>> {
    let conn = db.conn();
    let _new_user_result = user_data.into_new_user(&conn);
    unimplemented!()
}

请注意,这里没有借用的内容; user_datadb 都是拥有它们的。尽管如此,在编译时我会收到以下错误:
error[E0507]: cannot move out of borrowed content
  --> src/views/user_account.rs:75:28
   |
75 |     let _new_user_result = user_data.into_new_user(&conn);
   |                            ^^^^^^^^^ cannot move out of borrowed content

作为参考,into_new_user函数的函数签名如下:

fn into_new_user(self, conn: &SqliteConnection) -> Result<NewUser, Status<Json<Value>>> {
    ...
}

这里出了什么问题?如果我借用了什么东西,这个错误就好理解多了,但是考虑到所有相关的东西都是我的,我感到十分困惑。

$ rustc --version; cargo --version
rustc 1.22.0-nightly (a47c9f870 2017-10-11)
cargo 0.23.0-nightly (e447ac7e9 2017-09-27)

{btsdaf} - coriolinus
{btsdaf} - coriolinus
1个回答

7
这里的问题出在user_data的类型上。具体来说,就像函数签名中写的一样,它的类型是Json<UserData>Json<T>是一个包装类型,告诉Rocket如何包装和解包JSON值; 它是一种方便的方法,可以包装您的结构体,但不存储任何额外的数据。因此,它实现了Deref<Target = T>,让您大部分情况下可以忽略它。但是,只有在您不尝试消耗它时才起作用。
实现Deref<Target=T>的类型通常可以像T一样使用; 编译器会为您处理间接引用。但是,在该函数调用中实际发生的事情更类似于<Json<UserData> as Deref<Target=UserData>>::deref().into_new_user();,这就是问题出现的地方:deref被定义为fn deref(&self) -> &Self::Target。借用隐式且不可见,但它确实存在。
在这种情况下,Json类型不再是必需的;它只是用于反序列化UserData结构。因此,我们可以通过丢弃它来解决问题。Json::into_inner方法丢弃了Json包装器,给出了一个拥有的UserData。然后可以按计划使用它。将其组合,函数应该如下所示:
fn create_user(user_data: Json<UserData>, db: DB) -> Status<Json<Value>> {
    let conn = db.conn();
    let _new_user_result = user_data.into_inner().into_new_user(&conn);
    unimplemented!()
}

1
{btsdaf} - Boiethios
{btsdaf} - trent

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接