From d6870d7a62c405086779a62b7462d977d7d9c9a5 Mon Sep 17 00:00:00 2001 From: Brummel Date: Sun, 10 May 2026 02:16:21 +0200 Subject: [PATCH] iter env-unify.1: extract build_check_env, mono uses it --- crates/ailang-check/src/lib.rs | 86 +++++++++++++++++++++++++++++ crates/ailang-check/src/mono.rs | 95 +++------------------------------ 2 files changed, 94 insertions(+), 87 deletions(-) diff --git a/crates/ailang-check/src/lib.rs b/crates/ailang-check/src/lib.rs index 4dcb9f4..227aeb6 100644 --- a/crates/ailang-check/src/lib.rs +++ b/crates/ailang-check/src/lib.rs @@ -1085,6 +1085,92 @@ pub fn build_module_globals( /// - The body-check phase is multi-diagnose: each def is checked /// independently against the assembled env; a failure is recorded and /// the next def is attempted. +/// Build the workspace-flat `Env` shared by `check_in_workspace` +/// and `mono::build_workspace_env`. Populates every field whose +/// contents are derivable from `Workspace` alone — no +/// `current_module` overlay applied. Both call sites are thin +/// consumers: each clones this env and applies the per-call +/// overlay (`current_module`, `globals` augmented with module fns, +/// `imports`, `rigid_vars`) at the call site. +/// +/// Pre-condition: typecheck has succeeded for the workspace +/// (otherwise `build_module_globals` panics — same caller-contract +/// as the pre-refactor `mono::build_workspace_env`). +pub fn build_check_env(ws: &Workspace) -> Env { + let mut env = Env::default(); + builtins::install(&mut env); + + // env.types + env.ctor_index — workspace-flat from every + // module's Def::Type. Safe to flatten because `check_workspace` + // has already accepted the workspace, so duplicate names cannot + // occur. Mirrors the per-module loop in the pre-refactor + // `check_in_workspace` (which fail-fast aborted on duplicates, + // unreachable here). + for m in ws.modules.values() { + for d in &m.defs { + if let Def::Type(td) = d { + for c in &td.ctors { + env.ctor_index.insert( + c.name.clone(), + CtorRef { type_name: td.name.clone() }, + ); + } + env.types.insert(td.name.clone(), td.clone()); + } + } + } + + // env.module_globals + env.class_methods — built from + // `build_module_globals(ws)`. The .fns projection feeds + // `module_globals`; the .class_methods entries are merged + // workspace-wide into `class_methods` (uniqueness enforced + // earlier by `workspace::build_registry`'s + // method-name-collision check). + let mg = build_module_globals(ws) + .expect("build_module_globals: pre-condition (typecheck succeeded) violated"); + env.module_globals = mg + .iter() + .map(|(k, v)| (k.clone(), v.fns.clone())) + .collect(); + for g in mg.values() { + for (n, e) in &g.class_methods { + env.class_methods.insert(n.clone(), e.clone()); + } + } + + // env.module_types — per-module ADT index. + env.module_types = build_module_types(ws); + + // env.module_imports — per-module alias-or-name -> module-name. + // Per-module because aliases collide across modules; sibling + // shape to `module_globals`. + for m in ws.modules.values() { + let mut import_map: BTreeMap = BTreeMap::new(); + for imp in &m.imports { + let key = imp.alias.clone().unwrap_or_else(|| imp.module.clone()); + import_map.insert(key, imp.module.clone()); + } + env.module_imports.insert(m.name.clone(), import_map); + } + + // env.class_superclasses — walk every module's Def::Class. + for m in ws.modules.values() { + for d in &m.defs { + if let Def::Class(cd) = d { + if let Some(sc) = &cd.superclass { + env.class_superclasses.insert(cd.name.clone(), sc.class.clone()); + } + } + } + } + + // env.workspace_registry — clone of ws.registry. Used by + // `check_fn`'s concrete-residual no-instance check. + env.workspace_registry = ws.registry.clone(); + + env +} + fn check_in_workspace( m: &Module, ws: &Workspace, diff --git a/crates/ailang-check/src/mono.rs b/crates/ailang-check/src/mono.rs index f6f471e..d303fe1 100644 --- a/crates/ailang-check/src/mono.rs +++ b/crates/ailang-check/src/mono.rs @@ -355,94 +355,15 @@ pub(crate) fn mono_target_key(t: &MonoTarget) -> (String, String, String) { ) } -/// Iter 22b.3: build the workspace-wide [`crate::Env`] used by -/// the mono pass to re-run [`crate::synth`] on each fn body. -/// Mirrors `check_in_workspace`'s setup: builtins + workspace -/// registry + per-module globals + class-method table + -/// superclass map. Cross-module type defs and consts are NOT -/// installed here — `synth` for mono only needs to (a) recognise -/// class-method names and (b) unify call-site arg types with -/// declared param types. Module-resident fns are still needed -/// for non-class-method calls inside instance bodies. +/// Iter 22b.3 / 2026-05-10 unify: thin wrapper over +/// [`crate::build_check_env`]. The mono pass needs the same +/// workspace-flat `Env` shape as `check_in_workspace`, so both +/// share one source of truth. Per-fn entry points +/// (`collect_mono_targets`, `collect_residuals_ordered`) clone the +/// env and apply per-fn overlay (current_module, globals from +/// module_globals, imports from module_imports, rigid_vars). pub fn build_workspace_env(ws: &Workspace) -> crate::Env { - // Drift risk: this fn and `crate::check_in_workspace` both - // populate `crate::Env`. If `synth` starts reading a new `Env` - // field, update both paths. - let mut env = crate::Env::default(); - crate::builtins::install(&mut env); - env.workspace_registry = ws.registry.clone(); - - // Per-module globals + class method table + superclass map. - // The construction order matches `check_in_workspace` so the - // env shape is interchangeable. `build_module_globals` may - // surface duplicate-def errors for malformed workspaces; the - // mono pass's pre-condition is that typecheck has already - // succeeded, so a failure here is a caller-contract violation. - let module_globals_index = crate::build_module_globals(ws) - .expect("build_module_globals: pre-condition (typecheck succeeded) violated"); - env.module_globals = module_globals_index - .iter() - .map(|(mname, g)| (mname.clone(), g.fns.clone())) - .collect(); - env.module_types = crate::build_module_types(ws); - // Iter 22c (sibling of commit 13b36cc): per-module import maps so - // `collect_mono_targets` / `collect_residuals_ordered` can seed - // `env.imports` before re-running `synth`. Mirrors - // `check_in_workspace` (lib.rs:1147-1152). Scoped per-module - // because import aliases collide across modules — same shape as - // `env.module_globals`, unlike the workspace-wide flat tables for - // user ADTs (5c5180f). - for m in ws.modules.values() { - let mut import_map: BTreeMap = BTreeMap::new(); - for imp in &m.imports { - let key = imp.alias.clone().unwrap_or_else(|| imp.module.clone()); - import_map.insert(key, imp.module.clone()); - } - env.module_imports.insert(m.name.clone(), import_map); - } - - // Workspace-wide class-method table: merge per module's - // ModuleGlobals.class_methods. - for (_mname, g) in &module_globals_index { - for (name, entry) in &g.class_methods { - env.class_methods.insert(name.clone(), entry.clone()); - } - } - // Superclass map: walk every module's class defs. - for m in ws.modules.values() { - for d in &m.defs { - if let Def::Class(c) = d { - if let Some(sc) = &c.superclass { - env.class_superclasses.insert(c.name.clone(), sc.class.clone()); - } - } - } - } - - // Iter 22c: seed `env.types` and `env.ctor_index` from every - // module's `Def::Type` entries. `synth`'s bare-name `Term::Ctor` - // path (and three sibling sites in `lib.rs`) consult these flat - // tables; without them, re-running `synth` on an instance method - // body whose type references a user ADT yields `UnknownType`. - // Workspace-wide flat tables are safe here because `check_workspace` - // has already accepted the workspace, so duplicate names cannot - // occur. Mirrors `check_in_workspace` (lib.rs:1099-1128). - for m in ws.modules.values() { - for d in &m.defs { - if let Def::Type(td) = d { - for c in &td.ctors { - env.ctor_index.insert( - c.name.clone(), - crate::CtorRef { - type_name: td.name.clone(), - }, - ); - } - env.types.insert(td.name.clone(), td.clone()); - } - } - } - env + crate::build_check_env(ws) } /// Iter 22b.3: re-run [`crate::synth`] on `f`'s body to recover