Another lifetime question

My prior post asked for help on lifetimes. I am still stuck. I have

pub struct DynCaller {
    libs: HashMap<String, DynamicLibrary>,
}

with this method

pub fn define_function_by_str(&mut self, funcdef: &str) -> Result<FuncDef<'_>> {
...
}

and

pub struct FuncDef<'argval> {
    cif: ffi_cif,
    entry_point: unsafe extern "C" fn(),
    ffi_arg_types: Vec<*mut ffi_type>,
    ffi_return_type: ffi_type,
    pub(crate) arg_types: Vec<ArgType>,
    return_type: ArgType,
    pub(crate) arg_ptrs: Vec<*mut c_void>,
    pub(crate) arg_vals: Vec<ArgVal<'argval>>,
}

I had to add the lifetimes because I needed to store references in arg_vals. The problem is now that this (which worked before adding lifetimes)

        let mut dyncaller = DynCaller::new();
        let mut fopen = dyncaller
            .define_function_by_str("msvcrt.dll|fopen|cstr,cstr|ptr")
            .unwrap();

        let mut fread = dyncaller
            .define_function_by_str("msvcrt.dll|fread|ocstr,i32,i32,ptr|i32")
            .unwrap();

I get

error[E0499]: cannot borrow `dyncaller` as mutable more than once at a time
   --> src\test.rs:167:25
    |
163 |         let mut fopen = dyncaller
    |                         --------- first mutable borrow occurs here
...
167 |         let mut fread = dyncaller
    |                         ^^^^^^^^^ second mutable borrow occurs here

This I do not get at all. the return values from the define call are not holding onto the DynCaller at all.

In this situation the lifetime of retun value isn't related to self or that str, but the signature suggests this. To Rust, you are borrowing self until the FuncDef is dropped.

The Rustonomicon (1):

If there are multiple input lifetime positions, but one of them is &self or &mut self, the lifetime of self is assigned to all elided output lifetimes.

The solution would be to make it clear that those lifetimes are separate. The lifetime of FuncDef in not yet known, it may be anything, but it certainly doesn't interfere with self or str

So write lifetimes explicitly:

pub fn define_function_by_str<'a, 'b, 'c>(&'a mut self, funcdef: &'b str) -> Result<FuncDef<'c>> {
...
}

This should do. Then you can go the other way and try reducing the amount of lifetimes. I am pretty sure 'a and 'b can be merged together, and maybe you can even omit them both entirely, compiler should understand that you mean that FuncDef does not borrow from any of them and the lifetime is not restricted by this function.

I strongly recommend reading the Rustonomicon.


I have read those a lot :frowning:

thank you