Search code examples
pointerstypesrustborrow-checkerlmdb

Trait is not implemented for the type `&A` when passing an array of pairs to a function


I am trying to write the function set which calls the Rust LMDB library (docs), and an example I'm working off of.

I can't for the life of me get this to work. Here is my current attempt:

fn main() {
    let env = getenv("duperdb");
    let dbhandle = get_dbhandle("", &env);
    let txn = new_transaction(&env);
    let vec = vec![("foo", "another text"), ("bar", "and another")];
    set(&dbhandle, &env, &vec);

    let reader = env.get_reader().unwrap();
    let db = reader.bind(&dbhandle);
    let note = db.get::<&str>("foo").unwrap();

    println!("NOTE: {}", note);
}

Where set is defined as:

pub fn set<A: ToMdbValue, B: ToMdbValue>(
    handle: &DbHandle,
    env: &Environment,
    pairs: &Vec<(&A, &B)>) -> () {

    let txn = new_transaction(&env);

    {
        let db = txn.bind(&handle);

        for &(id, note) in pairs.iter() {
            db.set(&id, &note).unwrap();
        }
    }

    match txn.commit() {
            Err(_) => panic!("Failed to commit!"),
            Ok(_) => (),
    }
}

This spits out the following error:

src/db/wrapper.rs:28:20: 28:23 error: the trait `lmdb::traits::ToMdbValue` is not implemented for the type `&A` [E0277]
src/db/wrapper.rs:28             db.set(&id, &note).unwrap();
                                        ^~~

I also tried db.set(id, note).unwrap();, but this time I get:

src/main.rs:13:5: 13:8 error: the trait `core::marker::Sized` is not implemented for the type `str` [E0277]
src/main.rs:13     set(&dbhandle, &env, &vec);
                   ^~~
src/main.rs:13:5: 13:8 help: run `rustc --explain E0277` to see a detailed explanation
src/main.rs:13:5: 13:8 note: `str` does not have a constant size known at compile-time
src/main.rs:13:5: 13:8 note: required by `dupernote::db::wrapper::set`
src/main.rs:13:5: 13:8 error: the trait `lmdb_rs::traits::ToMdbValue` is not implemented for the type `str` [E0277]
src/main.rs:13     set(&dbhandle, &env, &vec);
                   ^~~

I also tried stuff like:

    for (id, note) in pairs.iter() {
        db.set(id, note).unwrap();
    }

But that doesn't work either... I don't fully understand why. Doesn't id and note have type &str, not str?


Solution

  • I managed to get it working. I'm not sure how kosher this solution is, but I'll post it.

    So now, in main(), I do the following (example with an (int, string) kv pair):

    let k = 1;
    let val = "hello there";
    let vec = vec![(&k, &val)];
    set(&dbhandle, &env, &vec);
    

    I had to declare them separately since vec![(&1, &"hello there")] threw an error of the form borrowed value does not live long enough.

    set now looks like this:

    pub fn set<A, B>(handle: &DbHandle, env: &Environment, pairs: &Vec<(&A, &B)>)
        -> ()
        where A: ToMdbValue,
              B: ToMdbValue {
    
        let txn = new_transaction(&env);
    
        {
            let db = txn.bind(&handle);
    
            for &(id, note) in pairs.iter() {
                db.set(id, note).unwrap();
            }
        }
    
        match txn.commit() {
                Err(_) => panic!("Failed to commit!"),
                Ok(_) => (),
        }
    }