Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

undocumented api change: choose_multiple_weighted now returns an error when insufficient nonzero items are available #1619

Open
sporksmith opened this issue Mar 20, 2025 · 2 comments
Labels
X-bug Type: bug report

Comments

@sporksmith
Copy link

Summary

Prior to 0.9.0, choose_multiple_weighted, if fewer nonzero items were available than requested, the items that were available would be returned (including items with 0 weight). At 0.9.0 the error InsufficientNonZero is returned instead.

While the behavior in this case is unspecified in the doc-comments, and the new behavior may be an improvement, this is effectively a breaking change that isn't included in the changelog. In the arti project this resulted in subtle breakage that took on the order of 10-20 engineer-hours to debug. https://gitlab.torproject.org/tpo/core/arti/-/issues/1902

Incidentally, at 0.9.0, choose_multiple_weighted will still return fewer items than requested if no items had zero weight.

Code sample

At 0.8.5:

use rand::prelude::*;

fn main() {
    let mut rng = thread_rng();
    for choices in [vec![1, 2, 3], vec![0, 1, 2], vec![1, 2]] {
        println!(
            "{:?}",
            choices
                .choose_multiple_weighted(&mut rng, 3, |x| *x)
                .map(|x| x.collect::<Vec<_>>())
        );
    }
}

output:

Ok([3, 1, 2])
Ok([1, 2, 0])
Ok([2, 1])

At 0.9.0:

diff --git a/src/main.rs b/src/main.rs
index 56770b2..8e26c10 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,7 +1,7 @@
 use rand::prelude::*;
 
 fn main() {
-    let mut rng = thread_rng();
+    let mut rng = rand::rng();
     for choices in [vec![1, 2, 3], vec![0, 1, 2], vec![1, 2]] {
         println!(
             "{:?}",

output:

Ok([1, 2, 3])
Err(InsufficientNonZero)
Ok([1, 2])
@sporksmith sporksmith added the X-bug Type: bug report label Mar 20, 2025
@sporksmith
Copy link
Author

sporksmith commented Mar 20, 2025

This is mostly intended as a request to update the changelog and/or otherwise notify users of the breaking change, though API-wise it seems odd that it's willing to return fewer items than requested as long as none have zero weight. It seems like either both cases should result in errors, or neither should.

@sporksmith
Copy link
Author

Actually, after reading the doc comment again it includes "If all of the weights are equal, even if they are all zero, each element has an equal likelihood of being selected.", which seems to contradict the new behavior of returning an error. (I also verified that it returns an error when all weights are zero)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
X-bug Type: bug report
Projects
None yet
Development

No branches or pull requests

1 participant