iter env-unify.1: extract build_check_env, mono uses it
This commit is contained in:
@@ -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<String, String> = 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,
|
||||
|
||||
@@ -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<String, String> = 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
|
||||
|
||||
Reference in New Issue
Block a user