weak-table-rs icon indicating copy to clipboard operation
weak-table-rs copied to clipboard

WeakHashSet::retain doesn't iterate over all valid items

Open m-demare opened this issue 2 years ago • 0 comments

Hi, I'm having this issue where sometimes WeakHashSet::retain skips some valid items.

For example, the following code fails about 1 out of 5 times I run it (I think the randomness is probably related to the randomness in a HashSet's iteration order):

use std::{
    fmt::Write,
    rc::{Rc, Weak},
};

use weak_table::WeakHashSet;

fn main() {
    let mut set = WeakHashSet::default();
    let mut v = Vec::new();

    let n = 5;

    for i in 0..n {
        let rc = Rc::new(i);
        v.push(rc.clone());
        set.insert(rc);
    }

    let rc = Rc::new(n);
    set.insert(rc.clone());

    print_set(&set, "before drop");

    drop(v);

    print_set(&set, "after drop");

    let mut retain_calls = Vec::new();
    set.retain(|val| {
        retain_calls.push(val);
        false
    });

    assert!(
        retain_calls.iter().any(|v| v == &n.into()),
        "retain was not called on {n}"
    );
}

fn print_set(set: &WeakHashSet<Weak<u32>>, name: &str) {
    let elems = set.iter().fold(String::new(), |mut f, val| {
        let _ = write!(f, "{val}, ");
        f
    });
    println!("elems ({name}): {elems}");
}

If you need any further info, please tell me. Thanks for making this incredibly useful crate!

m-demare avatar Nov 28 '23 02:11 m-demare