Recommended Free Tools
With current rand 0.10.3, obtain the thread-local generator with rand::rng(), bind it as mutable, and call random() or random_range(). The older-looking thread_rng() name belongs to earlier API versions, so check the rand version in your Cargo.toml before copying examples.
use rand::RngExt;
fn main() {
let mut rng = rand::rng();
let coin_flip: bool = rng.random();
let die_roll: i32 = rng.random_range(1..=6);
println!("{coin_flip}, {die_roll}");
}
This article explains setup, ranges, repeated generation, thread boundaries, seeding, security limits, errors, and the older thread_rng spelling.
Check which rand API your project uses
Rust code is version-sensitive because the accessor changed. The current rand::rng() documentation and ThreadRng documentation are for rand 0.10.3. The old spelling thread_rng() may still appear in examples written for earlier releases.
Inspect Cargo.toml and the lockfile
[dependencies]
rand = { version = "0.10.3", features = ["thread_rng"] }
Use the version selected by your project rather than blindly replacing it. The current thread-local accessor and convenience functions are exposed through the thread_rng crate feature. If your dependency is pinned to an older major or minor release, open that release’s documentation and use its API.
#1 Best Overall
Why the name matters
In rand 0.10.3, rand::rng() returns a handle to the current thread’s ThreadRng. Code that calls rand::thread_rng() can fail to compile when it is moved to a release whose public API uses rng().
Generate random values with a local ThreadRng
Complete example
use rand::RngExt;
fn main() {
let mut rng = rand::rng();
let byte: u8 = rng.random();
let fraction: f64 = rng.random();
let die: i32 = rng.random_range(1..=6);
println!("byte: {byte}");
println!("fraction: {fraction}");
println!("die: {die}");
}
The type annotation tells random() which supported type to produce. In this example it generates an unsigned byte, an f64, and an integer die result.
Why the binding must be mutable
Random generation advances the generator state, so methods are called through a mutable handle. Declare it with let mut rng; otherwise Rust reports that a mutable borrow is required.
Generate booleans and other values
use rand::RngExt;
fn main() {
let mut rng = rand::rng();
let enabled: bool = rng.random();
let sample: u32 = rng.random();
println!("enabled={enabled}, sample={sample}");
}
The random() method uses the destination type to select the distribution supported for that type. Keep the annotation when inference cannot determine the type.
Free tools Windows power users keep installed
One-click scans. No signup required.
Generate a number in a range
Inclusive and exclusive bounds
use rand::RngExt;
fn main() {
let mut rng = rand::rng();
let inclusive = rng.random_range(1..=6); // 1 through 6
let exclusive = rng.random_range(0..10); // 0 through 9
println!("{inclusive} {exclusive}");
}
1..=6 includes both endpoints, which is useful for a six-sided die. 0..10 excludes 10, producing values from 0 through 9. The range’s element type is inferred from its bounds and the receiving variable.
Ranges for other numeric types
use rand::RngExt;
fn main() {
let mut rng = rand::rng();
let percentage: f64 = rng.random_range(0.0..=100.0);
let offset: i16 = rng.random_range(-20..=20);
println!("{percentage:.2}% ({offset})");
}
Choose bounds that are valid for the target type. An empty or invalid range is a programming error; validate values before constructing a range supplied by user input.
Rank #2
Reuse one handle for repeated calls
For a loop or a function that generates many values, create one local handle and reuse it:
use rand::RngExt;
fn main() {
let mut rng = rand::rng();
let mut rolls = [0_i32; 10];
for roll in &mut rolls {
*roll = rng.random_range(1..=6);
}
println!("{rolls:?}");
}
The rand documentation recommends a local binding for repeated calls because it avoids an initialization check on every use. Keep the handle in the scope that performs the work instead of repeatedly calling the accessor.
Shuffle a collection
use rand::seq::SliceRandom;
fn main() {
let mut rng = rand::rng();
let mut cards = ["A", "K", "Q", "J"];
cards.shuffle(&mut rng);
println!("{cards:?}");
}
Pass the mutable handle to APIs such as shuffle. The exact trait import can vary with the rand release, so follow the versioned sequence documentation if your compiler reports an unresolved import.
Use convenience functions for one-off values
The rand::random() documentation provides a shorthand for common types, and rand::random_range() is shorthand for calling rng().random_range(range).
fn main() {
let coin: bool = rand::random();
let roll: i32 = rand::random_range(1..=6);
println!("{coin}, {roll}");
}
These functions are convenient for isolated calls. For a loop, prefer one mutable local handle so the thread-local lookup and initialization check are not repeated.
Understand ThreadRng’s thread and lifecycle rules
It belongs to the current thread
ThreadRng is a reference to a lazily initialized thread-local generator. Its handle is neither Send nor Sync, so do not move it into another thread or store it in a structure that must cross thread boundaries. Create a separate handle inside each worker:
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Rank #3
use std::thread;
use rand::RngExt;
fn main() {
let worker = thread::spawn(|| {
let mut rng = rand::rng();
let value: u32 = rng.random();
value
});
println!("{}", worker.join().expect("worker panicked"));
}
Move ordinary generated values between threads after generation, not the ThreadRng handle itself.
Initialization, reseeding, and fork
The generator is initialized lazily and seeded from SysRng. The current documentation describes reseeding after every 64 kB of output, but it does not automatically reseed after a process fork. If your program forks, explicitly reseed in the child according to the versioned rand API.
Initial seeding can panic if the operating-system random source (SysRng) fails. Treat that as a startup failure and investigate the host’s entropy source rather than assuming the generator returned a predictable fallback.
Reentrancy and interrupts
Calls are not reentrant-safe. Do not call the same generator from an interrupt or signal context unless you can rule out concurrent use of that generator.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Repair Windows errors before they cause bigger problems3Fix the driver behind crashes, sound loss and screen glitchesChoose the right randomness source
ThreadRng for general application randomness
ThreadRng is convenient, fast for general-purpose use, thread-local, automatically seeded, and periodically reseeded. Those properties make it a practical default for simulations, randomized UI behavior, sampling, and games.
SysRng when you need the operating-system source directly
The Rand RNG module overview describes SysRng as a stateless interface over the operating system’s random source and identifies it as the source used to seed ThreadRng. Use it when your design calls for direct operating-system randomness rather than a cached thread-local generator. See the Rand RNG module documentation.
Seeded generators for reproducible sequences
An explicitly seeded generator is appropriate for repeatable tests or simulations. Standard generators are deterministic, but the RNG module documentation warns that sequences are not portable across all releases and platforms. Record the rand version, algorithm, and seed when reproducibility matters.
Security qualifications you should not skip
Rand describes the current thread generator as ChaCha-based, fast, and reasonably secure, but leaves it to the user to decide whether it meets a particular threat model. It does not provide additional protection for in-memory state and is not required to zero that memory at process or thread exit.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →Therefore, do not make blanket claims that ThreadRng is suitable for every cryptographic or secret-handling task. Define the attacker, lifetime, process model, and state-protection requirements first; use SysRng or a specialized design when those requirements call for it.
Troubleshoot common compile and runtime problems
cannot find function thread_rng
Cause: The example targets an older API or the needed feature is disabled.
Fix: Check the selected rand version, enable the thread_rng feature where appropriate, and use let mut rng = rand::rng(); for rand 0.10.3.
no method named random or random_range
Cause: The extension trait is not in scope.
Fix: Add use rand::RngExt; for the current documented API. If your project uses an older rand release, consult that release’s trait name and method documentation.
Borrowing or mutability errors
Cause: The handle was declared with let rng or borrowed immutably.
Fix: Declare it as let mut rng and pass &mut rng to APIs such as shuffle.
Thread-safety trait errors
Cause: A ThreadRng handle is being moved into another thread or shared across threads.
Fix: Construct rand::rng() inside each thread and send only the resulting data.
Unexpected panic during startup
Cause: Initial seeding through SysRng failed.
Fix: Check operating-system entropy availability, container or sandbox restrictions, and host errors. Do not silently substitute a predictable source for security-sensitive work.
Or skip the browser setup
If your Rust project also needs website screenshots for documentation, testing, or generated reports, ScreenshotNeo provides a one-request API instead of maintaining browser automation:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo API documentation for parameters and response details. Before capture, it accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing result. It also offers an MCP server with take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. The Free plan includes 1,000 screenshots per month without a card; paid plans start at $5 for 3,000 screenshots. Create a free ScreenshotNeo account.
The Bottom Line
For rand 0.10.3, use a mutable rand::rng() handle with RngExt::random and random_range. Keep the handle within its thread, verify the crate version before using older thread_rng() examples, and choose SysRng or a seeded generator when your threat model or reproducibility requirements demand it.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

