fix(ir): resolve forward identifier type aliases in scanDecls (issue 0069)
scanDecls' `.identifier` alias branch registered `A :: B` into ProgramIndex.type_alias_map only 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 as `unknown type 'MyChain'`. Add 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 (forward alias + forward chain). Gate: zig build, zig build test, run_examples.sh -> 353/0.
This commit is contained in:
@@ -1253,6 +1253,43 @@ pub const Lowering = struct {
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
self.resolveForwardIdentifierAliases(decls);
|
||||
}
|
||||
|
||||
/// Resolve identifier-RHS type aliases whose target is declared LATER in the
|
||||
/// file. The forward scan above only registers an alias (`A :: B`) when `B`
|
||||
/// is already in `type_alias_map` / the `TypeTable`; a forward target isn't
|
||||
/// yet present, so `A` is left unregistered and its uses get falsely flagged
|
||||
/// as an unknown type (issue 0069). Re-resolve to a fixpoint now that every
|
||||
/// top-level name has been seen, so `A :: B; B :: s32;` converges the same as
|
||||
/// the ordered `B :: s32; A :: B;`. A value const is never an `.identifier`
|
||||
/// node (`NotAType :: 123` is an int literal), and an alias whose target is a
|
||||
/// value const still misses both lookups, so neither this pass nor issue 0068
|
||||
/// can register a non-type name.
|
||||
fn resolveForwardIdentifierAliases(self: *Lowering, decls: []const *const Node) void {
|
||||
var progressed = true;
|
||||
while (progressed) {
|
||||
progressed = false;
|
||||
for (decls) |decl| {
|
||||
const cd = switch (decl.data) {
|
||||
.const_decl => |c| c,
|
||||
else => continue,
|
||||
};
|
||||
if (cd.value.data != .identifier) continue;
|
||||
if (self.program_index.type_alias_map.contains(cd.name)) continue;
|
||||
const rhs_name = cd.value.data.identifier.name;
|
||||
if (self.program_index.type_alias_map.get(rhs_name)) |chained| {
|
||||
self.program_index.type_alias_map.put(cd.name, chained) catch {};
|
||||
progressed = true;
|
||||
} else {
|
||||
const name_id = self.module.types.internString(rhs_name);
|
||||
if (self.module.types.findByName(name_id)) |tid| {
|
||||
self.program_index.type_alias_map.put(cd.name, tid) catch {};
|
||||
progressed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Try to convert an array literal's elements into a compile-time ConstantValue.aggregate.
|
||||
|
||||
Reference in New Issue
Block a user