Skip to content

Commit

Permalink
Add and apply pedantic lints
Browse files Browse the repository at this point in the history
  • Loading branch information
dtrifuno committed Nov 22, 2023
1 parent a997f50 commit b5444a3
Show file tree
Hide file tree
Showing 8 changed files with 44 additions and 17 deletions.
13 changes: 13 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
3 changes: 3 additions & 0 deletions quickphf/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,6 @@ rust-version = "1.56"
[dependencies]
quickdiv = "0.1.1"
wyhash = "0.5.0"

[lints]
workspace = true
2 changes: 1 addition & 1 deletion quickphf/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
//! ```
#![no_std]
#![forbid(unsafe_code)]
#![allow(clippy::unreadable_literal)]

#[doc(hidden)]
pub mod examples;
Expand Down
4 changes: 2 additions & 2 deletions quickphf/src/raw_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -52,7 +52,7 @@ impl<K, V> RawPhfMap<K, V> {
///
/// 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
///
Expand Down
4 changes: 3 additions & 1 deletion quickphf_codegen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
1 change: 1 addition & 0 deletions quickphf_codegen/src/const_instantiable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
13 changes: 7 additions & 6 deletions quickphf_codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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, "]")
Expand Down
21 changes: 14 additions & 7 deletions quickphf_codegen/src/phf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<H: Eq + Hash>(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],
};
Expand All @@ -51,7 +55,7 @@ pub fn generate_phf<H: Eq + Hash>(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<H: Eq + Hash>(
Expand Down Expand Up @@ -85,9 +89,12 @@ fn try_generate_phf<H: Eq + Hash>(
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;
}
}
Expand Down Expand Up @@ -141,7 +148,7 @@ fn try_generate_phf<H: Eq + Hash>(
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 {
Expand Down

0 comments on commit b5444a3

Please sign in to comment.