tidy: rustdoc-sweep + drift-test-narrowing — autonomous batch
Two unrelated hygiene iters bundled because they shipped together in one autonomous-while-Boss-away batch: - iter rustdoc-sweep: cleared all 23 `cargo doc --workspace --no-deps` warnings (17 in ailang-check + 4 in ailang-core + 2 in ailang-surface). Two warning classes: pub-doc-comment links to pub(crate)/private items (15 hits — replaced with plain backtick-code-spans), and unresolved/ambiguous links (8 hits — fully-qualified, disambiguated to fn-form, or escaped). No behaviour change; tests 562 → 562. - iter drift-test-narrowing: design_schema_drift.rs now scans §"Data model" only via new helper data_model_section(), instead of full DESIGN.md. Closes the audit-form-a-precursor [high] "anchor-elsewhere-passes-silently" failure mode. All 38 anchors verified pre-edit to live in §"Data model" so the tightening doesn't regress to red. New pin data_model_section_is_bounded guards the extractor against silent regression. Tests 562 → 563.
This commit is contained in:
@@ -79,7 +79,7 @@
|
||||
//! desugar pass eliminates it before typecheck/codegen by **lifting**
|
||||
//! the LetRec to a synthetic top-level fn in the same module. The
|
||||
//! lifted name has the form `<hint>$lr_N`, fresh against both the
|
||||
//! existing module-top-level def names and the [`Desugarer::used`] set.
|
||||
//! existing module-top-level def names and the `Desugarer::used` set.
|
||||
//! Inside the LetRec's `body` and `in_term`, every reference to the
|
||||
//! original local name is rewritten via [`subst_var`] to the lifted
|
||||
//! name. The lifted [`FnDef`] is appended to the module's `defs` so
|
||||
|
||||
@@ -90,7 +90,7 @@ pub struct Registry {
|
||||
/// defining module. Used by [`Self::normalize_type_for_lookup`] to
|
||||
/// rewrite a bare `Type::Con.name` to its always-qualified form
|
||||
/// before computing the registry key. Primitives are not present.
|
||||
/// Populated in [`build_registry`] from the same scan that builds
|
||||
/// Populated in `build_registry` from the same scan that builds
|
||||
/// the entry map.
|
||||
///
|
||||
/// Keyed by `(owning_module, bare_name)`, value is the
|
||||
@@ -99,7 +99,7 @@ pub struct Registry {
|
||||
/// module M is `(M, "Foo")`, bare `Foo` from module N is
|
||||
/// `(N, "Foo")`, and the two carry distinct canonical
|
||||
/// qualifications under
|
||||
/// [`normalize_type_for_registry`]. Pre-ctt.2 the key was
|
||||
/// `normalize_type_for_registry`. Pre-ctt.2 the key was
|
||||
/// the bare name alone, and a workspace with two `type Foo`
|
||||
/// declarations silently overwrote one entry, then tripped
|
||||
/// `DuplicateInstance` on the loser-side instance after
|
||||
@@ -441,7 +441,7 @@ pub fn load_workspace(entry_path: &Path) -> Result<Workspace, WorkspaceLoadError
|
||||
/// Load a workspace using a caller-supplied per-module loader.
|
||||
///
|
||||
/// The standard entry point [`load_workspace`] is a thin wrapper that
|
||||
/// passes [`load_one`] as the loader and so only accepts `.ail.json`
|
||||
/// passes `load_one` as the loader and so only accepts `.ail.json`
|
||||
/// files. Pass a different loader (for example, an extension-dispatching
|
||||
/// loader from `ailang-surface`) to accept `.ail` source files as well.
|
||||
///
|
||||
|
||||
@@ -8,7 +8,11 @@
|
||||
//! The exhaustive `match` per enum is the load-bearing mechanism: adding a
|
||||
//! new variant without a matching arm fails compilation before the test runs.
|
||||
//! Once the variant is matched, the test asserts the anchor is present in
|
||||
//! DESIGN.md.
|
||||
//! §"Data model" specifically — not anywhere in DESIGN.md. The narrow scope
|
||||
//! is load-bearing: before this tightening, the test scanned the whole
|
||||
//! document, so an anchor that appeared only in §"Decision 11" (or any
|
||||
//! other discussion section) was treated as "present" even though
|
||||
//! §"Data model" — the canonical schema reference — was missing it.
|
||||
|
||||
use ailang_core::ast::{
|
||||
ClassDef, ClassMethod, Constraint, ConstDef, Ctor, Def, FnDef, InstanceDef,
|
||||
@@ -17,6 +21,21 @@ use ailang_core::ast::{
|
||||
|
||||
const DESIGN_MD: &str = include_str!("../../../docs/DESIGN.md");
|
||||
|
||||
/// Slice of `DESIGN_MD` covering only §"Data model": from the `## Data model`
|
||||
/// header to the next top-level `## ` header. Returned as a `&'static str`
|
||||
/// because `DESIGN_MD` is itself static. Panics if §"Data model" is missing
|
||||
/// — that itself would be drift.
|
||||
fn data_model_section() -> &'static str {
|
||||
let start = DESIGN_MD
|
||||
.find("## Data model")
|
||||
.expect("DESIGN.md must contain `## Data model` header");
|
||||
let from_start = &DESIGN_MD[start..];
|
||||
match from_start.find("\n## ") {
|
||||
Some(end) => &from_start[..end],
|
||||
None => from_start,
|
||||
}
|
||||
}
|
||||
|
||||
/// Every `Term` variant must have its JSON-schema anchor present in
|
||||
/// DESIGN.md §"Data model". An LLM author cannot produce a term variant
|
||||
/// whose `"t"` tag is absent from the canonical schema document.
|
||||
@@ -139,7 +158,7 @@ fn design_md_anchors_every_term_variant() {
|
||||
Term::ReuseAs { .. } => "reuse-as",
|
||||
};
|
||||
assert!(
|
||||
DESIGN_MD.contains(anchor),
|
||||
data_model_section().contains(anchor),
|
||||
"DESIGN.md §Data-model is missing anchor `{anchor}` for a Term variant — \
|
||||
add it to docs/DESIGN.md"
|
||||
);
|
||||
@@ -169,7 +188,7 @@ fn design_md_anchors_every_pattern_variant() {
|
||||
Pattern::Ctor { .. } => "ctor",
|
||||
};
|
||||
assert!(
|
||||
DESIGN_MD.contains(anchor),
|
||||
data_model_section().contains(anchor),
|
||||
"DESIGN.md §Data-model is missing anchor `{anchor}` for a Pattern variant"
|
||||
);
|
||||
}
|
||||
@@ -202,7 +221,7 @@ fn design_md_anchors_every_type_variant() {
|
||||
Type::Forall { .. } => "forall",
|
||||
};
|
||||
assert!(
|
||||
DESIGN_MD.contains(anchor),
|
||||
data_model_section().contains(anchor),
|
||||
"DESIGN.md §Data-model is missing anchor `{anchor}` for a Type variant"
|
||||
);
|
||||
}
|
||||
@@ -231,7 +250,7 @@ fn design_md_anchors_every_literal_variant() {
|
||||
Literal::Float { .. } => "float",
|
||||
};
|
||||
assert!(
|
||||
DESIGN_MD.contains(anchor),
|
||||
data_model_section().contains(anchor),
|
||||
"DESIGN.md §Data-model is missing anchor `{anchor}` for a Literal variant"
|
||||
);
|
||||
}
|
||||
@@ -302,7 +321,7 @@ fn design_md_anchors_every_def_kind() {
|
||||
Def::Instance(_) => "instance",
|
||||
};
|
||||
assert!(
|
||||
DESIGN_MD.contains(anchor),
|
||||
data_model_section().contains(anchor),
|
||||
"DESIGN.md §Data-model is missing anchor `{anchor}` for a Def kind"
|
||||
);
|
||||
}
|
||||
@@ -326,7 +345,7 @@ fn design_md_anchors_every_parammode_variant() {
|
||||
ParamMode::Borrow => "borrow",
|
||||
};
|
||||
assert!(
|
||||
DESIGN_MD.contains(anchor),
|
||||
data_model_section().contains(anchor),
|
||||
"DESIGN.md §Data-model is missing anchor `{anchor}` for a ParamMode variant"
|
||||
);
|
||||
}
|
||||
@@ -363,8 +382,35 @@ fn design_md_anchors_nested_struct_keys() {
|
||||
|
||||
for anchor in anchors {
|
||||
assert!(
|
||||
DESIGN_MD.contains(anchor),
|
||||
data_model_section().contains(anchor),
|
||||
"DESIGN.md §Data-model is missing nested-struct-key anchor `{anchor}`"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Pin the §"Data model" section extractor itself: it must return a
|
||||
/// non-empty slice starting with `## Data model`, and it must NOT bleed
|
||||
/// into the next top-level section (`## Pipeline` today). A bug in the
|
||||
/// extractor would otherwise silently widen every drift test's scope
|
||||
/// back toward full-document scanning — the failure mode this file's
|
||||
/// tightening exists to prevent.
|
||||
#[test]
|
||||
fn data_model_section_is_bounded() {
|
||||
let section = data_model_section();
|
||||
assert!(
|
||||
section.starts_with("## Data model"),
|
||||
"section must start at the §Data model header; got first 40 bytes: {:?}",
|
||||
§ion[..40.min(section.len())]
|
||||
);
|
||||
assert!(
|
||||
!section.contains("\n## Pipeline"),
|
||||
"section must stop before the next top-level header (\\n## Pipeline); \
|
||||
extractor regressed to whole-document scanning"
|
||||
);
|
||||
assert!(
|
||||
section.len() > 1000,
|
||||
"§Data model is the canonical schema reference; a slice shorter than \
|
||||
1 KB suggests the extractor truncated; got {} bytes",
|
||||
section.len()
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user