Skip to content

Deprecate rand::rngs::mock module and StepRng#1634

Merged
dhardy merged 4 commits intomasterfrom
push-szklqvxtvrvw
Apr 25, 2025
Merged

Deprecate rand::rngs::mock module and StepRng#1634
dhardy merged 4 commits intomasterfrom
push-szklqvxtvrvw

Conversation

@dhardy
Copy link
Member

@dhardy dhardy commented Apr 23, 2025

  • Added a CHANGELOG.md entry

Summary

Deprecate rand::rngs::mock module and StepRng

Motivation

We have had many reports of unexpected outputs when using StepRng with other random algorithms (especially Uniform / random_range): #628, #1020, #1303, #1578, #1633. These reports are due to people assuming that StepRng::new(0, 1) will immediately cycle over all possible outputs of a small range; it won't because our uniform range algorithms use variations on widening multiply, not division-with-remainder.

Moreover, our algorithms should only be expected to yield outputs of the expected distribution when fed random inputs. As such, the only expectation which may be met when using a StepRng as input is that all outputs will be valid outputs. (Unless someone were to test all possible outputs until StepRng loops — get back to me when your test suite has finished counting to u64::MAX! But even then, assumptions wouldn't hold to algorithms potentially consuming multiple random values in sequence.)

Further motivation is that we can't think of a good reason to use StepRng over something like SmallRng Pcg* or Xoshiro*, which are easy to implement and yield pseudo-random output. The rand tests show some good reasons to want a StepRng: in order to test how a randomised algorithm behaves with fixed input. This of course only has value where the exact behaviour of the algorithm is known, which is usually limited to the test code in the module where it is defined since this behaviour is usually not specified.

In other words, StepRng should not be used except when testing a randomised algorithm implementation (thus all the issues linked above are mis-uses).

Details

StepRng and the mock module are deprecated, awaiting removal in the next breaking release.

@dhardy dhardy requested a review from newpavlov April 23, 2025 07:03
@dhardy dhardy force-pushed the push-szklqvxtvrvw branch from 91daf72 to fdaf424 Compare April 23, 2025 07:46
@newpavlov
Copy link
Member

I think we can simply remove benchmarks for StepRng.

@dhardy
Copy link
Member Author

dhardy commented Apr 23, 2025

I think we can simply remove benchmarks for StepRng.

Yes...

The more questionable case are the tests in src/rng.rs and src/rngs/reseeding.rs. Some of those appear to want a ConstRng.

Then there is a usage in uniform_float.rs which actually uses stepped output (lowering_max_rng).

Maybe we should keep StepRng (but make it private to the crate)?

Note: I updated the motivation above (last two paragraphs). I also note one usage in rand_distr (testing the Triangular distribution), but we don't need to care much about that (we could copy the StepRng code to that crate).

@newpavlov
Copy link
Member

The easiest solution would be to just use #[allow(deprecated)] on the affected test modules. In future it may be worth to add const initialization methods to some of small PRNGs and rewrite tests accordingly

@dhardy
Copy link
Member Author

dhardy commented Apr 23, 2025

add const initialization methods to some of small PRNGs

This is not why those tests use StepRng. They use it in order to feed specific inputs to the random algorithms being tested. This use-case is a valid use of StepRng, but one that's only applicable when writing random algorithms (as in rand and rand_distr, though the latter only has one use-case).

@newpavlov
Copy link
Member

newpavlov commented Apr 23, 2025

They use it in order to feed specific inputs to the random algorithms being tested.

For this we can use an internal mock RNG which just reads values from a static array. Something like this:

pub MockRng32 {
    values: &'static [u32],
    pos: usize,
}

Or indeed keep StepRng and make it private (which is equivalent to removal for external users).

@dhardy dhardy force-pushed the push-szklqvxtvrvw branch from f38ce9b to e560ced Compare April 24, 2025 08:13
@dhardy
Copy link
Member Author

dhardy commented Apr 24, 2025

Tests still generate warnings like this:

warning: use of deprecated constant `rngs::mock::tests::test_bool`
   --> src/rngs/mock.rs:99:5
    |
99  | /     fn test_bool() {
100 | |         use crate::{distr::StandardUniform, Rng};
...   |
105 | |         assert_eq!(&result, &[false, true, false, true, false, true]);
106 | |     }
    | |_____^
    |
    = note: `#[warn(deprecated)]` on by default

There's already #![allow(deprecated)] at the top of the file; additional annotations don't help. I'm guessing this may be a side effect of the #[test] annotation.

Shall I just delete the tests?

@newpavlov
Copy link
Member

I think, yes. It does not look like such tests add anything useful (I assume stability of distributions using a proper PRNG is tested in relevant modules).

@dhardy dhardy merged commit 86262ac into master Apr 25, 2025
15 checks passed
@dhardy dhardy deleted the push-szklqvxtvrvw branch April 25, 2025 07:38
@dhardy dhardy mentioned this pull request Jul 20, 2025
dhardy added a commit that referenced this pull request Jul 20, 2025
# Summary

Requested by @aleb in #1646.

## [0.9.2 — 2025-07-20]
### Deprecated
- Deprecate `rand::rngs::mock` module and `StepRng` generator (#1634)

### Additions
- Enable `WeightedIndex<usize>` (de)serialization (#1646)
apoelstra added a commit to apoelstra/rust-secp256k1 that referenced this pull request Sep 1, 2025
The docs for rand::StepRng say "deprecated without replacement". In fact,
according to rust-random/rand#1634 which removed
them, the "replacements" are SmallRng, or Pcg*, or Xoshiro*. That is,
the replacement is a separate crate.

`rand` exposes Xoshiro256PlusPlus as "SmallRng", if you enable a feature
that enables the extra dep. Unfortunately we cannot do this for tests
only, because Cargo does not support optional dev-dependencies. (Ten year
old issue: rust-lang/cargo#1596 .. last comment
three years ago.)

Directly use rand_xoshiro instead.
chain-forgexcr45 added a commit to chain-forgexcr45/rust-secp256k1 that referenced this pull request Sep 28, 2025
The docs for rand::StepRng say "deprecated without replacement". In fact,
according to rust-random/rand#1634 which removed
them, the "replacements" are SmallRng, or Pcg*, or Xoshiro*. That is,
the replacement is a separate crate.

`rand` exposes Xoshiro256PlusPlus as "SmallRng", if you enable a feature
that enables the extra dep. Unfortunately we cannot do this for tests
only, because Cargo does not support optional dev-dependencies. (Ten year
old issue: rust-lang/cargo#1596 .. last comment
three years ago.)

Directly use rand_xoshiro instead.
william2332-limf added a commit to william2332-limf/rust-secp256k1 that referenced this pull request Oct 2, 2025
The docs for rand::StepRng say "deprecated without replacement". In fact,
according to rust-random/rand#1634 which removed
them, the "replacements" are SmallRng, or Pcg*, or Xoshiro*. That is,
the replacement is a separate crate.

`rand` exposes Xoshiro256PlusPlus as "SmallRng", if you enable a feature
that enables the extra dep. Unfortunately we cannot do this for tests
only, because Cargo does not support optional dev-dependencies. (Ten year
old issue: rust-lang/cargo#1596 .. last comment
three years ago.)

Directly use rand_xoshiro instead.
@yancyribbens
Copy link

Hello,

Is there any suggestion for downstream projects that use this now deprecated feature in tests? It seems like there is some admission that it's useful for testing yet the only solution seems to be to flag with allow deprecated which doesn't seem like a good long-term solution.

@newpavlov
Copy link
Member

newpavlov commented Oct 8, 2025

Users should use a proper PRNG, e.g. rand::rngs::SmallRng or rand_xoshiro directly if you want reproducibility across targets.

@yancyribbens
Copy link

Thanks, using SmallRng::seed_from_u64(1) works for determinism. I'm not sure how I came to use StepRng in the first place.

@yancyribbens
Copy link

Thanks, using SmallRng::seed_from_u64(1) works for determinism. I'm not sure how I came to use StepRng in the first place.

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