| author | |
| committer | |
| log | 99b90a431538de898ad2d49fb719f64572d849ab |
| tree | 719c3b59eac4d6adea5c711ee2bef0dd7c58183a |
| parent | 9c7759bdc3cc6e44ef5ab1c5ce58d310659177df |
4 files changed, 163 insertions(+), 12 deletions(-)
lib/std/zig/AstGen.zig+15-12| ... | ... | @@ -5001,6 +5001,10 @@ fn structDeclInner( |
| 5001 | 5001 | ); |
| 5002 | 5002 | if (field_comptime_bits) |bits| @memset(bits.get(astgen), 0); |
| 5003 | 5003 | |
| 5004 | const old_hasher = astgen.src_hasher; | |
| 5005 | defer astgen.src_hasher = old_hasher; | |
| 5006 | astgen.src_hasher = .init(.{}); | |
| 5007 | ||
| 5004 | 5008 | // Before any field bodies comes the backing int type, if specified. |
| 5005 | 5009 | const backing_int_type_body_len: ?u32 = if (maybe_backing_int_node.unwrap()) |backing_int_node| len: { |
| 5006 | 5010 | if (layout != .@"packed") return astgen.failNode( |
| ... | ... | @@ -5008,6 +5012,7 @@ fn structDeclInner( |
| 5008 | 5012 | "non-packed struct does not support backing integer type", |
| 5009 | 5013 | .{}, |
| 5010 | 5014 | ); |
| 5015 | astgen.src_hasher.update(astgen.tree.getNodeSource(backing_int_node)); | |
| 5011 | 5016 | const type_ref = try typeExpr(&block_scope, &namespace.base, backing_int_node); |
| 5012 | 5017 | if (!block_scope.endsWithNoReturn()) { |
| 5013 | 5018 | _ = try block_scope.addBreak(.break_inline, decl_inst, type_ref); |
| ... | ... | @@ -5017,10 +5022,6 @@ fn structDeclInner( |
| 5017 | 5022 | break :len body_len; |
| 5018 | 5023 | } else null; |
| 5019 | 5024 | |
| 5020 | const old_hasher = astgen.src_hasher; | |
| 5021 | defer astgen.src_hasher = old_hasher; | |
| 5022 | astgen.src_hasher = .init(.{}); | |
| 5023 | ||
| 5024 | 5025 | var next_field_idx: u32 = 0; |
| 5025 | 5026 | for (container_decl.ast.members) |member_node| { |
| 5026 | 5027 | var member = switch (try containerMember(&block_scope, &namespace.base, &wip_decls, member_node)) { |
| ... | ... | @@ -5281,8 +5282,13 @@ fn unionDeclInner( |
| 5281 | 5282 | const field_align_body_lens = try scratch.addOptionalSlice(scan_result.any_field_aligns, scan_result.fields_len); |
| 5282 | 5283 | const field_value_body_lens = try scratch.addOptionalSlice(scan_result.any_field_values, scan_result.fields_len); |
| 5283 | 5284 | |
| 5285 | const old_hasher = astgen.src_hasher; | |
| 5286 | defer astgen.src_hasher = old_hasher; | |
| 5287 | astgen.src_hasher = .init(.{}); | |
| 5288 | ||
| 5284 | 5289 | // Before any field bodies comes the tag/backing type, if specified. |
| 5285 | 5290 | const arg_type_body_len: ?u32 = if (opt_arg_node.unwrap()) |arg_node| len: { |
| 5291 | astgen.src_hasher.update(astgen.tree.getNodeSource(arg_node)); | |
| 5286 | 5292 | const type_ref = try typeExpr(&block_scope, &namespace.base, arg_node); |
| 5287 | 5293 | if (!block_scope.endsWithNoReturn()) { |
| 5288 | 5294 | _ = try block_scope.addBreak(.break_inline, decl_inst, type_ref); |
| ... | ... | @@ -5292,10 +5298,6 @@ fn unionDeclInner( |
| 5292 | 5298 | break :len body_len; |
| 5293 | 5299 | } else null; |
| 5294 | 5300 | |
| 5295 | const old_hasher = astgen.src_hasher; | |
| 5296 | defer astgen.src_hasher = old_hasher; | |
| 5297 | astgen.src_hasher = .init(.{}); | |
| 5298 | ||
| 5299 | 5301 | var next_field_idx: u32 = 0; |
| 5300 | 5302 | for (members) |member_node| { |
| 5301 | 5303 | var member = switch (try containerMember(&block_scope, &namespace.base, &wip_decls, member_node)) { |
| ... | ... | @@ -5486,8 +5488,13 @@ fn containerDecl( |
| 5486 | 5488 | const field_names = try scratch.addSlice(fields_len); |
| 5487 | 5489 | const field_value_body_lens = try scratch.addOptionalSlice(scan_result.any_field_values, fields_len); |
| 5488 | 5490 | |
| 5491 | const old_hasher = astgen.src_hasher; | |
| 5492 | defer astgen.src_hasher = old_hasher; | |
| 5493 | astgen.src_hasher = .init(.{}); | |
| 5494 | ||
| 5489 | 5495 | // Before any field bodies comes the tag type, if specified. |
| 5490 | 5496 | 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)); | |
| 5491 | 5498 | const type_ref = try typeExpr(&block_scope, &namespace.base, tag_type_node); |
| 5492 | 5499 | if (!block_scope.endsWithNoReturn()) { |
| 5493 | 5500 | _ = try block_scope.addBreak(.break_inline, decl_inst, type_ref); |
| ... | ... | @@ -5497,10 +5504,6 @@ fn containerDecl( |
| 5497 | 5504 | break :len body_len; |
| 5498 | 5505 | } else null; |
| 5499 | 5506 | |
| 5500 | const old_hasher = astgen.src_hasher; | |
| 5501 | defer astgen.src_hasher = old_hasher; | |
| 5502 | astgen.src_hasher = .init(.{}); | |
| 5503 | ||
| 5504 | 5507 | var next_field_idx: u32 = 0; |
| 5505 | 5508 | var opt_nonexhaustive_node: Ast.Node.OptionalIndex = .none; |
| 5506 | 5509 | 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 | |
| 3 | const Foo = packed struct(u8) { a: u4, b: i4 }; | |
| 4 | const Bar = packed union(u10) { a: u10, b: i10 }; | |
| 5 | pub fn main() void {} | |
| 6 | comptime { | |
| 7 | @compileLog(@typeInfo(Foo).@"struct".backing_integer.?); | |
| 8 | } | |
| 9 | comptime { | |
| 10 | @compileLog(@bitSizeOf(Bar)); | |
| 11 | } | |
| 12 | const std = @import("std"); | |
| 13 | const 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 | |
| 21 | const Foo = packed struct(i8) { a: u4, b: i4 }; | |
| 22 | const Bar = packed union(i10) { a: u10, b: i10 }; | |
| 23 | pub fn main() void {} | |
| 24 | comptime { | |
| 25 | @compileLog(@typeInfo(Foo).@"struct".backing_integer.?); | |
| 26 | } | |
| 27 | comptime { | |
| 28 | @compileLog(@bitSizeOf(Bar)); | |
| 29 | } | |
| 30 | const std = @import("std"); | |
| 31 | const 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 | |
| 39 | const Foo = packed struct(i5) { a: u4, b: i4 }; | |
| 40 | const Bar = packed union(i8) { a: u10, b: i10 }; | |
| 41 | pub fn main() void {} | |
| 42 | comptime { | |
| 43 | @compileLog(@typeInfo(Foo).@"struct".backing_integer.?); | |
| 44 | } | |
| 45 | comptime { | |
| 46 | @compileLog(@bitSizeOf(Bar)); | |
| 47 | } | |
| 48 | const std = @import("std"); | |
| 49 | const 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 | |
| 60 | const Foo = packed struct(u10) { a: u4, b: i4 }; | |
| 61 | const Bar = packed union(u32) { a: u10, b: i10 }; | |
| 62 | pub fn main() void {} | |
| 63 | comptime { | |
| 64 | @compileLog(@typeInfo(Foo).@"struct".backing_integer.?); | |
| 65 | } | |
| 66 | comptime { | |
| 67 | @compileLog(@bitSizeOf(Bar)); | |
| 68 | } | |
| 69 | const std = @import("std"); | |
| 70 | const 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 { |
| 59 | 59 | const std = @import("std"); |
| 60 | 60 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 61 | 61 | #expect_stdout="a\n" |
| 62 | #update=specify tag directly | |
| 63 | #file=main.zig | |
| 64 | const Foo = enum(u3) { | |
| 65 | a, | |
| 66 | b, | |
| 67 | c, | |
| 68 | d, | |
| 69 | e, | |
| 70 | }; | |
| 71 | pub fn main() !void { | |
| 72 | @compileLog(@typeInfo(Foo).@"enum".tag_type); | |
| 73 | } | |
| 74 | const std = @import("std"); | |
| 75 | const 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 | |
| 80 | const Foo = enum(u8) { | |
| 81 | a, | |
| 82 | b, | |
| 83 | c, | |
| 84 | d, | |
| 85 | e, | |
| 86 | }; | |
| 87 | pub fn main() !void { | |
| 88 | @compileLog(@typeInfo(Foo).@"enum".tag_type); | |
| 89 | } | |
| 90 | const std = @import("std"); | |
| 91 | const 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 | |
| 3 | const A = enum(u8) { a }; | |
| 4 | const B = enum(u8) { b }; | |
| 5 | const Foo = union(A) { a: u8 }; | |
| 6 | pub 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 | } | |
| 11 | const std = @import("std"); | |
| 12 | #expect_stdout="a\n" | |
| 13 | ||
| 14 | #update=change tag type | |
| 15 | #file=main.zig | |
| 16 | const A = enum(u8) { a }; | |
| 17 | const B = enum(u8) { b }; | |
| 18 | const Foo = union(B) { a: u8 }; | |
| 19 | pub 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 | } | |
| 24 | const 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 | |
| 30 | const A = enum(u8) { a }; | |
| 31 | const B = enum(u8) { b }; | |
| 32 | const Foo = union(B) { b: u8 }; | |
| 33 | pub 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 | } | |
| 38 | const std = @import("std"); | |
| 39 | #expect_stdout="b\n" |