From 7b26e4043697aba7eeb67e21dc09c3c391da000d Mon Sep 17 00:00:00 2001 From: Solly Ross Date: Mon, 20 Oct 2025 19:16:46 -0700 Subject: [PATCH] Return paths in PackageSourceMap deterministically in v1.220.0, specifically 28ea1a05a, package source pathing was switched over to a helper utility. the `PackageSourceMap::paths` method looks very similar to the logic before, but has a very subtle difference: in order to avoid duplicate paths, it collects paths from each source map's source files into a `HashSet` and then returns an iterator over than (in contrast to before, which just presented a flat-mapped iterator over all source files directly). unfortunately, this means that iteration order is now random, which can produce non-deterministic compilation when wit-parser is used as part of the compilation macro, say for proc-macros like wasmtime-component macro. it's... difficult to notice this in ordinary cargo compilation, but it causes _extremely_ strange behavior in deterministic/caching build tooling like buck2: given a series of deps `outer -> inner -> [something that uses wasmtime-component-macro, like wasmtime-wasi]`, compiling `outer` will cause rustc to reject `wasmtime-wasi` on a hash mismatch, which will then surface as "unable to find crate "inner"` [^1] fixing this is relatively easy: since our input iteration order is deterministic, simply collecting into an `IndexMap` (already used elsewhere in the file for this purpose) instead of a `HashMap` gives us deterministic iteration order, and thus deterministic compilation. [^1]: i know this happens when compiling `outer` as a static-pic for library; i have not yet tested if it occurs in other compilation modes like binaries or shared libs. --- crates/wit-parser/src/resolve.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/wit-parser/src/resolve.rs b/crates/wit-parser/src/resolve.rs index f77a5c6341..301ceef41a 100644 --- a/crates/wit-parser/src/resolve.rs +++ b/crates/wit-parser/src/resolve.rs @@ -168,7 +168,7 @@ impl PackageSourceMap { .iter() .flatten() .map(|path_buf| path_buf.as_ref()) - .collect::>() + .collect::>() .into_iter() }