From 083ee8e0e28ed0d1c4e1df6b5aa12f2709731b50 Mon Sep 17 00:00:00 2001 From: mlugg Date: Mon, 14 Aug 2023 13:06:47 +0100 Subject: InternPool: preserve indices of builtin types when resolved Some builtin types have a special InternPool index (e.g. `.type_info_type`) so that AstGen can refer to them before semantic analysis. Unfortunately, this previously led to a second index existing to refer to the type once it was resolved, complicating Sema by having the concept of an "unresolved" type index. This change makes Sema modify these InternPool indices in-place to contain the expanded representation when resolved. The analysis of the corresponding decls is caught in `Module.semaDecl`, and a field is set on Sema telling it which index to place struct/union/enum types at. This system could break if `std.builtin` contained complex decls which evaluate multiple struct types, but this will be caught by the assertions in `InternPool.resolveBuiltinType`. The AstGen result types which were disabled in 6917a8c have been re-enabled. Resolves: #16603 --- src/InternPool.zig | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'src/InternPool.zig') diff --git a/src/InternPool.zig b/src/InternPool.zig index 178bc6870c..bde6c11256 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -7176,3 +7176,33 @@ fn unwrapCoercedFunc(ip: *const InternPool, i: Index) Index { else => unreachable, }; } + +/// Having resolved a builtin type to a real struct/union/enum (which is now at `resolverd_index`), +/// make `want_index` refer to this type instead. This invalidates `resolved_index`, so must be +/// called only when it is guaranteed that no reference to `resolved_index` exists. +pub fn resolveBuiltinType(ip: *InternPool, want_index: Index, resolved_index: Index) void { + assert(@intFromEnum(want_index) >= @intFromEnum(Index.first_type)); + assert(@intFromEnum(want_index) <= @intFromEnum(Index.last_type)); + + // Make sure the type isn't already resolved! + assert(ip.indexToKey(want_index) == .simple_type); + + // Make sure it's the same kind of type + assert((ip.zigTypeTagOrPoison(want_index) catch unreachable) == + (ip.zigTypeTagOrPoison(resolved_index) catch unreachable)); + + // Copy the data + const item = ip.items.get(@intFromEnum(resolved_index)); + ip.items.set(@intFromEnum(want_index), item); + + if (std.debug.runtime_safety) { + // Make the value unreachable - this is a weird value which will make (incorrect) existing + // references easier to spot + ip.items.set(@intFromEnum(resolved_index), .{ + .tag = .simple_value, + .data = @intFromEnum(SimpleValue.@"unreachable"), + }); + } else { + // TODO: add the index to a free-list for reuse + } +} -- cgit v1.2.3