Skip to content

fix: reject M < 2 at compile time (closes #32) - #35

Merged
danielhuici merged 3 commits into
reverseame:apotheosis2from
Dani-giron:m1-guard-m-generic
Sep 1, 2026
Merged

danielhuici merged 3 commits into
reverseame:apotheosis2from
Dani-giron:m1-guard-m-generic

Conversation

@Dani-giron

Copy link
Copy Markdown

Summary

Hnsw::random_level() computes the insertion level with -ln(uniform) / ln(M). With M=1, ln(1) = 0, so the division produces f64::INFINITY, which casts to usize::MAX instead of panicking. The first insert() then calls initialize(usize::MAX), whose loop tries to allocate that many layers, consuming all available memory until the process is killed. M=1 is a valid value at the type level, nothing rejected it before construction.

Changes

  • src/controllers/hnsw.rs: Hnsw::new() now has a compile-time const { assert!(M >= 2, ...) }. M=1 (or M=0) no longer compiles, with an error pointing at the exact Hnsw::new() instantiation that violates it. Apotheosis::new() calls Hnsw::new() internally, so this covers both entry points with a single guard.

Confirmed with Ricardo that the correct boundary is M > 1 (equivalently M >= 2): M=0 does not diverge (insertion_level comes out 0, a different and unrelated correctness issue with zero-capacity neighbor arrays, not covered by this fix), only M=1 produces the ln(M)=0 divergence.

Test plan

Verified locally with the same commands CI runs: cargo clippy --all-targets --all-features -- -D warnings clean, cargo fmt --check clean, and all 44 tests passing with the default M.

Also verified both directions manually: a scratch binary instantiating Apotheosis<_, _, 1, 2, 10> failed to compile with the assert's message, pointing at the Hnsw::new() call site; a normal build with default generics (M=16) compiled and ran unaffected.

@danielhuici
danielhuici merged commit 052c545 into reverseame:apotheosis2 Sep 1, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants