【问题标题】:Cannot move out of borrowed content, with no borrowed content无法移出借用内容,没有借用内容
【发布时间】:2018-04-04 22:17:45
【问题描述】:

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

【问题讨论】:

  • 锈操场上的例子:play.rust-lang.org/…
  • 把这个例子放在一起给出了答案:user_data 不是一个拥有的UserData 对象。这是一个Json&lt;UserData&gt; 对象,其中Json&lt;T&gt; 取消引用T。碰巧Json&lt;T&gt; 仅用于其构造函数,但编译器不知道这一点。现在我只需要弄清楚如何解决这个问题,我会把它写下来作为解决方案。

标签: rust rust-rocket


【解决方案1】:

这里的问题在于user_data 的类型。具体来说,正如函数签名中所写的那样,它的类型是Json&lt;UserData&gt;

Json&lt;T&gt; 是一个包装器类型,它告诉 Rocket 如何包装和解包 JSON 值;这是一种包装结构的便捷方法,但不存储任何额外数据。因此它实现了Deref&lt;Target = T&gt;,这让你几乎可以忽略它。但是,这只在您不尝试使用它时才有效。

实现Deref&lt;Target=T&gt;的类型一般可以像T一样使用;编译器为您处理间接。但是,该函数调用中实际发生的事情更像&lt;Json&lt;UserData&gt; as Deref&lt;Target=UserData&gt;&gt;::deref().into_new_user();,这就是问题所在:deref 被定义为fn deref(&amp;self) -&gt; &amp;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!()
}

【讨论】:

  • 干得好。我本可以发现这一点,因为我已经遇到了与 Deref 相同的问题。也许你应该在 github 上打开一个问题来询问更明确的错误消息:例如Borrowed here: user_data.deref()
  • How do I get an owned value out of a Box? 是相关的。如果DerefMove 变成了一个东西,那么当前错误的代码可能会被改正。
猜你喜欢
  • 1970-01-01
  • 2015-04-20
  • 1970-01-01
  • 2017-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-25
  • 1970-01-01
相关资源
最近更新 更多