Michał Hanusek
Michał Hanusek

Reputation: 323

Passing variables to function and lifetime

I want passing HashMap and element - Foo to my function. I don't understand variables lifetimes. Please help.

Result : error[E0623]: lifetime mismatch

use std::collections::HashMap;

#[derive(Debug)]
struct Foo<'a> {
    x: &'a i32,
}

fn add_to_map<'l>(map: &'l HashMap<u32, &'l Foo>,  element : &'l Foo) 
{
    map.insert(1, element);
}

fn main()
{
    let mut map: HashMap<u32, &Foo> = HashMap::new();

    let v = 5;
    let mut f = Foo { x: &v };
    add_to_map(&map, &f);
    println!("now f is {:?}", f);
}

Compiler output:

error[E0623]: lifetime mismatch
  --> src/main.rs:11:19
   |
9  | fn add_to_map<'l>(map: &'l HashMap<u32, &'l Foo>,  element : &'l Foo) 
   |                                             ---                  --- these two types are declared with different lifetimes...
10 | {
11 |     map.insert(1, element);
   |                   ^^^^^^^ ...but data from `element` flows into `map` here

error: aborting due to previous error

Upvotes: 1

Views: 224

Answers (1)

Benjamin Bannier
Benjamin Bannier

Reputation: 58547

9  | fn add_to_map<'l>(map: &'l HashMap<u32, &'l Foo>,  element : &'l Foo) 
   |                                             ---                  --- these two types are declared with different lifetimes...
10

Foo<'a> appears twice here ('a is the lifetime of x inside Foo). Since you didn't give explicit values for the lifetime 'a, the compiler will assume that the Foo as the HashMap value and element Foo will have different lifetimes 'a. This approach works well in general.

However, you want to actually insert element into map which requires matching lifetimes. The compiler rejects your code since the lifetimes do not match. You need to be explicit about the lifetimes of the x inside Foo, e.g.,

// Verbose.
fn add_to_map<'l>(map: &'l mut HashMap<u32, &'l Foo<'l>>,  element : &'l Foo<'l>) 

You do not need to give an explicit lifetime of map itself since the compiler can verify at the callsite that map lives at least as long as element,

// Slightly less verbose.
fn add_to_map<'l>(map: &mut HashMap<u32, &'l Foo<'l>>,  element : &'l Foo<'l>) 

Note that in any case map needs to be mut in add_to_map.

Upvotes: 4

Related Questions