authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-02-09 15:50:46+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-03-03 22:18:02+00:00
log501e84a96aa18fae7c345b0b54efa652cea85b38
treecf5464d10baaf7365140c894513c9a44431645f5
parentedabcf61927f9699f9b869f304e9aed97f2c4a47

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.

2 files changed, 38 insertions(+), 10 deletions(-)

src/Zcu/PerThread.zig+13-10
...@@ -479,36 +479,39 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void {...@@ -479,36 +479,39 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void {
479 };479 };
480 if (!has_namespace) continue;480 if (!has_namespace) continue;
481481
482 var old_names: std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, void) = .empty;482 // Value is whether the declaration is `pub`.
483 var old_names: std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, bool) = .empty;
483 defer old_names.deinit(zcu.gpa);484 defer old_names.deinit(zcu.gpa);
484 {485 {
485 var it = old_zir.declIterator(old_inst);486 var it = old_zir.declIterator(old_inst);
486 while (it.next()) |decl_inst| {487 while (it.next()) |decl_inst| {
487 const name_zir = old_zir.getDeclaration(decl_inst).name;488 const old_decl = old_zir.getDeclaration(decl_inst);
488 if (name_zir == .empty) continue;489 if (old_decl.name == .empty) continue;
489 const name_ip = try zcu.intern_pool.getOrPutString(490 const name_ip = try zcu.intern_pool.getOrPutString(
490 zcu.gpa,491 zcu.gpa,
491 pt.tid,492 pt.tid,
492 old_zir.nullTerminatedString(name_zir),493 old_zir.nullTerminatedString(old_decl.name),
493 .no_embedded_nulls,494 .no_embedded_nulls,
494 );495 );
495 try old_names.put(zcu.gpa, name_ip, {});496 try old_names.put(zcu.gpa, name_ip, old_decl.is_pub);
496 }497 }
497 }498 }
498 var any_change = false;499 var any_change = false;
499 {500 {
500 var it = new_zir.declIterator(new_inst);501 var it = new_zir.declIterator(new_inst);
501 while (it.next()) |decl_inst| {502 while (it.next()) |decl_inst| {
502 const name_zir = new_zir.getDeclaration(decl_inst).name;503 const new_decl = new_zir.getDeclaration(decl_inst);
503 if (name_zir == .empty) continue;504 if (new_decl.name == .empty) continue;
504 const name_ip = try zcu.intern_pool.getOrPutString(505 const name_ip = try zcu.intern_pool.getOrPutString(
505 zcu.gpa,506 zcu.gpa,
506 pt.tid,507 pt.tid,
507 new_zir.nullTerminatedString(name_zir),508 new_zir.nullTerminatedString(new_decl.name),
508 .no_embedded_nulls,509 .no_embedded_nulls,
509 );510 );
510 if (old_names.swapRemove(name_ip)) continue;511 if (old_names.fetchSwapRemove(name_ip)) |kv| {
511 // Name added512 if (kv.value == new_decl.is_pub) continue;
513 }
514 // Name added, or changed whether it's pub
512 any_change = true;515 any_change = true;
513 try zcu.markDependeeOutdated(.not_marked_po, .{ .namespace_name = .{516 try zcu.markDependeeOutdated(.not_marked_po, .{ .namespace_name = .{
514 .namespace = tracked_inst_index,517 .namespace = tracked_inst_index,
test/incremental/make_decl_pub created+25
...@@ -0,0 +1,25 @@
1#target=x86_64-linux-selfhosted
2#target=x86_64-linux-cbe
3#target=x86_64-windows-cbe
4#target=wasm32-wasi-selfhosted
5#update=initial version
6#file=main.zig
7const foo = @import("foo.zig");
8pub fn main() !void {
9 try foo.hello();
10}
11#file=foo.zig
12const std = @import("std");
13fn hello() !void {
14 try std.io.getStdOut().writeAll("Hello, World!\n");
15}
16#expect_error=main.zig:3:12: error: 'hello' is not marked 'pub'
17#expect_error=foo.zig:2:1: note: declared here
18
19#update=make hello pub
20#file=foo.zig
21const std = @import("std");
22pub fn hello() !void {
23 try std.io.getStdOut().writeAll("Hello, World!\n");
24}
25#expect_stdout="Hello, World!\n"