Build a `PermCtx` for the block: the congruence comparator uses it to walk gen vs orig in lockstep with permutation awareness. See `ix_compile::congruence::perm` for details. `n_primary = all.len()` because Phase 2 uses singleton classes (one class per original, no alpha-collapse at the primary level).
(
all: &[Name],
env: &Env,
stt: &ix_compile::compile::CompileState,
perm: &[usize],
)
| 1918 | .downcast_ref::<String>() |
| 1919 | .map(|s| s.as_str()) |
| 1920 | .or_else(|| panic.downcast_ref::<&str>().copied()) |
| 1921 | .unwrap_or("(non-string panic)"); |
| 1922 | p1.record_fail(format!("compile_env PANICKED: {msg}")); |
| 1923 | p1.report(); |
| 1924 | println!( |
| 1925 | "{VALIDATE_PREFIX} RESULT: {} total failures (aborted after Phase 1)", |
| 1926 | p1.fail |
| 1927 | ); |
| 1928 | return p1.fail; |
| 1929 | }, |
| 1930 | }; |
| 1931 | println!("{VALIDATE_PREFIX} compiled in {:.2}s", t0.elapsed().as_secs_f32()); |
| 1932 | |
| 1933 | // Parallel scan of all 707k+ constants against `stt`. Each check is an |
| 1934 | // independent pair of DashMap lookups (`ungrounded.contains_key` + |
| 1935 | // `resolve_addr`), so `env.par_iter()` over the FxHashMap is safe and |
| 1936 | // dramatically faster than a serial walk on Mathlib-scale inputs. |
| 1937 | { |
| 1938 | use std::sync::Mutex; |
| 1939 | use std::sync::atomic::{AtomicUsize, Ordering}; |
| 1940 | |
| 1941 | let passes = AtomicUsize::new(0); |
| 1942 | let fails = AtomicUsize::new(0); |
| 1943 | let fail_msgs: Mutex<Vec<String>> = Mutex::new(Vec::new()); |
| 1944 | |
| 1945 | let env_names: Vec<&Name> = env.keys().collect(); |
| 1946 | env_names.par_iter().for_each(|&name| { |
| 1947 | if stt.ungrounded.contains_key(name) { |
| 1948 | return; |
| 1949 | } |
| 1950 | if stt.resolve_addr(name).is_some() { |
| 1951 | passes.fetch_add(1, Ordering::Relaxed); |
| 1952 | } else { |
| 1953 | fails.fetch_add(1, Ordering::Relaxed); |
| 1954 | let mut msgs = fail_msgs.lock().unwrap(); |
| 1955 | if msgs.len() < 20 { |
| 1956 | msgs.push(format!("{}: not compiled", name.pretty())); |
| 1957 | } |
| 1958 | } |
| 1959 | }); |
| 1960 | |
| 1961 | p1.pass = passes.load(Ordering::Relaxed); |
| 1962 | p1.fail = fails.load(Ordering::Relaxed); |
| 1963 | p1.failures = fail_msgs.into_inner().unwrap(); |
| 1964 | } |
| 1965 | p1.report(); |
| 1966 | |
| 1967 | // ══════════════════════════════════════════════════════════════════════ |
| 1968 | // Phase 2: Aux_gen congruence (post-compilation, uses real CompileState) |
| 1969 | // ══════════════════════════════════════════════════════════════════════ |
| 1970 | // |
| 1971 | // Structure: three passes. |
| 1972 | // 1. Serial — collect unique blocks (dedup by sorted `.all` names) and |
| 1973 | // build `MutConst` values eagerly. Can't parallelize: the env iter |
| 1974 | // is serial and the dedup set needs cross-iteration visibility. |
| 1975 | // 2. Serial — pre-ingress each block's transitive ctor-field deps into |
| 1976 | // the shared `p2_kctx`. Serial because the visited set |
| 1977 | // (`p2_ingressed`) is shared across blocks, and we want each name |
no test coverage detected