# 0069 — forward identifier type alias is falsely rejected by unknown-type pass > **RESOLVED.** Root cause: `Lowering.scanDecls`' `.identifier` alias branch only > registered `A :: B` into `ProgramIndex.type_alias_map` when `B` was already > known (in `type_alias_map` or the `TypeTable`). A forward target declared later > (`MyChain :: MyInt; MyInt :: s32;`) was never present during the single forward > scan, so the alias name went unregistered and the A2.4 unknown-type pass — which > treats `type_alias_map` keys as declared types — flagged its uses. > Fix: added a fixpoint post-pass `resolveForwardIdentifierAliases` at the end of > `scanDecls` that re-resolves identifier-RHS aliases until no progress, after every > top-level name has been seen. A value const is never an `.identifier` node and an > alias whose target is a value const still misses both lookups, so issue 0068's > value-const rejection is preserved. Regression: > `examples/0132-types-forward-type-alias.sx`. ## Symptom A forward-referenced identifier type alias is rejected as an unknown type, even though the same alias chain works when ordered after its target. Observed: `MyChain` is diagnosed as an unknown type. Expected: `MyChain :: MyInt; MyInt :: s32;` should resolve `MyChain` to `s32` when used in a type annotation, matching the existing ordered-chain behavior (`MyInt :: s32; MyChain :: MyInt;`). ## Reproduction ```sx MyChain :: MyInt; MyInt :: s32; main :: () -> s32 { v: MyChain = 7; return v; } ``` Run: ```sh ./zig-out/bin/sx run .sx-tmp/probe-0068-forward-alias.sx ``` Observed output: ```text error: unknown type 'MyChain' --> .sx-tmp/probe-0068-forward-alias.sx:7:8 | 7 | v: MyChain = 7; | ^^^^^^^ ``` The repro is standalone; the inline source above is sufficient to recreate the scratch file under `.sx-tmp/`. ## Investigation prompt Fix issue 0069: a forward-referenced identifier type alias must not be falsely rejected by the A2.4 unknown-type diagnostic pass. Context: - This surfaced while re-reviewing `8770145`, the issue-0068 fix. That fix correctly stopped arbitrary value consts (`NotAType :: 123`) from satisfying the unknown-type check. - Ordered identifier aliases still work: `MyInt :: s32; MyChain :: MyInt;`. - `.call` type aliases still work: `Vec3 :: Vec(3, f32);` and `Foo :: Complex(u32);`. - The failing shape is specifically a forward identifier alias: `MyChain :: MyInt; MyInt :: s32;`. Suspected area: - `src/ir/lower.zig`, `Lowering.scanDecls`, especially the `.identifier` alias branch for `const_decl` values. It only inserts `cd.name` into `ProgramIndex.type_alias_map` if the RHS is already in `type_alias_map` or already registered in the `TypeTable`. A forward target is not present yet, so the alias name is never recorded. - `src/ir/semantic_diagnostics.zig`, `UnknownTypeChecker.collectDeclaredTypeNames` / `reportIfUnknownType`. After issue 0068, `.identifier` aliases are intentionally excluded from `constValueIntroducesType` and are supposed to be covered by canonical facts (`ProgramIndex.type_alias_map` / `TypeTable`). Because the forward alias never reaches those facts, the checker flags the alias as unknown. Likely fix: - Do not reintroduce the issue-0068 bug by adding all `.identifier` const names to the declared-type set. - Instead, make identifier aliases converge through canonical alias facts even when the RHS is declared later. A small two-pass alias registration/resolution in `scanDecls`, or an explicit pending-alias graph that resolves after all top-level declarations are scanned, would keep `ProgramIndex.type_alias_map` authoritative without accepting value constants. - Preserve value const rejection: `NotAType :: 123; v: NotAType` must continue to emit `unknown type 'NotAType'`. - Preserve ordered/chained aliases and type-returning call aliases: `examples/0116-types-type-alias-size-align.sx`, `examples/0201-generics-generic-struct.sx`, and `examples/1117-diagnostics-value-const-as-type-rejected.sx`. Verification: - Add a focused regression for the repro above, likely in the `01xx` types block because the desired behavior is successful alias resolution. - Run the new regression and the existing alias/diagnostic guards: ```sh zig build zig build test bash tests/run_examples.sh ``` Expected result: the forward alias program compiles/runs (returning `7`), the issue-0068 value-const case still fails with a diagnostic, and the full suite passes.