Skip to content

Move dependencies to workspace for stdlib crate#7747

Merged
youknowone merged 2 commits intoRustPython:mainfrom
fanninpm:move-deps-to-workspace-for-stdlib
May 4, 2026
Merged

Move dependencies to workspace for stdlib crate#7747
youknowone merged 2 commits intoRustPython:mainfrom
fanninpm:move-deps-to-workspace-for-stdlib

Conversation

@fanninpm
Copy link
Copy Markdown
Contributor

@fanninpm fanninpm commented May 1, 2026

cc @ShaharNaveh

Conflicts with #7744. Rebased after #7744 was merged.

Summary by CodeRabbit

  • Chores
    • Consolidated dependency management to workspace-level configuration for improved consistency and maintainability across the project.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 1, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 12715665-edc8-4238-bf81-83cb3e611607

📥 Commits

Reviewing files that changed from the base of the PR and between 57c491f and 8dea442.

📒 Files selected for processing (2)
  • Cargo.toml
  • crates/stdlib/Cargo.toml

📝 Walkthrough

Walkthrough

Root workspace dependencies are consolidated with explicit version and feature pins for hashing, cryptography, compression, TLS implementations, GUI, and system utilities. Crate-level dependencies in crates/stdlib are migrated to reference these workspace declarations via workspace = true.

Changes

Dependency Version Consolidation

Layer / File(s) Summary
Workspace Dependency Pins
Cargo.toml
Root workspace declares explicit versions and features for 47+ crates across hashing (adler32, crc32fast), crypto (hmac, sha-1, sha2, sha3, blake2, md-5, pbkdf2), compression (flate2, bzip2, libz-sys, liblzma-sys), TLS stacks (rustls\* family, openssl\* family, aws-lc-rs), certificates (x509-cert, x509-parser, webpki-roots), GUI (tcl-sys, tk-sys via git), and utilities (base64, uuid, ucd, gethostname, memmap2, etc.).
Crate-Level Migration
crates/stdlib/Cargo.toml
~49 dependency declarations across main and platform-scoped targets switch from pinned versions to workspace = true, including hash/crypto (digest, blake2, pbkdf2), compression (adler32, crc32fast, flate2, bzip2), random (rand_core, mt19937), TLS backends (optional openssl\* and rustls\* sets), system/platform crates (mac_address, uuid, gethostname, socket2), and GUI (tcl-sys, tk-sys). Feature specifications and optional flags are preserved.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • ShaharNaveh
  • youknowone

Poem

🐰 Carrots of code grow tall and true,
When versions sprout from one garden view,
The workspace roots hold firm and deep,
No scattered pins—just order to keep!
Hashes and ciphers, bundled with care,
A unified feast beyond compare. 🥕✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: moving dependencies from the stdlib crate into the workspace, which aligns with the primary modifications across Cargo.toml files.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get your free trial and get 200 agent minutes per Slack user (a $50 value).


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 7/8 reviews remaining, refill in 7 minutes and 30 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

@fanninpm fanninpm force-pushed the move-deps-to-workspace-for-stdlib branch 2 times, most recently from 60c99ec to e6c16a3 Compare May 2, 2026 23:57
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
Cargo.toml (1)

271-275: Consider explicitly pinning git dependencies with immutable rev for clarity.

Lines 271 and 275 use tag = "v0.2.0" without explicit commit hash pinning. While Cargo.lock already resolves and pins these to commit 198fc35b1f18f4eda401f97a641908f321b1403a, explicitly specifying rev in Cargo.toml makes the immutable reference explicit and improves supply-chain clarity:

-tcl-sys = { git = "https://github.com/arihant2math/tkinter.git", tag = "v0.2.0" }
+tcl-sys = { git = "https://github.com/arihant2math/tkinter.git", rev = "198fc35b1f18f4eda401f97a641908f321b1403a" }

