diff --git a/Cargo.toml b/Cargo.toml index b2ec384..f8aa238 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,3 +3,16 @@ resolver = "2" exclude = ["benchmarks"] members = ["quickphf", "quickphf_codegen"] + +[workspace.lints.rust] +unsafe_code = "forbid" + +[workspace.lints.clippy] +pedantic = "warn" +cast_lossless = "allow" +cast_possible_truncation = "allow" +cast_precision_loss = "allow" +cast_sign_loss = "allow" +doc_markdown = "allow" +must_use_candidate = "allow" +module_name_repetitions = "allow" \ No newline at end of file diff --git a/quickphf/Cargo.toml b/quickphf/Cargo.toml index bc9e20e..fbbf206 100644 --- a/quickphf/Cargo.toml +++ b/quickphf/Cargo.toml @@ -14,3 +14,6 @@ rust-version = "1.56" [dependencies] quickdiv = "0.1.1" wyhash = "0.5.0" + +[lints] +workspace = true diff --git a/quickphf/src/lib.rs b/quickphf/src/lib.rs index 277e4e4..2419961 100644 --- a/quickphf/src/lib.rs +++ b/quickphf/src/lib.rs @@ -46,7 +46,7 @@ //! ``` #![no_std] -#![forbid(unsafe_code)] +#![allow(clippy::unreadable_literal)] #[doc(hidden)] pub mod examples; diff --git a/quickphf/src/raw_map.rs b/quickphf/src/raw_map.rs index ddac403..e17b68c 100644 --- a/quickphf/src/raw_map.rs +++ b/quickphf/src/raw_map.rs @@ -6,7 +6,7 @@ use core::marker::PhantomData; use quickdiv::DivisorU64; -use crate::shared::*; +use crate::shared::{get_bucket, get_index, hash_key, hash_pilot_value}; /// An immutable hash table constructed at compile time with perfect hashing which does not store its keys. #[derive(Debug)] @@ -52,7 +52,7 @@ impl RawPhfMap { /// /// If `key` is not one of the keys that was used when constructing the map, /// `get` will silently return an arbitrary value. If robustness to invalid - /// keys is needed, use a [PhfMap][crate::PhfMap] instead. + /// keys is needed, use a [`PhfMap`][crate::PhfMap] instead. /// /// # Panics /// diff --git a/quickphf_codegen/Cargo.toml b/quickphf_codegen/Cargo.toml index 424cd94..9095787 100644 --- a/quickphf_codegen/Cargo.toml +++ b/quickphf_codegen/Cargo.toml @@ -11,10 +11,12 @@ categories = ["algorithms", "data-structures"] keywords = ["hashing", "mphf", "hashmap", "codegen"] rust-version = "1.56" - [dependencies] quickdiv = "0.1.1" quickphf = { version = "0.1.0", path = "../quickphf" } +[lints] +workspace = true + [[bin]] name = "generate_examples" diff --git a/quickphf_codegen/src/const_instantiable.rs b/quickphf_codegen/src/const_instantiable.rs index cc78bf6..b36701e 100644 --- a/quickphf_codegen/src/const_instantiable.rs +++ b/quickphf_codegen/src/const_instantiable.rs @@ -4,6 +4,7 @@ use core::fmt; /// implementing type in a `const` context. pub trait ConstInstantiable { /// Print a `const` expression that can be used to instantiate this value. + #[allow(clippy::missing_errors_doc)] fn fmt_const_new(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result; } diff --git a/quickphf_codegen/src/lib.rs b/quickphf_codegen/src/lib.rs index 29b5dbc..d149335 100644 --- a/quickphf_codegen/src/lib.rs +++ b/quickphf_codegen/src/lib.rs @@ -78,9 +78,10 @@ //! impl quickphf_codegen::DebugInstantiable for PositionType {} //! ``` //! -//! 2. Otherwise, the user has to provide a custom implementation. For example, the following struct has -//! private fields and thus its values cannot be instantiated using the `{}` syntax, but provides -//! a `new` constructor that is a `const fn`. Thus, given +//! 2. Otherwise, the user has to provide a custom implementation. For example, +//! the following struct has private fields and thus its values cannot be +//! instantiated using the `{}` syntax, but provides a `new` constructor +//! that is a `const fn`. Thus, given //! //! ```ignore //! #[derive(Debug, Hash, PartialEq, Eq)] @@ -237,7 +238,7 @@ impl<'a, K: ConstInstantiable, V: ConstInstantiable> CodeWriter<'a, K, V> { for &idx in &self.phf.map { if prev_entry { - write!(f, ", ")? + write!(f, ", ")?; } else { prev_entry = true; } @@ -280,12 +281,12 @@ impl<'a, K: ConstInstantiable, V: ConstInstantiable> CodeWriter<'a, K, V> { let mut prev_entry = false; for entry in entries { if prev_entry { - write!(f, ", ")? + write!(f, ", ")?; } else { prev_entry = true; } - entry.fmt_const_new(f)? + entry.fmt_const_new(f)?; } write!(f, "]") diff --git a/quickphf_codegen/src/phf.rs b/quickphf_codegen/src/phf.rs index 183907b..b0fc26b 100644 --- a/quickphf_codegen/src/phf.rs +++ b/quickphf_codegen/src/phf.rs @@ -3,7 +3,7 @@ use core::hash::Hash; use quickdiv::DivisorU64; -use quickphf::shared::*; +use quickphf::shared::{get_bucket, get_index, hash_key, hash_pilot_value}; const MAX_ALPHA: f64 = 0.99; const MIN_C: f64 = 1.5; @@ -22,13 +22,17 @@ pub struct Phf { } /// Generate a perfect hash function using PTHash for the given collection of keys. +/// +/// # Panics +/// +/// Panics if `entries` contains a duplicate key. pub fn generate_phf(entries: &[H]) -> Phf { if entries.is_empty() { return Phf { seed: 0, map: vec![], // These vectors have to be non-empty so that the number of buckets and codomain - // length are non-zero, and thus can be used to instantiate precomputed divisors. + // length are non-zero, and thus can be used as divisors. pilots_table: vec![0], free: vec![0], }; @@ -51,7 +55,7 @@ pub fn generate_phf(entries: &[H]) -> Phf { (1..) .find_map(|n| try_generate_phf(entries, buckets_len, codomain_len, n << 32)) - .unwrap() + .expect("failed to resolve hash collision") } fn try_generate_phf( @@ -85,9 +89,12 @@ fn try_generate_phf( let e1 = &window[1]; if e0.hash == e1.hash && e0.bucket == e1.bucket { - if entries[e0.idx] == entries[e1.idx] { - panic!("duplicate keys at indices {} and {}", e0.idx, e1.idx); - } + assert!( + entries[e0.idx] != entries[e1.idx], + "duplicate keys at indices {} and {}", + e0.idx, + e1.idx + ); return None; } } @@ -141,7 +148,7 @@ fn try_generate_phf( let pilot_hash = hash_pilot_value(pilot); // Check for collisions with items from previous buckets. - for entry in bucket_entries.iter() { + for entry in bucket_entries { let destination = get_index(entry.hash, pilot_hash, codomain_len); if map[destination as usize] != EMPTY {