Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
[package]
name = "hashconsing"
version = "1.6.0"
authors = ["Adrien Champion <adrien.champion@email.com>"]
version = "1.7.0"
authors = [
"Adrien Champion <adrien.champion@email.com>",
"Leni Aniva <aniva@stanford.edu>",
]
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"
Expand Down
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
14 changes: 8 additions & 6 deletions src/coll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ where
}
/// An iterator visiting all elements.
#[inline]
pub fn iter(&self) -> ::std::collections::hash_set::Iter<HConsed<T::Inner>> {
pub fn iter<'a>(&'a self) -> ::std::collections::hash_set::Iter<'a, HConsed<T::Inner>> {
self.set.iter()
}
}
Expand Down Expand Up @@ -322,12 +322,14 @@ where
}
/// An iterator visiting all elements.
#[inline]
pub fn iter(&self) -> ::std::collections::hash_map::Iter<HConsed<T::Inner>, V> {
pub fn iter<'a>(&'a self) -> ::std::collections::hash_map::Iter<'a, HConsed<T::Inner>, V> {
self.map.iter()
}
/// An iterator visiting all elements.
#[inline]
pub fn iter_mut(&mut self) -> ::std::collections::hash_map::IterMut<HConsed<T::Inner>, V> {
pub fn iter_mut<'a>(
&'a mut self,
) -> ::std::collections::hash_map::IterMut<'a, HConsed<T::Inner>, V> {
self.map.iter_mut()
}
}
Expand Down Expand Up @@ -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 {
Expand All @@ -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);
Expand Down
24 changes: 13 additions & 11 deletions src/hash_coll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@
//! be the natural one, *e.g.* `HConSet<Term>`.
//!
//! However, since `Term` is really an alias for `HConsed<RTerm>`, then if we wanted to declare
//! `HConSet` as an alias for `HashSet` we would get `type HConSet<Inner> = HashSet< HConsed<Inner>
//! >` (omitting the custom hasher). That is, our sets would have type `HConSet<RTerm>`, which is
//! not very pretty. We could just define an alias though: `type TermSet = HConSet<RTerm>`, 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<Inner> = HashSet<HConsed<Inner>>`
//! (omitting the custom hasher). That is, our sets would have type `HConSet<RTerm>`, which is not
//! very pretty. We could just define an alias though: `type TermSet = HConSet<RTerm>`, 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
Expand Down Expand Up @@ -322,7 +322,7 @@ where
{
/// An iterator visiting all elements.
#[inline]
pub fn iter(&self) -> ::std::collections::hash_set::Iter<HConsed<T::Inner>> {
pub fn iter<'a>(&'a self) -> ::std::collections::hash_set::Iter<'a, HConsed<T::Inner>> {
self.set.iter()
}
}
Expand Down Expand Up @@ -520,12 +520,14 @@ where
{
/// An iterator visiting all elements.
#[inline]
pub fn iter(&self) -> ::std::collections::hash_map::Iter<HConsed<T::Inner>, V> {
pub fn iter<'a>(&'a self) -> ::std::collections::hash_map::Iter<'a, HConsed<T::Inner>, V> {
self.map.iter()
}
/// An iterator visiting all elements.
#[inline]
pub fn iter_mut(&mut self) -> ::std::collections::hash_map::IterMut<HConsed<T::Inner>, V> {
pub fn iter_mut<'a>(
&'a mut self,
) -> ::std::collections::hash_map::IterMut<'a, HConsed<T::Inner>, V> {
self.map.iter_mut()
}
}
Expand Down Expand Up @@ -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 {
Expand All @@ -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)
}
Expand Down
12 changes: 6 additions & 6 deletions src/hash_coll/hashers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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)
}
Expand Down Expand Up @@ -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 {
Expand All @@ -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);
Expand Down
12 changes: 7 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand All @@ -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 {
(
Expand Down Expand Up @@ -353,7 +355,7 @@ impl<T> Eq for HConsed<T> {}
impl<T> PartialOrd for HConsed<T> {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.uid.partial_cmp(&other.uid)
Some(self.cmp(other))
}
}
impl<T> Ord for HConsed<T> {
Expand Down Expand Up @@ -445,7 +447,7 @@ impl<T> Eq for WHConsed<T> {}
impl<T> PartialOrd for WHConsed<T> {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.uid.partial_cmp(&other.uid)
Some(self.cmp(other))
Comment thread
lenianiva marked this conversation as resolved.
}
}
impl<T> Ord for WHConsed<T> {
Expand Down Expand Up @@ -672,7 +674,7 @@ pub trait HashConsign<T: Hash>: Sized {
/// Reserves capacity for at least `additional` more elements.
fn reserve(self, additional: usize);
}
impl<'a, T: Hash + Eq + Clone, S: BuildHasher> HashConsign<T> for &'a mut HConsign<T, S> {
impl<T: Hash + Eq + Clone, S: BuildHasher> HashConsign<T> for &mut HConsign<T, S> {
fn mk_is_new(self, elm: T) -> (HConsed<T>, bool) {
// If the element is known and upgradable return it.
if let Some(hconsed) = self.get(&elm) {
Expand Down Expand Up @@ -745,7 +747,7 @@ macro_rules! get {
};
}

impl<'a, T: Hash + Eq + Clone> HashConsign<T> for &'a RwLock<HConsign<T>> {
impl<T: Hash + Eq + Clone> HashConsign<T> for &RwLock<HConsign<T>> {
/// If the element is already in the consign, only read access will be
/// requested.
fn mk_is_new(self, elm: T) -> (HConsed<T>, bool) {
Expand Down