Je mis en place un Tokio Future
qui a la logique de haut niveau suivant:Ne peut pas déduire une durée de vie appropriée: Emprunts tampons mutables à terme
- Faire un appel à une fonction
recv_dgram
. Cela devrait retourner unFuture
qui est prêt quand un petit datagramme est reçu. - Lorsque le
Future
est prêt, conservez le petit datagramme. - Si nous avons suffisamment de petits datagrammes pour reconstruire un grand datagramme, réglez le
Future
comme prêt et renvoyez le datagramme reconstruit. Sinon, revenez à l'étape 1.
J'ai un problème de durée de vie que je n'arrive pas à comprendre. J'ai créé un morceau de code simplifié autonome pour le démontrer.
Dans le code ci-dessous, RecvMsg
est le Future
qui est prêt lorsque suffisamment de petits datagrammes ont été reçus. recv_dgram
est une fonction qui renvoie un Future
qui est prêt lorsqu'un petit datagramme est arrivé.
Je suis en train de compiler le code suivant (playground):
extern crate futures;
use self::futures::{Future, Poll, Async};
struct RecvMsg<'d,R>
where
R: for <'r> FnMut(&'r mut [u8]) -> Box<Future<Item=&'r mut [u8], Error=()> + 'r>,
{
recv_dgram: R,
temp_buff: Vec<u8>,
opt_read_future: Option<Box<Future<Item=&'d mut [u8], Error=()> + 'd>>,
}
impl<'d,R> Future for RecvMsg<'d,R>
where
R: for <'r> FnMut(&'r mut [u8]) -> Box<Future<Item=&'r mut [u8], Error=()> + 'r>,
{
type Item =();
type Error =();
fn poll(&mut self) -> Poll<Self::Item,()> {
// Obtain a future datagram,
let mut fdgram = (self.recv_dgram)(&mut self.temp_buff);
// Code compiles if this line is commented out:
self.opt_read_future = Some(fdgram);
return Ok(Async::NotReady);
}
}
fn main() {}
Ceci est le message d'erreur que je reçois:
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src/main.rs:25:44
|
25 | let mut fdgram = (self.recv_dgram)(&mut self.temp_buff);
| ^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 22:5...
--> src/main.rs:22:5
|
22 |/ fn poll(&mut self) -> Poll<Self::Item,()> {
23 | |
24 | | // Obtain a future datagram,
25 | | let mut fdgram = (self.recv_dgram)(&mut self.temp_buff);
... |
28 | | return Ok(Async::NotReady);
29 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:25:44
|
25 | let mut fdgram = (self.recv_dgram)(&mut self.temp_buff);
| ^^^^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'd as defined on the impl at 13:1...
--> src/main.rs:13:1
|
13 |/impl<'d,R> Future for RecvMsg<'d,R>
14 | | where
15 | | R: for <'r> FnMut(&'r mut [u8]) -> Box<Future<Item=&'r mut [u8], Error=()> + 'r>,
16 | | {
... |
29 | | }
30 | | }
| |_^
note: ...so that expression is assignable (expected std::option::Option<std::boxed::Box<futures::Future<Error=(), Item=&'d mut [u8]> + 'd>>, found std::option::Option<std::boxed::Box<futures::Future<Error=(), Item=&mut [u8]>>>)
--> src/main.rs:27:32
|
27 | self.opt_read_future = Some(fdgram);
| ^^^^^^^^^^^^
J'ai quelques idées sur ce qui pourrait se tromper. Je sais que si je commente la ligne:
reading_state.opt_read_future = Some(fdgram);
Le code compile avec succès. En outre, je pense que le fait que reading_state.temp_buff
est utilisé ici comme argument:
let mut fdgram = (reading_state.frag_msg_receiver.recv_dgram)(
&mut reading_state.temp_buff);
a quelque chose à voir avec le problème. (Voir aussi Why can't I store a value and a reference to that value in the same struct?)
Oui, il est (https://stackoverflow.com/questions/32300132/why-cant-i-store-a-value-and-a-reference-to-that-value-in-the-same-struct). 'opt_read_future' contient une référence à' temp_buf'. – red75prime
@ red75prime: En lisant votre commentaire, j'ai essayé de simplifier le code encore plus pour trouver le problème de base. Je me rends compte que j'ai à la fois 'temp_buff' et une référence à son contenu sur la même structure, mais' temp_buff' est un vecteur et son contenu est sur le tas. Pourquoi cela serait-il un problème? Je n'arrive pas à comprendre ce qui pourrait mal tourner ici. En outre, avez-vous une idée pour une solution de contournement? Où dois-je mettre 'temp_buff'? – real