-tk-sys = { git = "https://github.com/arihant2math/tkinter.git", tag = "v0.2.0" }
+tk-sys = { git = "https://github.com/arihant2math/tkinter.git", rev = "198fc35b1f18f4eda401f97a641908f321b1403a" }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Cargo.toml` around lines 271 - 275, Update the git dependency declarations
for tcl-sys and tk-sys to include the immutable commit hash: locate the entries
referencing tag = "v0.2.0" for the tcl-sys and tk-sys dependencies and add rev =
"198fc35b1f18f4eda401f97a641908f321b1403a" (or replace the tag with that rev) so
the Cargo.toml explicitly pins the exact commit used by Cargo.lock for better
supply-chain clarity.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@Cargo.toml`:
- Around line 271-275: Update the git dependency declarations for tcl-sys and
tk-sys to include the immutable commit hash: locate the entries referencing tag
= "v0.2.0" for the tcl-sys and tk-sys dependencies and add rev =
"198fc35b1f18f4eda401f97a641908f321b1403a" (or replace the tag with that rev) so
the Cargo.toml explicitly pins the exact commit used by Cargo.lock for better
supply-chain clarity.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 134e9704-089a-498a-aed0-a11ed2fc8098

📥 Commits

Reviewing files that changed from the base of the PR and between 60c99ec and e6c16a3.

