Skip to content

Update Rust tolchains#5554

Closed
deuszx wants to merge 17 commits intotestnet_conwayfrom
issue-5264
Closed

Update Rust tolchains#5554
deuszx wants to merge 17 commits intotestnet_conwayfrom
issue-5264

Conversation

@deuszx
Copy link
Copy Markdown
Contributor

@deuszx deuszx commented Mar 2, 2026

Motivation

#5264

The project has been pinned to Rust 1.86.0 stable / nightly-2025-03-21 for a long time. Bumping to a recent toolchain was blocked by three independent issues:

Proposal

Bump stable toolchain to 1.93.1 and nightly to nightly-2026-03-01.

Dependency fixes (git branches, until crates.io releases are available)

  • linera-wasm-instrumentlinera-io/wasm-instrument@bulk-memory-support: enables bulk-memory support in parity-wasm so it can parse opcode 0xFC. Also enable the bulk feature in linera-execution so
    the instrumentation pass handles these opcodes. Fixes Applications don't load with Rust 1.87 or later #4742.
  • linera-wasmer{,-compiler,-compiler-singlepass,-vm}linera-io/wasmer@fix-rust-probestack: vendors __rust_probestack in linera-wasmer-vm using rustversion to conditionally provide the symbol only
    on Rust 1.89+. Addresses the Wasmer portion of Upgrade to Wasmer ~5~ ~6~ 7 #4203.
  • ruzstd: unpin from =0.8.1 to 0.8 (the build failure on 0.8.2 that motivated the pin is fixed in newer Rust).

Custom wasm32-mvp target for testnet_conway compatibility

Rust 1.93/LLVM 18 enables bulk-memory, bulk-memory-opt, and nontrapping-fptoint as default features for wasm32-unknown-unknown. All use the 0xFC opcode prefix, which testnet_conway validators
reject.

The standard -C target-feature=-bulk-memory,... flag is silently ignored by LLVM 18 when these features are part of the target's default feature set. A custom target JSON is the only reliable solution:

  • linera-service/wasm32-mvp.json: identical to wasm32-unknown-unknown except "features": "-bulk-memory,-bulk-memory-opt,-nontrapping-fptoint".
  • examples/.cargo/config.toml: configures -Zunstable-options, build-std = ["std", "panic_abort"], and json-target-spec = true so cargo build --target wasm32-mvp works in the examples workspace.
  • .cargo/config.toml: sets RUST_TARGET_PATH to linera-service so the custom target resolves anywhere in the repo.
  • CliWrapper::build_application: builds contracts using +nightly-2026-03-01 --target wasm32-mvp.json -Z build-std -Z json-target-spec, then copies output from target/wasm32-mvp/release/ to
    target/wasm32-unknown-unknown/release/ so downstream code is unaffected. Also installs the nightly toolchain with rust-src on first run.
  • examples/rust-toolchain.toml: changed from a symlink to rust-toolchain.toml (stable) to a symlink to toolchains/nightly/rust-toolchain.toml (nightly), since -Z build-std and -Z json-target-spec
    require nightly cargo.
  • Example README files updated to use --target wasm32-mvp in build commands.

Clippy / lint fixes

Various Clippy fixes required by the new toolchain:

  • Replace format!("{}", x) with format!("{x}") (clippy::uninlined_format_args)
  • Replace deprecated GenericArray::as_slice() with slice indexing &digest[..] in the llm example (sha3 API change)
  • Replace .index() with .enumerate() where flagged
  • Add cargo-machete ignores for half in llm and gen-nft (transitive dependency)
  • Reformat half workspace dependency for taplo compliance

Web target fix

Remove -Z wasm_c_abi=spec (hard error in Rust 1.92+) and add explicit shared-memory linker flags (-Wl,--shared-memory, -Wl,--max-memory=...) for the web target, since atomics no longer auto-enable shared
memory.

Test Plan

CI

Release Plan

TBD

Links

#5264

deuszx and others added 3 commits March 2, 2026 09:52
      Bump the stable toolchain from 1.86.0 to 1.93.1 and the nightly
      toolchain to nightly-2026-02-23. This required three fixes:

      - Enable bulk memory support in wasm-instrument so parity-wasm can
        parse opcode 0xFC (bulk memory operations) that Rust 1.87+ emits
        in wasm output. Fixes #4742.

      - Vendor __rust_probestack in linera-wasmer-vm for Rust 1.89+ where
        the symbol is no longer exported from compiler-builtins. Addresses
        the wasmer build portion of #4203.

      - Remove -Z wasm_c_abi=spec (hard error in 1.92+) and add explicit
        shared-memory linker flags for the web target since atomics no
        longer auto-enable shared memory in Rust 1.92+.

      Also unpins ruzstd and updates wasm test fixtures and expected fuel
      counts for the new compiler output.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
deuszx and others added 13 commits March 2, 2026 15:49
…chete

