diff --git a/Cargo.toml b/Cargo.toml index 1a8cb41..d406671 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,18 +1,21 @@ [package] name = "hashconsing" -version = "1.6.0" -authors = ["Adrien Champion "] +version = "1.7.0" +authors = [ + "Adrien Champion ", + "Leni Aniva ", +] description = "A hash consing library." documentation = "https://docs.rs/hashconsing" homepage = "https://github.com/AdrienChampion/hashconsing" repository = "https://github.com/AdrienChampion/hashconsing" readme = "README.md" categories = [ - "caching", - "compression", - "concurrency", - "data-structures", - "memory-management", + "caching", + "compression", + "concurrency", + "data-structures", + "memory-management", ] keywords = ["hashconsing", "hash", "consing", "sharing", "caching"] license = "MIT/Apache-2.0" diff --git a/README.md b/README.md index bfce847..9e4b5bd 100644 --- a/README.md +++ b/README.md @@ -12,16 +12,16 @@ efficient as uses Rust's `HashMap`s, not a custom built structure. For more details see [the documentation][doc]. -# Known projects using `hashconsing` - -- [kinō][kino], a model-checker for transition systems -- [hoice][hoice], a machine-learning-based predicate synthesizer for horn clauses - # License MIT/Apache-2.0 -# Contributors +# Developers + +- [@adrienchampion](https://github.com/adrienchampion), original author +- [@lenianiva](https://github.com/lenianiva), maintainer + +## Contributors - [@alex-ozdemir](https://github.com/alex-ozdemir) diff --git a/src/coll.rs b/src/coll.rs index 85692ef..2855128 100644 --- a/src/coll.rs +++ b/src/coll.rs @@ -178,7 +178,7 @@ where } /// An iterator visiting all elements. #[inline] - pub fn iter(&self) -> ::std::collections::hash_set::Iter> { + pub fn iter<'a>(&'a self) -> ::std::collections::hash_set::Iter<'a, HConsed> { self.set.iter() } } @@ -322,12 +322,14 @@ where } /// An iterator visiting all elements. #[inline] - pub fn iter(&self) -> ::std::collections::hash_map::Iter, V> { + pub fn iter<'a>(&'a self) -> ::std::collections::hash_map::Iter<'a, HConsed, V> { self.map.iter() } /// An iterator visiting all elements. #[inline] - pub fn iter_mut(&mut self) -> ::std::collections::hash_map::IterMut, V> { + pub fn iter_mut<'a>( + &'a mut self, + ) -> ::std::collections::hash_map::IterMut<'a, HConsed, V> { self.map.iter_mut() } } @@ -437,7 +439,7 @@ mod hash { impl HashU64 { /// Checks that a slice of bytes has the length of a `usize`. Only active /// in debug. - #[cfg(debug)] + #[cfg(debug_assertions)] #[inline(always)] fn test_bytes(bytes: &[u8]) { if bytes.len() != 8 { @@ -451,13 +453,13 @@ mod hash { } /// Checks that a slice of bytes has the length of a `usize`. Only active /// in debug. - #[cfg(not(debug))] + #[cfg(not(debug_assertions))] #[inline(always)] fn test_bytes(_: &[u8]) {} } impl Hasher for HashU64 { fn finish(&self) -> u64 { - unsafe { ::std::mem::transmute(self.buf) } + u64::from_ne_bytes(self.buf) } fn write(&mut self, bytes: &[u8]) { Self::test_bytes(bytes); diff --git a/src/hash_coll.rs b/src/hash_coll.rs index 37d2623..a79d87c 100644 --- a/src/hash_coll.rs +++ b/src/hash_coll.rs @@ -42,11 +42,11 @@ //! be the natural one, *e.g.* `HConSet`. //! //! However, since `Term` is really an alias for `HConsed`, then if we wanted to declare -//! `HConSet` as an alias for `HashSet` we would get `type HConSet = HashSet< HConsed -//! >` (omitting the custom hasher). That is, our sets would have type `HConSet`, which is -//! not very pretty. We could just define an alias though: `type TermSet = HConSet`, but it -//! turns out it's better to wrap the actual set in a `struct` anyway. Mostly to be able to define -//! `new` and `with_capacity` without relying on a trait (users would need to import) to do that. +//! `HConSet` as an alias for `HashSet` we would get `type HConSet = HashSet>` +//! (omitting the custom hasher). That is, our sets would have type `HConSet`, which is not +//! very pretty. We could just define an alias though: `type TermSet = HConSet`, but it turns +//! out it's better to wrap the actual set in a `struct` anyway. Mostly to be able to define `new` +//! and `with_capacity` without relying on a trait (users would need to import) to do that. //! //! So actually `HConsed` types automatically implement the internal `trait HashConsed { type Inner; //! }`. The sole purpose of this trait (currently) is to pass the inner type implicitly thanks to a @@ -322,7 +322,7 @@ where { /// An iterator visiting all elements. #[inline] - pub fn iter(&self) -> ::std::collections::hash_set::Iter> { + pub fn iter<'a>(&'a self) -> ::std::collections::hash_set::Iter<'a, HConsed> { self.set.iter() } } @@ -520,12 +520,14 @@ where { /// An iterator visiting all elements. #[inline] - pub fn iter(&self) -> ::std::collections::hash_map::Iter, V> { + pub fn iter<'a>(&'a self) -> ::std::collections::hash_map::Iter<'a, HConsed, V> { self.map.iter() } /// An iterator visiting all elements. #[inline] - pub fn iter_mut(&mut self) -> ::std::collections::hash_map::IterMut, V> { + pub fn iter_mut<'a>( + &'a mut self, + ) -> ::std::collections::hash_map::IterMut<'a, HConsed, V> { self.map.iter_mut() } } @@ -643,7 +645,7 @@ mod hash { impl HashU64 { /// Checks that a slice of bytes has the length of a `usize`. Only active /// in debug. - #[cfg(debug)] + #[cfg(debug_assertions)] #[inline(always)] fn test_bytes(bytes: &[u8]) { if bytes.len() != 8 { @@ -657,13 +659,13 @@ mod hash { } /// Checks that a slice of bytes has the length of a `usize`. Only active /// in debug. - #[cfg(not(debug))] + #[cfg(not(debug_assertions))] #[inline(always)] fn test_bytes(_: &[u8]) {} } impl Hasher for HashU64 { fn finish(&self) -> u64 { - let block: u64 = unsafe { ::std::mem::transmute(self.buf) }; + let block: u64 = u64::from_ne_bytes(self.buf); // Multiply by random 64-bit prime to distribute block.wrapping_mul(0xDA5DF7A7BD02F2C7u64) } diff --git a/src/hash_coll/hashers.rs b/src/hash_coll/hashers.rs index c7f5e3d..dc77af3 100644 --- a/src/hash_coll/hashers.rs +++ b/src/hash_coll/hashers.rs @@ -50,7 +50,7 @@ pub mod p_hash { impl Hasher { /// Checks that a slice of bytes has the length of a `usize`. Only active /// in debug. - #[cfg(debug)] + #[cfg(debug_assertions)] #[inline(always)] fn test_bytes(bytes: &[u8]) { if bytes.len() != 8 { @@ -64,13 +64,13 @@ pub mod p_hash { } /// Checks that a slice of bytes has the length of a `usize`. Only active /// in debug. - #[cfg(not(debug))] + #[cfg(not(debug_assertions))] #[inline(always)] fn test_bytes(_: &[u8]) {} } impl StdHasherExt for Hasher { fn finish(&self) -> u64 { - let block: u64 = unsafe { ::std::mem::transmute(self.buf) }; + let block: u64 = u64::from_ne_bytes(self.buf); // Multiply by random 64-bit prime to distribute block.wrapping_mul(0xDA5DF7A7BD02F2C7u64) } @@ -112,7 +112,7 @@ pub mod id_hash { impl Hasher { /// Checks that a slice of bytes has the length of a `usize`. Only active /// in debug. - #[cfg(debug)] + #[cfg(debug_assertions)] #[inline(always)] fn test_bytes(bytes: &[u8]) { if bytes.len() != 8 { @@ -126,13 +126,13 @@ pub mod id_hash { } /// Checks that a slice of bytes has the length of a `usize`. Only active /// in debug. - #[cfg(not(debug))] + #[cfg(not(debug_assertions))] #[inline(always)] fn test_bytes(_: &[u8]) {} } impl StdHasherExt for Hasher { fn finish(&self) -> u64 { - unsafe { ::std::mem::transmute(self.buf) } + u64::from_ne_bytes(self.buf) } fn write(&mut self, bytes: &[u8]) { Self::test_bytes(bytes); diff --git a/src/lib.rs b/src/lib.rs index 4c56359..ecb0876 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -213,6 +213,8 @@ //! [lazy static]: https://crates.io/crates/lazy_static //! (lazy_static library on crates.io) +#![deny(warnings)] + use std::{ borrow::Borrow, cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd}, @@ -239,7 +241,7 @@ mod test; /// - `$hash_builder:expr` optional hash builder, an /// implementation of [`std::hash::BuildHasher`] ; /// - `$typ:typ,` type being hashconsed (the underlying type, not the -/// hashconsed one) ; +/// hashconsed one) ; #[macro_export] macro_rules! consign { ( @@ -353,7 +355,7 @@ impl Eq for HConsed {} impl PartialOrd for HConsed { #[inline] fn partial_cmp(&self, other: &Self) -> Option { - self.uid.partial_cmp(&other.uid) + Some(self.cmp(other)) } } impl Ord for HConsed { @@ -445,7 +447,7 @@ impl Eq for WHConsed {} impl PartialOrd for WHConsed { #[inline] fn partial_cmp(&self, other: &Self) -> Option { - self.uid.partial_cmp(&other.uid) + Some(self.cmp(other)) } } impl Ord for WHConsed { @@ -672,7 +674,7 @@ pub trait HashConsign: Sized { /// Reserves capacity for at least `additional` more elements. fn reserve(self, additional: usize); } -impl<'a, T: Hash + Eq + Clone, S: BuildHasher> HashConsign for &'a mut HConsign { +impl HashConsign for &mut HConsign { fn mk_is_new(self, elm: T) -> (HConsed, bool) { // If the element is known and upgradable return it. if let Some(hconsed) = self.get(&elm) { @@ -745,7 +747,7 @@ macro_rules! get { }; } -impl<'a, T: Hash + Eq + Clone> HashConsign for &'a RwLock> { +impl HashConsign for &RwLock> { /// If the element is already in the consign, only read access will be /// requested. fn mk_is_new(self, elm: T) -> (HConsed, bool) {