Why does using hashbrown's HashSet cause a lifetime issue but std's HashSet does not

⚓ Rust    📅 2025-09-08    👤 surdeus    👁️ 2      

surdeus

I'm struggling to understand why the following code:

use hashbrown::HashSet;
fn foo<'a>(_: &'a HashSet<String>, _: &mut HashSet<&'a str>) {}
fn bar() -> HashSet<String> {
    let a = HashSet::new();
    let mut b = HashSet::new();
    foo(&a, &mut b);
    a
}

returns the following compilation error:

error[E0505]: cannot move out of `a` because it is borrowed
 --> src/lib.rs:7:5
  |
4 |     let a = HashSet::new();
  |         - binding `a` declared here
5 |     let mut b = HashSet::new();
6 |     foo(&a, &mut b);
  |         -- borrow of `a` occurs here
7 |     a
  |     ^ move out of `a` occurs here
8 | }
  | - borrow might be used here, when `b` is dropped and runs the destructor for type `hashbrown::HashSet<&str>`
  |
help: consider cloning the value if the performance cost is acceptable
  |
6 |     foo(&a.clone(), &mut b);
  |           ++++++++

For more information about this error, try `rustc --explain E0505`.
error: could not compile `remote` (lib) due to 1 previous error

yet the following all compile:

Replace the exclusive HashSet from hashbrown with the HashSet from std:

use hashbrown::HashSet;
use std::collections::HashSet as StdHashSet;
fn foo<'a>(_: &'a HashSet<String>, _: &mut StdHashSet<&'a str>) {}
fn bar() -> HashSet<String> {
    let a = HashSet::new();
    let mut b = StdHashSet::new();
    foo(&a, &mut b);
    a
}

Drop b via core::mem::drop:

use hashbrown::HashSet;
fn foo<'a>(_: &'a HashSet<String>, _: &mut HashSet<&'a str>) {}
fn bar() -> HashSet<String> {
    let a = HashSet::new();
    let mut b = HashSet::new();
    foo(&a, &mut b);
    drop(b);
    a
}

Drop b via local scope:

use hashbrown::HashSet;
fn foo<'a>(_: &'a HashSet<String>, _: &mut HashSet<&'a str>) {}
fn bar() -> HashSet<String> {
    let a = HashSet::new();
    {
        let mut b = HashSet::new();
        foo(&a, &mut b);
    }
    a
}

Make the exclusive HashSet in foo shared:

use hashbrown::HashSet;
fn foo<'a>(_: &'a HashSet<String>, _: &HashSet<&'a str>) {}
fn bar() -> HashSet<String> {
    let a = HashSet::new();
    let mut b = HashSet::new();
    foo(&a, &mut b);
    a
}

6 posts - 3 participants

Read full topic

🏷️ Rust_feed