Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
654 changes: 416 additions & 238 deletions Cargo.lock

Large diffs are not rendered by default.

7 changes: 3 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ flamer = "0.5"
flate2 = { version = "1.1.9", default-features = false }
foreign-types-shared = "0.3.1"
gethostname = "1.0.2"
getrandom = { version = "0.3", features = ["std"] }
getrandom = { version = "0.4", features = ["std"] }
glob = "0.3"
half = "2"
hex = "0.4.3"
Expand Down Expand Up @@ -236,7 +236,7 @@ maplit = "1.0.2"
md-5 = "0.10.1"
memchr = "2.8.0"
memmap2 = "0.9.10"
mt19937 = "<=3.2" # upgrade it once rand is upgraded
mt19937 = "3.3"
num-complex = "0.4.6"
num-integer = "0.1.46"
num-traits = "0.2"
Expand All @@ -258,8 +258,7 @@ psm = "0.1"
pymath = { version = "0.2.0", features = ["mul_add", "malachite-bigint", "complex"] }
quote = "1.0.45"
radium = "1.1.1"
rand = "0.9"
rand_core = { version = "0.9", features = ["os_rng"] }
rand = "0.10"
result-like = "0.5.0"
rustix = { version = "1.1", features = ["event"] }
rustls = { version = "0.23.39", default-features = false }
Expand Down
3 changes: 3 additions & 0 deletions crates/common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,8 @@ lock_api = { workspace = true }
siphasher = { workspace = true }
num-complex = { workspace = true }

[target.'cfg(all(target_arch = "wasm32", target_os = "unknown"))'.dependencies]
getrandom = { workspace = true, features = ["wasm_js"] }

