incremental: invalidate namespace dependencies when a name changes visibility

We could have more fine-grained dependencies here, but I think this is
fine for now.
This commit is contained in:
mlugg 2025-02-09 15:50:46 +00:00 committed by Matthew Lugg
parent edabcf6192
commit 501e84a96a
2 changed files with 38 additions and 10 deletions

View file

@ -479,36 +479,39 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void {
}; };
if (!has_namespace) continue; if (!has_namespace) continue;
var old_names: std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, void) = .empty; // Value is whether the declaration is `pub`.
var old_names: std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, bool) = .empty;
defer old_names.deinit(zcu.gpa); defer old_names.deinit(zcu.gpa);
{ {
var it = old_zir.declIterator(old_inst); var it = old_zir.declIterator(old_inst);
while (it.next()) |decl_inst| { while (it.next()) |decl_inst| {
const name_zir = old_zir.getDeclaration(decl_inst).name; const old_decl = old_zir.getDeclaration(decl_inst);
if (name_zir == .empty) continue; if (old_decl.name == .empty) continue;
const name_ip = try zcu.intern_pool.getOrPutString( const name_ip = try zcu.intern_pool.getOrPutString(
zcu.gpa, zcu.gpa,
pt.tid, pt.tid,
old_zir.nullTerminatedString(name_zir), old_zir.nullTerminatedString(old_decl.name),
.no_embedded_nulls, .no_embedded_nulls,
); );
try old_names.put(zcu.gpa, name_ip, {}); try old_names.put(zcu.gpa, name_ip, old_decl.is_pub);
} }
} }
var any_change = false; var any_change = false;
{ {
var it = new_zir.declIterator(new_inst); var it = new_zir.declIterator(new_inst);
while (it.next()) |decl_inst| { while (it.next()) |decl_inst| {
const name_zir = new_zir.getDeclaration(decl_inst).name; const new_decl = new_zir.getDeclaration(decl_inst);
if (name_zir == .empty) continue; if (new_decl.name == .empty) continue;
const name_ip = try zcu.intern_pool.getOrPutString( const name_ip = try zcu.intern_pool.getOrPutString(
zcu.gpa, zcu.gpa,
pt.tid, pt.tid,
new_zir.nullTerminatedString(name_zir), new_zir.nullTerminatedString(new_decl.name),
.no_embedded_nulls, .no_embedded_nulls,
); );
if (old_names.swapRemove(name_ip)) continue; if (old_names.fetchSwapRemove(name_ip)) |kv| {
// Name added if (kv.value == new_decl.is_pub) continue;
}
// Name added, or changed whether it's pub
any_change = true; any_change = true;
try zcu.markDependeeOutdated(.not_marked_po, .{ .namespace_name = .{ try zcu.markDependeeOutdated(.not_marked_po, .{ .namespace_name = .{
.namespace = tracked_inst_index, .namespace = tracked_inst_index,

View file

@ -0,0 +1,25 @@
#target=x86_64-linux-selfhosted
#target=x86_64-linux-cbe
#target=x86_64-windows-cbe
#target=wasm32-wasi-selfhosted
#update=initial version
#file=main.zig
const foo = @import("foo.zig");
pub fn main() !void {
try foo.hello();
}
#file=foo.zig
const std = @import("std");
fn hello() !void {
try std.io.getStdOut().writeAll("Hello, World!\n");
}
#expect_error=main.zig:3:12: error: 'hello' is not marked 'pub'
#expect_error=foo.zig:2:1: note: declared here
#update=make hello pub
#file=foo.zig
const std = @import("std");
pub fn hello() !void {
try std.io.getStdOut().writeAll("Hello, World!\n");
}
#expect_stdout="Hello, World!\n"