Skip to content

Make Neighbor less incorrect#1273

Open
hildebrandmw wants to merge 2 commits into
mainfrom
mhildebr/neighbor
Open

Make Neighbor less incorrect#1273
hildebrandmw wants to merge 2 commits into
mainfrom
mhildebr/neighbor

Conversation

@hildebrandmw

Copy link
Copy Markdown
Contributor

Our current Neighbor type has several inter-related issues:

  1. It structurally requires Eq for the ID type, even though this is only needed when comparing equality. This makes it impossible to construct a Neighbor containing arbitrary external ID types and is the reason SearchOutputBuffer has to take tuples instead of Neighbors. This leads to duplicated sorting logic all over the code base.

    This structural requirement is preventing some aspects of ID handling cleanup.

  2. Its members are public.

  3. Its implementation of Ord is not consistent with its PartialEq method.

  4. Its implementation of Ord is explicitly called out as invalid.

This PR attempts to address many of these issues. Mainly, it turns Neighbor into a pretty simple tuple-like type with the various ordering methods implemented as free functions in neighbors::ord. Algorithms that need to sort Neighbors can pick and choose the correct ord::* methods needed, which in turn are quite greppable. These ord::* methods do not quite patch the issue of NaNs showing up in as distances, but at least we have a better way of documenting our requirements.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Refactors diskann::neighbor::Neighbor into a tuple-like aggregate with private fields and removes its problematic Ord/Eq semantics, replacing them with explicit comparator functions in neighbor::ord so algorithms can choose the intended ordering (and make NaN behavior easier to document).

Changes:

  • Simplifies Neighbor (private id/distance, accessors, tuple conversion) and moves ordering to neighbor::ord::* comparators.
  • Updates search, postprocess, and test code across crates to use Neighbor::id(), Neighbor::distance(), Neighbor::as_tuple(), and neighbor::ord comparators for sorting.
  • Improves test diagnostics by using assert_eq_verbose!/VerboseEq in several updated test assertions.

Reviewed changes

Copilot reviewed 26 out of 27 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
diskann/src/test/cmp.rs Minor update in verbose_eq! macro expansion formatting.
diskann/src/neighbor/queue.rs Updates fixed-capacity fast-path to compare by distance() instead of relying on Neighbor ordering.
diskann/src/neighbor/mod.rs Core refactor: tuple-like Neighbor, accessors, VerboseEq (tests), new ord comparator module, and updated tests.
diskann/src/graph/test/provider.rs Updates deletion filtering to use n.id() accessor.
diskann/src/graph/test/cases/range_search.rs Updates range-search test helpers and baselines to use accessors/as_tuple().
diskann/src/graph/test/cases/paged_search.rs Updates paged-search invariants/baselines to use accessors/as_tuple().
diskann/src/graph/test/cases/multihop.rs Updates multihop tests to use id() accessor.
diskann/src/graph/search/record.rs Updates visited-id extraction and recall accounting to use id() accessor.
diskann/src/graph/search/range_search.rs Updates range search logic/tests to use distance()/id() accessors.
diskann/src/graph/search/paged.rs Updates start-point filtering to use id() accessor.
diskann/src/graph/search/multihop_filter_search.rs Switches sorts to neighbor::ord::fast_distance and updates ID extraction via id().
diskann/src/graph/search/inline_filter_search.rs Switches matched-results sorting to neighbor::ord::fast_distance and updates ID extraction via id().
diskann/src/graph/internal/sorted_neighbors.rs Replaces sort_unstable/select_nth_unstable ordering with neighbor::ord::fast_distance to keep behavior explicit.
diskann/src/graph/index.rs Updates various ID extraction points and replaces sort_unstable() with sort_unstable_by(neighbor::ord::fast_distance).
diskann/src/graph/glue.rs Uses Neighbor::as_tuple() for SearchOutputBuffer::extend and updates start-point filtering via id().
diskann/src/flat/test/harness.rs Removes bespoke neighbor sorting logic and uses neighbor::ord::fast_distance_total; updates tuple mapping/filtering via accessors.
diskann-tools/src/utils/ground_truth.rs Replaces struct-literal neighbor construction and field access with Neighbor::new/accessors.
diskann-providers/src/test_utils/search_utils.rs Updates sorting to neighbor::ord comparators and switches distance/id reads to accessors.
diskann-providers/src/model/graph/provider/async_/postprocess.rs Updates deletion filtering and output extension to use accessors/as_tuple().
diskann-providers/src/model/graph/provider/async_/inmem/full_precision.rs Updates deletion filtering, vector reads, and extraction of ids/distances to use accessors.
diskann-providers/src/index/wrapped_async.rs Updates assertions to use id()/distance() accessors.
diskann-providers/src/index/diskann_async.rs Updates test sorting to neighbor::ord and replaces direct field mutation/access with accessor-based rebuilding.
diskann-label-filter/src/inline_beta_search/inline_beta_filter.rs Updates attribute lookup to use id() accessor and avoids reconstructing neighbors unnecessarily.
diskann-garnet/src/provider.rs Updates external ID mapping and push logic to use id()/distance() accessors.
diskann-disk/src/search/provider/disk_provider.rs Updates candidate-id extraction to use id() accessor.
diskann-bftree/src/provider.rs Updates vector reads and test assertions to use id() accessor.
diskann-benchmark/src/exhaustive/algos.rs Updates output ID fill to use id() accessor.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +326 to 330
// The following tests the behavior of NAN.
//
// This **must not** be taken as a guarantee of stability for this behavior.
let nan = Neighbor::new(3, 3.0);

