Warning about exclusive access on drop

Good day all. I am working on updating the yara-rust wrapper to support the latest Yara version and also transition to Rust 2018 edition. I am seeing the warning below:

warning[E0713]: borrow may still be in use when destructor runs
   --> src/compiler.rs:99:39
    |
16  | impl<'a> Compiler<'a> {
    |      -- lifetime `'a` defined here
...
99  |         internals::compiler_get_rules(self.inner).map(Rules::from)
    |         ------------------------------^^^^^^^^^^------------------ returning this value requires that `*self.inner` is borrowed for `'a`
100 |     }
    |     - here, drop of `self` needs exclusive access to `*self.inner`, because the type `compiler::Compiler<'_>` implements the `Drop` trait
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
    = note: for more information, try `rustc --explain E0729`

So I changed the function signature to:

pub fn compiler_get_rules<'a>(compiler: &'a mut YR_COMPILER) -> Result<&'a mut YR_RULES, YaraError> {

but the warning stays the same. When I changed self in the containing function to mutable then all the tests break.

I’d appreciate some guidance on where I should be placing/removing lifetime parameters. Thanks!

The value self goes out of scope at the end of compile_rules. Due to the Drop impl for Compiler<'a>, the body of compile_rules is effectively this:

let ret = internals::compiler_get_rules(self.inner).map(Rules::from);

/* self goes out of scope: */ {
    internals::compiler_destroy(self.inner);
    std::mem::forget(self);
}

ret

Notice that ret is borrowed from self.inner but compiler_destroy mutates self.inner. You are not supposed to be able to mutate something while parts of it are borrowed.

You will need to change the logic so that nothing is mutated while borrowed. I wouldn’t expect this to be a matter of placing/removing more lifetime parameters.

1 Like