Skip to content

Conversation

@dhardy
Copy link
Member

@dhardy dhardy commented Feb 4, 2026

  • Added a CHANGELOG.md entry

Summary

Disable several features by default: std_rng, sys_rng and thread_rng

Motivation

This enables rand to use a smaller dependency tree by default: getrandom and chacha20 are no longer default-dependencies.

While a minor inconvenience to users, explicit opt-in to these features may help users evaluate which features they wish to use

Details

Related: #1545.

Additional rules enable these features in the playground and (as required) for examples.

Also, core::error::Error implementations no longer require feature std.

Copy link
Member

@newpavlov newpavlov left a comment

Choose a reason for hiding this comment

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

I am on the fence about this change. I think it makes sense to have the "default" RNG available by default, but it also makes sense to guard users against unintentionally pulling chacha20 and getrandom. So I would like to hear opinion of others.


#[cfg(feature = "std")]
impl std::error::Error for Error {}
impl core::error::Error for Error {}
Copy link
Member

Choose a reason for hiding this comment

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

I think it's better to do this change in a separate PR.

It also may be worth to review all uses of #[cfg(feature = "std")]. I think some of them can be changed to alloc.

Copy link
Member Author

Choose a reason for hiding this comment

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

I did review these uses; the ones in seq require f64::ln and the other case requires std::io.

Sure, I can move it to a new PR.

@dhardy
Copy link
Member Author

dhardy commented Feb 4, 2026

I am on the fence about this change.

As am I, hence asking for many reviewers to comment.

I think it makes sense to have the "default" RNG available by default

I am less sure that a thread-local rng should be enabled by default. It's why I opened #1545, but to quote @hpenne from that issue:

I'm not a fan of the thread_local RNGs. I really don't think global or thread local storage is something that should be encouraged or be an easier API to use than creating proper RNG instances. The disadvantages are many. Anyhow, that is probably too late to change now.

In this case, making rng() default to the OsRng instead of the normal random generator seems to me like doing something odd and surprising (defaulting to OsRng) to counter an inconvenient side effect of a design that is unfortunate in the first place (thread local storage).

So, maybe just disabling it by default is the best option?

Comment on lines 77 to +78
[dev-dependencies]
rand = { path = ".", features = ["chacha", "thread_rng"] }
Copy link
Member Author

Choose a reason for hiding this comment

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

This might be slightly problematic; e.g. we have CI tests like this which will now use additional features:

cargo test --target ${{ matrix.target }} --lib --tests --no-default-features

But, is there a better alternative? It's nice if examples just work.

Copy link
Member Author

Choose a reason for hiding this comment

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

(BTW "chacha" is not strictly required.)

Copy link
Member

@newpavlov newpavlov Feb 4, 2026

Choose a reason for hiding this comment

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

Usually I just gate tests on features instead of forcibly enabling them like that.

With chacha tests you also could add chacha20 as a dev dependency.

@newpavlov
Copy link
Member

newpavlov commented Feb 4, 2026

One radical option is to not expose any RNGs in rand at all and instead guide users towards RNG crates.

@dhardy
Copy link
Member Author

dhardy commented Feb 4, 2026

One radical option is to not expose any RNGs in rand at all in favor of separate RNG crates.

No thanks. "Batteries included" makes life easier for users; we already opted to include rand::rngs::Xoshiro* and ChaCha* for this reason.

I have proposed moving ThreadRng to a new crate in the past but it wasn't a popular idea.

@newpavlov
Copy link
Member

newpavlov commented Feb 4, 2026

"Batteries included" makes life easier for users

Well, according to this stance shouldn't you keep the thread_rng feature enabled by default?

I have proposed moving ThreadRng to a new crate in the past but it wasn't a popular idea.

Personally, I do support it. :)

@dhardy dhardy requested a review from josephlr February 4, 2026 12:31
@dhardy dhardy force-pushed the push-ksmykntpltnz branch from a8d3fbc to 3c9a37a Compare February 4, 2026 16:36
Copy link

@mstoeckl mstoeckl left a comment

Choose a reason for hiding this comment

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

  1. While a minor inconvenience to users, explicit opt-in to these features may help users evaluate which features they wish to use

    In general, I think people who want to consider which precise features to use (working on libraries, or relatively mature programs where unused features are expensive) would already look over the feature set and/or set no-default-features in Cargo.toml.

  2. I generally would prefer to not making breaking changes if there is no large benefit. This change could require reading the documentation and updating Cargo.toml for any light users of the library that want to update. The error message when building without the thread_rng feature is somewhat tricky:

error[E0423]: expected function, found module `rand::rng`
  --> examples/monty-hall.rs:80:19
   |
80 |     let mut rng = rand::rng();
   |                   ^^^^^^^^^ not a function

error[E0603]: module `rng` is private
  --> examples/print-next.rs:4:25
   |
 4 |     let mut rng = rand::rng();
   |                         ^^^ private module
   |
note: the module `rng` is defined here
  --> <path>/rand/src/lib.rs:80:1
   |
80 | mod rng;
   | ^^^^^^^
  1. I think the default feature set should be sufficient for the basic uses of the library. For example, with the default feature set it should be possible to write a simple program that randomly prints "heads" or "tails", or does a simple simulation like examples/monte_carlo.rs. This requires std_rng at minimum, but the current examples/ rely on thread_rng.

@dhardy
Copy link
Member Author

dhardy commented Feb 5, 2026

Thanks for the thoughts @mstoeckl. I am quite prepared to abandon this PR.

I would like to merge #1734 (or some equivalent); opinions welcome there too.

@dhardy dhardy closed this Feb 7, 2026
@dhardy dhardy mentioned this pull request Feb 7, 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