@codecov-commenter

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 85.52036% with 32 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.49%. Comparing base (6caca35) to head (03966ef).

Files with missing lines Patch % Lines
...ilter/src/inline_beta_search/inline_beta_filter.rs 0.00% 10 Missing ⚠️
diskann/src/graph/test/cases/paged_search.rs 37.50% 5 Missing ⚠️
diskann/src/graph/test/cases/range_search.rs 66.66% 4 Missing ⚠️
...odel/graph/provider/async_/inmem/full_precision.rs 50.00% 3 Missing ⚠️
diskann-tools/src/utils/ground_truth.rs 57.14% 3 Missing ⚠️
diskann/src/graph/glue.rs 72.72% 3 Missing ⚠️
diskann/src/neighbor/mod.rs 97.14% 2 Missing ⚠️
diskann-providers/src/index/diskann_async.rs 88.88% 1 Missing ⚠️
diskann/src/graph/test/cases/multihop.rs 80.00% 1 Missing ⚠️

❌ Your patch status has failed because the patch coverage (85.52%) is below the target coverage (90.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1273      +/-   ##
==========================================
- Coverage   91.50%   91.49%   -0.01%     
==========================================
  Files         498      498              
  Lines       95522    95546      +24     
==========================================
+ Hits        87407    87424      +17     
- Misses       8115     8122       +7     
Flag Coverage Δ
miri 91.49% <85.52%> (-0.01%) ⬇️
unittests 91.46% <85.52%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
diskann-bftree/src/provider.rs 90.43% <100.00%> (ø)
diskann-disk/src/search/provider/disk_provider.rs 93.92% <100.00%> (ø)
diskann-garnet/src/provider.rs 80.35% <100.00%> (ø)
diskann-providers/src/index/wrapped_async.rs 60.12% <100.00%> (+0.24%) ⬆️
...ers/src/model/graph/provider/async_/postprocess.rs 100.00% <100.00%> (ø)
diskann-providers/src/test_utils/search_utils.rs 88.05% <100.00%> (+0.36%) ⬆️
diskann/src/flat/test/harness.rs 100.00% <100.00%> (ø)
diskann/src/graph/index.rs 95.74% <100.00%> (ø)
diskann/src/graph/internal/sorted_neighbors.rs 100.00% <100.00%> (ø)
diskann/src/graph/search/inline_filter_search.rs 97.91% <100.00%> (-0.05%) ⬇️
... and 16 more

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@hildebrandmw hildebrandmw changed the title Make Neighbor less cursed Make Neighbor less incorrect Jul 24, 2026
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.

3 participants