- Replace deprecated `GenericArray::as_slice()` with `as_ref()` in llm service
- Reformat half workspace dependency to multi-line (taplo requirement)
- Move half to alphabetical position in workspace.dependencies
- Add cargo-machete ignore for `half` in llm and gen-nft (transitive dep)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…hange

      Use &digest[..] slice indexing instead of .as_ref() to unambiguously
      yield &[u8] in assert_eq!, avoiding "type annotations needed" errors
      when the compiler can't infer the AsRef target type.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ontracts

  Rust 1.93 enables bulk-memory and nontrapping-fptoint by default for
  wasm32-unknown-unknown (unlike 1.86), causing compiled contracts to emit
  opcode 0xFC which testnet_conway validators do not support.

  Add -C target-feature=-bulk-memory,-nontrapping-fptoint to
  .cargo/config.toml so all contracts built on this branch are compatible
  with testnet_conway validators.

  Re-enable +bulk-memory in web/.cargo/config.toml since the web client
  requires it for shared-memory threading support.
  The RUSTFLAGS env var (e.g. "-D warnings" in CI) takes priority over
  [target.wasm32-unknown-unknown] rustflags in .cargo/config.toml, so the
  config-file fix was silently ignored in CI.

  Explicitly append -C target-feature=-bulk-memory,-nontrapping-fptoint
  to RUSTFLAGS in build_application so the 0xFC opcode suppression is
  always effective regardless of the calling environment.
…nway

      Rust 1.93/LLVM 18 added bulk-memory, bulk-memory-opt, and nontrapping-fptoint
      as default features for wasm32-unknown-unknown. All use opcode prefix 0xFC,
      which testnet_conway validators reject as an unknown opcode.

      The previous approach of -C target-feature=-bulk-memory,-nontrapping-fptoint
      is silently ignored by LLVM 18 when those features are part of the target's
      default feature set. A custom target JSON is the only reliable fix.

      wasm32-mvp.json is identical to wasm32-unknown-unknown except for:
        "features": "-bulk-memory,-bulk-memory-opt,-nontrapping-fptoint"

      build_application now builds with this custom target (using -Z build-std to
      also recompile stdlib from source without the disabled opcodes), then copies
      the wasm files to the standard wasm32-unknown-unknown/release/ directory so
      callers are unaffected.

      Also add a regression test that builds the fungible contract and verifies
      the output contains no 0xFC instructions (bulk-memory / nontrapping-fptoint)
      by disassembling with wasm2wat and checking for the instruction names.

      examples/rust-toolchain.toml is changed from a symlink to a real file
      specifying nightly, since -Z build-std and -Z json-target-spec require it.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
And update README.md-s for readability.
linker = "aarch64-linux-gnu-gcc"

[env]
# Makes `--target wasm32-mvp` resolve to linera-service/wasm32-mvp.json
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.

Rather than using wasm32-mvp, let's add two targets that we can distinguish:

  • wasm32-linera-chain for on-chain applications (contract and service)
  • wasm32-unknown-js-web for the Web browser (@linera/client)

Then we can throw away the web features that are currently polluting our codebase.

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.

(I'll suggest one target for both contract and service, even though it might be cleaner to separate them, because it eases compilation of applications for the end-user)

@@ -1 +1 @@
../rust-toolchain.toml No newline at end of file
../toolchains/nightly/rust-toolchain.toml No newline at end of file
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.

I wonder if it's time to migrate wholesale to nightly Rust and forget about stable. Basically all our codepaths now depend on nightly features except for the CLI build, and having just the one Rust version would simplify our build a lot. (We can still forbid #![feature]s in the core codebase.)

Comment on lines +1252 to +1257
// Write the custom target spec to a temporary file. The spec disables
// bulk-memory, bulk-memory-opt, and nontrapping-fptoint — opcodes that
// use the 0xFC prefix and are not supported by testnet_conway validators.
// Using a custom target JSON (rather than -C target-feature flags) is
// necessary because Rust 1.93/LLVM 18 ignores the flag for these features
// when they are part of the target's default feature set.
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.

Can we not just add the target to the application template (linera-service/template)?

Comment on lines +1273 to +1281
Command::new("rustup")
.args([
"toolchain",
"install",
WASM_NIGHTLY_TOOLCHAIN,
"--component",
"rust-src",
])
.spawn_and_wait_for_stdout()
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.

Please let's not rely on the presence of rustup and mutating the user's home directory! We should specify the relevant features in the toolchain file and if rustup is present it should do the right thing.

Command::new("cargo")
.current_dir(self.path_provider.path())
.current_dir(path)
.arg(format!("+{WASM_NIGHTLY_TOOLCHAIN}"))
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.

As above, this should also be unnecessary if the toolchain file is set up correctly.

@Twey
Copy link
Copy Markdown
Contributor

Twey commented Mar 9, 2026

This PR is muddied a lot by the warning cleanups. Can we add them to a separate PR? is_multiple_of might require some conditional-compilation finagling (or I guess just that one can stay here — it's small) but the rest I think is backward-compatible.

@deuszx
Copy link
Copy Markdown
Contributor Author

deuszx commented Mar 10, 2026

Being superseeded by #5646 and #5650

@deuszx deuszx closed this Mar 10, 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.

2 participants