Skip to content

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

@sporksmith

Description

@sporksmith

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])

Metadata

Metadata

Assignees

No one assigned

    Labels

    X-bugType: bug report

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions