authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-04-22 13:08:52+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-04-23 01:13:22+02:00
log99b90a431538de898ad2d49fb719f64572d849ab
tree719c3b59eac4d6adea5c711ee2bef0dd7c58183a
parent9c7759bdc3cc6e44ef5ab1c5ce58d310659177df

incremental: add misssing dependency on backing/tag type source code


4 files changed, 163 insertions(+), 12 deletions(-)

lib/std/zig/AstGen.zig+15-12
......@@ -5001,6 +5001,10 @@ fn structDeclInner(
50015001 );
50025002 if (field_comptime_bits) |bits| @memset(bits.get(astgen), 0);
50035003
5004 const old_hasher = astgen.src_hasher;
5005 defer astgen.src_hasher = old_hasher;
5006 astgen.src_hasher = .init(.{});
5007
50045008 // Before any field bodies comes the backing int type, if specified.
50055009 const backing_int_type_body_len: ?u32 = if (maybe_backing_int_node.unwrap()) |backing_int_node| len: {
50065010 if (layout != .@"packed") return astgen.failNode(
......@@ -5008,6 +5012,7 @@ fn structDeclInner(
50085012 "non-packed struct does not support backing integer type",
50095013 .{},
50105014 );
5015 astgen.src_hasher.update(astgen.tree.getNodeSource(backing_int_node));
50115016 const type_ref = try typeExpr(&block_scope, &namespace.base, backing_int_node);
50125017 if (!block_scope.endsWithNoReturn()) {
50135018 _ = try block_scope.addBreak(.break_inline, decl_inst, type_ref);
......@@ -5017,10 +5022,6 @@ fn structDeclInner(
50175022 break :len body_len;
50185023 } else null;
50195024
5020 const old_hasher = astgen.src_hasher;
5021 defer astgen.src_hasher = old_hasher;
5022 astgen.src_hasher = .init(.{});
5023
50245025 var next_field_idx: u32 = 0;
50255026 for (container_decl.ast.members) |member_node| {
50265027 var member = switch (try containerMember(&block_scope, &namespace.base, &wip_decls, member_node)) {
......@@ -5281,8 +5282,13 @@ fn unionDeclInner(
52815282 const field_align_body_lens = try scratch.addOptionalSlice(scan_result.any_field_aligns, scan_result.fields_len);
52825283 const field_value_body_lens = try scratch.addOptionalSlice(scan_result.any_field_values, scan_result.fields_len);
52835284
5285 const old_hasher = astgen.src_hasher;
5286 defer astgen.src_hasher = old_hasher;
5287 astgen.src_hasher = .init(.{});
5288
52845289 // Before any field bodies comes the tag/backing type, if specified.
52855290 const arg_type_body_len: ?u32 = if (opt_arg_node.unwrap()) |arg_node| len: {
5291 astgen.src_hasher.update(astgen.tree.getNodeSource(arg_node));
52865292 const type_ref = try typeExpr(&block_scope, &namespace.base, arg_node);
52875293 if (!block_scope.endsWithNoReturn()) {
52885294 _ = try block_scope.addBreak(.break_inline, decl_inst, type_ref);
......@@ -5292,10 +5298,6 @@ fn unionDeclInner(
52925298 break :len body_len;
52935299 } else null;
52945300
5295 const old_hasher = astgen.src_hasher;
5296 defer astgen.src_hasher = old_hasher;
5297 astgen.src_hasher = .init(.{});
5298
52995301 var next_field_idx: u32 = 0;
53005302 for (members) |member_node| {
53015303 var member = switch (try containerMember(&block_scope, &namespace.base, &wip_decls, member_node)) {
......@@ -5486,8 +5488,13 @@ fn containerDecl(
54865488 const field_names = try scratch.addSlice(fields_len);
54875489 const field_value_body_lens = try scratch.addOptionalSlice(scan_result.any_field_values, fields_len);
54885490
5491 const old_hasher = astgen.src_hasher;
5492 defer astgen.src_hasher = old_hasher;
5493 astgen.src_hasher = .init(.{});
5494
54895495 // Before any field bodies comes the tag type, if specified.
54905496 const tag_type_body_len: ?u32 = if (container_decl.ast.arg.unwrap()) |tag_type_node| len: {
5497 astgen.src_hasher.update(astgen.tree.getNodeSource(tag_type_node));
54915498 const type_ref = try typeExpr(&block_scope, &namespace.base, tag_type_node);
54925499 if (!block_scope.endsWithNoReturn()) {
54935500 _ = try block_scope.addBreak(.break_inline, decl_inst, type_ref);
......@@ -5497,10 +5504,6 @@ fn containerDecl(
54975504 break :len body_len;
54985505 } else null;
54995506
5500 const old_hasher = astgen.src_hasher;
5501 defer astgen.src_hasher = old_hasher;
5502 astgen.src_hasher = .init(.{});
5503
55045507 var next_field_idx: u32 = 0;
55055508 var opt_nonexhaustive_node: Ast.Node.OptionalIndex = .none;
55065509 for (container_decl.ast.members) |member_node| {
test/incremental/change_bitpack_backing_int created+77
......@@ -0,0 +1,77 @@
1#update=initial version
2#file=main.zig
3const Foo = packed struct(u8) { a: u4, b: i4 };
4const Bar = packed union(u10) { a: u10, b: i10 };
5pub fn main() void {}
6comptime {
7 @compileLog(@typeInfo(Foo).@"struct".backing_integer.?);
8}
9comptime {
10 @compileLog(@bitSizeOf(Bar));
11}
12const std = @import("std");
13const io = std.Io.Threaded.global_single_threaded.io();
14#expect_error=main.zig:5:5: error: found compile log statement
15#expect_error=main.zig:8:5: note: also here
16#expect_compile_log=@as(type, u8)
17#expect_compile_log=@as(comptime_int, 10)
18
19#update=make backing types signed
20#file=main.zig
21const Foo = packed struct(i8) { a: u4, b: i4 };
22const Bar = packed union(i10) { a: u10, b: i10 };
23pub fn main() void {}
24comptime {
25 @compileLog(@typeInfo(Foo).@"struct".backing_integer.?);
26}
27comptime {
28 @compileLog(@bitSizeOf(Bar));
29}
30const std = @import("std");
31const io = std.Io.Threaded.global_single_threaded.io();
32#expect_error=main.zig:5:5: error: found compile log statement
33#expect_error=main.zig:8:5: note: also here
34#expect_compile_log=@as(type, i8)
35#expect_compile_log=@as(comptime_int, 10)
36
37#update=make backing types too small
38#file=main.zig
39const Foo = packed struct(i5) { a: u4, b: i4 };
40const Bar = packed union(i8) { a: u10, b: i10 };
41pub fn main() void {}
42comptime {
43 @compileLog(@typeInfo(Foo).@"struct".backing_integer.?);
44}
45comptime {
46 @compileLog(@bitSizeOf(Bar));
47}
48const std = @import("std");
49const io = std.Io.Threaded.global_single_threaded.io();
50#expect_error=main.zig:1:20: error: backing integer bit width does not match total bit width of fields
51#expect_error=main.zig:1:27: note: backing integer 'i5' has bit width '5'
52#expect_error=main.zig:1:20: note: struct fields have total bit width '8'
53#expect_error=main.zig:2:35: error: field bit width does not match backing integer
54#expect_error=main.zig:2:35: note: field type 'u10' has bit width '10'
55#expect_error=main.zig:2:26: note: backing integer 'i8' has bit width '8'
56#expect_error=main.zig:2:35: note: all fields in a packed union must have the same bit width
57
58#update=make backing types too big
59#file=main.zig
60const Foo = packed struct(u10) { a: u4, b: i4 };
61const Bar = packed union(u32) { a: u10, b: i10 };
62pub fn main() void {}
63comptime {
64 @compileLog(@typeInfo(Foo).@"struct".backing_integer.?);
65}
66comptime {
67 @compileLog(@bitSizeOf(Bar));
68}
69const std = @import("std");
70const io = std.Io.Threaded.global_single_threaded.io();
71#expect_error=main.zig:1:20: error: backing integer bit width does not match total bit width of fields
72#expect_error=main.zig:1:27: note: backing integer 'u10' has bit width '10'
73#expect_error=main.zig:1:20: note: struct fields have total bit width '8'
74#expect_error=main.zig:2:36: error: field bit width does not match backing integer
75#expect_error=main.zig:2:36: note: field type 'u10' has bit width '10'
76#expect_error=main.zig:2:26: note: backing integer 'u32' has bit width '32'
77#expect_error=main.zig:2:36: note: all fields in a packed union must have the same bit width
test/incremental/change_enum_tag_type+32
......@@ -59,3 +59,35 @@ pub fn main() !void {
5959const std = @import("std");
6060const io = std.Io.Threaded.global_single_threaded.io();
6161#expect_stdout="a\n"
62#update=specify tag directly
63#file=main.zig
64const Foo = enum(u3) {
65 a,
66 b,
67 c,
68 d,
69 e,
70};
71pub fn main() !void {
72 @compileLog(@typeInfo(Foo).@"enum".tag_type);
73}
74const std = @import("std");
75const io = std.Io.Threaded.global_single_threaded.io();
76#expect_error=main.zig:9:5: error: found compile log statement
77#expect_compile_log=@as(type, u3)
78#update=change directly-specified tag type
79#file=main.zig
80const Foo = enum(u8) {
81 a,
82 b,
83 c,
84 d,
85 e,
86};
87pub fn main() !void {
88 @compileLog(@typeInfo(Foo).@"enum".tag_type);
89}
90const std = @import("std");
91const io = std.Io.Threaded.global_single_threaded.io();
92#expect_error=main.zig:9:5: error: found compile log statement
93#expect_compile_log=@as(type, u8)
test/incremental/change_union_tag_type created+39
......@@ -0,0 +1,39 @@
1#update=initial version
2#file=main.zig
3const A = enum(u8) { a };
4const B = enum(u8) { b };
5const Foo = union(A) { a: u8 };
6pub fn main(init: std.process.Init) !void {
7 const field_name = @typeInfo(Foo).@"union".fields[0].name;
8 var stdout_writer = std.Io.File.stdout().writerStreaming(init.io, &.{});
9 try stdout_writer.interface.print("{s}\n", .{field_name});
10}
11const std = @import("std");
12#expect_stdout="a\n"
13
14#update=change tag type
15#file=main.zig
16const A = enum(u8) { a };
17const B = enum(u8) { b };
18const Foo = union(B) { a: u8 };
19pub fn main(init: std.process.Init) !void {
20 const field_name = @typeInfo(Foo).@"union".fields[0].name;
21 var stdout_writer = std.Io.File.stdout().writerStreaming(init.io, &.{});
22 try stdout_writer.interface.print("{s}\n", .{field_name});
23}
24const std = @import("std");
25#expect_error=main.zig:3:24: error: no field named 'a' in enum 'main.B'
26#expect_error=main.zig:2:11: note: enum declared here
27
28#update=change field name to match new tag type
29#file=main.zig
30const A = enum(u8) { a };
31const B = enum(u8) { b };
32const Foo = union(B) { b: u8 };
33pub fn main(init: std.process.Init) !void {
34 const field_name = @typeInfo(Foo).@"union".fields[0].name;
35 var stdout_writer = std.Io.File.stdout().writerStreaming(init.io, &.{});
36 try stdout_writer.interface.print("{s}\n", .{field_name});
37}
38const std = @import("std");
39#expect_stdout="b\n"