[lints]
workspace = true
2 changes: 1 addition & 1 deletion crates/literal/src/float.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ pub fn to_hex(value: f64) -> String {

#[test]
fn test_to_hex() {
use rand::Rng;
use rand::RngExt;
for _ in 0..20000 {
let bytes = rand::rng().random::<u64>();
let f = f64::from_bits(bytes);
Expand Down
2 changes: 1 addition & 1 deletion crates/stdlib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ pymath = { workspace = true }
xml = { workspace = true }

# random
rand_core = { workspace = true }
rand = { workspace = true }
mt19937 = { workspace = true }

# Crypto:
Expand Down
6 changes: 2 additions & 4 deletions crates/stdlib/src/random.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,14 @@ mod _random {
use crate::vm::{
PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
builtins::{PyInt, PyTupleRef},
convert::ToPyException,
function::OptionalOption,
types::{Constructor, Initializer},
};
use itertools::Itertools;
use malachite_bigint::{BigInt, BigUint, Sign};
use mt19937::MT19937;
use num_traits::{Signed, Zero};
use rand_core::{RngCore, SeedableRng};
use rand::{Rng, SeedableRng};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check what rand/RngCore/Rng methods are called in random.rs
rg -n "\.next_u32\|\.next_u64\|\.fill_bytes\|\.gen\b\|\.random\b\|rand::Rng\|rand::RngCore\|rand_core" crates/stdlib/src/random.rs

Repository: RustPython/RustPython

Length of output: 47


🏁 Script executed:

# Check if file exists and get the imports section
head -30 crates/stdlib/src/random.rs

Repository: RustPython/RustPython

Length of output: 851


🏁 Script executed:

# Search more broadly for any 'use' statements and RNG variable usage
rg -A 5 -B 5 "use rand" crates/stdlib/src/random.rs

Repository: RustPython/RustPython

Length of output: 387


🏁 Script executed:

# Look for where the RNG object is actually being used
rg -n "rng\|Rng\|RngCore" crates/stdlib/src/random.rs

Repository: RustPython/RustPython

Length of output: 47


🏁 Script executed:

# Read the full file to understand RNG usage
cat -n crates/stdlib/src/random.rs | head -100

Repository: RustPython/RustPython

Length of output: 4288


🏁 Script executed:

# Search for method calls on 'rng' variable without escaping
rg -n "\brng\." crates/stdlib/src/random.rs

Repository: RustPython/RustPython

Length of output: 530


🏁 Script executed:

# Check what MT19937 implements - search documentation or trait bounds
rg -n "MT19937" crates/stdlib/src/random.rs | head -20

Repository: RustPython/RustPython

Length of output: 249


🏁 Script executed:

# Check if there are any compiler errors or clippy warnings in the repo
# Try to find cargo check or build output
cd crates/stdlib && cargo check 2>&1 | grep -A 5 -B 5 "random\|Rng\|error\|warning" | head -50

Repository: RustPython/RustPython

Length of output: 151


🏁 Script executed:

# Search for MT19937::from_rng usage and documentation in mt19937 crate
rg -A 2 "from_rng" crates/stdlib/src/random.rs

Repository: RustPython/RustPython

Length of output: 160


🏁 Script executed:

# Check what trait MT19937 implements by searching for impl statements
rg "impl.*MT19937\|impl.*for.*MT19937" --type rust

Repository: RustPython/RustPython

Length of output: 47


🌐 Web query:

mt19937 Rust crate from_rng method parameter trait

💡 Result:

In the rand_core-based Rust ecosystem, the MT19937 generator’s “from_rng” style constructor is exposed via the rand_core::SeedableRng trait as: fn from_rng<R: RngCore>(rng: R) -> Result<Self, Error> So the parameter is a type parameter R constrained by rand_core::RngCore (an RNG producing values without error), passed by value (rng: R) and returns Result<Self, Error>. This is the generic trait signature in rand_core’s SeedableRng: [1]. Common related (infallible) variant in rand_mt: rand_mt’s Mt implements a method with signature: fn from_rng(rng: &mut R) -> Self where R: Rng +?Sized Here the parameter is &mut R, where R: rand::Rng (the infallible high-level RNG trait), and the method returns Self directly. [2] For the “mt19937” crate specifically (coolreader18/hiroshima-univ translation), its source shows implementations of rand_core::TryRng and rand_core::SeedableRng for MT19937 (but the exact from_rng signature there follows the rand_core::SeedableRng trait; the trait provides from_rng generically). [3][4] Therefore, when you ask “mt19937 Rust crate from_rng method parameter trait”, the trait bound for from_rng is R: RngCore in rand_core::SeedableRng. [1] If instead you are referring to rand_mt’s Mt::from_rng convenience API, the parameter uses &mut R where R: rand::Rng +?Sized. [2]

Citations:


🏁 Script executed:

# Check if RngCore is imported elsewhere or re-exported
rg "RngCore\|rand_core" crates/stdlib/src/random.rs

Repository: RustPython/RustPython

Length of output: 47


🏁 Script executed:

# Check if there's a re-export of RngCore in the rand crate imports
rg "use rand" crates/stdlib/src/random.rs -A 1 -B 1

Repository: RustPython/RustPython

Length of output: 185


🏁 Script executed:

# Try to check Cargo.toml to see rand version and features
cat crates/stdlib/Cargo.toml | grep -A 5 -B 5 "rand"

Repository: RustPython/RustPython

Length of output: 325


🏁 Script executed:

# Search for any build output or error logs
find . -name "*.log" -type f 2>/dev/null | head -5

Repository: RustPython/RustPython

Length of output: 47


Replace Rng with RngCore in the import statement.

The MT19937::from_rng() call at line 62 uses the SeedableRng::from_rng() trait method, which requires a generic parameter bound by RngCore, not Rng. The current import (use rand::{Rng, SeedableRng}) is missing RngCore and cannot satisfy the trait bound for from_rng(). While next_u32() at line 82 is a concrete method on MT19937 itself (not requiring a trait import), the trait-based from_rng() method cannot be properly used without RngCore in scope.

Proposed fix
-    use rand::{Rng, SeedableRng};
+    use rand_core::RngCore;
+    use rand::SeedableRng;

or equivalently:

-    use rand::{Rng, SeedableRng};
+    use rand::{SeedableRng};
+    use rand_core::RngCore;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/stdlib/src/random.rs` at line 18, Import the correct trait so
SeedableRng::from_rng can use an RngCore source: replace the current import use
rand::{Rng, SeedableRng} with use rand::{RngCore, SeedableRng} (so
MT19937::from_rng / SeedableRng::from_rng has the required RngCore bound); no
changes needed for MT19937::next_u32 since that is a concrete method.

use rustpython_vm::types::DefaultConstructor;

#[pyattr]
Expand Down Expand Up @@ -60,8 +59,7 @@ mod _random {
let key = if key.is_empty() { &[0] } else { key.as_slice() };
MT19937::new_with_slice_seed(key)
}
None => MT19937::try_from_os_rng()
.map_err(|e| std::io::Error::from(e).to_pyexception(vm))?,
None => MT19937::from_rng(&mut rand::rng()),
};
Ok(())
}
Expand Down
3 changes: 2 additions & 1 deletion crates/vm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ ast = ["ruff_python_ast", "ruff_text_size"]
codegen = ["rustpython-codegen", "ast"]
parser = ["ast"]
serde = ["dep:serde"]
wasmbind = ["rustpython-common/wasm_js", "chrono/wasmbind", "wasm-bindgen"]
wasmbind = ["rustpython-common/wasm_js", "chrono/wasmbind", "getrandom/wasm_js", "wasm-bindgen"]

[dependencies]
rustpython-compiler = { workspace = true, optional = true }
Expand Down Expand Up @@ -142,6 +142,7 @@ features = [

[target.'cfg(all(target_arch = "wasm32", target_os = "unknown"))'.dependencies]
wasm-bindgen = { workspace = true, optional = true }
getrandom = { workspace = true, features = ["wasm_js"] }

[build-dependencies]
glob = { workspace = true }
Expand Down
2 changes: 1 addition & 1 deletion crates/wasm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ freeze-stdlib = ["rustpython-vm/freeze-stdlib", "rustpython-pylib/freeze-stdlib"
no-start-func = []

[dependencies]
rustpython-common = { workspace = true }
rustpython-common = { workspace = true, features = ["wasm_js"] }
rustpython-pylib = { workspace = true, optional = true }
rustpython-stdlib = { workspace = true, default-features = false, optional = true }
# make sure no threading! otherwise wasm build will fail
Expand Down
Loading