📒 Files selected for processing (2)
  • Cargo.toml
  • crates/stdlib/Cargo.toml
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/stdlib/Cargo.toml

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@crates/stdlib/Cargo.toml`:
- Line 65: Remove the unused dependency entry "rand = { workspace = true }" from
the crates/stdlib Cargo.toml; this dependency is not referenced by the crate
(code uses rand_core and getrandom) so delete that line and then run cargo
check/cargo build to verify the unused_dependency lint is resolved.
- Line 64: The crate uses getrandom::SysRng in crates/stdlib/src/random.rs but
the workspace dependency for getrandom only enables std; update the getrandom
dependency entry (the getrandom = { workspace = true } line) to enable the
sys_rng feature as well (e.g., add features ["std","sys_rng"]) so SysRng is
available at compile time.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 12ab32a4-e80f-4bee-9166-6b78f0b6e5c0

📥 Commits

Reviewing files that changed from the base of the PR and between e6c16a3 and 57c491f.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (4)
  • Cargo.toml
  • crates/literal/src/float.rs
  • crates/stdlib/Cargo.toml
  • crates/stdlib/src/random.rs

Comment thread crates/stdlib/Cargo.toml Outdated
Comment thread crates/stdlib/Cargo.toml Outdated
@fanninpm
Copy link
Copy Markdown
Contributor Author

fanninpm commented May 3, 2026

@coderabbitai Why is the wasm32-unknown-unknown build failing?

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 3, 2026

Tip

For best results, initiate chat on the files or code changes.

@fanninpm The most likely cause is the wasm_js feature being unconditionally enabled on getrandom at the workspace level in Cargo.toml.

Here's what's happening:

The wasm32-unknown-unknown target is not automatically supported by getrandom because the target name alone doesn't indicate whether JavaScript is available. Support is excluded from the default configuration because the JS backend requires wasm-bindgen, which can break builds on non-web WASM platforms.

To enable getrandom's functionality on wasm32-unknown-unknown via Crypto.getRandomValues, you enable the wasm_js crate feature — but the official docs strongly warn against enabling this feature in libraries, since "it is known to break non-Web WASM builds."

In this PR, getrandom is declared in [workspace.dependencies] with features = ["wasm_js"]. This means the feature is applied unconditionally across the entire workspace, not just for web-targeted builds. The only acceptable exception is if your crate already unconditionally depends on wasm-bindgen or js-sys on "unknown" WASM targets. If RustPython's wasm32-unknown-unknown build is not a wasm-bindgen-based web build, this will cause a compile failure.

The fix is to conditionalize the wasm_js feature so it's only applied when building for a web/wasm-bindgen context. This is typically done using a [target.'cfg(target_arch = "wasm32")'.dependencies] block in the relevant crate's Cargo.toml rather than at the workspace level, or by gating the feature behind a Cargo feature flag. For example, in Cargo.toml:

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

And keeping the workspace declaration without the wasm_js feature:

[workspace.dependencies]
getrandom = { version = "0.4" }  # no wasm_js here

@fanninpm
Copy link
Copy Markdown
Contributor Author

fanninpm commented May 3, 2026

@coderabbitai Why is the wasm32-unknown-unknown build still failing?

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 3, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

Let me inspect the current state of the relevant files to identify the remaining issue.


🏁 Script executed:

#!/bin/bash
# Check current getrandom config in workspace Cargo.toml
grep -n "getrandom\|wasm_js\|wasm-bindgen\|js-sys" Cargo.toml

echo "---stdlib Cargo.toml---"
grep -n "getrandom\|wasm_js\|wasm-bindgen\|rand\b" crates/stdlib/Cargo.toml

echo "---wasm crate if any---"
fd "Cargo.toml" --search-path . -x grep -l "wasm32-unknown-unknown\|wasm_js\|getrandom" {} \;

echo "---CI config---"
fd -e yml -e yaml . .github/workflows/ --exec grep -l "wasm32\|wasm" {} \;

Length of output: 510


🏁 Script executed:

#!/bin/bash
# Check context around line 54 in workspace Cargo.toml (what target block?)
sed -n '40,70p' Cargo.toml

echo "=== wasm32_without_js Cargo.toml ==="
cat example_projects/wasm32_without_js/rustpython-without-js/Cargo.toml

echo "=== vm/Cargo.toml getrandom context ==="
grep -n -A2 -B2 "getrandom\|wasm_js" crates/vm/Cargo.toml

echo "=== common/Cargo.toml getrandom context ==="
grep -n -A2 -B2 "getrandom\|wasm_js" crates/common/Cargo.toml

echo "=== CI wasm job steps ==="
grep -n -A5 -B2 "wasm32\|wasm-pack\|wasm_js\|without.js" .github/workflows/ci.yaml | head -80

Length of output: 4599


@fanninpm There's a second issue beyond the wasm_js feature placement. The root cause of the continued failure is in example_projects/wasm32_without_js/rustpython-without-js/.

Here's what's happening:

  1. getrandom 0.4 requires an explicit backend for wasm32-unknown-unknown. The wasm32-unknown-unknown target is not automatically supported since, from the target name alone, it cannot be deduced which JavaScript interface should be used (or if JavaScript is available at all). With getrandom 0.4, you must pick a backend — either wasm_js, a getrandom_backend RUSTFLAGS cfg, or the unsupported feature.

  2. The without-js example project still pins getrandom = "0.3" (its own direct dep), but it pulls in rustpython-vm via a path dependency, which resolves getrandom = { workspace = true } to 0.4 from the main workspace. That transitive getrandom 0.4 has no backend configured for wasm32-unknown-unknown → compilation fails.

  3. In rare scenarios where you're compiling for wasm32-unknown-unknown but getrandom's functionality is not actually used by your code, you can enable the unsupported backend, which always returns Err(Error::UNSUPPORTED). This is exactly the case for the "without-js" build — it doesn't call getrandom at runtime.

The fix is to update example_projects/wasm32_without_js/rustpython-without-js/Cargo.toml to override the transitive getrandom 0.4 dependency with the unsupported backend:

[dependencies]
# Updated from 0.3 to match workspace; "unsupported" backend is correct for
# wasm32-unknown-unknown without JS — getrandom is not called at runtime here.
getrandom = { version = "0.4", features = ["unsupported"] }
rustpython-vm = { path = "../../../crates/vm", default-features = false, features = ["compiler"] }

Alternatively, you can use a .cargo/config.toml in the example_projects/wasm32_without_js/ directory to set the backend via RUSTFLAGS:

# example_projects/wasm32_without_js/.cargo/config.toml
[target.wasm32-unknown-unknown]
rustflags = ['--cfg', 'getrandom_backend="unsupported"']

The config.toml approach is cleaner because it doesn't require the example project to explicitly depend on getrandom at all, but either approach will resolve the compilation failure.

@fanninpm
Copy link
Copy Markdown
Contributor Author

fanninpm commented May 3, 2026

@coderabbitai Why is the wasm32-unknown-unknown build still failing now?

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 3, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

Let me inspect the current state of the relevant files to identify what's still causing the failure.


🏁 Script executed:

#!/bin/bash
echo "=== workspace Cargo.toml getrandom/wasm context ==="
grep -n "getrandom\|wasm_js\|wasm-bindgen\|rand\b\|rand_core\|rand " Cargo.toml

echo ""
echo "=== stdlib/Cargo.toml getrandom/rand context ==="
grep -n "getrandom\|wasm_js\|wasm-bindgen\|rand\b\|rand_core\|rand " crates/stdlib/Cargo.toml

echo ""
echo "=== without-js example Cargo.toml ==="
cat example_projects/wasm32_without_js/rustpython-without-js/Cargo.toml

echo ""
echo "=== without-js .cargo/config.toml (if exists) ==="
cat example_projects/wasm32_without_js/.cargo/config.toml 2>/dev/null || echo "(not found)"
cat example_projects/wasm32_without_js/rustpython-without-js/.cargo/config.toml 2>/dev/null || echo "(not found in subdir)"

echo ""
echo "=== CI wasm job ==="
grep -n -A10 -B2 "wasm32\|without.js\|wasm_js\|wasm-pack" .github/workflows/ci.yaml | head -100

echo ""
echo "=== vm/Cargo.toml getrandom context ==="
grep -n -A2 -B2 "getrandom\|wasm_js" crates/vm/Cargo.toml

echo ""
echo "=== common/Cargo.toml getrandom context ==="
grep -n -A2 -B2 "getrandom\|wasm_js" crates/common/Cargo.toml

echo ""
echo "=== random.rs current state ==="
cat crates/stdlib/src/random.rs | head -60

echo ""
echo "=== float.rs rand import ==="
grep -n "rand\|Rng\|RngExt" crates/literal/src/float.rs | head -20

Length of output: 7234


Let me check getrandom 0.4's API to verify the sys_rng feature and SysRng availability.

Let me dig deeper into the literal crate and check for any missing rand dependency.


🏁 Script executed:

#!/bin/bash
echo "=== literal/Cargo.toml ==="
cat crates/literal/Cargo.toml

echo ""
echo "=== float.rs full rand context ==="
grep -n -B5 -A5 "rand\|RngExt\|Rng" crates/literal/src/float.rs

echo ""
echo "=== What does rand 0.10 default features include? ==="
grep -n "rand\b" Cargo.toml

echo ""
echo "=== Check if rand is in vm/Cargo.toml ==="
grep -n "rand\b\|rand_core\|rand " crates/vm/Cargo.toml

echo ""
echo "=== Check if SysRng is used anywhere else ==="
rg "SysRng\|sys_rng\|getrandom" crates/ --type toml -n

echo ""
echo "=== Check rand_core in workspace ==="
grep -n "rand_core" Cargo.toml

echo ""
echo "=== Without-js example tree ==="
find example_projects/wasm32_without_js -type f | sort

echo ""
echo "=== What crates are compiled for without-js (check vm features) ==="
grep -n "stdlib\|freeze-stdlib" crates/vm/Cargo.toml | head -20

Length of output: 1973


Let me look at the wasm crate since the CI also compiles it as part of the wasm test job.


🏁 Script executed:

#!/bin/bash
echo "=== crates/wasm/Cargo.toml ==="
cat crates/wasm/Cargo.toml

echo ""
echo "=== Check rand in wasm crate ==="
grep -n "rand\|getrandom\|wasm_js" crates/wasm/Cargo.toml

echo ""
echo "=== Check random.rs full seed() function ==="
grep -n -A30 "fn seed" crates/stdlib/src/random.rs | head -50

echo ""
echo "=== rand_core version used by mt19937 ==="
rg "rand_core\|rand-core" --type toml -n

echo ""
echo "=== Check if there's a Cargo.lock entry for rand_core to see what version resolves ==="
grep -A3 'name = "rand_core"' Cargo.lock | head -20

echo ""
echo "=== Check mt19937 crate for wasm compatibility ==="
grep -rn "wasm\|getrandom\|rand_core" Cargo.lock | grep -A2 'mt19937' | head -20

echo ""
echo "=== Without-js example .cargo/config.toml exact content ==="
cat example_projects/wasm32_without_js/rustpython-without-js/.cargo/config.toml

Length of output: 3748


That rand_core 0.6.4 entry in Cargo.lock is suspicious. Let me check which crate it's coming from.


🏁 Script executed:

#!/bin/bash
echo "=== mt19937 in Cargo.lock ==="
grep -A10 '^name = "mt19937"' Cargo.lock

echo ""
echo "=== getrandom in Cargo.lock (look for sys_rng or wasm) ==="
grep -A15 '^name = "getrandom"' Cargo.lock

echo ""
echo "=== Who depends on rand_core 0.6.4? ==="
# Find all packages that list rand_core 0.6 as a dependency
python3 - <<'EOF'
import re

with open("Cargo.lock") as f:
    content = f.read()

# Parse all packages
packages = re.split(r'\n\[\[package\]\]\n', content)

rand_core_06_users = []
for pkg in packages:
    name_match = re.search(r'^name = "(.+)"', pkg, re.MULTILINE)
    version_match = re.search(r'^version = "(.+)"', pkg, re.MULTILINE)
    # Check if this package depends on rand_core 0.6.x
    if re.search(r'"rand_core 0\.6', pkg):
        if name_match and version_match:
            rand_core_06_users.append(f"{name_match.group(1)} {version_match.group(1)}")

print("Packages depending on rand_core 0.6.x:")
for p in sorted(rand_core_06_users):
    print(" ", p)
EOF

echo ""
echo "=== What rand_core version does mt19937 need ==="
grep -A20 '^name = "mt19937"' Cargo.lock | grep -E "name|version|rand"

echo ""
echo "=== Check workspace mt19937 version ==="
grep -n "mt19937" Cargo.toml
grep -n "mt19937" crates/stdlib/Cargo.toml

echo ""
echo "=== getrandom SysRng - check what rand_core version it uses ==="
grep -A20 '^name = "getrandom"' Cargo.lock | head -30

Length of output: 2381


The getrandom 0.4.2 entry in the lock file now depends on js-sys and wasm-bindgen, which is suspicious. Let me check the exact backend configuration syntax for getrandom 0.4 — it may have changed from 0.3.

Critical finding: for getrandom 0.3, setting RUSTFLAGS='--cfg getrandom_backend="wasm_js"' "is allowed but is no longer required and does nothing" — and more importantly, that --cfg getrandom_backend= mechanism has no effect on getrandom 0.2.x at all.

There are three versions of getrandom in your lock file: 0.2.17, 0.3.4, and 0.4.2. The --cfg=getrandom_backend="unsupported" RUSTFLAGS only helps getrandom 0.4. Let me find what's pulling in getrandom 0.2.17.


🏁 Script executed:

#!/bin/bash
echo "=== Who depends on getrandom 0.2.x in Cargo.lock? ==="
python3 - <<'EOF'
import re

with open("Cargo.lock") as f:
    content = f.read()

packages = re.split(r'\n\[\[package\]\]\n', content)

getrandom_02_users = []
getrandom_03_users = []
for pkg in packages:
    name_match = re.search(r'^name = "(.+)"', pkg, re.MULTILINE)
    version_match = re.search(r'^version = "(.+)"', pkg, re.MULTILINE)
    if re.search(r'"getrandom 0\.2', pkg):
        if name_match and version_match:
            getrandom_02_users.append(f"{name_match.group(1)} {version_match.group(1)}")
    if re.search(r'"getrandom 0\.3', pkg):
        if name_match and version_match:
            getrandom_03_users.append(f"{name_match.group(1)} {version_match.group(1)}")

print("Packages depending on getrandom 0.2.x:")
for p in sorted(getrandom_02_users):
    print(" ", p)

print("\nPackages depending on getrandom 0.3.x:")
for p in sorted(getrandom_03_users):
    print(" ", p)
EOF

echo ""
echo "=== What crates pull in rand 0.8.5? ==="
python3 - <<'EOF'
import re

with open("Cargo.lock") as f:
    content = f.read()

packages = re.split(r'\n\[\[package\]\]\n', content)

rand_08_users = []
for pkg in packages:
    name_match = re.search(r'^name = "(.+)"', pkg, re.MULTILINE)
    version_match = re.search(r'^version = "(.+)"', pkg, re.MULTILINE)
    if re.search(r'"rand 0\.8', pkg):
        if name_match and version_match:
            rand_08_users.append(f"{name_match.group(1)} {version_match.group(1)}")

print("Packages depending on rand 0.8.x:")
for p in sorted(rand_08_users):
    print(" ", p)
EOF

echo ""
echo "=== common/Cargo.toml full content ==="
cat crates/common/Cargo.toml

echo ""
echo "=== Check if vm transitively uses uuid or any getrandom 0.2 dep ==="
grep -n "uuid\|chrono\|ring\|aws" crates/vm/Cargo.toml

Length of output: 1649


Let me check whether ring lands in the wasm crate build and whether any non-optional stdlib deps are wasm32-incompatible.


🏁 Script executed:

#!/bin/bash
echo "=== Who depends on ring in Cargo.lock? ==="
python3 - <<'EOF'
import re

with open("Cargo.lock") as f:
    content = f.read()

packages = re.split(r'\n\[\[package\]\]\n', content)

ring_users = []
for pkg in packages:
    name_match = re.search(r'^name = "(.+)"', pkg, re.MULTILINE)
    version_match = re.search(r'^version = "(.+)"', pkg, re.MULTILINE)
    if re.search(r'"ring ', pkg):
        if name_match and version_match:
            ring_users.append(f"{name_match.group(1)} {version_match.group(1)}")

print("Packages depending on ring:")
for p in sorted(ring_users):
    print(" ", p)
EOF

echo ""
echo "=== stdlib non-optional direct deps (check for wasm32 incompatible ones) ==="
# Show all [dependencies] entries in stdlib Cargo.toml that are NOT optional
python3 - <<'EOF'
import re

with open("crates/stdlib/Cargo.toml") as f:
    content = f.read()

# Find the [dependencies] section (not target-specific ones)
# Look for lines that don't have optional = true
deps_section = re.search(r'\[dependencies\](.*?)(?=\n\[)', content, re.DOTALL)
if deps_section:
    section = deps_section.group(1)
    lines = section.strip().split('\n')
    non_optional = []
    for line in lines:
        if line.strip() and not line.strip().startswith('#'):
            if 'optional' not in line:
                non_optional.append(line.strip())
    print("Non-optional [dependencies]:")
    for l in non_optional:
        print(" ", l)
EOF

echo ""
echo "=== stdlib Cargo.toml features section ==="
python3 - <<'EOF'
import re

with open("crates/stdlib/Cargo.toml") as f:
    content = f.read()

features_section = re.search(r'\[features\](.*?)(?=\n\[)', content, re.DOTALL)
if features_section:
    print("[features]")
    print(features_section.group(1))
else:
    print("No [features] section found")
EOF

echo ""
echo "=== Check flate2/bzip2/compression optional in stdlib ==="
grep -n "flate2\|bzip2\|libz\|compression\|zlib" crates/stdlib/Cargo.toml

echo ""
echo "=== Check if wasm CI job compiles without stdlib ==="
grep -n -B5 -A15 "clippy.*wasm\|wasm.*clippy\|wasm-pack\|wasm_pack" .github/workflows/ci.yaml | head -60

Length of output: 4243


This is very revealing. nix, bzip2, and libz-sys are all non-optional in stdlib's [dependencies]. Let me check whether any of these were previously gated behind a target.cfg block in the ORIGINAL stdlib/Cargo.toml before this PR.

Let me check whether bzip2 is a new unconditional dependency (requiring C compilation on wasm32) and what changed vs. the original main branch.


🏁 Script executed:

#!/bin/bash
echo "=== bzip2 version in Cargo.lock ==="
grep -A8 '^name = "bzip2"' Cargo.lock | head -20

echo ""
echo "=== bzip2-sys in Cargo.lock ==="
grep -A8 '^name = "bzip2-sys"' Cargo.lock | head -20

echo ""
echo "=== libz-sys workspace entry ==="
grep -n "libz-sys\|libz-rs" Cargo.toml

echo ""
echo "=== Original stdlib Cargo.toml on main branch (diff) ==="
git diff origin/main -- crates/stdlib/Cargo.toml | head -120

echo ""
echo "=== What deps were added to [dependencies] vs were in target cfg blocks ==="
git show origin/main:crates/stdlib/Cargo.toml | grep -n "bzip2\|flate2\|libz\|nix\b" | head -20

echo ""
echo "=== nix version and wasm32 support ==="
grep -A8 '^name = "nix"' Cargo.lock | head -15

echo ""
echo "=== Check bzip2 workspace declaration details ==="
grep -n -A2 "bzip2" Cargo.toml

Length of output: 5925


Let me check whether getrandom 0.3.x (used by ahash) respects the same getrandom_backend RUSTFLAGS mechanism, since feature enabling is per-package in Cargo.

@fanninpm — I've identified the root cause with high confidence.

The issue is with getrandom 0.3.x, which behaves differently from getrandom 0.4.x on wasm32-unknown-unknown. Your Cargo.lock contains three different versions of getrandom: 0.2.17, 0.3.4, and 0.4.2. The 0.3.4 version is pulled in by ahash 0.8.12 (transitively via indexmapahash), which is compiled as a runtime library dependency — not just a build script.

Why this is different from getrandom 0.4:

In getrandom 0.4, to use wasm32-unknown-unknown, you only need to enable the wasm_js crate feature — no RUSTFLAGS required.

In getrandom 0.3, however, you must do both: use the wasm_js feature flag (e.g. getrandom = { version = "0.3", features = ["wasm_js"] }, which "only makes the backend available"), and also set RUSTFLAGS='--cfg getrandom_backend="wasm_js"' to actually select it.

Your current setup only enables the wasm_js feature on getrandom 0.4 (via the wasmbindrustpython-common/wasm_jsgetrandom/wasm_js chain). The getrandom 0.3.4 used by ahash gets neither treatment.

Why the without-js build is likely fine:

For the unsupported backend, no crate feature is required — it's entirely configured via --cfg getrandom_backend="unsupported" in RUSTFLAGS, and this mechanism works in both getrandom 0.3 and 0.4. Your .cargo/config.toml in rustpython-without-js/ should cover that case.


The fix for the wasm crate:

Step 1 — Force the wasm_js feature onto getrandom 0.3 in crates/wasm/Cargo.toml:

[target.'cfg(target_arch = "wasm32")'.dependencies]
# Force wasm_js feature on getrandom 0.3.x used transitively via ahash -> indexmap
getrandom03 = { package = "getrandom", version = "0.3", features = ["wasm_js"] }

Step 2 — Create crates/wasm/.cargo/config.toml to select the wasm_js backend via RUSTFLAGS for getrandom 0.3:

[target.wasm32-unknown-unknown]
rustflags = ['--cfg', 'getrandom_backend="wasm_js"']

The getrandom_backend configuration flag can be set by specifying the rustflags field in .cargo/config.toml, recommended on a per-target basis.

Note: for getrandom 0.4, setting RUSTFLAGS='--cfg getrandom_backend="wasm_js"' is "allowed but is no longer required and does nothing", so having this RUSTFLAGS in the wasm crate's config is safe — it will activate the needed backend for getrandom 0.3.4 without interfering with getrandom 0.4.


Quick dependency chain summary:

crates/wasm
 ├─ rustpython-vm (wasmbind feature)
 │   └─ rustpython-common → getrandom 0.4 [wasm_js feature] ✓
 └─ rustpython-stdlib (via freeze-stdlib)
     └─ indexmap → ahash 0.8.12 → getrandom 0.3.4
         ├─ [wasm_js feature] ✗ (missing — added by Step 1 above)
         └─ [getrandom_backend="wasm_js" RUSTFLAGS] ✗ (missing — added by Step 2 above)

@fanninpm fanninpm force-pushed the move-deps-to-workspace-for-stdlib branch from 29205d9 to 8dea442 Compare May 3, 2026 04:35
@fanninpm fanninpm requested a review from ShaharNaveh May 3, 2026 17:22
@fanninpm
Copy link
Copy Markdown
Contributor Author

fanninpm commented May 3, 2026

@ShaharNaveh tried again from scratch, making sure Cargo.lock did not change at all.

Copy link
Copy Markdown
Contributor

@ShaharNaveh ShaharNaveh left a comment

Choose a reason for hiding this comment

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

Great!

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