没有借来的内容,无法摆脱借来的内容

时间:2017-10-24 07:54:53

标签: rust rust-rocket

我正在使用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)

1 个答案:

答案 0 :(得分: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