Help with lifetime 'a

I've this working fine with numbers.

I'm trying to use &'a str and life times, to have this:

use std::collections::VecDeque;
use std::collections::HashMap;
use std::hash::Hash;

pub struct Inventory<'a, Warehouse: Eq + Hash, Item: Eq + Hash> {
    pub(crate) table: HashMap<Warehouse, HashMap<Item, Transactions<'a>>>
}

#[derive(Debug, Default)]
pub(crate) struct Transactions<'a> {
    pub(crate) trx: VecDeque<Transaction<'a>>
}

#[derive(Debug, Default)]
pub(crate) struct Transaction<'a> {
    pub(crate) item: &'a str,
    pub(crate) date: &'a str,
    pub(crate) batch: &'a str,
    pub(crate) quantity: i64
}

trait Memory<A: Eq + Hash, B: Eq + Hash> {

    fn get(&self, a: &A, b: &B) -> Option<&Transactions>;

    fn set(&mut self, a: A, b: B, v: Transactions<'_>);
}

impl<'a, A: Eq + Hash, B: Eq + Hash> Inventory<'a, A, B> {
    fn new() -> Inventory<'a, A, B> {
        Inventory {
            table: HashMap::new(),
        }
    }
}

impl<'a, A: Eq + Hash, B: Eq + Hash> Memory<A, B> for Inventory<'a, A, B> {

    fn get(&self, a: &A, b: &B) -> Option<&Transactions> {
        self.table.get(a)?.get(b)
    }

    fn set(&mut self, a: A, b: B, v: Transactions<'a>) {
        let inner = self.table.entry(a).or_insert(HashMap::new());
        inner.insert(b, v);
    }
}

fn main() {
    println!("Test");
}

But got errors with lifetime as:

   Compiling playground v0.0.1 (/playground)
error[E0308]: method not compatible with trait
  --> src/main.rs:43:5
   |
43 |     fn set(&mut self, a: A, b: B, v: Transactions<'a>) {
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
   |
   = note: expected fn pointer `fn(&mut Inventory<'a, A, B>, _, _, Transactions<'_>)`
              found fn pointer `fn(&mut Inventory<'a, A, B>, _, _, Transactions<'a>)`
note: the anonymous lifetime #2 defined on the method body at 43:5...
  --> src/main.rs:43:5
   |
43 | /     fn set(&mut self, a: A, b: B, v: Transactions<'a>) {
44 | |         let inner = self.table.entry(a).or_insert(HashMap::new());
45 | |         inner.insert(b, v);
46 | |     }
   | |_____^
note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 37:6
  --> src/main.rs:37:6
   |
37 | impl<'a, A: Eq + Hash, B: Eq + Hash> Memory<A, B> for Inventory<'a, A, B> {
   |      ^^

error: aborting due to previous error

This definition in the trait:

fn set(&mut self, a: A, b: B, v: Transactions<'_>);

says that the set function must accept a transactions with any lifetime, but when you implemented the trait, you instead wrote this:

fn set(&mut self, a: A, b: B, v: Transactions<'a>) { ...

Since 'a is defined on the impl block, this is saying that you only accept transactions with a specific lifetime. This does not match the trait.

If you define the trait so that you don't have to accept all lifetimes, but only a specific one, then it works:

trait Memory<'a, A: Eq + Hash, B: Eq + Hash> {
    fn get(&self, a: &A, b: &B) -> Option<&Transactions<'a>>;
    fn set(&mut self, a: A, b: B, v: Transactions<'a>);
}
impl<'a, A: Eq + Hash, B: Eq + Hash> Memory<'a, A, B> for Inventory<'a, A, B> {
    fn get(&self, a: &A, b: &B) -> Option<&Transactions<'a>> {
        self.table.get(a)?.get(b)
    }
    fn set(&mut self, a: A, b: B, v: Transactions<'a>) {
        let inner = self.table.entry(a).or_insert(HashMap::new());
        inner.insert(b, v);
    }
}

playground

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.