#[jni-rs] How to get this code to pass the borrow checker?

3 messages · Page 1 of 1 (latest)

toxic kayak
#

I'm trying to use the jni-rs crate and want to store the jvm instance along side the attachment which requires and explicit lifetime. I've tried boxing JavaVM to no avail.

/// Wrapper for booting and interaction with the JVM
pub struct Jvm<'a>
{
    pub env: AttachGuard<'a>,
    pub jvm: Box<JavaVM>
}

impl<'a> Jvm<'a> {
    /// Boots a jvm on the current thread
    pub fn boot() -> Result<Self> {
        let jvm_args = InitArgsBuilder::new()
            .version(JNIVersion::V8)
            // .option("-Xcheck:jni")
            .build()
            .context("Failed to init JVM args")?;

        let jvm = Box::new(JavaVM::new(jvm_args).context("Failed to boot JVM")?);

        let env = jvm
            .attach_current_thread()
            .context("Failed to attach current thread to JVM")?;

        Ok(Self { env, jvm })
    }
}

Current errors:

error[E0597]: `*jvm` does not live long enough
  --> src/jdbc/jvm.rs:22:19
   |
11 |   impl<'a> Jvm<'a> {
   |        -- lifetime `'a` defined here
...
22 |           let env = jvm
   |  ___________________^
23 | |             .attach_current_thread()
   | |____________________________________^ borrowed value does not live long enough
...
26 |           Ok(Self { env, jvm })
   |                     --- this usage requires that `*jvm` is borrowed for `'a`
27 |       }
   |       - `*jvm` dropped here while still borrowed

error[E0505]: cannot move out of `jvm` because it is borrowed
  --> src/jdbc/jvm.rs:26:24
   |
11 |   impl<'a> Jvm<'a> {
   |        -- lifetime `'a` defined here
...
22 |           let env = jvm
   |  ___________________-
23 | |             .attach_current_thread()
   | |____________________________________- borrow of `*jvm` occurs here
...
26 |           Ok(Self { env, jvm })
   |                     ---  ^^^ move out of `jvm` occurs here
   |                     |
   |                     this usage requires that `*jvm` is borrowed for `'a`

Any help is appreciated.

uneven seal
#

When Rust sees 'a, it make the most pessimistic guess, that is the shortest lived one, of all options.

Here we have env, jvm, and Self. Our intuition may reason: I am returning env and jvm wrapped in Self, so 'a should be one of Self. But Rust sees that env only lives to the end of boot, and that is not enough for 'a which has to be returned.

This is a self-referencing struct problem. You may try using the crate ouroboros for constructing it.
https://lib.rs/crates/ouroboros

#

That said, in general it is discouraged to wrap *Guard types in your struct. They are supposed to be associated with their calling scope to provide guarding.