2017-09-13 4 views
1

への参照を含む構造体の寿命を推測することはできません:は、私は私のコードのコンパイルのこの単純化と自己完結型のバージョンにしようとしています閉鎖

struct FragMsgReceiver<'a, 'b: 'a> { 
    recv_dgram: &'a mut FnMut(&mut [u8]) -> Result<&'b mut [u8],()>, 
} 

impl<'a, 'b> FragMsgReceiver<'a, 'b> { 
    fn new(
     recv_dgram: &'a mut FnMut(&mut [u8]) 
      -> Result<&'b mut [u8],()> 
    ) -> Self { 
     FragMsgReceiver { recv_dgram } 
    } 
} 

fn main() { 
    let recv_dgram = |buff: &mut [u8]| Ok(buff); 
    let fmr = FragMsgReceiver::new(&mut recv_dgram); 
} 

ここを誤りである:

error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements 
    --> src/main.rs:15:43 
    | 
15 |  let recv_dgram = |buff: &mut [u8]| Ok(buff); 
    |           ^^^^ 
    | 
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 15:22... 
    --> src/main.rs:15:22 
    | 
15 |  let recv_dgram = |buff: &mut [u8]| Ok(buff); 
    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^ 
note: ...so that expression is assignable (expected &mut [u8], found &mut [u8]) 
    --> src/main.rs:15:43 
    | 
15 |  let recv_dgram = |buff: &mut [u8]| Ok(buff); 
    |           ^^^^ 
note: but, the lifetime must be valid for the block suffix following statement 1 at 16:53... 
    --> src/main.rs:16:53 
    | 
16 |  let fmr = FragMsgReceiver::new(&mut recv_dgram); 
    | _____________________________________________________^ 
17 | | } 
    | |_^ 
note: ...so that variable is valid at time of its declaration 
    --> src/main.rs:16:9 
    | 
16 |  let fmr = FragMsgReceiver::new(&mut recv_dgram); 
    |   ^^^ 

エラーメッセージからわかるように、コンパイラはbuffの参照(引数はrecv_dgram)が実際にrecv_dgramの内部の本体より長く存続することを理解していません。私は間違っている可能性があります。

いくつかのコンテキストを与えるために、私はRust Tokio UDPソケットをラップする構造体を作成しようとしています。これを行うために、私は関数recv_dgramへの参照を取る。私の元のコードでは、この関数は引数としてバッファをとり、Futureを返します。 Futureが準備完了状態になると、バッファがいっぱいになります。 Futureの項目には、送信者のアドレスとバッファに書き込まれたバイト数も含まれています。

+0

これは機能ではありません。それは閉鎖です。ジェネリックを使うのではなく、特性オブジェクトへの参照が必要な理由はありますか? – Shepmaster

+0

クロージャ引数に型指定子をドロップして、推論を有効にしてから、クロージャに渡す値が結果と同じ寿命になるように指定してから、 'mut'修飾子を修正します。 [完了例](https://play.rust-lang.org/?gist=5650836c790a4394e853ebc76bb84148&version=stable)。 – Shepmaster

+0

@Shepmaster:ありがとう!私は解決できないことがまだあります:recv_dgramはさまざまなバッファを取得し、私の意見ではその寿命は 'a'に関係すべきではないので、 'aはより長く使える'ようにします。私が 'b:'を削除しようとすると、コンパイルエラーが発生します。 '' '&' a mut型:: ops :: FnMut(& 'b mut [u8]) - >&' b mut [u8] + 'a、参照はそれが参照するデータよりも寿命が長い''。どのようにこれを解決することができますか? – real

答えて

1

のは、あなたの宣言で省略さ寿命を復元してみましょう

struct FragMsgReceiver<'a, 'b: 'a> { 
    recv_dgram: &'a mut for<'c> FnMut(&'c mut [u8]) -> Result<&'b mut [u8],()>, 
} 

この宣言は、FragMsgReceiverが持つスライスへの変更可能な参照任意の寿命'cとリターンを取るFnMut形質オブジェクトへの変更可能な参照を保持していることを意味します生涯の参照'b: 'a

これは必要なものではありません。 FnMutが必要です。このパラメーターは、入力パラメーターの存続期間と同じ有効期間の参照を戻します。これは以下のように書くことができる

type FnTraitObject = FnMut(&mut [u8]) -> Result<&mut [u8],()>; 

struct FragMsgReceiver<'a> { 
    recv_dgram: &'a mut FnTraitObject, 
} 

impl<'a> FragMsgReceiver<'a> { 
    fn new(recv_dgram: &'a mut FnTraitObject) -> Self { 
     FragMsgReceiver { recv_dgram } 
    } 
} 

生涯エリジオンは、ここでは正しいことを行いますが、コンパイラは、まだ文句を言う:「バウンド寿命パラメータを期待される具体的な寿命を見つけた」FragMsgReceiver::new(&mut recv_dgram)を指し、。

このエラーは、Rustの型推論の制限によって発生します。私たちは、for<'c>'cは任意の寿命することができ、寿命が呼び出しサイトで決定されることを意味し、それは明確にするためpointed out by DK.

fn constrain_handler<F>(f: F) -> F 
where 
    F: FnMut(&mut [u8]) -> Result<&mut [u8],()>, 
{ 
    f 
} 

// ... 

let mut recv_dgram = constrain_handler(|buff| Ok(buff)); 

Complete code on the playground

たとして閉鎖の種類を強制することで推論を支援する必要があります。たとえば、関数fn foo(_: &u32) -> &u32へのポインタのタイプはfor<'a> fn(&'a u32) -> &'a u32です。

+0

red75primeとshepmaster、あなたは私の一日保存しました! – real

関連する問題