jpernst / rental

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

Several type parameters #39

Closed mikevoronov closed 5 years ago

mikevoronov commented 5 years ago

Hi!

Is there a way to use rental for structs (like this one) that have fields with several type parameters?

jpernst commented 5 years ago

If the last 3 fields all only need to borrow the first field, the best way to do this is to pack the last 3 fields into a regular struct, then have that struct be the second field of the rental struct, so that the rental struct now only has 2 fields.

mikevoronov commented 5 years ago

Thank you for the quick answer! It helped, but currently I stumbled with another problem while trying to compile this:

pub struct FrankFuncs<'a> {
    pub allocate: Func<'a, i32, i32>,
    pub deallocate: Func<'a, (i32, i32), ()>,
    pub invoke: Func<'a, (i32, i32), i32>,
}

rental! {
    pub mod frank_rent {
        use super::*;

        #[rental]
        pub struct FrankRental {
            #[subrental = 2]
            instance: Box<Instance>,
            funcs: FrankFuncs<'instance_0>,
            memory: &'instance_1 mut Memory,
        }
    }
}

It works without memory or without funcs. I've tried to decouple Memory to a separate struct with explicit lifetime parameter and deleted subrental, but there were various errors.

For this example error is message: Struct FrankRental field funcs must be a type path with 1 type param,String, or a reference. If I swap memory and funcs, the error will be binding for associated type Output references lifetime 'instance_0, which does not appear in the trait input types.

jpernst commented 5 years ago

You don't need to use subrental here. The subrental feature is for nesting one rental struct inside of another. Your FrankFuncs struct is just a normal struct so doesn't need this. Your rental struct should just look like this:

#[rental_mut]
        pub struct FrankRental {
            instance: Box<Instance>,
            funcs: FrankFuncs<'instance>,
            memory: &'funcs mut Memory,
        }

Note the rental_mut instead of rental. A regular rental struct has each field doing a shared borrow of the previous field, but since you want a mutable reference for memory, you must use a rental_mut struct that allow mutable borrows.

mikevoronov commented 5 years ago

Thank you again!)

Interesting, that your example doesn't work for me, but it works with swapped func and memory fields.