iter ct.1.1: validator scaffolding + Type::Con canonical-form rules

Adds BareCrossModuleTypeRef / BadCrossModuleTypeRef / QualifiedClassName
to WorkspaceLoadError plus the validate_canonical_type_names function
that enforces the canonical-form rule on every Type::Con name reachable
from any def (including Term::Lam.param_tys / .ret_ty and Term::LetRec.ty).
Term::Ctor.type_name and class-name fields land in Tasks 2 + 3; the
validator is not yet wired into load_workspace (Task 6). Seven RED-first
unit tests cover the cases enumerated in spec section Testing strategy
plus a Lam-embedded-type smuggle-prevention test.

main.rs gains diagnostic arms for the three new variants to keep the
exhaustive match compiling.
This commit is contained in:
2026-05-11 00:58:37 +02:00
parent 7ee4300ae2
commit 000b84dda7
2 changed files with 549 additions and 1 deletions
+49
View File
@@ -1153,6 +1153,55 @@ fn workspace_error_to_diagnostic(
"module": name,
})),
),
// ct.1 (canonical-type-names): bare `Type::Con` that does not
// resolve to a primitive or a local TypeDef of the owning
// module. `candidates` lists qualified suggestions scanned
// from imports.
W::BareCrossModuleTypeRef { module, name, candidates } => Some(
ailang_check::Diagnostic::error(
"bare-cross-module-type-ref",
format!(
"module `{module}` contains bare type name `{name}` that does not resolve to a local type; \
candidates from imports: {candidates:?}"
),
)
.with_ctx(serde_json::json!({
"module": module,
"name": name,
"candidates": candidates,
})),
),
// ct.1: qualified `<owner>.<type>` where `<owner>` is not a
// known module or `<owner>` has no `TypeDef <type>`.
W::BadCrossModuleTypeRef { module, name } => Some(
ailang_check::Diagnostic::error(
"bad-cross-module-type-ref",
format!(
"module `{module}` references qualified type `{name}` but the owner module is not known \
or does not declare a type 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(
ailang_check::Diagnostic::error(
"qualified-class-name",
format!(
"module `{module}` contains qualified class name `{name}` in field `{field}`; \
class names are not module-qualified in this milestone"
),
)
.with_ctx(serde_json::json!({
"module": module,
"name": name,
"field": field,
})),
),
}
}