jpernst / rental

Rust macro to generate self-referential structs
Apache License 2.0
211 stars 11 forks source link

Lifetime problems #11

Closed MarkSwanson closed 7 years ago

MarkSwanson commented 7 years ago

Hello,

Please help. I'm totally stuck...

#[rental_mut]
        pub struct RentContextWrite2<T: Memory + 'static> {
            memory: Box<VecMemory>,
            saw: Box<SAW<'memory, T>>,
            message_builder: Box<message::Builder<SAW<'saw, T>>>,
            point_builder: point::Builder<'message_builder>,
        }
let mut rent_context_write2 = rent_point::RentContextWrite2::new(
        Box::new(vec_memory),
        |memory| {
            let mut saw = SAW::new(memory);
            Box::new(saw)
        },
        |saw| {
            match saw.start() {
                Ok(o) => (),
                Err(e) => panic!("{}", e)
            };

            // debug: saw += 1
            let message_builder = message::Builder::new(saw.clone());
            // (debug - to get the type) message_builder += 1
            Box::new(message_builder)
        },
        |message_builder| {
            message_builder.init_root::<point::Builder>()
        }
    );

The problem is in |saw| - it fails to compile with: cannot infer an appropriate lifetime due to conflicting requirements

Some debugging info: messagebuilder == message::Builder<SAW<', VecMemory>> (I note the lifetime '_)

saw type: cannot use += on type &'saw mut SAW<'memory, VecMemory>

So, it seems positive that SAW<'memory ...> lifetime is mentioned.

The compiler message isn't helping - because it doesn't tell me what the 'conflicting requirements' are :-(

Any ideas?

Thanks!

jpernst commented 7 years ago

If I had to guess, it's probably because the saw field is SAW<'memory, T> while message_builder expects a SAW<'saw, T>. If SAW is invariant, which is probably is if it contains a mutable reference inside, then its lifetime parameter can't be coerced like this. Try using 'memory instead of 'saw for the message_builder field.

jpernst commented 7 years ago

Actually, since it appears Builder consumes SAW, you probably don't need to have them as two separate fields in the first place. You could also try removing the saw field altogether and just constructing the SAW and the Builder in the first closure.

MarkSwanson commented 7 years ago

Great guess - using 'memory works fine. I may also remove saw. Thank you very much.

In hindsight this seems obvious :-), and is exactly what I want/need.