Невозможно выйти из заемного контента, без заемного контента

Я работаю над созданием REST API с использованием Rust и Rocket. У меня есть конечная точка, в которой я создаю нового пользователя, определенного следующим образом:

/// 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_data а также db являются собственностью Тем не менее, я получаю следующую ошибку при компиляции:

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 ответ

Проблема здесь была с типом 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!()
}
Другие вопросы по тегам