Conversation
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>
…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 |
There was a problem hiding this comment.
Rather than using wasm32-mvp, let's add two targets that we can distinguish:
wasm32-linera-chainfor on-chain applications (contract and service)wasm32-unknown-js-webfor the Web browser (@linera/client)
Then we can throw away the web features that are currently polluting our codebase.
There was a problem hiding this comment.
(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 | |||
There was a problem hiding this comment.
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.)
| // 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. |
There was a problem hiding this comment.
Can we not just add the target to the application template (linera-service/template)?
| Command::new("rustup") | ||
| .args([ | ||
| "toolchain", | ||
| "install", | ||
| WASM_NIGHTLY_TOOLCHAIN, | ||
| "--component", | ||
| "rust-src", | ||
| ]) | ||
| .spawn_and_wait_for_stdout() |
There was a problem hiding this comment.
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}")) |
There was a problem hiding this comment.
As above, this should also be unnecessary if the toolchain file is set up correctly.
|
This PR is muddied a lot by the warning cleanups. Can we add them to a separate PR? |
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:
0xFC) thatlinera-wasm-instrument(backed byparity-wasm) could not parse, causing applications to fail to load.__rust_probestackfromcompiler-builtins, breaking the Wasmer VM build.-Z wasm_c_abi=speca hard error, and atomics no longer auto-enable shared memory for the web target.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-instrument→linera-io/wasm-instrument@bulk-memory-support: enables bulk-memory support in parity-wasm so it can parse opcode0xFC. Also enable thebulkfeature inlinera-executionsothe 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_probestackinlinera-wasmer-vmusingrustversionto conditionally provide the symbol onlyon Rust 1.89+. Addresses the Wasmer portion of Upgrade to Wasmer ~5~ ~6~ 7 #4203.
ruzstd: unpin from=0.8.1to0.8(the build failure on 0.8.2 that motivated the pin is fixed in newer Rust).Custom
wasm32-mvptarget for testnet_conway compatibilityRust 1.93/LLVM 18 enables
bulk-memory,bulk-memory-opt, andnontrapping-fptointas default features forwasm32-unknown-unknown. All use the0xFCopcode prefix, which testnet_conway validatorsreject.
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 towasm32-unknown-unknownexcept"features": "-bulk-memory,-bulk-memory-opt,-nontrapping-fptoint".examples/.cargo/config.toml: configures-Zunstable-options,build-std = ["std", "panic_abort"], andjson-target-spec = truesocargo build --target wasm32-mvpworks in the examples workspace..cargo/config.toml: setsRUST_TARGET_PATHtolinera-serviceso 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 fromtarget/wasm32-mvp/release/totarget/wasm32-unknown-unknown/release/so downstream code is unaffected. Also installs the nightly toolchain withrust-srcon first run.examples/rust-toolchain.toml: changed from a symlink torust-toolchain.toml(stable) to a symlink totoolchains/nightly/rust-toolchain.toml(nightly), since-Z build-stdand-Z json-target-specrequire nightly cargo.
--target wasm32-mvpin build commands.Clippy / lint fixes
Various Clippy fixes required by the new toolchain:
format!("{}", x)withformat!("{x}")(clippy::uninlined_format_args)GenericArray::as_slice()with slice indexing&digest[..]in thellmexample (sha3 API change).index()with.enumerate()where flaggedcargo-macheteignores forhalfinllmandgen-nft(transitive dependency)halfworkspace dependency fortaplocomplianceWeb 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 sharedmemory.
Test Plan
CI
Release Plan
TBD
Links
#5264