( env_consts_ptr: LeanList<LeanBorrowed<'_>>, )
| 287 | /// FFI: compile a Lean environment and stream the serialized Ixon.Env |
| 288 | /// straight to `out_path` (see `Env::put_file`) — no env-sized `Vec` or |
| 289 | /// Lean `ByteArray` is built. Writes `<out_path>.tmp`, then renames, so |
| 290 | /// a crash cannot leave a truncated file. The file is the canonical |
| 291 | /// `Env::put` encoding (see `put_file`'s equivalence test). |
| 292 | /// |
| 293 | /// Fail-closed semantics live here, behind the FFI: when |
| 294 | /// `allow_partial == 0` and any requested constant landed in |
| 295 | /// `CompileState.ungrounded`, nothing is written — the final path is |
| 296 | /// never created — and the returned status carries the full ungrounded |
| 297 | /// list for the caller to report. With `allow_partial != 0`, the |
| 298 | /// grounded subset is serialized and the same status discloses what |
| 299 | /// was omitted (see plans/aux-recursor-alias-collision.md §8). |
| 300 | /// |
| 301 | /// Returns `Ix.CompileM.CompileEnvStatus` (layout |
| 302 | /// `LeanIxCompileEnvStatus`): root (64-hex canonical consts merkle |
| 303 | /// root — matches the serialized header, computed even when nothing is |
| 304 | /// written), ungrounded (`Array (String × String)` of pretty-name / |
| 305 | /// reason, sorted by name), bytes (0 when not written), named count, |
| 306 | /// unique anon count. |
| 307 | #[unsafe(no_mangle)] |
| 308 | pub extern "C" fn rs_compile_env( |
| 309 | env_consts_ptr: LeanList<LeanBorrowed<'_>>, |
| 310 | out_path: LeanString<LeanBorrowed<'_>>, |
| 311 | allow_partial: u8, |
| 312 | ) -> LeanIOResult<LeanOwned> { |
| 313 | let rust_env = crate::lean_env::decode_env_for_compile(env_consts_ptr); |
| 314 | let rust_env = Arc::new(rust_env); |
| 315 | |
| 316 | let compile_stt = |
| 317 | match compile_env_with_options(&rust_env, CompileOptions::default()) { |
| 318 | Ok(stt) => stt, |
| 319 | Err(e) => { |
| 320 | let msg = format!("rs_compile_env: Rust compilation failed: {:?}", e); |
| 321 | return LeanIOResult::error_string(&msg); |
| 322 | }, |
| 323 | }; |
| 324 | |
| 325 | // Deterministically ordered (pretty name, reason) pairs — DashMap |
| 326 | // iteration order is shard-dependent. |
| 327 | let mut ungrounded: Vec<(String, String)> = compile_stt |
| 328 | .ungrounded |
| 329 | .iter() |
| 330 | .map(|e| (e.key().pretty(), e.value().clone())) |
| 331 | .collect(); |
| 332 | ungrounded.sort_by(|a, b| a.0.cmp(&b.0)); |
| 333 | |
| 334 | // Canonical consts merkle root — equals the serialized header root |
| 335 | // when a file is written; still reported on a fail-closed abort so |
| 336 | // callers can record what the complete-subset content was. Computed |
| 337 | // once here (parallel sort + tree) and handed to the writer — the |
| 338 | // sort and the ~2·N-node tree used to run twice per compile. |
| 339 | let mut const_addrs: Vec<Address> = |
| 340 | compile_stt.env.consts.iter().map(|e| e.key().clone()).collect(); |
| 341 | { |
| 342 | use rayon::prelude::*; |
| 343 | const_addrs.par_sort_unstable(); |
| 344 | } |
| 345 | let root = ixon::merkle::merkle_root_canonical_sorted(&const_addrs) |
| 346 | .unwrap_or_else(ixon::merkle::zero_address); |
nothing calls this directly
no test coverage detected