2017-10-24 14 views
2

私は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) 
+0

例:https://play.rust-lang.org/?gist=21175b41b1adcbf3a28c1f6affc74ccd&version=stable – coriolinus

+0

は一緒にその例を置く答えを示唆しています: ' user_data'は、所有された 'UserData'オブジェクトではありません。 'Json 'が 'T'に逆参照する' Json 'オブジェクトです。 'Json 'はそのコンストラクタのためだけに使われますが、コンパイラはそのことを知らないのです。今私はこれを解決する方法を理解する必要があります。私はそれを解決策として書きます。 – coriolinus

答えて

6

ここでの問題は、タイプがuser_dataの場合です。具体的には、関数シグネチャに記述されているとおり、その型はJson<UserData>です。

Json<T>は、JSocket値をラップしてラップする方法をRocketに伝えるラッパー型です。それはあなたの構造体をラップする便利なメソッドですが、余分なデータは保存しません。したがって、それはあなたがほとんど無視することができますDeref<Target = T>を実装します。しかし、それはあなたがそれを消費しようとしないときにのみ動作します。それらはTであるかのようDeref<Target=T>一般的に使用することができる実装

タイプ。コンパイラが間接指示を処理します。しかし、その関数呼び出しで実際に起こっていることは、<Json<UserData> as Deref<Target=UserData>>::deref().into_new_user();のようなもので、それが問題の発生場所です。dereffn 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

よくできました。私はすでに「Deref」と同じ問題があったので、そのことを知ることができました。たとえば、 – Boiethios

+0

のような 'Borrowed here:user_data.deref()'のような、より明示的なエラーメッセージを出すためにgithubに関する問題をオープンする必要があります([Box'から所有値を取得する方法は?](https:// stackoverflow.com/q/42264041/3650362)が関連しています。 'DerefMove'がこれまでに何かになった場合、現在誤っているコードを正しいものにすることができます。 – trentcl

関連する問題