diff --git a/src/lib.rs b/src/lib.rs index 4d673e98..91f0cce9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -238,7 +238,7 @@ missing_docs, missing_debug_implementations, unreachable_pub, - intra_doc_link_resolution_failure + broken_intra_doc_links )] #![warn(rust_2018_idioms)] #![allow(clippy::cognitive_complexity)] diff --git a/src/map.rs b/src/map.rs index 7975dbf2..bdf89f89 100644 --- a/src/map.rs +++ b/src/map.rs @@ -1815,11 +1815,14 @@ where let current_value = unsafe { current_value.deref() }; if no_replacement { - // the key is not absent, so don't update - // because of `no_replacement`, we don't use the - // new value, so we need to clean it up + // the key is not absent, so don't update because of + // `no_replacement`, we don't use the new value, so we need to clean + // it up and return it back to the caller // safety: we own value and did not share it - let _ = unsafe { value.into_owned() }; + return PutResult::Exists { + current: current_value, + not_inserted: unsafe { value.into_owned().into_box() }, + }; } else { // update the value in the existing node let now_garbage = n.value.swap(value, Ordering::SeqCst, guard); @@ -1902,11 +1905,14 @@ where // next epoch, which won't arrive until after we drop our guard. let current_value = unsafe { current_value.deref() }; if no_replacement { - // the key is not absent, so don't update - // because of `no_replacement`, we don't use the - // new value, so we need to clean it up + // the key is not absent, so don't update because of + // `no_replacement`, we don't use the new value, so we need to clean + // it up and return it back to the caller // safety: we own value and did not share it - let _ = unsafe { value.into_owned() }; + return PutResult::Exists { + current: current_value, + not_inserted: unsafe { value.into_owned().into_box() }, + }; } else { let now_garbage = tree_node.node.value.swap(value, Ordering::SeqCst, guard); diff --git a/tests/regressions.rs b/tests/regressions.rs new file mode 100644 index 00000000..9536a030 --- /dev/null +++ b/tests/regressions.rs @@ -0,0 +1,18 @@ +use flurry::{epoch::pin, *}; +use rand::{thread_rng, Rng}; + +#[test] +fn issue90() { + #[cfg(not(miri))] + const ITERATIONS: usize = 100_000; + #[cfg(miri)] + const ITERATIONS: usize = 100; + + let mut rng = thread_rng(); + let map = HashMap::new(); + let g = pin(); + for _ in 0..ITERATIONS { + let el = rng.gen_range(0, 1000); + let _ = map.try_insert(el, el, &g); + } +}