iter mq.1: class-ref canonical-form extension + workspace-internal class-name qualification

Three schema fields move bare → canonical (bare for same-module,
<module>.<Class> for cross-module): InstanceDef.class,
Constraint.class, SuperclassRef.class. Symmetric to ct.1's
Type::Con.name rule. ClassDef.name stays bare.

validate_canonical_type_names gains three field-walks via new
check_class_ref helper + two sibling diagnostics
BareCrossModuleClassRef / BadCrossModuleClassRef.
check_class_name_fields narrowed to ClassDef.name-only.

Workspace-internal class-name keys all qualified:
class_def_module, class_by_name, registry entries.0,
ClassMethodEntry.class_name, class_superclasses, mono's
class_index, Origin::Class.class_name. New qualify_class_ref
helper at workspace.rs scope plus sibling
qualify_class_ref_in_check in ailang-check.

Two new positive on-disk fixtures (mq1_xmod_constraint_class{,_dep})
exercise the qualified Constraint.class shape.

Recon claim that all existing fixtures' class-refs are intra-module
was empirically wrong — 10 fixtures required minimal canonical-form
migration. Duplicate-instance test architecturally restructured:
post-mq.1 orphan-freedom makes two-modules-on-same-(class,type)
structurally impossible; new test_22b1_dup_same_module fixture
lands both instances in the class's module.

Plan defects fixed inline: Origin::Class.class_name single
construction site (plan recon off-by-one); build_class_index in
mono.rs needed qualifying; build_module_globals needed Def::Instance
carve-out; check_fn declared-constraint matching needed inline
canonical-form lifting; NoInstance Float-aware message arm needed
prelude.Eq/prelude.Ord match; coherence type-leg needed qualified-
head split-and-lookup. Tasks 3-6 ran as one coherent fix.

7/7 tasks, 520 tests green. bench/compile_check.py + cross_lang.py
exit 0; bench/check.py exit 1 (4 improvements-beyond-tolerance,
audit-ratifiable, not a regression).

MethodNameCollision + dispatch path unchanged; iters mq.2 + mq.3
land them.
This commit is contained in:
2026-05-13 01:11:56 +02:00
parent 1a5f8289b7
commit 0eb33235eb
28 changed files with 1159 additions and 234 deletions
+32
View File
@@ -1280,6 +1280,38 @@ fn workspace_error_to_diagnostic(
"name": name,
})),
),
// mq.1 (canonical-class-names): bare class-ref that does not
// resolve to a local class of the owning module. Sibling of
// `BareCrossModuleTypeRef` for class-reference fields.
W::BareCrossModuleClassRef { module, name, candidates } => Some(
ailang_check::Diagnostic::error(
"bare-cross-module-class-ref",
format!(
"module `{module}` contains bare class name `{name}` that does not resolve to a local class; \
candidates from imports: {candidates:?}"
),
)
.with_ctx(serde_json::json!({
"module": module,
"name": name,
"candidates": candidates,
})),
),
// mq.1: qualified `<owner>.<class>` where `<owner>` is not a
// known module or `<owner>` has no class `<class>`.
W::BadCrossModuleClassRef { module, name } => Some(
ailang_check::Diagnostic::error(
"bad-cross-module-class-ref",
format!(
"module `{module}` references qualified class `{name}` but the owner module is not known \
or does not declare a class by that name"
),
)
.with_ctx(serde_json::json!({
"module": module,
"name": name,
})),
),
// ct.1: a class-reference field contains a `.` — class names
// are not module-qualified in this milestone.
W::QualifiedClassName { module, name, field } => Some(