| author | |
| committer | |
| log | ec261c5e8d569a7bf90a51638d41de6053f98e1a |
| tree | 7688c129c251adce9d1cb547a697fe9d72a7a3ce |
| parent | 4e4e8902e5bec12befd191b6ce412d60ced819f4 |
86 files changed, 1900 insertions(+), 2470 deletions(-)
build.zig+1-18| ... | @@ -125,7 +125,6 @@ pub fn build(b: *std.Build) !void { | ... | @@ -125,7 +125,6 @@ pub fn build(b: *std.Build) !void { |
| 125 | const skip_darwin = b.option(bool, "skip-darwin", "Main test suite skips targets with darwin OSs") orelse false; | 125 | const skip_darwin = b.option(bool, "skip-darwin", "Main test suite skips targets with darwin OSs") orelse false; |
| 126 | const skip_linux = b.option(bool, "skip-linux", "Main test suite skips targets with linux OS") orelse false; | 126 | const skip_linux = b.option(bool, "skip-linux", "Main test suite skips targets with linux OS") orelse false; |
| 127 | const skip_llvm = b.option(bool, "skip-llvm", "Main test suite skips targets that use LLVM backend") orelse false; | 127 | const skip_llvm = b.option(bool, "skip-llvm", "Main test suite skips targets that use LLVM backend") orelse false; |
| 128 | const skip_test_incremental = b.option(bool, "skip-test-incremental", "Main test step omits dependency on test-incremental step") orelse false; | ||
| 129 | 128 | ||
| 130 | const only_install_lib_files = b.option(bool, "lib-files-only", "Only install library files") orelse false; | 129 | const only_install_lib_files = b.option(bool, "lib-files-only", "Only install library files") orelse false; |
| 131 | 130 | ||
| ... | @@ -781,22 +780,6 @@ pub fn build(b: *std.Build) !void { | ... | @@ -781,22 +780,6 @@ pub fn build(b: *std.Build) !void { |
| 781 | test_step.dependOn(check_oracle_step); | 780 | test_step.dependOn(check_oracle_step); |
| 782 | } | 781 | } |
| 783 | 782 | ||
| 784 | const test_incremental_step = b.step("test-incremental", "Run the incremental compilation test cases"); | ||
| 785 | try tests.addIncrementalTests(b, test_incremental_step, .{ | ||
| 786 | .test_filters = test_filters, | ||
| 787 | .test_target_filters = test_target_filters, | ||
| 788 | .skip_non_native = skip_non_native, | ||
| 789 | .skip_wasm = skip_wasm, | ||
| 790 | .skip_freebsd = skip_freebsd, | ||
| 791 | .skip_netbsd = skip_netbsd, | ||
| 792 | .skip_openbsd = skip_openbsd, | ||
| 793 | .skip_windows = skip_windows, | ||
| 794 | .skip_darwin = skip_darwin, | ||
| 795 | .skip_linux = skip_linux, | ||
| 796 | .skip_llvm = skip_llvm, | ||
| 797 | }); | ||
| 798 | if (!skip_test_incremental) test_step.dependOn(test_incremental_step); | ||
| 799 | |||
| 800 | if (tests.addLibcTestNszTests(b, .{ | 783 | if (tests.addLibcTestNszTests(b, .{ |
| 801 | .optimize_modes = optimize_modes, | 784 | .optimize_modes = optimize_modes, |
| 802 | .test_filters = test_filters, | 785 | .test_filters = test_filters, |
| ... | @@ -812,7 +795,7 @@ pub fn build(b: *std.Build) !void { | ... | @@ -812,7 +795,7 @@ pub fn build(b: *std.Build) !void { |
| 812 | .target = b.graph.host, | 795 | .target = b.graph.host, |
| 813 | }), | 796 | }), |
| 814 | }); | 797 | }); |
| 815 | test_step.dependOn(try tests.addNewIncrementalTests(b, runner, .{ | 798 | test_step.dependOn(try tests.addIncrementalTests(b, runner, .{ |
| 816 | .test_filters = test_filters, | 799 | .test_filters = test_filters, |
| 817 | .test_target_filters = test_target_filters, | 800 | .test_target_filters = test_target_filters, |
| 818 | .skip_non_native = skip_non_native, | 801 | .skip_non_native = skip_non_native, |
test/incremental/add_decl+45-18| ... | @@ -1,15 +1,21 @@ | ... | @@ -1,15 +1,21 @@ |
| 1 | #update=initial version | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | const std = @import("std"); | 6 | const std = @import("std"); |
| 4 | pub fn main() !void { | 7 | pub fn main() !void { |
| 5 | try std.Io.File.stdout().writeStreamingAll(io, foo); | 8 | try std.Io.File.stdout().writeStreamingAll(io, foo); |
| 6 | } | 9 | } |
| 7 | const foo = "good morning\n"; | 10 | const foo = "good morning\n"; |
| 8 | const io = std.Io.Threaded.global_single_threaded.io(); | 11 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 9 | #expect_stdout="good morning\n" | 12 | #} |
| 13 | #update | ||
| 14 | #check stdout { | ||
| 15 | good morning | ||
| 16 | #} | ||
| 10 | 17 | ||
| 11 | #update=add new declaration | 18 | #write main.zig { |
| 12 | #file=main.zig | ||
| 13 | const std = @import("std"); | 19 | const std = @import("std"); |
| 14 | pub fn main() !void { | 20 | pub fn main() !void { |
| 15 | try std.Io.File.stdout().writeStreamingAll(io, foo); | 21 | try std.Io.File.stdout().writeStreamingAll(io, foo); |
| ... | @@ -17,10 +23,14 @@ pub fn main() !void { | ... | @@ -17,10 +23,14 @@ pub fn main() !void { |
| 17 | const foo = "good morning\n"; | 23 | const foo = "good morning\n"; |
| 18 | const bar = "good evening\n"; | 24 | const bar = "good evening\n"; |
| 19 | const io = std.Io.Threaded.global_single_threaded.io(); | 25 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 20 | #expect_stdout="good morning\n" | 26 | #} |
| 27 | #update { | ||
| 28 | add new declaration#} | ||
| 29 | #check stdout { | ||
| 30 | good morning | ||
| 31 | #} | ||
| 21 | 32 | ||
| 22 | #update=reference new declaration | 33 | #write main.zig { |
| 23 | #file=main.zig | ||
| 24 | const std = @import("std"); | 34 | const std = @import("std"); |
| 25 | pub fn main() !void { | 35 | pub fn main() !void { |
| 26 | try std.Io.File.stdout().writeStreamingAll(io, bar); | 36 | try std.Io.File.stdout().writeStreamingAll(io, bar); |
| ... | @@ -28,10 +38,14 @@ pub fn main() !void { | ... | @@ -28,10 +38,14 @@ pub fn main() !void { |
| 28 | const foo = "good morning\n"; | 38 | const foo = "good morning\n"; |
| 29 | const bar = "good evening\n"; | 39 | const bar = "good evening\n"; |
| 30 | const io = std.Io.Threaded.global_single_threaded.io(); | 40 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 31 | #expect_stdout="good evening\n" | 41 | #} |
| 42 | #update { | ||
| 43 | reference new declaration#} | ||
| 44 | #check stdout { | ||
| 45 | good evening | ||
| 46 | #} | ||
| 32 | 47 | ||
| 33 | #update=reference missing declaration | 48 | #write main.zig { |
| 34 | #file=main.zig | ||
| 35 | const std = @import("std"); | 49 | const std = @import("std"); |
| 36 | pub fn main() !void { | 50 | pub fn main() !void { |
| 37 | try std.Io.File.stdout().writeStreamingAll(io, qux); | 51 | try std.Io.File.stdout().writeStreamingAll(io, qux); |
| ... | @@ -39,10 +53,14 @@ pub fn main() !void { | ... | @@ -39,10 +53,14 @@ pub fn main() !void { |
| 39 | const foo = "good morning\n"; | 53 | const foo = "good morning\n"; |
| 40 | const bar = "good evening\n"; | 54 | const bar = "good evening\n"; |
| 41 | const io = std.Io.Threaded.global_single_threaded.io(); | 55 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 42 | #expect_error=main.zig:3:52: error: use of undeclared identifier 'qux' | 56 | #} |
| 57 | #update { | ||
| 58 | reference missing declaration#} | ||
| 59 | #check errors { | ||
| 60 | main.zig:3:52: error: use of undeclared identifier 'qux' | ||
| 61 | #} | ||
| 43 | 62 | ||
| 44 | #update=add missing declaration | 63 | #write main.zig { |
| 45 | #file=main.zig | ||
| 46 | const std = @import("std"); | 64 | const std = @import("std"); |
| 47 | pub fn main() !void { | 65 | pub fn main() !void { |
| 48 | try std.Io.File.stdout().writeStreamingAll(io, qux); | 66 | try std.Io.File.stdout().writeStreamingAll(io, qux); |
| ... | @@ -51,14 +69,23 @@ const foo = "good morning\n"; | ... | @@ -51,14 +69,23 @@ const foo = "good morning\n"; |
| 51 | const bar = "good evening\n"; | 69 | const bar = "good evening\n"; |
| 52 | const qux = "good night\n"; | 70 | const qux = "good night\n"; |
| 53 | const io = std.Io.Threaded.global_single_threaded.io(); | 71 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 54 | #expect_stdout="good night\n" | 72 | #} |
| 73 | #update { | ||
| 74 | add missing declaration#} | ||
| 75 | #check stdout { | ||
| 76 | good night | ||
| 77 | #} | ||
| 55 | 78 | ||
| 56 | #update=remove unused declarations | 79 | #write main.zig { |
| 57 | #file=main.zig | ||
| 58 | const std = @import("std"); | 80 | const std = @import("std"); |
| 59 | pub fn main() !void { | 81 | pub fn main() !void { |
| 60 | try std.Io.File.stdout().writeStreamingAll(io, qux); | 82 | try std.Io.File.stdout().writeStreamingAll(io, qux); |
| 61 | } | 83 | } |
| 62 | const qux = "good night\n"; | 84 | const qux = "good night\n"; |
| 63 | const io = std.Io.Threaded.global_single_threaded.io(); | 85 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 64 | #expect_stdout="good night\n" | 86 | #} |
| 87 | #update { | ||
| 88 | remove unused declarations#} | ||
| 89 | #check stdout { | ||
| 90 | good night | ||
| 91 | #} |
test/incremental/add_decl_namespaced+46-19| ... | @@ -1,15 +1,21 @@ | ... | @@ -1,15 +1,21 @@ |
| 1 | #update=initial version | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | const std = @import("std"); | 6 | const std = @import("std"); |
| 4 | pub fn main() !void { | 7 | pub fn main() !void { |
| 5 | try std.Io.File.stdout().writeStreamingAll(io, @This().foo); | 8 | try std.Io.File.stdout().writeStreamingAll(io, @This().foo); |
| 6 | } | 9 | } |
| 7 | const foo = "good morning\n"; | 10 | const foo = "good morning\n"; |
| 8 | const io = std.Io.Threaded.global_single_threaded.io(); | 11 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 9 | #expect_stdout="good morning\n" | 12 | #} |
| 13 | #update | ||
| 14 | #check stdout { | ||
| 15 | good morning | ||
| 16 | #} | ||
| 10 | 17 | ||
| 11 | #update=add new declaration | 18 | #write main.zig { |
| 12 | #file=main.zig | ||
| 13 | const std = @import("std"); | 19 | const std = @import("std"); |
| 14 | pub fn main() !void { | 20 | pub fn main() !void { |
| 15 | try std.Io.File.stdout().writeStreamingAll(io, @This().foo); | 21 | try std.Io.File.stdout().writeStreamingAll(io, @This().foo); |
| ... | @@ -17,10 +23,14 @@ pub fn main() !void { | ... | @@ -17,10 +23,14 @@ pub fn main() !void { |
| 17 | const foo = "good morning\n"; | 23 | const foo = "good morning\n"; |
| 18 | const bar = "good evening\n"; | 24 | const bar = "good evening\n"; |
| 19 | const io = std.Io.Threaded.global_single_threaded.io(); | 25 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 20 | #expect_stdout="good morning\n" | 26 | #} |
| 27 | #update { | ||
| 28 | add new declaration#} | ||
| 29 | #check stdout { | ||
| 30 | good morning | ||
| 31 | #} | ||
| 21 | 32 | ||
| 22 | #update=reference new declaration | 33 | #write main.zig { |
| 23 | #file=main.zig | ||
| 24 | const std = @import("std"); | 34 | const std = @import("std"); |
| 25 | pub fn main() !void { | 35 | pub fn main() !void { |
| 26 | try std.Io.File.stdout().writeStreamingAll(io, @This().bar); | 36 | try std.Io.File.stdout().writeStreamingAll(io, @This().bar); |
| ... | @@ -28,10 +38,14 @@ pub fn main() !void { | ... | @@ -28,10 +38,14 @@ pub fn main() !void { |
| 28 | const foo = "good morning\n"; | 38 | const foo = "good morning\n"; |
| 29 | const bar = "good evening\n"; | 39 | const bar = "good evening\n"; |
| 30 | const io = std.Io.Threaded.global_single_threaded.io(); | 40 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 31 | #expect_stdout="good evening\n" | 41 | #} |
| 42 | #update { | ||
| 43 | reference new declaration#} | ||
| 44 | #check stdout { | ||
| 45 | good evening | ||
| 46 | #} | ||
| 32 | 47 | ||
| 33 | #update=reference missing declaration | 48 | #write main.zig { |
| 34 | #file=main.zig | ||
| 35 | const std = @import("std"); | 49 | const std = @import("std"); |
| 36 | pub fn main() !void { | 50 | pub fn main() !void { |
| 37 | try std.Io.File.stdout().writeStreamingAll(io, @This().qux); | 51 | try std.Io.File.stdout().writeStreamingAll(io, @This().qux); |
| ... | @@ -39,11 +53,15 @@ pub fn main() !void { | ... | @@ -39,11 +53,15 @@ pub fn main() !void { |
| 39 | const foo = "good morning\n"; | 53 | const foo = "good morning\n"; |
| 40 | const bar = "good evening\n"; | 54 | const bar = "good evening\n"; |
| 41 | const io = std.Io.Threaded.global_single_threaded.io(); | 55 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 42 | #expect_error=main.zig:3:59: error: root source file struct 'main' has no member named 'qux' | 56 | #} |
| 43 | #expect_error=main.zig:1:1: note: struct declared here | 57 | #update { |
| 58 | reference missing declaration#} | ||
| 59 | #check errors { | ||
| 60 | main.zig:3:59: error: root source file struct 'main' has no member named 'qux' | ||
| 61 | main.zig:1:1: note: struct declared here | ||
| 62 | #} | ||
| 44 | 63 | ||
| 45 | #update=add missing declaration | 64 | #write main.zig { |
| 46 | #file=main.zig | ||
| 47 | const std = @import("std"); | 65 | const std = @import("std"); |
| 48 | pub fn main() !void { | 66 | pub fn main() !void { |
| 49 | try std.Io.File.stdout().writeStreamingAll(io, @This().qux); | 67 | try std.Io.File.stdout().writeStreamingAll(io, @This().qux); |
| ... | @@ -52,14 +70,23 @@ const foo = "good morning\n"; | ... | @@ -52,14 +70,23 @@ const foo = "good morning\n"; |
| 52 | const bar = "good evening\n"; | 70 | const bar = "good evening\n"; |
| 53 | const qux = "good night\n"; | 71 | const qux = "good night\n"; |
| 54 | const io = std.Io.Threaded.global_single_threaded.io(); | 72 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 55 | #expect_stdout="good night\n" | 73 | #} |
| 74 | #update { | ||
| 75 | add missing declaration#} | ||
| 76 | #check stdout { | ||
| 77 | good night | ||
| 78 | #} | ||
| 56 | 79 | ||
| 57 | #update=remove unused declarations | 80 | #write main.zig { |
| 58 | #file=main.zig | ||
| 59 | const std = @import("std"); | 81 | const std = @import("std"); |
| 60 | pub fn main() !void { | 82 | pub fn main() !void { |
| 61 | try std.Io.File.stdout().writeStreamingAll(io, @This().qux); | 83 | try std.Io.File.stdout().writeStreamingAll(io, @This().qux); |
| 62 | } | 84 | } |
| 63 | const qux = "good night\n"; | 85 | const qux = "good night\n"; |
| 64 | const io = std.Io.Threaded.global_single_threaded.io(); | 86 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 65 | #expect_stdout="good night\n" | 87 | #} |
| 88 | #update { | ||
| 89 | remove unused declarations#} | ||
| 90 | #check stdout { | ||
| 91 | good night | ||
| 92 | #} |
test/incremental/add_field_and_nested_struct_uses_changed_decl+16-6| ... | @@ -1,5 +1,8 @@ | ... | @@ -1,5 +1,8 @@ |
| 1 | #update=initial version | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | pub fn main() void { | 6 | pub fn main() void { |
| 4 | _ = @as(S, undefined); | 7 | _ = @as(S, undefined); |
| 5 | } | 8 | } |
| ... | @@ -9,9 +12,12 @@ const SomeType = u8; | ... | @@ -9,9 +12,12 @@ const SomeType = u8; |
| 9 | const S = struct { | 12 | const S = struct { |
| 10 | foo: struct { inner: SomeType }, | 13 | foo: struct { inner: SomeType }, |
| 11 | }; | 14 | }; |
| 12 | #expect_stdout="" | 15 | #} |
| 13 | #update=add field to outer struct, change decl used by inner struct | 16 | #update |
| 14 | #file=main.zig | 17 | #check stdout { |
| 18 | #} | ||
| 19 | |||
| 20 | #write main.zig { | ||
| 15 | pub fn main() void { | 21 | pub fn main() void { |
| 16 | _ = @as(S, undefined); | 22 | _ = @as(S, undefined); |
| 17 | } | 23 | } |
| ... | @@ -22,4 +28,8 @@ const S = struct { | ... | @@ -22,4 +28,8 @@ const S = struct { |
| 22 | foo: struct { inner: SomeType }, | 28 | foo: struct { inner: SomeType }, |
| 23 | bar: u32, | 29 | bar: u32, |
| 24 | }; | 30 | }; |
| 25 | #expect_stdout="" | 31 | #} |
| 32 | #update { | ||
| 33 | add field to outer struct, change decl used by inner struct#} | ||
| 34 | #check stdout { | ||
| 35 | #} |
test/incremental/add_remove_struct_fields deleted-93| ... | @@ -1,93 +0,0 @@ | ||
| 1 | #update=initial version | ||
| 2 | #file=main.zig | ||
| 3 | const S = struct { x: u8 }; | ||
| 4 | pub fn main(init: std.process.Init) !void { | ||
| 5 | var stdout_writer = std.Io.File.stdout().writerStreaming(init.io, &.{}); | ||
| 6 | printFieldCount(&stdout_writer.interface) catch |err| switch (err) { | ||
| 7 | error.WriteFailed => return stdout_writer.err.?, | ||
| 8 | }; | ||
| 9 | printOneField(&stdout_writer.interface) catch |err| switch (err) { | ||
| 10 | error.WriteFailed => return stdout_writer.err.?, | ||
| 11 | }; | ||
| 12 | } | ||
| 13 | fn printFieldCount(w: *Writer) Writer.Error!void { | ||
| 14 | try w.print("{d} ", .{@typeInfo(S).@"struct".field_names.len}); | ||
| 15 | } | ||
| 16 | fn printOneField(w: *Writer) Writer.Error!void { | ||
| 17 | const val: S = .{ .x = 100 }; | ||
| 18 | try w.print("{d}\n", .{val.x}); | ||
| 19 | } | ||
| 20 | const std = @import("std"); | ||
| 21 | const Writer = std.Io.Writer; | ||
| 22 | #expect_stdout="1 100\n" | ||
| 23 | |||
| 24 | #update=add a field | ||
| 25 | #file=main.zig | ||
| 26 | const S = struct { x: u8, y: u16 = 200 }; | ||
| 27 | pub fn main(init: std.process.Init) !void { | ||
| 28 | var stdout_writer = std.Io.File.stdout().writerStreaming(init.io, &.{}); | ||
| 29 | printFieldCount(&stdout_writer.interface) catch |err| switch (err) { | ||
| 30 | error.WriteFailed => return stdout_writer.err.?, | ||
| 31 | }; | ||
| 32 | printOneField(&stdout_writer.interface) catch |err| switch (err) { | ||
| 33 | error.WriteFailed => return stdout_writer.err.?, | ||
| 34 | }; | ||
| 35 | } | ||
| 36 | fn printFieldCount(w: *Writer) Writer.Error!void { | ||
| 37 | try w.print("{d} ", .{@typeInfo(S).@"struct".field_names.len}); | ||
| 38 | } | ||
| 39 | fn printOneField(w: *Writer) Writer.Error!void { | ||
| 40 | const val: S = .{ .x = 100 }; | ||
| 41 | try w.print("{d}\n", .{val.x}); | ||
| 42 | } | ||
| 43 | const std = @import("std"); | ||
| 44 | const Writer = std.Io.Writer; | ||
| 45 | #expect_stdout="2 100\n" | ||
| 46 | |||
| 47 | #update=remove all fields | ||
| 48 | #file=main.zig | ||
| 49 | const S = struct {}; | ||
| 50 | pub fn main(init: std.process.Init) !void { | ||
| 51 | var stdout_writer = std.Io.File.stdout().writerStreaming(init.io, &.{}); | ||
| 52 | printFieldCount(&stdout_writer.interface) catch |err| switch (err) { | ||
| 53 | error.WriteFailed => return stdout_writer.err.?, | ||
| 54 | }; | ||
| 55 | printOneField(&stdout_writer.interface) catch |err| switch (err) { | ||
| 56 | error.WriteFailed => return stdout_writer.err.?, | ||
| 57 | }; | ||
| 58 | } | ||
| 59 | fn printFieldCount(w: *Writer) Writer.Error!void { | ||
| 60 | try w.print("{d} ", .{@typeInfo(S).@"struct".field_names.len}); | ||
| 61 | } | ||
| 62 | fn printOneField(w: *Writer) Writer.Error!void { | ||
| 63 | const val: S = .{ .x = 100 }; | ||
| 64 | try w.print("{d}\n", .{val.x}); | ||
| 65 | } | ||
| 66 | const std = @import("std"); | ||
| 67 | const Writer = std.Io.Writer; | ||
| 68 | #expect_error=main.zig:15:24: error: no field named 'x' in struct 'main.S' | ||
| 69 | #expect_error=main.zig:1:11: note: struct declared here | ||
| 70 | |||
| 71 | #update=remove reference to non-existent field | ||
| 72 | #file=main.zig | ||
| 73 | const S = struct {}; | ||
| 74 | pub fn main(init: std.process.Init) !void { | ||
| 75 | var stdout_writer = std.Io.File.stdout().writerStreaming(init.io, &.{}); | ||
| 76 | printFieldCount(&stdout_writer.interface) catch |err| switch (err) { | ||
| 77 | error.WriteFailed => return stdout_writer.err.?, | ||
| 78 | }; | ||
| 79 | printOneField(&stdout_writer.interface) catch |err| switch (err) { | ||
| 80 | error.WriteFailed => return stdout_writer.err.?, | ||
| 81 | }; | ||
| 82 | } | ||
| 83 | fn printFieldCount(w: *Writer) Writer.Error!void { | ||
| 84 | try w.print("{d} ", .{@typeInfo(S).@"struct".field_names.len}); | ||
| 85 | } | ||
| 86 | fn printOneField(w: *Writer) Writer.Error!void { | ||
| 87 | //const val: S = .{ .x = 100 }; | ||
| 88 | //try w.print("{d}\n", .{val.x}); | ||
| 89 | try w.writeAll("<no fields>\n"); | ||
| 90 | } | ||
| 91 | const std = @import("std"); | ||
| 92 | const Writer = std.Io.Writer; | ||
| 93 | #expect_stdout="0 <no fields>\n" | ||
test/incremental/add_remove_struct_fields/0/main.zig created+19| ... | @@ -0,0 +1,19 @@ | ||
| 1 | const S = struct { x: u8 }; | ||
| 2 | pub fn main(init: std.process.Init) !void { | ||
| 3 | var stdout_writer = std.Io.File.stdout().writerStreaming(init.io, &.{}); | ||
| 4 | printFieldCount(&stdout_writer.interface) catch |err| switch (err) { | ||
| 5 | error.WriteFailed => return stdout_writer.err.?, | ||
| 6 | }; | ||
| 7 | printOneField(&stdout_writer.interface) catch |err| switch (err) { | ||
| 8 | error.WriteFailed => return stdout_writer.err.?, | ||
| 9 | }; | ||
| 10 | } | ||
| 11 | fn printFieldCount(w: *Writer) Writer.Error!void { | ||
| 12 | try w.print("{d} ", .{@typeInfo(S).@"struct".field_names.len}); | ||
| 13 | } | ||
| 14 | fn printOneField(w: *Writer) Writer.Error!void { | ||
| 15 | const val: S = .{ .x = 100 }; | ||
| 16 | try w.print("{d}\n", .{val.x}); | ||
| 17 | } | ||
| 18 | const std = @import("std"); | ||
| 19 | const Writer = std.Io.Writer; | ||
test/incremental/add_remove_struct_fields/1/main.zig created+19| ... | @@ -0,0 +1,19 @@ | ||
| 1 | const S = struct { x: u8, y: u16 = 200 }; | ||
| 2 | pub fn main(init: std.process.Init) !void { | ||
| 3 | var stdout_writer = std.Io.File.stdout().writerStreaming(init.io, &.{}); | ||
| 4 | printFieldCount(&stdout_writer.interface) catch |err| switch (err) { | ||
| 5 | error.WriteFailed => return stdout_writer.err.?, | ||
| 6 | }; | ||
| 7 | printOneField(&stdout_writer.interface) catch |err| switch (err) { | ||
| 8 | error.WriteFailed => return stdout_writer.err.?, | ||
| 9 | }; | ||
| 10 | } | ||
| 11 | fn printFieldCount(w: *Writer) Writer.Error!void { | ||
| 12 | try w.print("{d} ", .{@typeInfo(S).@"struct".field_names.len}); | ||
| 13 | } | ||
| 14 | fn printOneField(w: *Writer) Writer.Error!void { | ||
| 15 | const val: S = .{ .x = 100 }; | ||
| 16 | try w.print("{d}\n", .{val.x}); | ||
| 17 | } | ||
| 18 | const std = @import("std"); | ||
| 19 | const Writer = std.Io.Writer; | ||
test/incremental/add_remove_struct_fields/2/main.zig created+19| ... | @@ -0,0 +1,19 @@ | ||
| 1 | const S = struct {}; | ||
| 2 | pub fn main(init: std.process.Init) !void { | ||
| 3 | var stdout_writer = std.Io.File.stdout().writerStreaming(init.io, &.{}); | ||
| 4 | printFieldCount(&stdout_writer.interface) catch |err| switch (err) { | ||
| 5 | error.WriteFailed => return stdout_writer.err.?, | ||
| 6 | }; | ||
| 7 | printOneField(&stdout_writer.interface) catch |err| switch (err) { | ||
| 8 | error.WriteFailed => return stdout_writer.err.?, | ||
| 9 | }; | ||
| 10 | } | ||
| 11 | fn printFieldCount(w: *Writer) Writer.Error!void { | ||
| 12 | try w.print("{d} ", .{@typeInfo(S).@"struct".field_names.len}); | ||
| 13 | } | ||
| 14 | fn printOneField(w: *Writer) Writer.Error!void { | ||
| 15 | const val: S = .{ .x = 100 }; | ||
| 16 | try w.print("{d}\n", .{val.x}); | ||
| 17 | } | ||
| 18 | const std = @import("std"); | ||
| 19 | const Writer = std.Io.Writer; | ||
test/incremental/add_remove_struct_fields/3/main.zig created+20| ... | @@ -0,0 +1,20 @@ | ||
| 1 | const S = struct {}; | ||
| 2 | pub fn main(init: std.process.Init) !void { | ||
| 3 | var stdout_writer = std.Io.File.stdout().writerStreaming(init.io, &.{}); | ||
| 4 | printFieldCount(&stdout_writer.interface) catch |err| switch (err) { | ||
| 5 | error.WriteFailed => return stdout_writer.err.?, | ||
| 6 | }; | ||
| 7 | printOneField(&stdout_writer.interface) catch |err| switch (err) { | ||
| 8 | error.WriteFailed => return stdout_writer.err.?, | ||
| 9 | }; | ||
| 10 | } | ||
| 11 | fn printFieldCount(w: *Writer) Writer.Error!void { | ||
| 12 | try w.print("{d} ", .{@typeInfo(S).@"struct".field_names.len}); | ||
| 13 | } | ||
| 14 | fn printOneField(w: *Writer) Writer.Error!void { | ||
| 15 | //const val: S = .{ .x = 100 }; | ||
| 16 | //try w.print("{d}\n", .{val.x}); | ||
| 17 | try w.writeAll("<no fields>\n"); | ||
| 18 | } | ||
| 19 | const std = @import("std"); | ||
| 20 | const Writer = std.Io.Writer; | ||
test/incremental/add_remove_struct_fields/manifest created+31| ... | @@ -0,0 +1,31 @@ | ||
| 1 | #exe { | ||
| 2 | -Mroot=main.zig | ||
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig 0/main.zig | ||
| 6 | #update | ||
| 7 | #check stdout { | ||
| 8 | 1 100 | ||
| 9 | #} | ||
| 10 | |||
| 11 | #write main.zig 1/main.zig | ||
| 12 | #update { | ||
| 13 | add a field#} | ||
| 14 | #check stdout { | ||
| 15 | 2 100 | ||
| 16 | #} | ||
| 17 | |||
| 18 | #write main.zig 2/main.zig | ||
| 19 | #update { | ||
| 20 | remove all fields#} | ||
| 21 | #check errors { | ||
| 22 | main.zig:15:24: error: no field named 'x' in struct 'main.S' | ||
| 23 | main.zig:1:11: note: struct declared here | ||
| 24 | #} | ||
| 25 | |||
| 26 | #write main.zig 3/main.zig | ||
| 27 | #update { | ||
| 28 | remove reference to non-existent field#} | ||
| 29 | #check stdout { | ||
| 30 | 0 <no fields> | ||
| 31 | #} | ||
test/incremental/add_remove_toplevel_fields deleted-96| ... | @@ -1,96 +0,0 @@ | ||
| 1 | #update=initial version | ||
| 2 | #file=main.zig | ||
| 3 | const S = @This(); | ||
| 4 | x: u8, | ||
| 5 | pub fn main(init: std.process.Init) !void { | ||
| 6 | var stdout_writer = std.Io.File.stdout().writerStreaming(init.io, &.{}); | ||
| 7 | printFieldCount(&stdout_writer.interface) catch |err| switch (err) { | ||
| 8 | error.WriteFailed => return stdout_writer.err.?, | ||
| 9 | }; | ||
| 10 | printOneField(&stdout_writer.interface) catch |err| switch (err) { | ||
| 11 | error.WriteFailed => return stdout_writer.err.?, | ||
| 12 | }; | ||
| 13 | } | ||
| 14 | fn printFieldCount(w: *Writer) Writer.Error!void { | ||
| 15 | try w.print("{d} ", .{@typeInfo(S).@"struct".field_names.len}); | ||
| 16 | } | ||
| 17 | fn printOneField(w: *Writer) Writer.Error!void { | ||
| 18 | const val: S = .{ .x = 100 }; | ||
| 19 | try w.print("{d}\n", .{val.x}); | ||
| 20 | } | ||
| 21 | const std = @import("std"); | ||
| 22 | const Writer = std.Io.Writer; | ||
| 23 | #expect_stdout="1 100\n" | ||
| 24 | |||
| 25 | #update=add a field | ||
| 26 | #file=main.zig | ||
| 27 | const S = @This(); | ||
| 28 | x: u8, | ||
| 29 | y: u16 = 200, | ||
| 30 | pub fn main(init: std.process.Init) !void { | ||
| 31 | var stdout_writer = std.Io.File.stdout().writerStreaming(init.io, &.{}); | ||
| 32 | printFieldCount(&stdout_writer.interface) catch |err| switch (err) { | ||
| 33 | error.WriteFailed => return stdout_writer.err.?, | ||
| 34 | }; | ||
| 35 | printOneField(&stdout_writer.interface) catch |err| switch (err) { | ||
| 36 | error.WriteFailed => return stdout_writer.err.?, | ||
| 37 | }; | ||
| 38 | } | ||
| 39 | fn printFieldCount(w: *Writer) Writer.Error!void { | ||
| 40 | try w.print("{d} ", .{@typeInfo(S).@"struct".field_names.len}); | ||
| 41 | } | ||
| 42 | fn printOneField(w: *Writer) Writer.Error!void { | ||
| 43 | const val: S = .{ .x = 100 }; | ||
| 44 | try w.print("{d}\n", .{val.x}); | ||
| 45 | } | ||
| 46 | const std = @import("std"); | ||
| 47 | const Writer = std.Io.Writer; | ||
| 48 | #expect_stdout="2 100\n" | ||
| 49 | |||
| 50 | #update=remove all fields | ||
| 51 | #file=main.zig | ||
| 52 | const S = @This(); | ||
| 53 | pub fn main(init: std.process.Init) !void { | ||
| 54 | var stdout_writer = std.Io.File.stdout().writerStreaming(init.io, &.{}); | ||
| 55 | printFieldCount(&stdout_writer.interface) catch |err| switch (err) { | ||
| 56 | error.WriteFailed => return stdout_writer.err.?, | ||
| 57 | }; | ||
| 58 | printOneField(&stdout_writer.interface) catch |err| switch (err) { | ||
| 59 | error.WriteFailed => return stdout_writer.err.?, | ||
| 60 | }; | ||
| 61 | } | ||
| 62 | fn printFieldCount(w: *Writer) Writer.Error!void { | ||
| 63 | try w.print("{d} ", .{@typeInfo(S).@"struct".field_names.len}); | ||
| 64 | } | ||
| 65 | fn printOneField(w: *Writer) Writer.Error!void { | ||
| 66 | const val: S = .{ .x = 100 }; | ||
| 67 | try w.print("{d}\n", .{val.x}); | ||
| 68 | } | ||
| 69 | const std = @import("std"); | ||
| 70 | const Writer = std.Io.Writer; | ||
| 71 | #expect_error=main.zig:15:24: error: no field named 'x' in struct 'main' | ||
| 72 | #expect_error=main.zig:1:1: note: struct declared here | ||
| 73 | |||
| 74 | #update=remove reference to non-existent field | ||
| 75 | #file=main.zig | ||
| 76 | const S = @This(); | ||
| 77 | pub fn main(init: std.process.Init) !void { | ||
| 78 | var stdout_writer = std.Io.File.stdout().writerStreaming(init.io, &.{}); | ||
| 79 | printFieldCount(&stdout_writer.interface) catch |err| switch (err) { | ||
| 80 | error.WriteFailed => return stdout_writer.err.?, | ||
| 81 | }; | ||
| 82 | printOneField(&stdout_writer.interface) catch |err| switch (err) { | ||
| 83 | error.WriteFailed => return stdout_writer.err.?, | ||
| 84 | }; | ||
| 85 | } | ||
| 86 | fn printFieldCount(w: *Writer) Writer.Error!void { | ||
| 87 | try w.print("{d} ", .{@typeInfo(S).@"struct".field_names.len}); | ||
| 88 | } | ||
| 89 | fn printOneField(w: *Writer) Writer.Error!void { | ||
| 90 | //const val: S = .{ .x = 100 }; | ||
| 91 | //try w.print("{d}\n", .{val.x}); | ||
| 92 | try w.writeAll("<no fields>\n"); | ||
| 93 | } | ||
| 94 | const std = @import("std"); | ||
| 95 | const Writer = std.Io.Writer; | ||
| 96 | #expect_stdout="0 <no fields>\n" | ||
test/incremental/add_remove_toplevel_fields/0/main.zig created+20| ... | @@ -0,0 +1,20 @@ | ||
| 1 | const S = @This(); | ||
| 2 | x: u8, | ||
| 3 | pub fn main(init: std.process.Init) !void { | ||
| 4 | var stdout_writer = std.Io.File.stdout().writerStreaming(init.io, &.{}); | ||
| 5 | printFieldCount(&stdout_writer.interface) catch |err| switch (err) { | ||
| 6 | error.WriteFailed => return stdout_writer.err.?, | ||
| 7 | }; | ||
| 8 | printOneField(&stdout_writer.interface) catch |err| switch (err) { | ||
| 9 | error.WriteFailed => return stdout_writer.err.?, | ||
| 10 | }; | ||
| 11 | } | ||
| 12 | fn printFieldCount(w: *Writer) Writer.Error!void { | ||
| 13 | try w.print("{d} ", .{@typeInfo(S).@"struct".field_names.len}); | ||
| 14 | } | ||
| 15 | fn printOneField(w: *Writer) Writer.Error!void { | ||
| 16 | const val: S = .{ .x = 100 }; | ||
| 17 | try w.print("{d}\n", .{val.x}); | ||
| 18 | } | ||
| 19 | const std = @import("std"); | ||
| 20 | const Writer = std.Io.Writer; | ||
test/incremental/add_remove_toplevel_fields/1/main.zig created+21| ... | @@ -0,0 +1,21 @@ | ||
| 1 | const S = @This(); | ||
| 2 | x: u8, | ||
| 3 | y: u16 = 200, | ||
| 4 | pub fn main(init: std.process.Init) !void { | ||
| 5 | var stdout_writer = std.Io.File.stdout().writerStreaming(init.io, &.{}); | ||
| 6 | printFieldCount(&stdout_writer.interface) catch |err| switch (err) { | ||
| 7 | error.WriteFailed => return stdout_writer.err.?, | ||
| 8 | }; | ||
| 9 | printOneField(&stdout_writer.interface) catch |err| switch (err) { | ||
| 10 | error.WriteFailed => return stdout_writer.err.?, | ||
| 11 | }; | ||
| 12 | } | ||
| 13 | fn printFieldCount(w: *Writer) Writer.Error!void { | ||
| 14 | try w.print("{d} ", .{@typeInfo(S).@"struct".field_names.len}); | ||
| 15 | } | ||
| 16 | fn printOneField(w: *Writer) Writer.Error!void { | ||
| 17 | const val: S = .{ .x = 100 }; | ||
| 18 | try w.print("{d}\n", .{val.x}); | ||
| 19 | } | ||
| 20 | const std = @import("std"); | ||
| 21 | const Writer = std.Io.Writer; | ||
test/incremental/add_remove_toplevel_fields/2/main.zig created+19| ... | @@ -0,0 +1,19 @@ | ||
| 1 | const S = @This(); | ||
| 2 | pub fn main(init: std.process.Init) !void { | ||
| 3 | var stdout_writer = std.Io.File.stdout().writerStreaming(init.io, &.{}); | ||
| 4 | printFieldCount(&stdout_writer.interface) catch |err| switch (err) { | ||
| 5 | error.WriteFailed => return stdout_writer.err.?, | ||
| 6 | }; | ||
| 7 | printOneField(&stdout_writer.interface) catch |err| switch (err) { | ||
| 8 | error.WriteFailed => return stdout_writer.err.?, | ||
| 9 | }; | ||
| 10 | } | ||
| 11 | fn printFieldCount(w: *Writer) Writer.Error!void { | ||
| 12 | try w.print("{d} ", .{@typeInfo(S).@"struct".field_names.len}); | ||
| 13 | } | ||
| 14 | fn printOneField(w: *Writer) Writer.Error!void { | ||
| 15 | const val: S = .{ .x = 100 }; | ||
| 16 | try w.print("{d}\n", .{val.x}); | ||
| 17 | } | ||
| 18 | const std = @import("std"); | ||
| 19 | const Writer = std.Io.Writer; | ||
test/incremental/add_remove_toplevel_fields/3/main.zig created+20| ... | @@ -0,0 +1,20 @@ | ||
| 1 | const S = @This(); | ||
| 2 | pub fn main(init: std.process.Init) !void { | ||
| 3 | var stdout_writer = std.Io.File.stdout().writerStreaming(init.io, &.{}); | ||
| 4 | printFieldCount(&stdout_writer.interface) catch |err| switch (err) { | ||
| 5 | error.WriteFailed => return stdout_writer.err.?, | ||
| 6 | }; | ||
| 7 | printOneField(&stdout_writer.interface) catch |err| switch (err) { | ||
| 8 | error.WriteFailed => return stdout_writer.err.?, | ||
| 9 | }; | ||
| 10 | } | ||
| 11 | fn printFieldCount(w: *Writer) Writer.Error!void { | ||
| 12 | try w.print("{d} ", .{@typeInfo(S).@"struct".field_names.len}); | ||
| 13 | } | ||
| 14 | fn printOneField(w: *Writer) Writer.Error!void { | ||
| 15 | //const val: S = .{ .x = 100 }; | ||
| 16 | //try w.print("{d}\n", .{val.x}); | ||
| 17 | try w.writeAll("<no fields>\n"); | ||
| 18 | } | ||
| 19 | const std = @import("std"); | ||
| 20 | const Writer = std.Io.Writer; | ||
test/incremental/add_remove_toplevel_fields/manifest created+31| ... | @@ -0,0 +1,31 @@ | ||
| 1 | #exe { | ||
| 2 | -Mroot=main.zig | ||
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig 0/main.zig | ||
| 6 | #update | ||
| 7 | #check stdout { | ||
| 8 | 1 100 | ||
| 9 | #} | ||
| 10 | |||
| 11 | #write main.zig 1/main.zig | ||
| 12 | #update { | ||
| 13 | add a field#} | ||
| 14 | #check stdout { | ||
| 15 | 2 100 | ||
| 16 | #} | ||
| 17 | |||
| 18 | #write main.zig 2/main.zig | ||
| 19 | #update { | ||
| 20 | remove all fields#} | ||
| 21 | #check errors { | ||
| 22 | main.zig:15:24: error: no field named 'x' in struct 'main' | ||
| 23 | main.zig:1:1: note: struct declared here | ||
| 24 | #} | ||
| 25 | |||
| 26 | #write main.zig 3/main.zig | ||
| 27 | #update { | ||
| 28 | remove reference to non-existent field#} | ||
| 29 | #check stdout { | ||
| 30 | 0 <no fields> | ||
| 31 | #} | ||
test/incremental/analysis_error_and_syntax_error+44-18| ... | @@ -1,38 +1,64 @@ | ... | @@ -1,38 +1,64 @@ |
| 1 | #update=initial version | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | pub fn main() !void { | 6 | pub fn main() !void { |
| 4 | @compileError("uh oh"); | 7 | @compileError("uh oh"); |
| 5 | } | 8 | } |
| 6 | #expect_error=main.zig:2:5: error: uh oh | 9 | #} |
| 10 | #update | ||
| 11 | #check errors { | ||
| 12 | main.zig:2:5: error: uh oh | ||
| 13 | #} | ||
| 7 | 14 | ||
| 8 | #update=add parse error | 15 | #write main.zig { |
| 9 | #file=main.zig | ||
| 10 | pub fn main() !void { | 16 | pub fn main() !void { |
| 11 | @compileError("uh oh"); | 17 | @compileError("uh oh"); |
| 12 | #expect_error=main.zig:3:1: error: expected statement, found 'EOF' | 18 | #} |
| 19 | #update { | ||
| 20 | add parse error#} | ||
| 21 | #check errors { | ||
| 22 | main.zig:3:1: error: expected statement, found 'EOF' | ||
| 23 | #} | ||
| 13 | 24 | ||
| 14 | #update=fix parse error | 25 | #write main.zig { |
| 15 | #file=main.zig | ||
| 16 | pub fn main() !void { | 26 | pub fn main() !void { |
| 17 | @compileError("uh oh"); | 27 | @compileError("uh oh"); |
| 18 | } | 28 | } |
| 19 | #expect_error=main.zig:2:5: error: uh oh | 29 | #} |
| 30 | #update { | ||
| 31 | fix parse error#} | ||
| 32 | #check errors { | ||
| 33 | main.zig:2:5: error: uh oh | ||
| 34 | #} | ||
| 20 | 35 | ||
| 21 | #update=add parse error again | 36 | #write main.zig { |
| 22 | #file=main.zig | ||
| 23 | pub fn main() !void { | 37 | pub fn main() !void { |
| 24 | @compileError("uh oh"); | 38 | @compileError("uh oh"); |
| 25 | #expect_error=main.zig:3:1: error: expected statement, found 'EOF' | 39 | #} |
| 40 | #update { | ||
| 41 | add parse error again#} | ||
| 42 | #check errors { | ||
| 43 | main.zig:3:1: error: expected statement, found 'EOF' | ||
| 44 | #} | ||
| 26 | 45 | ||
| 27 | #update=comment @compileError call | 46 | #write main.zig { |
| 28 | #file=main.zig | ||
| 29 | pub fn main() !void { | 47 | pub fn main() !void { |
| 30 | //@compileError("uh oh"); | 48 | //@compileError("uh oh"); |
| 31 | #expect_error=main.zig:3:1: error: expected statement, found 'EOF' | 49 | #} |
| 50 | #update { | ||
| 51 | comment @compileError call#} | ||
| 52 | #check errors { | ||
| 53 | main.zig:3:1: error: expected statement, found 'EOF' | ||
| 54 | #} | ||
| 32 | 55 | ||
| 33 | #update=fix parse error again | 56 | #write main.zig { |
| 34 | #file=main.zig | ||
| 35 | pub fn main() !void { | 57 | pub fn main() !void { |
| 36 | //@compileError("uh oh"); | 58 | //@compileError("uh oh"); |
| 37 | } | 59 | } |
| 38 | #expect_stdout="" | 60 | #} |
| 61 | #update { | ||
| 62 | fix parse error again#} | ||
| 63 | #check stdout { | ||
| 64 | #} |
test/incremental/bad_import+28-12| ... | @@ -1,32 +1,48 @@ | ... | @@ -1,32 +1,48 @@ |
| 1 | #update=initial version | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | pub fn main() !void { | 6 | pub fn main() !void { |
| 4 | _ = @import("foo.zig"); | 7 | _ = @import("foo.zig"); |
| 5 | try std.Io.File.stdout().writeStreamingAll(io, "success\n"); | 8 | try std.Io.File.stdout().writeStreamingAll(io, "success\n"); |
| 6 | } | 9 | } |
| 7 | const std = @import("std"); | 10 | const std = @import("std"); |
| 8 | const io = std.Io.Threaded.global_single_threaded.io(); | 11 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 9 | #file=foo.zig | 12 | #} |
| 13 | #write foo.zig { | ||
| 10 | comptime { | 14 | comptime { |
| 11 | _ = @import("bad.zig"); | 15 | _ = @import("bad.zig"); |
| 12 | } | 16 | } |
| 13 | #expect_error=bad.zig:1:1: error: unable to load "bad.zig": FileNotFound | 17 | #} |
| 14 | #expect_error=foo.zig:2:17: note: file imported here | 18 | #update |
| 19 | #check errors { | ||
| 20 | bad.zig:1:1: error: unable to load "bad.zig": FileNotFound | ||
| 21 | foo.zig:2:17: note: file imported here | ||
| 22 | #} | ||
| 15 | 23 | ||
| 16 | #update=change bad import | 24 | #write foo.zig { |
| 17 | #file=foo.zig | ||
| 18 | comptime { | 25 | comptime { |
| 19 | _ = @import("this_is/not_real.zig"); | 26 | _ = @import("this_is/not_real.zig"); |
| 20 | } | 27 | } |
| 21 | #expect_error=this_is/not_real.zig:1:1: error: unable to load "not_real.zig": FileNotFound | 28 | #} |
| 22 | #expect_error=foo.zig:2:17: note: file imported here | 29 | #update { |
| 30 | change bad import#} | ||
| 31 | #check errors { | ||
| 32 | this_is/not_real.zig:1:1: error: unable to load "not_real.zig": FileNotFound | ||
| 33 | foo.zig:2:17: note: file imported here | ||
| 34 | #} | ||
| 23 | 35 | ||
| 24 | #update=remove import of 'foo.zig' | 36 | #write main.zig { |
| 25 | #file=main.zig | ||
| 26 | pub fn main() !void { | 37 | pub fn main() !void { |
| 27 | //_ = @import("foo.zig"); | 38 | //_ = @import("foo.zig"); |
| 28 | try std.Io.File.stdout().writeStreamingAll(io, "success\n"); | 39 | try std.Io.File.stdout().writeStreamingAll(io, "success\n"); |
| 29 | } | 40 | } |
| 30 | const std = @import("std"); | 41 | const std = @import("std"); |
| 31 | const io = std.Io.Threaded.global_single_threaded.io(); | 42 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 32 | #expect_stdout="success\n" | 43 | #} |
| 44 | #update { | ||
| 45 | remove import of 'foo.zig'#} | ||
| 46 | #check stdout { | ||
| 47 | success | ||
| 48 | #} |
test/incremental/change_bitpack_backing_int+53-30| ... | @@ -1,5 +1,8 @@ | ... | @@ -1,5 +1,8 @@ |
| 1 | #update=initial version | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | const Foo = packed struct(u8) { a: u4, b: i4 }; | 6 | const Foo = packed struct(u8) { a: u4, b: i4 }; |
| 4 | const Bar = packed union(u10) { a: u10, b: i10 }; | 7 | const Bar = packed union(u10) { a: u10, b: i10 }; |
| 5 | pub fn main() void {} | 8 | pub fn main() void {} |
| ... | @@ -11,13 +14,18 @@ comptime { | ... | @@ -11,13 +14,18 @@ comptime { |
| 11 | } | 14 | } |
| 12 | const std = @import("std"); | 15 | const std = @import("std"); |
| 13 | const io = std.Io.Threaded.global_single_threaded.io(); | 16 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 14 | #expect_error=main.zig:5:5: error: found compile log statement | 17 | #} |
| 15 | #expect_error=main.zig:8:5: note: also here | 18 | #update |
| 16 | #expect_compile_log=@as(type, u8) | 19 | #check errors { |
| 17 | #expect_compile_log=@as(comptime_int, 10) | 20 | main.zig:5:5: error: found compile log statement |
| 21 | main.zig:8:5: note: also here | ||
| 22 | |||
| 23 | Compile Log Output: | ||
| 24 | @as(type, u8) | ||
| 25 | @as(comptime_int, 10) | ||
| 26 | #} | ||
| 18 | 27 | ||
| 19 | #update=make backing types signed | 28 | #write main.zig { |
| 20 | #file=main.zig | ||
| 21 | const Foo = packed struct(i8) { a: u4, b: i4 }; | 29 | const Foo = packed struct(i8) { a: u4, b: i4 }; |
| 22 | const Bar = packed union(i10) { a: u10, b: i10 }; | 30 | const Bar = packed union(i10) { a: u10, b: i10 }; |
| 23 | pub fn main() void {} | 31 | pub fn main() void {} |
| ... | @@ -29,13 +37,19 @@ comptime { | ... | @@ -29,13 +37,19 @@ comptime { |
| 29 | } | 37 | } |
| 30 | const std = @import("std"); | 38 | const std = @import("std"); |
| 31 | const io = std.Io.Threaded.global_single_threaded.io(); | 39 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 32 | #expect_error=main.zig:5:5: error: found compile log statement | 40 | #} |
| 33 | #expect_error=main.zig:8:5: note: also here | 41 | #update { |
| 34 | #expect_compile_log=@as(type, i8) | 42 | make backing types signed#} |
| 35 | #expect_compile_log=@as(comptime_int, 10) | 43 | #check errors { |
| 44 | main.zig:5:5: error: found compile log statement | ||
| 45 | main.zig:8:5: note: also here | ||
| 46 | |||
| 47 | Compile Log Output: | ||
| 48 | @as(type, i8) | ||
| 49 | @as(comptime_int, 10) | ||
| 50 | #} | ||
| 36 | 51 | ||
| 37 | #update=make backing types too small | 52 | #write main.zig { |
| 38 | #file=main.zig | ||
| 39 | const Foo = packed struct(i5) { a: u4, b: i4 }; | 53 | const Foo = packed struct(i5) { a: u4, b: i4 }; |
| 40 | const Bar = packed union(i8) { a: u10, b: i10 }; | 54 | const Bar = packed union(i8) { a: u10, b: i10 }; |
| 41 | pub fn main() void {} | 55 | pub fn main() void {} |
| ... | @@ -47,16 +61,20 @@ comptime { | ... | @@ -47,16 +61,20 @@ comptime { |
| 47 | } | 61 | } |
| 48 | const std = @import("std"); | 62 | const std = @import("std"); |
| 49 | const io = std.Io.Threaded.global_single_threaded.io(); | 63 | 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 | 64 | #} |
| 51 | #expect_error=main.zig:1:27: note: backing integer 'i5' has bit width '5' | 65 | #update { |
| 52 | #expect_error=main.zig:1:20: note: struct fields have total bit width '8' | 66 | make backing types too small#} |
| 53 | #expect_error=main.zig:2:35: error: field bit width does not match backing integer | 67 | #check errors { |
| 54 | #expect_error=main.zig:2:35: note: field type 'u10' has bit width '10' | 68 | main.zig:1:20: error: backing integer bit width does not match total bit width of fields |
| 55 | #expect_error=main.zig:2:26: note: backing integer 'i8' has bit width '8' | 69 | main.zig:1:27: note: backing integer 'i5' has bit width '5' |
| 56 | #expect_error=main.zig:2:35: note: all fields in a packed union must have the same bit width | 70 | main.zig:1:20: note: struct fields have total bit width '8' |
| 71 | main.zig:2:35: error: field bit width does not match backing integer | ||
| 72 | main.zig:2:35: note: field type 'u10' has bit width '10' | ||
| 73 | main.zig:2:26: note: backing integer 'i8' has bit width '8' | ||
| 74 | main.zig:2:35: note: all fields in a packed union must have the same bit width | ||
| 75 | #} | ||
| 57 | 76 | ||
| 58 | #update=make backing types too big | 77 | #write main.zig { |
| 59 | #file=main.zig | ||
| 60 | const Foo = packed struct(u10) { a: u4, b: i4 }; | 78 | const Foo = packed struct(u10) { a: u4, b: i4 }; |
| 61 | const Bar = packed union(u32) { a: u10, b: i10 }; | 79 | const Bar = packed union(u32) { a: u10, b: i10 }; |
| 62 | pub fn main() void {} | 80 | pub fn main() void {} |
| ... | @@ -68,10 +86,15 @@ comptime { | ... | @@ -68,10 +86,15 @@ comptime { |
| 68 | } | 86 | } |
| 69 | const std = @import("std"); | 87 | const std = @import("std"); |
| 70 | const io = std.Io.Threaded.global_single_threaded.io(); | 88 | 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 | 89 | #} |
| 72 | #expect_error=main.zig:1:27: note: backing integer 'u10' has bit width '10' | 90 | #update { |
| 73 | #expect_error=main.zig:1:20: note: struct fields have total bit width '8' | 91 | make backing types too big#} |
| 74 | #expect_error=main.zig:2:36: error: field bit width does not match backing integer | 92 | #check errors { |
| 75 | #expect_error=main.zig:2:36: note: field type 'u10' has bit width '10' | 93 | main.zig:1:20: error: backing integer bit width does not match total bit width of fields |
| 76 | #expect_error=main.zig:2:26: note: backing integer 'u32' has bit width '32' | 94 | main.zig:1:27: note: backing integer 'u10' has bit width '10' |
| 77 | #expect_error=main.zig:2:36: note: all fields in a packed union must have the same bit width | 95 | main.zig:1:20: note: struct fields have total bit width '8' |
| 96 | main.zig:2:36: error: field bit width does not match backing integer | ||
| 97 | main.zig:2:36: note: field type 'u10' has bit width '10' | ||
| 98 | main.zig:2:26: note: backing integer 'u32' has bit width '32' | ||
| 99 | main.zig:2:36: note: all fields in a packed union must have the same bit width | ||
| 100 | #} |
test/incremental/change_container_kind+94-41| ... | @@ -1,61 +1,114 @@ | ... | @@ -1,61 +1,114 @@ |
| 1 | #update=initial version, T is struct | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | const T = @import("foo.zig").T; | 6 | const T = @import("foo.zig").T; |
| 4 | pub fn main() void { | 7 | pub fn main() void { |
| 5 | @compileLog(T); | 8 | @compileLog(T); |
| 6 | @compileLog(@tagName(@typeInfo(T))); | 9 | @compileLog(@tagName(@typeInfo(T))); |
| 7 | } | 10 | } |
| 8 | #file=foo.zig | 11 | #} |
| 12 | #write foo.zig { | ||
| 9 | pub const T = struct { x: u8 }; | 13 | pub const T = struct { x: u8 }; |
| 10 | #expect_error=main.zig:3:5: error: found compile log statement | 14 | #} |
| 11 | #expect_compile_log=@as(type, foo.T) | 15 | #update { |
| 12 | #expect_compile_log=@as(*const [6:0]u8, "struct") | 16 | T is struct#} |
| 17 | #check errors { | ||
| 18 | main.zig:3:5: error: found compile log statement | ||
| 19 | |||
| 20 | Compile Log Output: | ||
| 21 | @as(type, foo.T) | ||
| 22 | @as(*const [6:0]u8, "struct") | ||
| 23 | #} | ||
| 13 | 24 | ||
| 14 | #update=T is union | 25 | #write foo.zig { |
| 15 | #file=foo.zig | ||
| 16 | pub const T = union {}; | 26 | pub const T = union {}; |
| 17 | #expect_error=main.zig:3:5: error: found compile log statement | 27 | #} |
| 18 | #expect_compile_log=@as(type, foo.T) | 28 | #update { |
| 19 | #expect_compile_log=@as(*const [5:0]u8, "union") | 29 | T is union#} |
| 30 | #check errors { | ||
| 31 | main.zig:3:5: error: found compile log statement | ||
| 32 | |||
| 33 | Compile Log Output: | ||
| 34 | @as(type, foo.T) | ||
| 35 | @as(*const [5:0]u8, "union") | ||
| 36 | #} | ||
| 20 | 37 | ||
| 21 | #update=T is enum | 38 | #write foo.zig { |
| 22 | #file=foo.zig | ||
| 23 | pub const T = enum {}; | 39 | pub const T = enum {}; |
| 24 | #expect_error=main.zig:3:5: error: found compile log statement | 40 | #} |
| 25 | #expect_compile_log=@as(type, foo.T) | 41 | #update { |
| 26 | #expect_compile_log=@as(*const [4:0]u8, "enum") | 42 | T is enum#} |
| 43 | #check errors { | ||
| 44 | main.zig:3:5: error: found compile log statement | ||
| 27 | 45 | ||
| 28 | #update=T is opaque | 46 | Compile Log Output: |
| 29 | #file=foo.zig | 47 | @as(type, foo.T) |
| 48 | @as(*const [4:0]u8, "enum") | ||
| 49 | #} | ||
| 50 | |||
| 51 | #write foo.zig { | ||
| 30 | pub const T = opaque {}; | 52 | pub const T = opaque {}; |
| 31 | #expect_error=main.zig:3:5: error: found compile log statement | 53 | #} |
| 32 | #expect_compile_log=@as(type, foo.T) | 54 | #update { |
| 33 | #expect_compile_log=@as(*const [6:0]u8, "opaque") | 55 | T is opaque#} |
| 56 | #check errors { | ||
| 57 | main.zig:3:5: error: found compile log statement | ||
| 58 | |||
| 59 | Compile Log Output: | ||
| 60 | @as(type, foo.T) | ||
| 61 | @as(*const [6:0]u8, "opaque") | ||
| 62 | #} | ||
| 34 | 63 | ||
| 35 | #update=T is packed struct | 64 | #write foo.zig { |
| 36 | #file=foo.zig | ||
| 37 | pub const T = packed struct {}; | 65 | pub const T = packed struct {}; |
| 38 | #expect_error=main.zig:3:5: error: found compile log statement | 66 | #} |
| 39 | #expect_compile_log=@as(type, foo.T) | 67 | #update { |
| 40 | #expect_compile_log=@as(*const [6:0]u8, "struct") | 68 | T is packed struct#} |
| 69 | #check errors { | ||
| 70 | main.zig:3:5: error: found compile log statement | ||
| 41 | 71 | ||
| 42 | #update=T is packed union | 72 | Compile Log Output: |
| 43 | #file=foo.zig | 73 | @as(type, foo.T) |
| 74 | @as(*const [6:0]u8, "struct") | ||
| 75 | #} | ||
| 76 | |||
| 77 | #write foo.zig { | ||
| 44 | pub const T = packed union { x: void }; // packed unions need at least 1 field | 78 | pub const T = packed union { x: void }; // packed unions need at least 1 field |
| 45 | #expect_error=main.zig:3:5: error: found compile log statement | 79 | #} |
| 46 | #expect_compile_log=@as(type, foo.T) | 80 | #update { |
| 47 | #expect_compile_log=@as(*const [5:0]u8, "union") | 81 | T is packed union#} |
| 82 | #check errors { | ||
| 83 | main.zig:3:5: error: found compile log statement | ||
| 84 | |||
| 85 | Compile Log Output: | ||
| 86 | @as(type, foo.T) | ||
| 87 | @as(*const [5:0]u8, "union") | ||
| 88 | #} | ||
| 48 | 89 | ||
| 49 | #update=T is extern struct | 90 | #write foo.zig { |
| 50 | #file=foo.zig | ||
| 51 | pub const T = extern struct {}; | 91 | pub const T = extern struct {}; |
| 52 | #expect_error=main.zig:3:5: error: found compile log statement | 92 | #} |
| 53 | #expect_compile_log=@as(type, foo.T) | 93 | #update { |
| 54 | #expect_compile_log=@as(*const [6:0]u8, "struct") | 94 | T is extern struct#} |
| 95 | #check errors { | ||
| 96 | main.zig:3:5: error: found compile log statement | ||
| 55 | 97 | ||
| 56 | #update=T is extern union | 98 | Compile Log Output: |
| 57 | #file=foo.zig | 99 | @as(type, foo.T) |
| 100 | @as(*const [6:0]u8, "struct") | ||
| 101 | #} | ||
| 102 | |||
| 103 | #write foo.zig { | ||
| 58 | pub const T = extern union { x: void }; // extern unions need at least 1 field | 104 | pub const T = extern union { x: void }; // extern unions need at least 1 field |
| 59 | #expect_error=main.zig:3:5: error: found compile log statement | 105 | #} |
| 60 | #expect_compile_log=@as(type, foo.T) | 106 | #update { |
| 61 | #expect_compile_log=@as(*const [5:0]u8, "union") | 107 | T is extern union#} |
| 108 | #check errors { | ||
| 109 | main.zig:3:5: error: found compile log statement | ||
| 110 | |||
| 111 | Compile Log Output: | ||
| 112 | @as(type, foo.T) | ||
| 113 | @as(*const [5:0]u8, "union") | ||
| 114 | #} |
test/incremental/change_embed_file+46-19| ... | @@ -1,45 +1,72 @@ | ... | @@ -1,45 +1,72 @@ |
| 1 | #update=initial version | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | const std = @import("std"); | 6 | const std = @import("std"); |
| 4 | const string = @embedFile("string.txt"); | 7 | const string = @embedFile("string.txt"); |
| 5 | pub fn main() !void { | 8 | pub fn main() !void { |
| 6 | try std.Io.File.stdout().writeStreamingAll(io, string); | 9 | try std.Io.File.stdout().writeStreamingAll(io, string); |
| 7 | } | 10 | } |
| 8 | const io = std.Io.Threaded.global_single_threaded.io(); | 11 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 9 | #file=string.txt | 12 | #} |
| 13 | #write string.txt { | ||
| 14 | Hello, World! | ||
| 15 | #} | ||
| 16 | #update | ||
| 17 | #check stdout { | ||
| 10 | Hello, World! | 18 | Hello, World! |
| 11 | #expect_stdout="Hello, World!\n" | 19 | #} |
| 12 | 20 | ||
| 13 | #update=change file contents | 21 | #write string.txt { |
| 14 | #file=string.txt | ||
| 15 | Hello again, World! | 22 | Hello again, World! |
| 16 | #expect_stdout="Hello again, World!\n" | 23 | #} |
| 24 | #update { | ||
| 25 | change file contents#} | ||
| 26 | #check stdout { | ||
| 27 | Hello again, World! | ||
| 28 | #} | ||
| 17 | 29 | ||
| 18 | #update=delete file | 30 | #delete string.txt |
| 19 | #rm_file=string.txt | 31 | #update { |
| 20 | #expect_error=main.zig:2:27: error: failed opening "string.txt": FileNotFound | 32 | delete file#} |
| 33 | #check errors { | ||
| 34 | main.zig:2:27: error: failed opening "string.txt": FileNotFound | ||
| 35 | #} | ||
| 21 | 36 | ||
| 22 | #update=remove reference to file | 37 | #write main.zig { |
| 23 | #file=main.zig | ||
| 24 | const std = @import("std"); | 38 | const std = @import("std"); |
| 25 | const string = @embedFile("string.txt"); | 39 | const string = @embedFile("string.txt"); |
| 26 | pub fn main() !void { | 40 | pub fn main() !void { |
| 27 | try std.Io.File.stdout().writeStreamingAll(io, "a hardcoded string\n"); | 41 | try std.Io.File.stdout().writeStreamingAll(io, "a hardcoded string\n"); |
| 28 | } | 42 | } |
| 29 | const io = std.Io.Threaded.global_single_threaded.io(); | 43 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 30 | #expect_stdout="a hardcoded string\n" | 44 | #} |
| 45 | #update { | ||
| 46 | remove reference to file#} | ||
| 47 | #check stdout { | ||
| 48 | a hardcoded string | ||
| 49 | #} | ||
| 31 | 50 | ||
| 32 | #update=re-introduce reference to file | 51 | #write main.zig { |
| 33 | #file=main.zig | ||
| 34 | const std = @import("std"); | 52 | const std = @import("std"); |
| 35 | const string = @embedFile("string.txt"); | 53 | const string = @embedFile("string.txt"); |
| 36 | pub fn main() !void { | 54 | pub fn main() !void { |
| 37 | try std.Io.File.stdout().writeStreamingAll(io, string); | 55 | try std.Io.File.stdout().writeStreamingAll(io, string); |
| 38 | } | 56 | } |
| 39 | const io = std.Io.Threaded.global_single_threaded.io(); | 57 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 40 | #expect_error=main.zig:2:27: error: failed opening "string.txt": FileNotFound | 58 | #} |
| 59 | #update { | ||
| 60 | re-introduce reference to file#} | ||
| 61 | #check errors { | ||
| 62 | main.zig:2:27: error: failed opening "string.txt": FileNotFound | ||
| 63 | #} | ||
| 41 | 64 | ||
| 42 | #update=recreate file | 65 | #write string.txt { |
| 43 | #file=string.txt | 66 | We're back, World! |
| 67 | #} | ||
| 68 | #update { | ||
| 69 | recreate file#} | ||
| 70 | #check stdout { | ||
| 44 | We're back, World! | 71 | We're back, World! |
| 45 | #expect_stdout="We're back, World!\n" | 72 | #} |
test/incremental/change_enum_tag_type deleted-93| ... | @@ -1,93 +0,0 @@ | ||
| 1 | #update=initial version | ||
| 2 | #file=main.zig | ||
| 3 | const Tag = u2; | ||
| 4 | const Foo = enum(Tag) { | ||
| 5 | a, | ||
| 6 | b, | ||
| 7 | c, | ||
| 8 | d, | ||
| 9 | }; | ||
| 10 | pub fn main() !void { | ||
| 11 | var val: Foo = undefined; | ||
| 12 | val = .a; | ||
| 13 | var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); | ||
| 14 | try stdout_writer.interface.print("{s}\n", .{@tagName(val)}); | ||
| 15 | } | ||
| 16 | const std = @import("std"); | ||
| 17 | const io = std.Io.Threaded.global_single_threaded.io(); | ||
| 18 | #expect_stdout="a\n" | ||
| 19 | #update=too many enum fields | ||
| 20 | #file=main.zig | ||
| 21 | const Tag = u2; | ||
| 22 | const Foo = enum(Tag) { | ||
| 23 | a, | ||
| 24 | b, | ||
| 25 | c, | ||
| 26 | d, | ||
| 27 | e, | ||
| 28 | }; | ||
| 29 | pub fn main() !void { | ||
| 30 | var val: Foo = undefined; | ||
| 31 | val = .a; | ||
| 32 | var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); | ||
| 33 | try stdout_writer.interface.print("{s}\n", .{@tagName(val)}); | ||
| 34 | } | ||
| 35 | comptime { | ||
| 36 | // These can't be true at the same time; analysis should stop as soon as it sees `Foo` | ||
| 37 | std.debug.assert(@intFromEnum(Foo.e) == 4); | ||
| 38 | std.debug.assert(@TypeOf(@intFromEnum(Foo.e)) == Tag); | ||
| 39 | } | ||
| 40 | const std = @import("std"); | ||
| 41 | const io = std.Io.Threaded.global_single_threaded.io(); | ||
| 42 | #expect_error=main.zig:7:5: error: enum tag value '4' too large for type 'u2' | ||
| 43 | #update=increase tag size | ||
| 44 | #file=main.zig | ||
| 45 | const Tag = u3; | ||
| 46 | const Foo = enum(Tag) { | ||
| 47 | a, | ||
| 48 | b, | ||
| 49 | c, | ||
| 50 | d, | ||
| 51 | e, | ||
| 52 | }; | ||
| 53 | pub fn main() !void { | ||
| 54 | var val: Foo = undefined; | ||
| 55 | val = .a; | ||
| 56 | var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); | ||
| 57 | try stdout_writer.interface.print("{s}\n", .{@tagName(val)}); | ||
| 58 | } | ||
| 59 | const std = @import("std"); | ||
| 60 | const io = std.Io.Threaded.global_single_threaded.io(); | ||
| 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_enum_tag_type/0/main.zig created+15| ... | @@ -0,0 +1,15 @@ | ||
| 1 | const Tag = u2; | ||
| 2 | const Foo = enum(Tag) { | ||
| 3 | a, | ||
| 4 | b, | ||
| 5 | c, | ||
| 6 | d, | ||
| 7 | }; | ||
| 8 | pub fn main() !void { | ||
| 9 | var val: Foo = undefined; | ||
| 10 | val = .a; | ||
| 11 | var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); | ||
| 12 | try stdout_writer.interface.print("{s}\n", .{@tagName(val)}); | ||
| 13 | } | ||
| 14 | const std = @import("std"); | ||
| 15 | const io = std.Io.Threaded.global_single_threaded.io(); | ||
test/incremental/change_enum_tag_type/1/main.zig created+21| ... | @@ -0,0 +1,21 @@ | ||
| 1 | const Tag = u2; | ||
| 2 | const Foo = enum(Tag) { | ||
| 3 | a, | ||
| 4 | b, | ||
| 5 | c, | ||
| 6 | d, | ||
| 7 | e, | ||
| 8 | }; | ||
| 9 | pub fn main() !void { | ||
| 10 | var val: Foo = undefined; | ||
| 11 | val = .a; | ||
| 12 | var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); | ||
| 13 | try stdout_writer.interface.print("{s}\n", .{@tagName(val)}); | ||
| 14 | } | ||
| 15 | comptime { | ||
| 16 | // These can't be true at the same time; analysis should stop as soon as it sees `Foo` | ||
| 17 | std.debug.assert(@backingInt(Foo.e) == 4); | ||
| 18 | std.debug.assert(@TypeOf(@backingInt(Foo.e)) == Tag); | ||
| 19 | } | ||
| 20 | const std = @import("std"); | ||
| 21 | const io = std.Io.Threaded.global_single_threaded.io(); | ||
test/incremental/change_enum_tag_type/2/main.zig created+16| ... | @@ -0,0 +1,16 @@ | ||
| 1 | const Tag = u3; | ||
| 2 | const Foo = enum(Tag) { | ||
| 3 | a, | ||
| 4 | b, | ||
| 5 | c, | ||
| 6 | d, | ||
| 7 | e, | ||
| 8 | }; | ||
| 9 | pub fn main() !void { | ||
| 10 | var val: Foo = undefined; | ||
| 11 | val = .a; | ||
| 12 | var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); | ||
| 13 | try stdout_writer.interface.print("{s}\n", .{@tagName(val)}); | ||
| 14 | } | ||
| 15 | const std = @import("std"); | ||
| 16 | const io = std.Io.Threaded.global_single_threaded.io(); | ||
test/incremental/change_enum_tag_type/3/main.zig created+12| ... | @@ -0,0 +1,12 @@ | ||
| 1 | const Foo = enum(u3) { | ||
| 2 | a, | ||
| 3 | b, | ||
| 4 | c, | ||
| 5 | d, | ||
| 6 | e, | ||
| 7 | }; | ||
| 8 | pub fn main() !void { | ||
| 9 | @compileLog(@typeInfo(Foo).@"enum".tag_type); | ||
| 10 | } | ||
| 11 | const std = @import("std"); | ||
| 12 | const io = std.Io.Threaded.global_single_threaded.io(); | ||
test/incremental/change_enum_tag_type/4/main.zig created+12| ... | @@ -0,0 +1,12 @@ | ||
| 1 | const Foo = enum(u8) { | ||
| 2 | a, | ||
| 3 | b, | ||
| 4 | c, | ||
| 5 | d, | ||
| 6 | e, | ||
| 7 | }; | ||
| 8 | pub fn main() !void { | ||
| 9 | @compileLog(@typeInfo(Foo).@"enum".tag_type); | ||
| 10 | } | ||
| 11 | const std = @import("std"); | ||
| 12 | const io = std.Io.Threaded.global_single_threaded.io(); | ||
test/incremental/change_enum_tag_type/manifest created+43| ... | @@ -0,0 +1,43 @@ | ||
| 1 | #exe { | ||
| 2 | -Mroot=main.zig | ||
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig 0/main.zig | ||
| 6 | #update | ||
| 7 | #check stdout { | ||
| 8 | a | ||
| 9 | #} | ||
| 10 | |||
| 11 | #write main.zig 1/main.zig | ||
| 12 | #update { | ||
| 13 | too many enum fields#} | ||
| 14 | #check errors { | ||
| 15 | main.zig:7:5: error: enum tag value '4' too large for type 'u2' | ||
| 16 | #} | ||
| 17 | |||
| 18 | #write main.zig 2/main.zig | ||
| 19 | #update { | ||
| 20 | increase tag size#} | ||
| 21 | #check stdout { | ||
| 22 | a | ||
| 23 | #} | ||
| 24 | |||
| 25 | #write main.zig 3/main.zig | ||
| 26 | #update { | ||
| 27 | specify tag directly#} | ||
| 28 | #check errors { | ||
| 29 | main.zig:9:5: error: found compile log statement | ||
| 30 | |||
| 31 | Compile Log Output: | ||
| 32 | @as(type, u3) | ||
| 33 | #} | ||
| 34 | |||
| 35 | #write main.zig 4/main.zig | ||
| 36 | #update { | ||
| 37 | change directly-specified tag type#} | ||
| 38 | #check errors { | ||
| 39 | main.zig:9:5: error: found compile log statement | ||
| 40 | |||
| 41 | Compile Log Output: | ||
| 42 | @as(type, u8) | ||
| 43 | #} | ||
test/incremental/change_exports deleted-169| ... | @@ -1,169 +0,0 @@ | ||
| 1 | #update=initial version | ||
| 2 | #file=main.zig | ||
| 3 | export fn foo() void {} | ||
| 4 | const bar: u32 = 123; | ||
| 5 | const other: u32 = 456; | ||
| 6 | comptime { | ||
| 7 | @export(&bar, .{ .name = "bar" }); | ||
| 8 | } | ||
| 9 | pub fn main() !void { | ||
| 10 | const S = struct { | ||
| 11 | extern fn foo() void; | ||
| 12 | extern const bar: u32; | ||
| 13 | }; | ||
| 14 | S.foo(); | ||
| 15 | var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); | ||
| 16 | try stdout_writer.interface.print("{}\n", .{S.bar}); | ||
| 17 | } | ||
| 18 | const std = @import("std"); | ||
| 19 | const io = std.Io.Threaded.global_single_threaded.io(); | ||
| 20 | #expect_stdout="123\n" | ||
| 21 | |||
| 22 | #update=add conflict | ||
| 23 | #file=main.zig | ||
| 24 | export fn foo() void {} | ||
| 25 | const bar: u32 = 123; | ||
| 26 | const other: u32 = 456; | ||
| 27 | comptime { | ||
| 28 | @export(&bar, .{ .name = "bar" }); | ||
| 29 | @export(&other, .{ .name = "foo" }); | ||
| 30 | } | ||
| 31 | pub fn main() !void { | ||
| 32 | const S = struct { | ||
| 33 | extern fn foo() void; | ||
| 34 | extern const bar: u32; | ||
| 35 | extern const other: u32; | ||
| 36 | }; | ||
| 37 | S.foo(); | ||
| 38 | var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); | ||
| 39 | try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other }); | ||
| 40 | } | ||
| 41 | const std = @import("std"); | ||
| 42 | const io = std.Io.Threaded.global_single_threaded.io(); | ||
| 43 | #expect_error=main.zig:6:5: error: exported symbol collision: foo | ||
| 44 | #expect_error=main.zig:1:1: note: other symbol here | ||
| 45 | |||
| 46 | #update=resolve conflict | ||
| 47 | #file=main.zig | ||
| 48 | export fn foo() void {} | ||
| 49 | const bar: u32 = 123; | ||
| 50 | const other: u32 = 456; | ||
| 51 | comptime { | ||
| 52 | @export(&bar, .{ .name = "bar" }); | ||
| 53 | @export(&other, .{ .name = "other" }); | ||
| 54 | } | ||
| 55 | pub fn main() !void { | ||
| 56 | const S = struct { | ||
| 57 | extern fn foo() void; | ||
| 58 | extern const bar: u32; | ||
| 59 | extern const other: u32; | ||
| 60 | }; | ||
| 61 | S.foo(); | ||
| 62 | var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); | ||
| 63 | try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other }); | ||
| 64 | } | ||
| 65 | const std = @import("std"); | ||
| 66 | const io = std.Io.Threaded.global_single_threaded.io(); | ||
| 67 | #expect_stdout="123 456\n" | ||
| 68 | |||
| 69 | #update=put exports in decl | ||
| 70 | #file=main.zig | ||
| 71 | export fn foo() void {} | ||
| 72 | const bar: u32 = 123; | ||
| 73 | const other: u32 = 456; | ||
| 74 | const does_exports = { | ||
| 75 | @export(&bar, .{ .name = "bar" }); | ||
| 76 | @export(&other, .{ .name = "other" }); | ||
| 77 | }; | ||
| 78 | comptime { | ||
| 79 | _ = does_exports; | ||
| 80 | } | ||
| 81 | pub fn main() !void { | ||
| 82 | const S = struct { | ||
| 83 | extern fn foo() void; | ||
| 84 | extern const bar: u32; | ||
| 85 | extern const other: u32; | ||
| 86 | }; | ||
| 87 | S.foo(); | ||
| 88 | var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); | ||
| 89 | try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other }); | ||
| 90 | } | ||
| 91 | const std = @import("std"); | ||
| 92 | const io = std.Io.Threaded.global_single_threaded.io(); | ||
| 93 | #expect_stdout="123 456\n" | ||
| 94 | |||
| 95 | #update=remove reference to exporting decl | ||
| 96 | #file=main.zig | ||
| 97 | export fn foo() void {} | ||
| 98 | const bar: u32 = 123; | ||
| 99 | const other: u32 = 456; | ||
| 100 | const does_exports = { | ||
| 101 | @export(&bar, .{ .name = "bar" }); | ||
| 102 | @export(&other, .{ .name = "other" }); | ||
| 103 | }; | ||
| 104 | comptime { | ||
| 105 | //_ = does_exports; | ||
| 106 | } | ||
| 107 | pub fn main() !void { | ||
| 108 | const S = struct { | ||
| 109 | extern fn foo() void; | ||
| 110 | }; | ||
| 111 | S.foo(); | ||
| 112 | } | ||
| 113 | const std = @import("std"); | ||
| 114 | #expect_stdout="" | ||
| 115 | |||
| 116 | #update=mark consts as export | ||
| 117 | #file=main.zig | ||
| 118 | export fn foo() void {} | ||
| 119 | export const bar: u32 = 123; | ||
| 120 | export const other: u32 = 456; | ||
| 121 | const does_exports = { | ||
| 122 | @export(&bar, .{ .name = "bar" }); | ||
| 123 | @export(&other, .{ .name = "other" }); | ||
| 124 | }; | ||
| 125 | comptime { | ||
| 126 | //_ = does_exports; | ||
| 127 | } | ||
| 128 | pub fn main() !void { | ||
| 129 | const S = struct { | ||
| 130 | extern fn foo() void; | ||
| 131 | extern const bar: u32; | ||
| 132 | extern const other: u32; | ||
| 133 | }; | ||
| 134 | S.foo(); | ||
| 135 | var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); | ||
| 136 | try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other }); | ||
| 137 | } | ||
| 138 | const std = @import("std"); | ||
| 139 | const io = std.Io.Threaded.global_single_threaded.io(); | ||
| 140 | #expect_stdout="123 456\n" | ||
| 141 | |||
| 142 | #update=reintroduce reference to exporting decl, introducing conflict | ||
| 143 | #file=main.zig | ||
| 144 | export fn foo() void {} | ||
| 145 | export const bar: u32 = 123; | ||
| 146 | export const other: u32 = 456; | ||
| 147 | const does_exports = { | ||
| 148 | @export(&bar, .{ .name = "bar" }); | ||
| 149 | @export(&other, .{ .name = "other" }); | ||
| 150 | }; | ||
| 151 | comptime { | ||
| 152 | _ = does_exports; | ||
| 153 | } | ||
| 154 | pub fn main() !void { | ||
| 155 | const S = struct { | ||
| 156 | extern fn foo() void; | ||
| 157 | extern const bar: u32; | ||
| 158 | extern const other: u32; | ||
| 159 | }; | ||
| 160 | S.foo(); | ||
| 161 | var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); | ||
| 162 | try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other }); | ||
| 163 | } | ||
| 164 | const std = @import("std"); | ||
| 165 | const io = std.Io.Threaded.global_single_threaded.io(); | ||
| 166 | #expect_error=main.zig:5:5: error: exported symbol collision: bar | ||
| 167 | #expect_error=main.zig:2:1: note: other symbol here | ||
| 168 | #expect_error=main.zig:6:5: error: exported symbol collision: other | ||
| 169 | #expect_error=main.zig:3:1: note: other symbol here | ||
test/incremental/change_exports/0/main.zig created+17| ... | @@ -0,0 +1,17 @@ | ||
| 1 | export fn foo() void {} | ||
| 2 | const bar: u32 = 123; | ||
| 3 | const other: u32 = 456; | ||
| 4 | comptime { | ||
| 5 | @export(&bar, .{ .name = "bar" }); | ||
| 6 | } | ||
| 7 | pub fn main() !void { | ||
| 8 | const S = struct { | ||
| 9 | extern fn foo() void; | ||
| 10 | extern const bar: u32; | ||
| 11 | }; | ||
| 12 | S.foo(); | ||
| 13 | var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); | ||
| 14 | try stdout_writer.interface.print("{}\n", .{S.bar}); | ||
| 15 | } | ||
| 16 | const std = @import("std"); | ||
| 17 | const io = std.Io.Threaded.global_single_threaded.io(); | ||
test/incremental/change_exports/1/main.zig created+19| ... | @@ -0,0 +1,19 @@ | ||
| 1 | export fn foo() void {} | ||
| 2 | const bar: u32 = 123; | ||
| 3 | const other: u32 = 456; | ||
| 4 | comptime { | ||
| 5 | @export(&bar, .{ .name = "bar" }); | ||
| 6 | @export(&other, .{ .name = "foo" }); | ||
| 7 | } | ||
| 8 | pub fn main() !void { | ||
| 9 | const S = struct { | ||
| 10 | extern fn foo() void; | ||
| 11 | extern const bar: u32; | ||
| 12 | extern const other: u32; | ||
| 13 | }; | ||
| 14 | S.foo(); | ||
| 15 | var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); | ||
| 16 | try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other }); | ||
| 17 | } | ||
| 18 | const std = @import("std"); | ||
| 19 | const io = std.Io.Threaded.global_single_threaded.io(); | ||
test/incremental/change_exports/2/main.zig created+19| ... | @@ -0,0 +1,19 @@ | ||
| 1 | export fn foo() void {} | ||
| 2 | const bar: u32 = 123; | ||
| 3 | const other: u32 = 456; | ||
| 4 | comptime { | ||
| 5 | @export(&bar, .{ .name = "bar" }); | ||
| 6 | @export(&other, .{ .name = "other" }); | ||
| 7 | } | ||
| 8 | pub fn main() !void { | ||
| 9 | const S = struct { | ||
| 10 | extern fn foo() void; | ||
| 11 | extern const bar: u32; | ||
| 12 | extern const other: u32; | ||
| 13 | }; | ||
| 14 | S.foo(); | ||
| 15 | var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); | ||
| 16 | try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other }); | ||
| 17 | } | ||
| 18 | const std = @import("std"); | ||
| 19 | const io = std.Io.Threaded.global_single_threaded.io(); | ||
test/incremental/change_exports/3/main.zig created+22| ... | @@ -0,0 +1,22 @@ | ||
| 1 | export fn foo() void {} | ||
| 2 | const bar: u32 = 123; | ||
| 3 | const other: u32 = 456; | ||
| 4 | const does_exports = { | ||
| 5 | @export(&bar, .{ .name = "bar" }); | ||
| 6 | @export(&other, .{ .name = "other" }); | ||
| 7 | }; | ||
| 8 | comptime { | ||
| 9 | _ = does_exports; | ||
| 10 | } | ||
| 11 | pub fn main() !void { | ||
| 12 | const S = struct { | ||
| 13 | extern fn foo() void; | ||
| 14 | extern const bar: u32; | ||
| 15 | extern const other: u32; | ||
| 16 | }; | ||
| 17 | S.foo(); | ||
| 18 | var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); | ||
| 19 | try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other }); | ||
| 20 | } | ||
| 21 | const std = @import("std"); | ||
| 22 | const io = std.Io.Threaded.global_single_threaded.io(); | ||
test/incremental/change_exports/4/main.zig created+17| ... | @@ -0,0 +1,17 @@ | ||
| 1 | export fn foo() void {} | ||
| 2 | const bar: u32 = 123; | ||
| 3 | const other: u32 = 456; | ||
| 4 | const does_exports = { | ||
| 5 | @export(&bar, .{ .name = "bar" }); | ||
| 6 | @export(&other, .{ .name = "other" }); | ||
| 7 | }; | ||
| 8 | comptime { | ||
| 9 | //_ = does_exports; | ||
| 10 | } | ||
| 11 | pub fn main() !void { | ||
| 12 | const S = struct { | ||
| 13 | extern fn foo() void; | ||
| 14 | }; | ||
| 15 | S.foo(); | ||
| 16 | } | ||
| 17 | const std = @import("std"); | ||
test/incremental/change_exports/5/main.zig created+22| ... | @@ -0,0 +1,22 @@ | ||
| 1 | export fn foo() void {} | ||
| 2 | export const bar: u32 = 123; | ||
| 3 | export const other: u32 = 456; | ||
| 4 | const does_exports = { | ||
| 5 | @export(&bar, .{ .name = "bar" }); | ||
| 6 | @export(&other, .{ .name = "other" }); | ||
| 7 | }; | ||
| 8 | comptime { | ||
| 9 | //_ = does_exports; | ||
| 10 | } | ||
| 11 | pub fn main() !void { | ||
| 12 | const S = struct { | ||
| 13 | extern fn foo() void; | ||
| 14 | extern const bar: u32; | ||
| 15 | extern const other: u32; | ||
| 16 | }; | ||
| 17 | S.foo(); | ||
| 18 | var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); | ||
| 19 | try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other }); | ||
| 20 | } | ||
| 21 | const std = @import("std"); | ||
| 22 | const io = std.Io.Threaded.global_single_threaded.io(); | ||
test/incremental/change_exports/6/main.zig created+22| ... | @@ -0,0 +1,22 @@ | ||
| 1 | export fn foo() void {} | ||
| 2 | export const bar: u32 = 123; | ||
| 3 | export const other: u32 = 456; | ||
| 4 | const does_exports = { | ||
| 5 | @export(&bar, .{ .name = "bar" }); | ||
| 6 | @export(&other, .{ .name = "other" }); | ||
| 7 | }; | ||
| 8 | comptime { | ||
| 9 | _ = does_exports; | ||
| 10 | } | ||
| 11 | pub fn main() !void { | ||
| 12 | const S = struct { | ||
| 13 | extern fn foo() void; | ||
| 14 | extern const bar: u32; | ||
| 15 | extern const other: u32; | ||
| 16 | }; | ||
| 17 | S.foo(); | ||
| 18 | var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); | ||
| 19 | try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other }); | ||
| 20 | } | ||
| 21 | const std = @import("std"); | ||
| 22 | const io = std.Io.Threaded.global_single_threaded.io(); | ||
test/incremental/change_exports/manifest created+54| ... | @@ -0,0 +1,54 @@ | ||
| 1 | #exe { | ||
| 2 | -Mroot=main.zig | ||
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig 0/main.zig | ||
| 6 | #update | ||
| 7 | #check stdout { | ||
| 8 | 123 | ||
| 9 | #} | ||
| 10 | |||
| 11 | #write main.zig 1/main.zig | ||
| 12 | #update { | ||
| 13 | add conflict#} | ||
| 14 | #check errors { | ||
| 15 | main.zig:6:5: error: exported symbol collision: foo | ||
| 16 | main.zig:1:1: note: other symbol here | ||
| 17 | #} | ||
| 18 | |||
| 19 | #write main.zig 2/main.zig | ||
| 20 | #update { | ||
| 21 | resolve conflict#} | ||
| 22 | #check stdout { | ||
| 23 | 123 456 | ||
| 24 | #} | ||
| 25 | |||
| 26 | #write main.zig 3/main.zig | ||
| 27 | #update { | ||
| 28 | put exports in decl#} | ||
| 29 | #check stdout { | ||
| 30 | 123 456 | ||
| 31 | #} | ||
| 32 | |||
| 33 | #write main.zig 4/main.zig | ||
| 34 | #update { | ||
| 35 | remove reference to exporting decl#} | ||
| 36 | #check stdout { | ||
| 37 | #} | ||
| 38 | |||
| 39 | #write main.zig 5/main.zig | ||
| 40 | #update { | ||
| 41 | mark consts as export#} | ||
| 42 | #check stdout { | ||
| 43 | 123 456 | ||
| 44 | #} | ||
| 45 | |||
| 46 | #write main.zig 6/main.zig | ||
| 47 | #update { | ||
| 48 | reintroduce reference to exporting decl, introducing conflict#} | ||
| 49 | #check errors { | ||
| 50 | main.zig:5:5: error: exported symbol collision: bar | ||
| 51 | main.zig:2:1: note: other symbol here | ||
| 52 | main.zig:6:5: error: exported symbol collision: other | ||
| 53 | main.zig:3:1: note: other symbol here | ||
| 54 | #} | ||
test/incremental/change_fn_type+24-9| ... | @@ -1,5 +1,8 @@ | ... | @@ -1,5 +1,8 @@ |
| 1 | #update=initial version | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | pub fn main() !void { | 6 | pub fn main() !void { |
| 4 | try foo(123); | 7 | try foo(123); |
| 5 | } | 8 | } |
| ... | @@ -9,10 +12,13 @@ fn foo(x: u8) !void { | ... | @@ -9,10 +12,13 @@ fn foo(x: u8) !void { |
| 9 | } | 12 | } |
| 10 | const std = @import("std"); | 13 | const std = @import("std"); |
| 11 | const io = std.Io.Threaded.global_single_threaded.io(); | 14 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 12 | #expect_stdout="123\n" | 15 | #} |
| 16 | #update | ||
| 17 | #check stdout { | ||
| 18 | 123 | ||
| 19 | #} | ||
| 13 | 20 | ||
| 14 | #update=change function type | 21 | #write main.zig { |
| 15 | #file=main.zig | ||
| 16 | pub fn main() !void { | 22 | pub fn main() !void { |
| 17 | try foo(123); | 23 | try foo(123); |
| 18 | } | 24 | } |
| ... | @@ -22,10 +28,14 @@ fn foo(x: i64) !void { | ... | @@ -22,10 +28,14 @@ fn foo(x: i64) !void { |
| 22 | } | 28 | } |
| 23 | const std = @import("std"); | 29 | const std = @import("std"); |
| 24 | const io = std.Io.Threaded.global_single_threaded.io(); | 30 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 25 | #expect_stdout="123\n" | 31 | #} |
| 32 | #update { | ||
| 33 | change function type#} | ||
| 34 | #check stdout { | ||
| 35 | 123 | ||
| 36 | #} | ||
| 26 | 37 | ||
| 27 | #update=change function argument | 38 | #write main.zig { |
| 28 | #file=main.zig | ||
| 29 | pub fn main() !void { | 39 | pub fn main() !void { |
| 30 | try foo(-42); | 40 | try foo(-42); |
| 31 | } | 41 | } |
| ... | @@ -35,4 +45,9 @@ fn foo(x: i64) !void { | ... | @@ -35,4 +45,9 @@ fn foo(x: i64) !void { |
| 35 | } | 45 | } |
| 36 | const std = @import("std"); | 46 | const std = @import("std"); |
| 37 | const io = std.Io.Threaded.global_single_threaded.io(); | 47 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 38 | #expect_stdout="-42\n" | 48 | #} |
| 49 | #update { | ||
| 50 | change function argument#} | ||
| 51 | #check stdout { | ||
| 52 | -42 | ||
| 53 | #} |
test/incremental/change_generic_line_number+20-6| ... | @@ -1,5 +1,8 @@ | ... | @@ -1,5 +1,8 @@ |
| 1 | #update=initial version | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | const std = @import("std"); | 6 | const std = @import("std"); |
| 4 | const io = std.Io.Threaded.global_single_threaded.io(); | 7 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 5 | fn Printer(message: []const u8) type { | 8 | fn Printer(message: []const u8) type { |
| ... | @@ -13,9 +16,14 @@ pub fn main() !void { | ... | @@ -13,9 +16,14 @@ pub fn main() !void { |
| 13 | try Printer("foo\n").print(); | 16 | try Printer("foo\n").print(); |
| 14 | try Printer("bar\n").print(); | 17 | try Printer("bar\n").print(); |
| 15 | } | 18 | } |
| 16 | #expect_stdout="foo\nbar\n" | 19 | #} |
| 17 | #update=change line number | 20 | #update |
| 18 | #file=main.zig | 21 | #check stdout { |
| 22 | foo | ||
| 23 | bar | ||
| 24 | #} | ||
| 25 | |||
| 26 | #write main.zig { | ||
| 19 | const std = @import("std"); | 27 | const std = @import("std"); |
| 20 | const io = std.Io.Threaded.global_single_threaded.io(); | 28 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 21 | 29 | ||
| ... | @@ -30,4 +38,10 @@ pub fn main() !void { | ... | @@ -30,4 +38,10 @@ pub fn main() !void { |
| 30 | try Printer("foo\n").print(); | 38 | try Printer("foo\n").print(); |
| 31 | try Printer("bar\n").print(); | 39 | try Printer("bar\n").print(); |
| 32 | } | 40 | } |
| 33 | #expect_stdout="foo\nbar\n" | 41 | #} |
| 42 | #update { | ||
| 43 | change line number#} | ||
| 44 | #check stdout { | ||
| 45 | foo | ||
| 46 | bar | ||
| 47 | #} |
test/incremental/change_line_number+18-6| ... | @@ -1,17 +1,29 @@ | ... | @@ -1,17 +1,29 @@ |
| 1 | #update=initial version | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | const std = @import("std"); | 6 | const std = @import("std"); |
| 4 | pub fn main() !void { | 7 | pub fn main() !void { |
| 5 | try std.Io.File.stdout().writeStreamingAll(io, "foo\n"); | 8 | try std.Io.File.stdout().writeStreamingAll(io, "foo\n"); |
| 6 | } | 9 | } |
| 7 | const io = std.Io.Threaded.global_single_threaded.io(); | 10 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 8 | #expect_stdout="foo\n" | 11 | #} |
| 9 | #update=change line number | 12 | #update |
| 10 | #file=main.zig | 13 | #check stdout { |
| 14 | foo | ||
| 15 | #} | ||
| 16 | |||
| 17 | #write main.zig { | ||
| 11 | const std = @import("std"); | 18 | const std = @import("std"); |
| 12 | 19 | ||
| 13 | pub fn main() !void { | 20 | pub fn main() !void { |
| 14 | try std.Io.File.stdout().writeStreamingAll(io, "foo\n"); | 21 | try std.Io.File.stdout().writeStreamingAll(io, "foo\n"); |
| 15 | } | 22 | } |
| 16 | const io = std.Io.Threaded.global_single_threaded.io(); | 23 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 17 | #expect_stdout="foo\n" | 24 | #} |
| 25 | #update { | ||
| 26 | change line number#} | ||
| 27 | #check stdout { | ||
| 28 | foo | ||
| 29 | #} |
test/incremental/change_module+49-23| ... | @@ -1,61 +1,87 @@ | ... | @@ -1,61 +1,87 @@ |
| 1 | #module=foo=foo.zig | 1 | #exe { |
| 2 | --dep foo -Mroot=main.zig | ||
| 3 | -Mfoo=foo.zig | ||
| 4 | #} | ||
| 2 | 5 | ||
| 3 | #update=initial version | 6 | #write main.zig { |
| 4 | #file=main.zig | ||
| 5 | pub fn main() void { | 7 | pub fn main() void { |
| 6 | _ = @import("foo"); | 8 | _ = @import("foo"); |
| 7 | //_ = @import("other.zig"); | 9 | //_ = @import("other.zig"); |
| 8 | } | 10 | } |
| 9 | #file=foo.zig | 11 | #} |
| 12 | #write foo.zig { | ||
| 10 | comptime { | 13 | comptime { |
| 11 | _ = @import("other.zig"); | 14 | _ = @import("other.zig"); |
| 12 | } | 15 | } |
| 13 | #file=other.zig | 16 | #} |
| 17 | #write other.zig { | ||
| 14 | fn f() void { | 18 | fn f() void { |
| 15 | @compileLog(@src().module); | 19 | @compileLog(@src().module); |
| 16 | } | 20 | } |
| 17 | comptime { | 21 | comptime { |
| 18 | f(); | 22 | f(); |
| 19 | } | 23 | } |
| 20 | #expect_error=other.zig:2:5: error: found compile log statement | 24 | #} |
| 21 | #expect_compile_log=@as([:0]const u8, "foo"[0..3]) | 25 | #update |
| 26 | #check errors { | ||
| 27 | other.zig:2:5: error: found compile log statement | ||
| 22 | 28 | ||
| 23 | #update=change module of other.zig | 29 | Compile Log Output: |
| 24 | #file=main.zig | 30 | @as([:0]const u8, "foo"[0..3]) |
| 31 | #} | ||
| 32 | |||
| 33 | #write main.zig { | ||
| 25 | pub fn main() void { | 34 | pub fn main() void { |
| 26 | _ = @import("foo"); | 35 | _ = @import("foo"); |
| 27 | _ = @import("other.zig"); | 36 | _ = @import("other.zig"); |
| 28 | } | 37 | } |
| 29 | #file=foo.zig | 38 | #} |
| 39 | #write foo.zig { | ||
| 30 | comptime { | 40 | comptime { |
| 31 | //_ = @import("other.zig"); | 41 | //_ = @import("other.zig"); |
| 32 | } | 42 | } |
| 33 | #expect_error=other.zig:2:5: error: found compile log statement | 43 | #} |
| 34 | #expect_compile_log=@as([:0]const u8, "root"[0..4]) | 44 | #update { |
| 45 | change module of other.zig#} | ||
| 46 | #check errors { | ||
| 47 | other.zig:2:5: error: found compile log statement | ||
| 48 | |||
| 49 | Compile Log Output: | ||
| 50 | @as([:0]const u8, "root"[0..4]) | ||
| 51 | #} | ||
| 35 | 52 | ||
| 36 | #update=put other.zig in both modules | 53 | #write main.zig { |
| 37 | #file=main.zig | ||
| 38 | pub fn main() void { | 54 | pub fn main() void { |
| 39 | _ = @import("foo"); | 55 | _ = @import("foo"); |
| 40 | _ = @import("other.zig"); | 56 | _ = @import("other.zig"); |
| 41 | } | 57 | } |
| 42 | #file=foo.zig | 58 | #} |
| 59 | #write foo.zig { | ||
| 43 | comptime { | 60 | comptime { |
| 44 | _ = @import("other.zig"); | 61 | _ = @import("other.zig"); |
| 45 | } | 62 | } |
| 46 | #expect_error=other.zig:1:1: error: file exists in modules 'root' and 'foo' | 63 | #} |
| 47 | #expect_error=other.zig:1:1: note: files must belong to only one module | 64 | #update { |
| 48 | #expect_error=main.zig:3:17: note: file is imported here by the root of module 'root' | 65 | put other.zig in both modules#} |
| 49 | #expect_error=foo.zig:2:17: note: file is imported here by the root of module 'foo' | 66 | #check errors { |
| 67 | other.zig:1:1: error: file exists in modules 'root' and 'foo' | ||
| 68 | other.zig:1:1: note: files must belong to only one module | ||
| 69 | main.zig:3:17: note: file is imported here by the root of module 'root' | ||
| 70 | foo.zig:2:17: note: file is imported here by the root of module 'foo' | ||
| 71 | #} | ||
| 50 | 72 | ||
| 51 | #update=put other.zig in no modules | 73 | #write main.zig { |
| 52 | #file=main.zig | ||
| 53 | pub fn main() void { | 74 | pub fn main() void { |
| 54 | _ = @import("foo"); | 75 | _ = @import("foo"); |
| 55 | //_ = @import("other.zig"); | 76 | //_ = @import("other.zig"); |
| 56 | } | 77 | } |
| 57 | #file=foo.zig | 78 | #} |
| 79 | #write foo.zig { | ||
| 58 | comptime { | 80 | comptime { |
| 59 | //_ = @import("other.zig"); | 81 | //_ = @import("other.zig"); |
| 60 | } | 82 | } |
| 61 | #expect_stdout="" | 83 | #} |
| 84 | #update { | ||
| 85 | put other.zig in no modules#} | ||
| 86 | #check stdout { | ||
| 87 | #} |
test/incremental/change_panic_handler+24-9| ... | @@ -1,5 +1,8 @@ | ... | @@ -1,5 +1,8 @@ |
| 1 | #update=initial version | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | pub fn main() !u8 { | 6 | pub fn main() !u8 { |
| 4 | var a: u8 = undefined; | 7 | var a: u8 = undefined; |
| 5 | a = 255; | 8 | a = 255; |
| ... | @@ -14,10 +17,13 @@ fn myPanic(msg: []const u8, _: ?usize) noreturn { | ... | @@ -14,10 +17,13 @@ fn myPanic(msg: []const u8, _: ?usize) noreturn { |
| 14 | } | 17 | } |
| 15 | const std = @import("std"); | 18 | const std = @import("std"); |
| 16 | const io = std.Io.Threaded.global_single_threaded.io(); | 19 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 17 | #expect_stdout="panic message: integer overflow\n" | 20 | #} |
| 21 | #update | ||
| 22 | #check stdout { | ||
| 23 | panic message: integer overflow | ||
| 24 | #} | ||
| 18 | 25 | ||
| 19 | #update=change the panic handler body | 26 | #write main.zig { |
| 20 | #file=main.zig | ||
| 21 | pub fn main() !u8 { | 27 | pub fn main() !u8 { |
| 22 | var a: u8 = undefined; | 28 | var a: u8 = undefined; |
| 23 | a = 255; | 29 | a = 255; |
| ... | @@ -32,10 +38,14 @@ fn myPanic(msg: []const u8, _: ?usize) noreturn { | ... | @@ -32,10 +38,14 @@ fn myPanic(msg: []const u8, _: ?usize) noreturn { |
| 32 | } | 38 | } |
| 33 | const std = @import("std"); | 39 | const std = @import("std"); |
| 34 | const io = std.Io.Threaded.global_single_threaded.io(); | 40 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 35 | #expect_stdout="new panic message: integer overflow\n" | 41 | #} |
| 42 | #update { | ||
| 43 | change the panic handler body#} | ||
| 44 | #check stdout { | ||
| 45 | new panic message: integer overflow | ||
| 46 | #} | ||
| 36 | 47 | ||
| 37 | #update=change the panic handler function value | 48 | #write main.zig { |
| 38 | #file=main.zig | ||
| 39 | pub fn main() !u8 { | 49 | pub fn main() !u8 { |
| 40 | var a: u8 = undefined; | 50 | var a: u8 = undefined; |
| 41 | a = 255; | 51 | a = 255; |
| ... | @@ -50,4 +60,9 @@ fn myPanicNew(msg: []const u8, _: ?usize) noreturn { | ... | @@ -50,4 +60,9 @@ fn myPanicNew(msg: []const u8, _: ?usize) noreturn { |
| 50 | } | 60 | } |
| 51 | const std = @import("std"); | 61 | const std = @import("std"); |
| 52 | const io = std.Io.Threaded.global_single_threaded.io(); | 62 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 53 | #expect_stdout="third panic message: integer overflow\n" | 63 | #} |
| 64 | #update { | ||
| 65 | change the panic handler function value#} | ||
| 66 | #check stdout { | ||
| 67 | third panic message: integer overflow | ||
| 68 | #} |
test/incremental/change_panic_handler_explicit deleted-149| ... | @@ -1,149 +0,0 @@ | ||
| 1 | #update=initial version | ||
| 2 | #file=main.zig | ||
| 3 | pub fn main() !u8 { | ||
| 4 | var a: u8 = undefined; | ||
| 5 | a = 255; | ||
| 6 | _ = a + 1; | ||
| 7 | return 1; | ||
| 8 | } | ||
| 9 | const no_panic = std.debug.no_panic; | ||
| 10 | pub const panic = struct { | ||
| 11 | pub const call = myPanic; | ||
| 12 | pub fn integerOverflow() noreturn { | ||
| 13 | @panic("integer overflow"); | ||
| 14 | } | ||
| 15 | pub const sentinelMismatch = no_panic.sentinelMismatch; | ||
| 16 | pub const unwrapError = no_panic.unwrapError; | ||
| 17 | pub const outOfBounds = no_panic.outOfBounds; | ||
| 18 | pub const startGreaterThanEnd = no_panic.startGreaterThanEnd; | ||
| 19 | pub const inactiveUnionField = no_panic.inactiveUnionField; | ||
| 20 | pub const sliceCastLenRemainder = no_panic.sliceCastLenRemainder; | ||
| 21 | pub const reachedUnreachable = no_panic.reachedUnreachable; | ||
| 22 | pub const unwrapNull = no_panic.unwrapNull; | ||
| 23 | pub const castToNull = no_panic.castToNull; | ||
| 24 | pub const incorrectAlignment = no_panic.incorrectAlignment; | ||
| 25 | pub const invalidErrorCode = no_panic.invalidErrorCode; | ||
| 26 | pub const unexpectedErrorCode = no_panic.unexpectedErrorCode; | ||
| 27 | pub const integerOutOfBounds = no_panic.integerOutOfBounds; | ||
| 28 | pub const shlOverflow = no_panic.shlOverflow; | ||
| 29 | pub const shrOverflow = no_panic.shrOverflow; | ||
| 30 | pub const divideByZero = no_panic.divideByZero; | ||
| 31 | pub const exactDivisionRemainder = no_panic.exactDivisionRemainder; | ||
| 32 | pub const integerPartOutOfBounds = no_panic.integerPartOutOfBounds; | ||
| 33 | pub const corruptSwitch = no_panic.corruptSwitch; | ||
| 34 | pub const shiftRhsTooBig = no_panic.shiftRhsTooBig; | ||
| 35 | pub const invalidEnumValue = no_panic.invalidEnumValue; | ||
| 36 | pub const forLenMismatch = no_panic.forLenMismatch; | ||
| 37 | pub const copyLenMismatch = no_panic.copyLenMismatch; | ||
| 38 | pub const memcpyAlias = no_panic.memcpyAlias; | ||
| 39 | pub const noreturnReturned = no_panic.noreturnReturned; | ||
| 40 | pub const loadUninstantiableType = no_panic.loadUninstantiableType; | ||
| 41 | }; | ||
| 42 | fn myPanic(msg: []const u8, _: ?usize) noreturn { | ||
| 43 | var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); | ||
| 44 | stdout_writer.interface.print("panic message: {s}\n", .{msg}) catch {}; | ||
| 45 | std.process.exit(0); | ||
| 46 | } | ||
| 47 | const std = @import("std"); | ||
| 48 | const io = std.Io.Threaded.global_single_threaded.io(); | ||
| 49 | #expect_stdout="panic message: integer overflow\n" | ||
| 50 | |||
| 51 | #update=change the panic handler body | ||
| 52 | #file=main.zig | ||
| 53 | pub fn main() !u8 { | ||
| 54 | var a: u8 = undefined; | ||
| 55 | a = 255; | ||
| 56 | _ = a + 1; | ||
| 57 | return 1; | ||
| 58 | } | ||
| 59 | const no_panic = std.debug.no_panic; | ||
| 60 | pub const panic = struct { | ||
| 61 | pub const call = myPanic; | ||
| 62 | pub fn integerOverflow() noreturn { | ||
| 63 | @panic("integer overflow"); | ||
| 64 | } | ||
| 65 | pub const sentinelMismatch = no_panic.sentinelMismatch; | ||
| 66 | pub const unwrapError = no_panic.unwrapError; | ||
| 67 | pub const outOfBounds = no_panic.outOfBounds; | ||
| 68 | pub const startGreaterThanEnd = no_panic.startGreaterThanEnd; | ||
| 69 | pub const inactiveUnionField = no_panic.inactiveUnionField; | ||
| 70 | pub const sliceCastLenRemainder = no_panic.sliceCastLenRemainder; | ||
| 71 | pub const reachedUnreachable = no_panic.reachedUnreachable; | ||
| 72 | pub const unwrapNull = no_panic.unwrapNull; | ||
| 73 | pub const castToNull = no_panic.castToNull; | ||
| 74 | pub const incorrectAlignment = no_panic.incorrectAlignment; | ||
| 75 | pub const invalidErrorCode = no_panic.invalidErrorCode; | ||
| 76 | pub const unexpectedErrorCode = no_panic.unexpectedErrorCode; | ||
| 77 | pub const integerOutOfBounds = no_panic.integerOutOfBounds; | ||
| 78 | pub const shlOverflow = no_panic.shlOverflow; | ||
| 79 | pub const shrOverflow = no_panic.shrOverflow; | ||
| 80 | pub const divideByZero = no_panic.divideByZero; | ||
| 81 | pub const exactDivisionRemainder = no_panic.exactDivisionRemainder; | ||
| 82 | pub const integerPartOutOfBounds = no_panic.integerPartOutOfBounds; | ||
| 83 | pub const corruptSwitch = no_panic.corruptSwitch; | ||
| 84 | pub const shiftRhsTooBig = no_panic.shiftRhsTooBig; | ||
| 85 | pub const invalidEnumValue = no_panic.invalidEnumValue; | ||
| 86 | pub const forLenMismatch = no_panic.forLenMismatch; | ||
| 87 | pub const copyLenMismatch = no_panic.copyLenMismatch; | ||
| 88 | pub const memcpyAlias = no_panic.memcpyAlias; | ||
| 89 | pub const noreturnReturned = no_panic.noreturnReturned; | ||
| 90 | pub const loadUninstantiableType = no_panic.loadUninstantiableType; | ||
| 91 | }; | ||
| 92 | fn myPanic(msg: []const u8, _: ?usize) noreturn { | ||
| 93 | var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); | ||
| 94 | stdout_writer.interface.print("new panic message: {s}\n", .{msg}) catch {}; | ||
| 95 | std.process.exit(0); | ||
| 96 | } | ||
| 97 | const std = @import("std"); | ||
| 98 | const io = std.Io.Threaded.global_single_threaded.io(); | ||
| 99 | #expect_stdout="new panic message: integer overflow\n" | ||
| 100 | |||
| 101 | #update=change the panic handler function value | ||
| 102 | #file=main.zig | ||
| 103 | pub fn main() !u8 { | ||
| 104 | var a: u8 = undefined; | ||
| 105 | a = 255; | ||
| 106 | _ = a + 1; | ||
| 107 | return 1; | ||
| 108 | } | ||
| 109 | const no_panic = std.debug.no_panic; | ||
| 110 | pub const panic = struct { | ||
| 111 | pub const call = myPanicNew; | ||
| 112 | pub fn integerOverflow() noreturn { | ||
| 113 | @panic("integer overflow"); | ||
| 114 | } | ||
| 115 | pub const sentinelMismatch = std.debug.no_panic.sentinelMismatch; | ||
| 116 | pub const unwrapError = std.debug.no_panic.unwrapError; | ||
| 117 | pub const outOfBounds = std.debug.no_panic.outOfBounds; | ||
| 118 | pub const startGreaterThanEnd = std.debug.no_panic.startGreaterThanEnd; | ||
| 119 | pub const inactiveUnionField = std.debug.no_panic.inactiveUnionField; | ||
| 120 | pub const sliceCastLenRemainder = no_panic.sliceCastLenRemainder; | ||
| 121 | pub const reachedUnreachable = no_panic.reachedUnreachable; | ||
| 122 | pub const unwrapNull = no_panic.unwrapNull; | ||
| 123 | pub const castToNull = no_panic.castToNull; | ||
| 124 | pub const incorrectAlignment = no_panic.incorrectAlignment; | ||
| 125 | pub const invalidErrorCode = no_panic.invalidErrorCode; | ||
| 126 | pub const unexpectedErrorCode = no_panic.unexpectedErrorCode; | ||
| 127 | pub const integerOutOfBounds = no_panic.integerOutOfBounds; | ||
| 128 | pub const shlOverflow = no_panic.shlOverflow; | ||
| 129 | pub const shrOverflow = no_panic.shrOverflow; | ||
| 130 | pub const divideByZero = no_panic.divideByZero; | ||
| 131 | pub const exactDivisionRemainder = no_panic.exactDivisionRemainder; | ||
| 132 | pub const integerPartOutOfBounds = no_panic.integerPartOutOfBounds; | ||
| 133 | pub const corruptSwitch = no_panic.corruptSwitch; | ||
| 134 | pub const shiftRhsTooBig = no_panic.shiftRhsTooBig; | ||
| 135 | pub const invalidEnumValue = no_panic.invalidEnumValue; | ||
| 136 | pub const forLenMismatch = no_panic.forLenMismatch; | ||
| 137 | pub const copyLenMismatch = no_panic.copyLenMismatch; | ||
| 138 | pub const memcpyAlias = no_panic.memcpyAlias; | ||
| 139 | pub const noreturnReturned = no_panic.noreturnReturned; | ||
| 140 | pub const loadUninstantiableType = no_panic.loadUninstantiableType; | ||
| 141 | }; | ||
| 142 | fn myPanicNew(msg: []const u8, _: ?usize) noreturn { | ||
| 143 | var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); | ||
| 144 | stdout_writer.interface.print("third panic message: {s}\n", .{msg}) catch {}; | ||
| 145 | std.process.exit(0); | ||
| 146 | } | ||
| 147 | const std = @import("std"); | ||
| 148 | const io = std.Io.Threaded.global_single_threaded.io(); | ||
| 149 | #expect_stdout="third panic message: integer overflow\n" | ||
test/incremental/change_panic_handler_explicit/0/main.zig created+46| ... | @@ -0,0 +1,46 @@ | ||
| 1 | pub fn main() !u8 { | ||
| 2 | var a: u8 = undefined; | ||
| 3 | a = 255; | ||
| 4 | _ = a + 1; | ||
| 5 | return 1; | ||
| 6 | } | ||
| 7 | const no_panic = std.debug.no_panic; | ||
| 8 | pub const panic = struct { | ||
| 9 | pub const call = myPanic; | ||
| 10 | pub fn integerOverflow() noreturn { | ||
| 11 | @panic("integer overflow"); | ||
| 12 | } | ||
| 13 | pub const sentinelMismatch = no_panic.sentinelMismatch; | ||
| 14 | pub const unwrapError = no_panic.unwrapError; | ||
| 15 | pub const outOfBounds = no_panic.outOfBounds; | ||
| 16 | pub const startGreaterThanEnd = no_panic.startGreaterThanEnd; | ||
| 17 | pub const inactiveUnionField = no_panic.inactiveUnionField; | ||
| 18 | pub const sliceCastLenRemainder = no_panic.sliceCastLenRemainder; | ||
| 19 | pub const reachedUnreachable = no_panic.reachedUnreachable; | ||
| 20 | pub const unwrapNull = no_panic.unwrapNull; | ||
| 21 | pub const castToNull = no_panic.castToNull; | ||
| 22 | pub const incorrectAlignment = no_panic.incorrectAlignment; | ||
| 23 | pub const invalidErrorCode = no_panic.invalidErrorCode; | ||
| 24 | pub const unexpectedErrorCode = no_panic.unexpectedErrorCode; | ||
| 25 | pub const integerOutOfBounds = no_panic.integerOutOfBounds; | ||
| 26 | pub const shlOverflow = no_panic.shlOverflow; | ||
| 27 | pub const shrOverflow = no_panic.shrOverflow; | ||
| 28 | pub const divideByZero = no_panic.divideByZero; | ||
| 29 | pub const exactDivisionRemainder = no_panic.exactDivisionRemainder; | ||
| 30 | pub const integerPartOutOfBounds = no_panic.integerPartOutOfBounds; | ||
| 31 | pub const corruptSwitch = no_panic.corruptSwitch; | ||
| 32 | pub const shiftRhsTooBig = no_panic.shiftRhsTooBig; | ||
| 33 | pub const invalidEnumValue = no_panic.invalidEnumValue; | ||
| 34 | pub const forLenMismatch = no_panic.forLenMismatch; | ||
| 35 | pub const copyLenMismatch = no_panic.copyLenMismatch; | ||
| 36 | pub const memcpyAlias = no_panic.memcpyAlias; | ||
| 37 | pub const noreturnReturned = no_panic.noreturnReturned; | ||
| 38 | pub const loadUninstantiableType = no_panic.loadUninstantiableType; | ||
| 39 | }; | ||
| 40 | fn myPanic(msg: []const u8, _: ?usize) noreturn { | ||
| 41 | var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); | ||
| 42 | stdout_writer.interface.print("panic message: {s}\n", .{msg}) catch {}; | ||
| 43 | std.process.exit(0); | ||
| 44 | } | ||
| 45 | const std = @import("std"); | ||
| 46 | const io = std.Io.Threaded.global_single_threaded.io(); | ||
test/incremental/change_panic_handler_explicit/1/main.zig created+46| ... | @@ -0,0 +1,46 @@ | ||
| 1 | pub fn main() !u8 { | ||
| 2 | var a: u8 = undefined; | ||
| 3 | a = 255; | ||
| 4 | _ = a + 1; | ||
| 5 | return 1; | ||
| 6 | } | ||
| 7 | const no_panic = std.debug.no_panic; | ||
| 8 | pub const panic = struct { | ||
| 9 | pub const call = myPanic; | ||
| 10 | pub fn integerOverflow() noreturn { | ||
| 11 | @panic("integer overflow"); | ||
| 12 | } | ||
| 13 | pub const sentinelMismatch = no_panic.sentinelMismatch; | ||
| 14 | pub const unwrapError = no_panic.unwrapError; | ||
| 15 | pub const outOfBounds = no_panic.outOfBounds; | ||
| 16 | pub const startGreaterThanEnd = no_panic.startGreaterThanEnd; | ||
| 17 | pub const inactiveUnionField = no_panic.inactiveUnionField; | ||
| 18 | pub const sliceCastLenRemainder = no_panic.sliceCastLenRemainder; | ||
| 19 | pub const reachedUnreachable = no_panic.reachedUnreachable; | ||
| 20 | pub const unwrapNull = no_panic.unwrapNull; | ||
| 21 | pub const castToNull = no_panic.castToNull; | ||
| 22 | pub const incorrectAlignment = no_panic.incorrectAlignment; | ||
| 23 | pub const invalidErrorCode = no_panic.invalidErrorCode; | ||
| 24 | pub const unexpectedErrorCode = no_panic.unexpectedErrorCode; | ||
| 25 | pub const integerOutOfBounds = no_panic.integerOutOfBounds; | ||
| 26 | pub const shlOverflow = no_panic.shlOverflow; | ||
| 27 | pub const shrOverflow = no_panic.shrOverflow; | ||
| 28 | pub const divideByZero = no_panic.divideByZero; | ||
| 29 | pub const exactDivisionRemainder = no_panic.exactDivisionRemainder; | ||
| 30 | pub const integerPartOutOfBounds = no_panic.integerPartOutOfBounds; | ||
| 31 | pub const corruptSwitch = no_panic.corruptSwitch; | ||
| 32 | pub const shiftRhsTooBig = no_panic.shiftRhsTooBig; | ||
| 33 | pub const invalidEnumValue = no_panic.invalidEnumValue; | ||
| 34 | pub const forLenMismatch = no_panic.forLenMismatch; | ||
| 35 | pub const copyLenMismatch = no_panic.copyLenMismatch; | ||
| 36 | pub const memcpyAlias = no_panic.memcpyAlias; | ||
| 37 | pub const noreturnReturned = no_panic.noreturnReturned; | ||
| 38 | pub const loadUninstantiableType = no_panic.loadUninstantiableType; | ||
| 39 | }; | ||
| 40 | fn myPanic(msg: []const u8, _: ?usize) noreturn { | ||
| 41 | var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); | ||
| 42 | stdout_writer.interface.print("new panic message: {s}\n", .{msg}) catch {}; | ||
| 43 | std.process.exit(0); | ||
| 44 | } | ||
| 45 | const std = @import("std"); | ||
| 46 | const io = std.Io.Threaded.global_single_threaded.io(); | ||
test/incremental/change_panic_handler_explicit/2/main.zig created+46| ... | @@ -0,0 +1,46 @@ | ||
| 1 | pub fn main() !u8 { | ||
| 2 | var a: u8 = undefined; | ||
| 3 | a = 255; | ||
| 4 | _ = a + 1; | ||
| 5 | return 1; | ||
| 6 | } | ||
| 7 | const no_panic = std.debug.no_panic; | ||
| 8 | pub const panic = struct { | ||
| 9 | pub const call = myPanicNew; | ||
| 10 | pub fn integerOverflow() noreturn { | ||
| 11 | @panic("integer overflow"); | ||
| 12 | } | ||
| 13 | pub const sentinelMismatch = no_panic.sentinelMismatch; | ||
| 14 | pub const unwrapError = no_panic.unwrapError; | ||
| 15 | pub const outOfBounds = no_panic.outOfBounds; | ||
| 16 | pub const startGreaterThanEnd = no_panic.startGreaterThanEnd; | ||
| 17 | pub const inactiveUnionField = no_panic.inactiveUnionField; | ||
| 18 | pub const sliceCastLenRemainder = no_panic.sliceCastLenRemainder; | ||
| 19 | pub const reachedUnreachable = no_panic.reachedUnreachable; | ||
| 20 | pub const unwrapNull = no_panic.unwrapNull; | ||
| 21 | pub const castToNull = no_panic.castToNull; | ||
| 22 | pub const incorrectAlignment = no_panic.incorrectAlignment; | ||
| 23 | pub const invalidErrorCode = no_panic.invalidErrorCode; | ||
| 24 | pub const unexpectedErrorCode = no_panic.unexpectedErrorCode; | ||
| 25 | pub const integerOutOfBounds = no_panic.integerOutOfBounds; | ||
| 26 | pub const shlOverflow = no_panic.shlOverflow; | ||
| 27 | pub const shrOverflow = no_panic.shrOverflow; | ||
| 28 | pub const divideByZero = no_panic.divideByZero; | ||
| 29 | pub const exactDivisionRemainder = no_panic.exactDivisionRemainder; | ||
| 30 | pub const integerPartOutOfBounds = no_panic.integerPartOutOfBounds; | ||
| 31 | pub const corruptSwitch = no_panic.corruptSwitch; | ||
| 32 | pub const shiftRhsTooBig = no_panic.shiftRhsTooBig; | ||
| 33 | pub const invalidEnumValue = no_panic.invalidEnumValue; | ||
| 34 | pub const forLenMismatch = no_panic.forLenMismatch; | ||
| 35 | pub const copyLenMismatch = no_panic.copyLenMismatch; | ||
| 36 | pub const memcpyAlias = no_panic.memcpyAlias; | ||
| 37 | pub const noreturnReturned = no_panic.noreturnReturned; | ||
| 38 | pub const loadUninstantiableType = no_panic.loadUninstantiableType; | ||
| 39 | }; | ||
| 40 | fn myPanicNew(msg: []const u8, _: ?usize) noreturn { | ||
| 41 | var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); | ||
| 42 | stdout_writer.interface.print("third panic message: {s}\n", .{msg}) catch {}; | ||
| 43 | std.process.exit(0); | ||
| 44 | } | ||
| 45 | const std = @import("std"); | ||
| 46 | const io = std.Io.Threaded.global_single_threaded.io(); | ||
test/incremental/change_panic_handler_explicit/manifest created+23| ... | @@ -0,0 +1,23 @@ | ||
| 1 | #exe { | ||
| 2 | -Mroot=main.zig | ||
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig 0/main.zig | ||
| 6 | #update | ||
| 7 | #check stdout { | ||
| 8 | panic message: integer overflow | ||
| 9 | #} | ||
| 10 | |||
| 11 | #write main.zig 1/main.zig | ||
| 12 | #update { | ||
| 13 | change the panic handler body#} | ||
| 14 | #check stdout { | ||
| 15 | new panic message: integer overflow | ||
| 16 | #} | ||
| 17 | |||
| 18 | #write main.zig 2/main.zig | ||
| 19 | #update { | ||
| 20 | change the panic handler function value#} | ||
| 21 | #check stdout { | ||
| 22 | third panic message: integer overflow | ||
| 23 | #} | ||
test/incremental/change_reify_struct_field_type+16-6| ... | @@ -1,5 +1,8 @@ | ... | @@ -1,5 +1,8 @@ |
| 1 | #update=initial version | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | fn getEnum(s: @Struct(.auto, null, &.{"field"}, &.{struct { tag: Enum }}, &.{.{}})) Enum { | 6 | fn getEnum(s: @Struct(.auto, null, &.{"field"}, &.{struct { tag: Enum }}, &.{.{}})) Enum { |
| 4 | return s.field.tag; | 7 | return s.field.tag; |
| 5 | } | 8 | } |
| ... | @@ -8,9 +11,12 @@ pub fn main(init: std.process.Init) !void { | ... | @@ -8,9 +11,12 @@ pub fn main(init: std.process.Init) !void { |
| 8 | } | 11 | } |
| 9 | const Enum = enum { foo, bar }; | 12 | const Enum = enum { foo, bar }; |
| 10 | const std = @import("std"); | 13 | const std = @import("std"); |
| 11 | #expect_stdout="foo" | 14 | #} |
| 12 | #update=change field type | 15 | #update |
| 13 | #file=main.zig | 16 | #check stdout { |
| 17 | foo#} | ||
| 18 | |||
| 19 | #write main.zig { | ||
| 14 | fn getEnum(s: @Struct(.auto, null, &.{"field"}, &.{Enum}, &.{.{}})) Enum { | 20 | fn getEnum(s: @Struct(.auto, null, &.{"field"}, &.{Enum}, &.{.{}})) Enum { |
| 15 | return s.field; | 21 | return s.field; |
| 16 | } | 22 | } |
| ... | @@ -19,4 +25,8 @@ pub fn main(init: std.process.Init) !void { | ... | @@ -19,4 +25,8 @@ pub fn main(init: std.process.Init) !void { |
| 19 | } | 25 | } |
| 20 | const Enum = enum { foo, bar }; | 26 | const Enum = enum { foo, bar }; |
| 21 | const std = @import("std"); | 27 | const std = @import("std"); |
| 22 | #expect_stdout="bar" | 28 | #} |
| 29 | #update { | ||
| 30 | change field type#} | ||
| 31 | #check stdout { | ||
| 32 | bar#} |
test/incremental/change_shift_op+18-6| ... | @@ -1,5 +1,8 @@ | ... | @@ -1,5 +1,8 @@ |
| 1 | #update=initial version | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | pub fn main() !void { | 6 | pub fn main() !void { |
| 4 | try foo(0x1300); | 7 | try foo(0x1300); |
| 5 | } | 8 | } |
| ... | @@ -9,9 +12,13 @@ fn foo(x: u16) !void { | ... | @@ -9,9 +12,13 @@ fn foo(x: u16) !void { |
| 9 | } | 12 | } |
| 10 | const std = @import("std"); | 13 | const std = @import("std"); |
| 11 | const io = std.Io.Threaded.global_single_threaded.io(); | 14 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 12 | #expect_stdout="0x3000\n" | 15 | #} |
| 13 | #update=change to right shift | 16 | #update |
| 14 | #file=main.zig | 17 | #check stdout { |
| 18 | 0x3000 | ||
| 19 | #} | ||
| 20 | |||
| 21 | #write main.zig { | ||
| 15 | pub fn main() !void { | 22 | pub fn main() !void { |
| 16 | try foo(0x1300); | 23 | try foo(0x1300); |
| 17 | } | 24 | } |
| ... | @@ -21,4 +28,9 @@ fn foo(x: u16) !void { | ... | @@ -21,4 +28,9 @@ fn foo(x: u16) !void { |
| 21 | } | 28 | } |
| 22 | const std = @import("std"); | 29 | const std = @import("std"); |
| 23 | const io = std.Io.Threaded.global_single_threaded.io(); | 30 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 24 | #expect_stdout="0x130\n" | 31 | #} |
| 32 | #update { | ||
| 33 | change to right shift#} | ||
| 34 | #check stdout { | ||
| 35 | 0x130 | ||
| 36 | #} |
test/incremental/change_struct_same_fields+24-9| ... | @@ -1,5 +1,8 @@ | ... | @@ -1,5 +1,8 @@ |
| 1 | #update=initial version | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | const S = extern struct { x: u8, y: u8 }; | 6 | const S = extern struct { x: u8, y: u8 }; |
| 4 | pub fn main() !void { | 7 | pub fn main() !void { |
| 5 | const val: S = .{ .x = 100, .y = 200 }; | 8 | const val: S = .{ .x = 100, .y = 200 }; |
| ... | @@ -14,10 +17,13 @@ fn foo(val: *const S) !void { | ... | @@ -14,10 +17,13 @@ fn foo(val: *const S) !void { |
| 14 | } | 17 | } |
| 15 | const std = @import("std"); | 18 | const std = @import("std"); |
| 16 | const io = std.Io.Threaded.global_single_threaded.io(); | 19 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 17 | #expect_stdout="100 200\n" | 20 | #} |
| 21 | #update | ||
| 22 | #check stdout { | ||
| 23 | 100 200 | ||
| 24 | #} | ||
| 18 | 25 | ||
| 19 | #update=change struct layout | 26 | #write main.zig { |
| 20 | #file=main.zig | ||
| 21 | const S = extern struct { x: u32, y: u32 }; | 27 | const S = extern struct { x: u32, y: u32 }; |
| 22 | pub fn main() !void { | 28 | pub fn main() !void { |
| 23 | const val: S = .{ .x = 100, .y = 200 }; | 29 | const val: S = .{ .x = 100, .y = 200 }; |
| ... | @@ -32,10 +38,14 @@ fn foo(val: *const S) !void { | ... | @@ -32,10 +38,14 @@ fn foo(val: *const S) !void { |
| 32 | } | 38 | } |
| 33 | const std = @import("std"); | 39 | const std = @import("std"); |
| 34 | const io = std.Io.Threaded.global_single_threaded.io(); | 40 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 35 | #expect_stdout="100 200\n" | 41 | #} |
| 42 | #update { | ||
| 43 | change struct layout#} | ||
| 44 | #check stdout { | ||
| 45 | 100 200 | ||
| 46 | #} | ||
| 36 | 47 | ||
| 37 | #update=change values | 48 | #write main.zig { |
| 38 | #file=main.zig | ||
| 39 | const S = extern struct { x: u32, y: u32 }; | 49 | const S = extern struct { x: u32, y: u32 }; |
| 40 | pub fn main() !void { | 50 | pub fn main() !void { |
| 41 | const val: S = .{ .x = 1234, .y = 5678 }; | 51 | const val: S = .{ .x = 1234, .y = 5678 }; |
| ... | @@ -50,4 +60,9 @@ fn foo(val: *const S) !void { | ... | @@ -50,4 +60,9 @@ fn foo(val: *const S) !void { |
| 50 | } | 60 | } |
| 51 | const std = @import("std"); | 61 | const std = @import("std"); |
| 52 | const io = std.Io.Threaded.global_single_threaded.io(); | 62 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 53 | #expect_stdout="1234 5678\n" | 63 | #} |
| 64 | #update { | ||
| 65 | change values#} | ||
| 66 | #check stdout { | ||
| 67 | 1234 5678 | ||
| 68 | #} |
test/incremental/change_union_tag_type+25-10| ... | @@ -1,5 +1,8 @@ | ... | @@ -1,5 +1,8 @@ |
| 1 | #update=initial version | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | const A = enum(u8) { a }; | 6 | const A = enum(u8) { a }; |
| 4 | const B = enum(u8) { b }; | 7 | const B = enum(u8) { b }; |
| 5 | const Foo = union(A) { a: u8 }; | 8 | const Foo = union(A) { a: u8 }; |
| ... | @@ -9,10 +12,13 @@ pub fn main(init: std.process.Init) !void { | ... | @@ -9,10 +12,13 @@ pub fn main(init: std.process.Init) !void { |
| 9 | try stdout_writer.interface.print("{s}\n", .{field_name}); | 12 | try stdout_writer.interface.print("{s}\n", .{field_name}); |
| 10 | } | 13 | } |
| 11 | const std = @import("std"); | 14 | const std = @import("std"); |
| 12 | #expect_stdout="a\n" | 15 | #} |
| 16 | #update | ||
| 17 | #check stdout { | ||
| 18 | a | ||
| 19 | #} | ||
| 13 | 20 | ||
| 14 | #update=change tag type | 21 | #write main.zig { |
| 15 | #file=main.zig | ||
| 16 | const A = enum(u8) { a }; | 22 | const A = enum(u8) { a }; |
| 17 | const B = enum(u8) { b }; | 23 | const B = enum(u8) { b }; |
| 18 | const Foo = union(B) { a: u8 }; | 24 | const Foo = union(B) { a: u8 }; |
| ... | @@ -22,11 +28,15 @@ pub fn main(init: std.process.Init) !void { | ... | @@ -22,11 +28,15 @@ pub fn main(init: std.process.Init) !void { |
| 22 | try stdout_writer.interface.print("{s}\n", .{field_name}); | 28 | try stdout_writer.interface.print("{s}\n", .{field_name}); |
| 23 | } | 29 | } |
| 24 | const std = @import("std"); | 30 | const std = @import("std"); |
| 25 | #expect_error=main.zig:3:24: error: no field named 'a' in enum 'main.B' | 31 | #} |
| 26 | #expect_error=main.zig:2:11: note: enum declared here | 32 | #update { |
| 33 | change tag type#} | ||
| 34 | #check errors { | ||
| 35 | main.zig:3:24: error: no field named 'a' in enum 'main.B' | ||
| 36 | main.zig:2:11: note: enum declared here | ||
| 37 | #} | ||
| 27 | 38 | ||
| 28 | #update=change field name to match new tag type | 39 | #write main.zig { |
| 29 | #file=main.zig | ||
| 30 | const A = enum(u8) { a }; | 40 | const A = enum(u8) { a }; |
| 31 | const B = enum(u8) { b }; | 41 | const B = enum(u8) { b }; |
| 32 | const Foo = union(B) { b: u8 }; | 42 | const Foo = union(B) { b: u8 }; |
| ... | @@ -36,4 +46,9 @@ pub fn main(init: std.process.Init) !void { | ... | @@ -36,4 +46,9 @@ pub fn main(init: std.process.Init) !void { |
| 36 | try stdout_writer.interface.print("{s}\n", .{field_name}); | 46 | try stdout_writer.interface.print("{s}\n", .{field_name}); |
| 37 | } | 47 | } |
| 38 | const std = @import("std"); | 48 | const std = @import("std"); |
| 39 | #expect_stdout="b\n" | 49 | #} |
| 50 | #update { | ||
| 51 | change field name to match new tag type#} | ||
| 52 | #check stdout { | ||
| 53 | b | ||
| 54 | #} |
test/incremental/change_zon_file+48-21| ... | @@ -1,47 +1,74 @@ | ... | @@ -1,47 +1,74 @@ |
| 1 | #update=initial version | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | const std = @import("std"); | 6 | const std = @import("std"); |
| 4 | const message: []const u8 = @import("message.zon"); | 7 | const message: []const u8 = @import("message.zon"); |
| 5 | pub fn main() !void { | 8 | pub fn main() !void { |
| 6 | try std.Io.File.stdout().writeStreamingAll(io, message); | 9 | try std.Io.File.stdout().writeStreamingAll(io, message); |
| 7 | } | 10 | } |
| 8 | const io = std.Io.Threaded.global_single_threaded.io(); | 11 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 9 | #file=message.zon | 12 | #} |
| 13 | #write message.zon { | ||
| 10 | "Hello, World!\n" | 14 | "Hello, World!\n" |
| 11 | #expect_stdout="Hello, World!\n" | 15 | #} |
| 16 | #update | ||
| 17 | #check stdout { | ||
| 18 | Hello, World! | ||
| 19 | #} | ||
| 12 | 20 | ||
| 13 | #update=change ZON file contents | 21 | #write message.zon { |
| 14 | #file=message.zon | ||
| 15 | "Hello again, World!\n" | 22 | "Hello again, World!\n" |
| 16 | #expect_stdout="Hello again, World!\n" | 23 | #} |
| 24 | #update { | ||
| 25 | change ZON file contents#} | ||
| 26 | #check stdout { | ||
| 27 | Hello again, World! | ||
| 28 | #} | ||
| 17 | 29 | ||
| 18 | #update=delete file | 30 | #delete message.zon |
| 19 | #rm_file=message.zon | 31 | #update { |
| 20 | #expect_error=message.zon:1:1: error: unable to load "message.zon": FileNotFound | 32 | delete file#} |
| 21 | #expect_error=main.zig:2:37: note: file imported here | 33 | #check errors { |
| 34 | message.zon:1:1: error: unable to load "message.zon": FileNotFound | ||
| 35 | main.zig:2:37: note: file imported here | ||
| 36 | #} | ||
| 22 | 37 | ||
| 23 | #update=remove reference to ZON file | 38 | #write main.zig { |
| 24 | #file=main.zig | ||
| 25 | const std = @import("std"); | 39 | const std = @import("std"); |
| 26 | const message: []const u8 = @import("message.zon"); | 40 | const message: []const u8 = @import("message.zon"); |
| 27 | pub fn main() !void { | 41 | pub fn main() !void { |
| 28 | try std.Io.File.stdout().writeStreamingAll(io, "a hardcoded string\n"); | 42 | try std.Io.File.stdout().writeStreamingAll(io, "a hardcoded string\n"); |
| 29 | } | 43 | } |
| 30 | const io = std.Io.Threaded.global_single_threaded.io(); | 44 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 31 | #expect_error=message.zon:1:1: error: unable to load "message.zon": FileNotFound | 45 | #} |
| 32 | #expect_error=main.zig:2:37: note: file imported here | 46 | #update { |
| 47 | remove reference to ZON file#} | ||
| 48 | #check errors { | ||
| 49 | message.zon:1:1: error: unable to load "message.zon": FileNotFound | ||
| 50 | main.zig:2:37: note: file imported here | ||
| 51 | #} | ||
| 33 | 52 | ||
| 34 | #update=recreate ZON file | 53 | #write message.zon { |
| 35 | #file=message.zon | ||
| 36 | "We're back, World!\n" | 54 | "We're back, World!\n" |
| 37 | #expect_stdout="a hardcoded string\n" | 55 | #} |
| 56 | #update { | ||
| 57 | recreate ZON file#} | ||
| 58 | #check stdout { | ||
| 59 | a hardcoded string | ||
| 60 | #} | ||
| 38 | 61 | ||
| 39 | #update=re-introduce reference to ZON file | 62 | #write main.zig { |
| 40 | #file=main.zig | ||
| 41 | const std = @import("std"); | 63 | const std = @import("std"); |
| 42 | const message: []const u8 = @import("message.zon"); | 64 | const message: []const u8 = @import("message.zon"); |
| 43 | pub fn main() !void { | 65 | pub fn main() !void { |
| 44 | try std.Io.File.stdout().writeStreamingAll(io, message); | 66 | try std.Io.File.stdout().writeStreamingAll(io, message); |
| 45 | } | 67 | } |
| 46 | const io = std.Io.Threaded.global_single_threaded.io(); | 68 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 47 | #expect_stdout="We're back, World!\n" | 69 | #} |
| 70 | #update { | ||
| 71 | re-introduce reference to ZON file#} | ||
| 72 | #check stdout { | ||
| 73 | We're back, World! | ||
| 74 | #} |
test/incremental/change_zon_file_no_result_type+19-7| ... | @@ -1,21 +1,33 @@ | ... | @@ -1,21 +1,33 @@ |
| 1 | #update=initial version | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | const std = @import("std"); | 6 | const std = @import("std"); |
| 4 | const io = std.Io.Threaded.global_single_threaded.io(); | 7 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 5 | pub fn main() !void { | 8 | pub fn main() !void { |
| 6 | try std.Io.File.stdout().writeStreamingAll(io, @import("foo.zon").message); | 9 | try std.Io.File.stdout().writeStreamingAll(io, @import("foo.zon").message); |
| 7 | } | 10 | } |
| 8 | #file=foo.zon | 11 | #} |
| 12 | #write foo.zon { | ||
| 9 | .{ | 13 | .{ |
| 10 | .message = "Hello, World!\n", | 14 | .message = "Hello, World!\n", |
| 11 | .a_number = 0, | 15 | .a_number = 0, |
| 12 | } | 16 | } |
| 13 | #expect_stdout="Hello, World!\n" | 17 | #} |
| 18 | #update | ||
| 19 | #check stdout { | ||
| 20 | Hello, World! | ||
| 21 | #} | ||
| 14 | 22 | ||
| 15 | #update=change ZON file | 23 | #write foo.zon { |
| 16 | #file=foo.zon | ||
| 17 | .{ | 24 | .{ |
| 18 | .message = "Hello again, World!\n", | 25 | .message = "Hello again, World!\n", |
| 19 | .b_number = 0, | 26 | .b_number = 0, |
| 20 | } | 27 | } |
| 21 | #expect_stdout="Hello again, World!\n" | 28 | #} |
| 29 | #update { | ||
| 30 | change ZON file#} | ||
| 31 | #check stdout { | ||
| 32 | Hello again, World! | ||
| 33 | #} |
test/incremental/compile_error_then_log+24-8| ... | @@ -1,5 +1,8 @@ | ... | @@ -1,5 +1,8 @@ |
| 1 | #update=initial version with compile error | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | pub fn main() void {} | 6 | pub fn main() void {} |
| 4 | comptime { | 7 | comptime { |
| 5 | @compileError("this is an error"); | 8 | @compileError("this is an error"); |
| ... | @@ -7,11 +10,17 @@ comptime { | ... | @@ -7,11 +10,17 @@ comptime { |
| 7 | comptime { | 10 | comptime { |
| 8 | @compileLog("this is a log"); | 11 | @compileLog("this is a log"); |
| 9 | } | 12 | } |
| 10 | #expect_error=main.zig:3:5: error: this is an error | 13 | #} |
| 11 | #expect_compile_log=@as(*const [13:0]u8, "this is a log") | 14 | #update { |
| 15 | compile error#} | ||
| 16 | #check errors { | ||
| 17 | main.zig:3:5: error: this is an error | ||
| 18 | |||
| 19 | Compile Log Output: | ||
| 20 | @as(*const [13:0]u8, "this is a log") | ||
| 21 | #} | ||
| 12 | 22 | ||
| 13 | #update=remove the compile error | 23 | #write main.zig { |
| 14 | #file=main.zig | ||
| 15 | pub fn main() void {} | 24 | pub fn main() void {} |
| 16 | comptime { | 25 | comptime { |
| 17 | //@compileError("this is an error"); | 26 | //@compileError("this is an error"); |
| ... | @@ -19,5 +28,12 @@ comptime { | ... | @@ -19,5 +28,12 @@ comptime { |
| 19 | comptime { | 28 | comptime { |
| 20 | @compileLog("this is a log"); | 29 | @compileLog("this is a log"); |
| 21 | } | 30 | } |
| 22 | #expect_error=main.zig:6:5: error: found compile log statement | 31 | #} |
| 23 | #expect_compile_log=@as(*const [13:0]u8, "this is a log") | 32 | #update { |
| 33 | remove the compile error#} | ||
| 34 | #check errors { | ||
| 35 | main.zig:6:5: error: found compile log statement | ||
| 36 | |||
| 37 | Compile Log Output: | ||
| 38 | @as(*const [13:0]u8, "this is a log") | ||
| 39 | #} |
test/incremental/compile_log+28-10| ... | @@ -1,28 +1,46 @@ | ... | @@ -1,28 +1,46 @@ |
| 1 | #update=initial version with no compile log | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | const std = @import("std"); | 6 | const std = @import("std"); |
| 4 | pub fn main() !void { | 7 | pub fn main() !void { |
| 5 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); | 8 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); |
| 6 | } | 9 | } |
| 7 | const io = std.Io.Threaded.global_single_threaded.io(); | 10 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 8 | #expect_stdout="Hello, World!\n" | 11 | #} |
| 12 | #update { | ||
| 13 | no compile log#} | ||
| 14 | #check stdout { | ||
| 15 | Hello, World! | ||
| 16 | #} | ||
| 9 | 17 | ||
| 10 | #update=add compile log | 18 | #write main.zig { |
| 11 | #file=main.zig | ||
| 12 | const std = @import("std"); | 19 | const std = @import("std"); |
| 13 | pub fn main() !void { | 20 | pub fn main() !void { |
| 14 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); | 21 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); |
| 15 | @compileLog("this is a log"); | 22 | @compileLog("this is a log"); |
| 16 | } | 23 | } |
| 17 | const io = std.Io.Threaded.global_single_threaded.io(); | 24 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 18 | #expect_error=main.zig:4:5: error: found compile log statement | 25 | #} |
| 19 | #expect_compile_log=@as(*const [13:0]u8, "this is a log") | 26 | #update { |
| 27 | add compile log#} | ||
| 28 | #check errors { | ||
| 29 | main.zig:4:5: error: found compile log statement | ||
| 30 | |||
| 31 | Compile Log Output: | ||
| 32 | @as(*const [13:0]u8, "this is a log") | ||
| 33 | #} | ||
| 20 | 34 | ||
| 21 | #update=remove compile log | 35 | #write main.zig { |
| 22 | #file=main.zig | ||
| 23 | const std = @import("std"); | 36 | const std = @import("std"); |
| 24 | pub fn main() !void { | 37 | pub fn main() !void { |
| 25 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); | 38 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); |
| 26 | } | 39 | } |
| 27 | const io = std.Io.Threaded.global_single_threaded.io(); | 40 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 28 | #expect_stdout="Hello, World!\n" | 41 | #} |
| 42 | #update { | ||
| 43 | remove compile log#} | ||
| 44 | #check stdout { | ||
| 45 | Hello, World! | ||
| 46 | #} |
test/incremental/delete_comptime_decls+20-9| ... | @@ -1,5 +1,8 @@ | ... | @@ -1,5 +1,8 @@ |
| 1 | #update=initial version | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | pub fn main() void {} | 6 | pub fn main() void {} |
| 4 | comptime { | 7 | comptime { |
| 5 | var array = [_:0]u8{ 1, 2, 3, 4 }; | 8 | var array = [_:0]u8{ 1, 2, 3, 4 }; |
| ... | @@ -22,13 +25,16 @@ comptime { | ... | @@ -22,13 +25,16 @@ comptime { |
| 22 | const slice = array[3..2]; | 25 | const slice = array[3..2]; |
| 23 | _ = slice; | 26 | _ = slice; |
| 24 | } | 27 | } |
| 25 | #expect_error=main.zig:5:32: error: end index 6 out of bounds for slice of length 4 +1 (sentinel) | 28 | #} |
| 26 | #expect_error=main.zig:10:28: error: end index 6 out of bounds for array of length 4 +1 (sentinel) | 29 | #update |
| 27 | #expect_error=main.zig:15:28: error: end index 5 out of bounds for array of length 4 | 30 | #check errors { |
| 28 | #expect_error=main.zig:20:25: error: start index 3 is larger than end index 2 | 31 | main.zig:5:32: error: end index 6 out of bounds for slice of length 4 +1 (sentinel) |
| 32 | main.zig:10:28: error: end index 6 out of bounds for array of length 4 +1 (sentinel) | ||
| 33 | main.zig:15:28: error: end index 5 out of bounds for array of length 4 | ||
| 34 | main.zig:20:25: error: start index 3 is larger than end index 2 | ||
| 35 | #} | ||
| 29 | 36 | ||
| 30 | #update=delete and modify comptime decls | 37 | #write main.zig { |
| 31 | #file=main.zig | ||
| 32 | pub fn main() void {} | 38 | pub fn main() void {} |
| 33 | comptime { | 39 | comptime { |
| 34 | const x: [*c]u8 = null; | 40 | const x: [*c]u8 = null; |
| ... | @@ -37,4 +43,9 @@ comptime { | ... | @@ -37,4 +43,9 @@ comptime { |
| 37 | const y = x[0..runtime_len]; | 43 | const y = x[0..runtime_len]; |
| 38 | _ = y; | 44 | _ = y; |
| 39 | } | 45 | } |
| 40 | #expect_error=main.zig:6:16: error: slice of null pointer | 46 | #} |
| 47 | #update { | ||
| 48 | delete and modify comptime decls#} | ||
| 49 | #check errors { | ||
| 50 | main.zig:6:16: error: slice of null pointer | ||
| 51 | #} |
test/incremental/dependency_on_type_of_inferred_global+17-6| ... | @@ -1,5 +1,8 @@ | ... | @@ -1,5 +1,8 @@ |
| 1 | #update=initial version | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | const foo = @as(u8, 123); | 6 | const foo = @as(u8, 123); |
| 4 | comptime { | 7 | comptime { |
| 5 | // depends on value of `foo` | 8 | // depends on value of `foo` |
| ... | @@ -10,9 +13,12 @@ comptime { | ... | @@ -10,9 +13,12 @@ comptime { |
| 10 | if (@TypeOf(&foo) != *const u8) unreachable; | 13 | if (@TypeOf(&foo) != *const u8) unreachable; |
| 11 | } | 14 | } |
| 12 | pub fn main() void {} | 15 | pub fn main() void {} |
| 13 | #expect_stdout="" | 16 | #} |
| 14 | #update=change the type | 17 | #update |
| 15 | #file=main.zig | 18 | #check stdout { |
| 19 | #} | ||
| 20 | |||
| 21 | #write main.zig { | ||
| 16 | const foo = @as(u16, 123); | 22 | const foo = @as(u16, 123); |
| 17 | comptime { | 23 | comptime { |
| 18 | // depends on value of `foo` | 24 | // depends on value of `foo` |
| ... | @@ -23,4 +29,9 @@ comptime { | ... | @@ -23,4 +29,9 @@ comptime { |
| 23 | if (@TypeOf(&foo) != *const u8) unreachable; | 29 | if (@TypeOf(&foo) != *const u8) unreachable; |
| 24 | } | 30 | } |
| 25 | pub fn main() void {} | 31 | pub fn main() void {} |
| 26 | #expect_error=main.zig:8:37: error: reached unreachable code | 32 | #} |
| 33 | #update { | ||
| 34 | change the type#} | ||
| 35 | #check errors { | ||
| 36 | main.zig:8:37: error: reached unreachable code | ||
| 37 | #} |
test/incremental/do_nothing+19-7| ... | @@ -1,6 +1,11 @@ | ... | @@ -1,6 +1,11 @@ |
| 1 | // TODO: it'd be great if we could actually check that no analysis happened! | 1 | #todo { |
| 2 | #update=initial version | 2 | it'd be great if we could actually check that no analysis happened! |
| 3 | #file=main.zig | 3 | #} |
| 4 | #exe { | ||
| 5 | -Mroot=main.zig | ||
| 6 | #} | ||
| 7 | |||
| 8 | #write main.zig { | ||
| 4 | pub fn main() void { | 9 | pub fn main() void { |
| 5 | const ptr: *const O = @ptrFromInt(0x1000); | 10 | const ptr: *const O = @ptrFromInt(0x1000); |
| 6 | _ = ptr; | 11 | _ = ptr; |
| ... | @@ -18,9 +23,12 @@ const O = opaque { | ... | @@ -18,9 +23,12 @@ const O = opaque { |
| 18 | _ = wrapper; | 23 | _ = wrapper; |
| 19 | } | 24 | } |
| 20 | }; | 25 | }; |
| 21 | #expect_stdout="" | 26 | #} |
| 22 | #update=do literally nothing | 27 | #update |
| 23 | #file=main.zig | 28 | #check stdout { |
| 29 | #} | ||
| 30 | |||
| 31 | #write main.zig { | ||
| 24 | pub fn main() void { | 32 | pub fn main() void { |
| 25 | const ptr: *const O = @ptrFromInt(0x1000); | 33 | const ptr: *const O = @ptrFromInt(0x1000); |
| 26 | _ = ptr; | 34 | _ = ptr; |
| ... | @@ -38,4 +46,8 @@ const O = opaque { | ... | @@ -38,4 +46,8 @@ const O = opaque { |
| 38 | _ = wrapper; | 46 | _ = wrapper; |
| 39 | } | 47 | } |
| 40 | }; | 48 | }; |
| 41 | #expect_stdout="" | 49 | #} |
| 50 | #update { | ||
| 51 | do literally nothing#} | ||
| 52 | #check stdout { | ||
| 53 | #} |
test/incremental/fix_astgen_failure+37-13| ... | @@ -1,35 +1,59 @@ | ... | @@ -1,35 +1,59 @@ |
| 1 | #update=initial version with error | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | pub fn main() !void { | 6 | pub fn main() !void { |
| 4 | try @import("foo.zig").hello(); | 7 | try @import("foo.zig").hello(); |
| 5 | } | 8 | } |
| 6 | #file=foo.zig | 9 | #} |
| 10 | #write foo.zig { | ||
| 7 | pub fn hello() !void { | 11 | pub fn hello() !void { |
| 8 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); | 12 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); |
| 9 | } | 13 | } |
| 10 | #expect_error=foo.zig:2:9: error: use of undeclared identifier 'std' | 14 | #} |
| 11 | #update=fix the error | 15 | #update { |
| 12 | #file=foo.zig | 16 | error#} |
| 17 | #check errors { | ||
| 18 | foo.zig:2:9: error: use of undeclared identifier 'std' | ||
| 19 | #} | ||
| 20 | |||
| 21 | #write foo.zig { | ||
| 13 | const std = @import("std"); | 22 | const std = @import("std"); |
| 14 | pub fn hello() !void { | 23 | pub fn hello() !void { |
| 15 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); | 24 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); |
| 16 | } | 25 | } |
| 17 | const io = std.Io.Threaded.global_single_threaded.io(); | 26 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 18 | #expect_stdout="Hello, World!\n" | 27 | #} |
| 19 | #update=add new error | 28 | #update { |
| 20 | #file=foo.zig | 29 | fix the error#} |
| 30 | #check stdout { | ||
| 31 | Hello, World! | ||
| 32 | #} | ||
| 33 | |||
| 34 | #write foo.zig { | ||
| 21 | const std = @import("std"); | 35 | const std = @import("std"); |
| 22 | pub fn hello() !void { | 36 | pub fn hello() !void { |
| 23 | try std.Io.File.stdout().writeStreamingAll(io, hello_str); | 37 | try std.Io.File.stdout().writeStreamingAll(io, hello_str); |
| 24 | } | 38 | } |
| 25 | const io = std.Io.Threaded.global_single_threaded.io(); | 39 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 26 | #expect_error=foo.zig:3:52: error: use of undeclared identifier 'hello_str' | 40 | #} |
| 27 | #update=fix the new error | 41 | #update { |
| 28 | #file=foo.zig | 42 | add new error#} |
| 43 | #check errors { | ||
| 44 | foo.zig:3:52: error: use of undeclared identifier 'hello_str' | ||
| 45 | #} | ||
| 46 | |||
| 47 | #write foo.zig { | ||
| 29 | const std = @import("std"); | 48 | const std = @import("std"); |
| 30 | const hello_str = "Hello, World! Again!\n"; | 49 | const hello_str = "Hello, World! Again!\n"; |
| 31 | pub fn hello() !void { | 50 | pub fn hello() !void { |
| 32 | try std.Io.File.stdout().writeStreamingAll(io, hello_str); | 51 | try std.Io.File.stdout().writeStreamingAll(io, hello_str); |
| 33 | } | 52 | } |
| 34 | const io = std.Io.Threaded.global_single_threaded.io(); | 53 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 35 | #expect_stdout="Hello, World! Again!\n" | 54 | #} |
| 55 | #update { | ||
| 56 | fix the new error#} | ||
| 57 | #check stdout { | ||
| 58 | Hello, World! Again! | ||
| 59 | #} |
test/incremental/function_becomes_inline+25-9| ... | @@ -1,5 +1,8 @@ | ... | @@ -1,5 +1,8 @@ |
| 1 | #update=non-inline version | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | pub fn main() !void { | 6 | pub fn main() !void { |
| 4 | try foo(); | 7 | try foo(); |
| 5 | } | 8 | } |
| ... | @@ -8,10 +11,14 @@ fn foo() !void { | ... | @@ -8,10 +11,14 @@ fn foo() !void { |
| 8 | } | 11 | } |
| 9 | const std = @import("std"); | 12 | const std = @import("std"); |
| 10 | const io = std.Io.Threaded.global_single_threaded.io(); | 13 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 11 | #expect_stdout="Hello, World!\n" | 14 | #} |
| 15 | #update { | ||
| 16 | non-inline version#} | ||
| 17 | #check stdout { | ||
| 18 | Hello, World! | ||
| 19 | #} | ||
| 12 | 20 | ||
| 13 | #update=make function inline | 21 | #write main.zig { |
| 14 | #file=main.zig | ||
| 15 | pub fn main() !void { | 22 | pub fn main() !void { |
| 16 | try foo(); | 23 | try foo(); |
| 17 | } | 24 | } |
| ... | @@ -20,10 +27,14 @@ inline fn foo() !void { | ... | @@ -20,10 +27,14 @@ inline fn foo() !void { |
| 20 | } | 27 | } |
| 21 | const std = @import("std"); | 28 | const std = @import("std"); |
| 22 | const io = std.Io.Threaded.global_single_threaded.io(); | 29 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 23 | #expect_stdout="Hello, World!\n" | 30 | #} |
| 31 | #update { | ||
| 32 | make function inline#} | ||
| 33 | #check stdout { | ||
| 34 | Hello, World! | ||
| 35 | #} | ||
| 24 | 36 | ||
| 25 | #update=change string | 37 | #write main.zig { |
| 26 | #file=main.zig | ||
| 27 | pub fn main() !void { | 38 | pub fn main() !void { |
| 28 | try foo(); | 39 | try foo(); |
| 29 | } | 40 | } |
| ... | @@ -32,4 +43,9 @@ inline fn foo() !void { | ... | @@ -32,4 +43,9 @@ inline fn foo() !void { |
| 32 | } | 43 | } |
| 33 | const std = @import("std"); | 44 | const std = @import("std"); |
| 34 | const io = std.Io.Threaded.global_single_threaded.io(); | 45 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 35 | #expect_stdout="Hello, `inline` World!\n" | 46 | #} |
| 47 | #update { | ||
| 48 | change string#} | ||
| 49 | #check stdout { | ||
| 50 | Hello, `inline` World! | ||
| 51 | #} |
test/incremental/hello+18-6| ... | @@ -1,16 +1,28 @@ | ... | @@ -1,16 +1,28 @@ |
| 1 | #update=initial version | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | const std = @import("std"); | 6 | const std = @import("std"); |
| 4 | const io = std.Io.Threaded.global_single_threaded.io(); | 7 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 5 | pub fn main() !void { | 8 | pub fn main() !void { |
| 6 | try std.Io.File.stdout().writeStreamingAll(io, "good morning\n"); | 9 | try std.Io.File.stdout().writeStreamingAll(io, "good morning\n"); |
| 7 | } | 10 | } |
| 8 | #expect_stdout="good morning\n" | 11 | #} |
| 9 | #update=change the string | 12 | #update |
| 10 | #file=main.zig | 13 | #check stdout { |
| 14 | good morning | ||
| 15 | #} | ||
| 16 | |||
| 17 | #write main.zig { | ||
| 11 | const std = @import("std"); | 18 | const std = @import("std"); |
| 12 | const io = std.Io.Threaded.global_single_threaded.io(); | 19 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 13 | pub fn main() !void { | 20 | pub fn main() !void { |
| 14 | try std.Io.File.stdout().writeStreamingAll(io, "おはようございます\n"); | 21 | try std.Io.File.stdout().writeStreamingAll(io, "おはようございます\n"); |
| 15 | } | 22 | } |
| 16 | #expect_stdout="おはようございます\n" | 23 | #} |
| 24 | #update { | ||
| 25 | change the string#} | ||
| 26 | #check stdout { | ||
| 27 | おはようございます | ||
| 28 | #} |
test/incremental/increase_array_field_length+17-6| ... | @@ -1,5 +1,8 @@ | ... | @@ -1,5 +1,8 @@ |
| 1 | #update=initial version | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | const Big = struct { arr: [10]u8 }; | 6 | const Big = struct { arr: [10]u8 }; |
| 4 | pub fn main(init: std.process.Init) !void { | 7 | pub fn main(init: std.process.Init) !void { |
| 5 | var big: Big = undefined; | 8 | var big: Big = undefined; |
| ... | @@ -12,10 +15,13 @@ pub fn main(init: std.process.Init) !void { | ... | @@ -12,10 +15,13 @@ pub fn main(init: std.process.Init) !void { |
| 12 | }; | 15 | }; |
| 13 | } | 16 | } |
| 14 | const std = @import("std"); | 17 | const std = @import("std"); |
| 15 | #expect_stdout="arr[9] = 234\n" | 18 | #} |
| 19 | #update | ||
| 20 | #check stdout { | ||
| 21 | arr[9] = 234 | ||
| 22 | #} | ||
| 16 | 23 | ||
| 17 | #update=increase array length | 24 | #write main.zig { |
| 18 | #file=main.zig | ||
| 19 | const Big = struct { arr: [1000]u8 }; | 25 | const Big = struct { arr: [1000]u8 }; |
| 20 | pub fn main(init: std.process.Init) !void { | 26 | pub fn main(init: std.process.Init) !void { |
| 21 | var big: Big = undefined; | 27 | var big: Big = undefined; |
| ... | @@ -28,4 +34,9 @@ pub fn main(init: std.process.Init) !void { | ... | @@ -28,4 +34,9 @@ pub fn main(init: std.process.Init) !void { |
| 28 | }; | 34 | }; |
| 29 | } | 35 | } |
| 30 | const std = @import("std"); | 36 | const std = @import("std"); |
| 31 | #expect_stdout="arr[999] = 234\n" | 37 | #} |
| 38 | #update { | ||
| 39 | increase array length#} | ||
| 40 | #check stdout { | ||
| 41 | arr[999] = 234 | ||
| 42 | #} |
test/incremental/make_decl_pub+20-8| ... | @@ -1,23 +1,35 @@ | ... | @@ -1,23 +1,35 @@ |
| 1 | #update=initial version | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | const foo = @import("foo.zig"); | 6 | const foo = @import("foo.zig"); |
| 4 | pub fn main() !void { | 7 | pub fn main() !void { |
| 5 | try foo.hello(); | 8 | try foo.hello(); |
| 6 | } | 9 | } |
| 7 | #file=foo.zig | 10 | #} |
| 11 | #write foo.zig { | ||
| 8 | const std = @import("std"); | 12 | const std = @import("std"); |
| 9 | fn hello() !void { | 13 | fn hello() !void { |
| 10 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); | 14 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); |
| 11 | } | 15 | } |
| 12 | const io = std.Io.Threaded.global_single_threaded.io(); | 16 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 13 | #expect_error=main.zig:3:12: error: 'hello' is not marked 'pub' | 17 | #} |
| 14 | #expect_error=foo.zig:2:1: note: declared here | 18 | #update |
| 19 | #check errors { | ||
| 20 | main.zig:3:12: error: 'hello' is not marked 'pub' | ||
| 21 | foo.zig:2:1: note: declared here | ||
| 22 | #} | ||
| 15 | 23 | ||
| 16 | #update=make hello pub | 24 | #write foo.zig { |
| 17 | #file=foo.zig | ||
| 18 | const std = @import("std"); | 25 | const std = @import("std"); |
| 19 | pub fn hello() !void { | 26 | pub fn hello() !void { |
| 20 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); | 27 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); |
| 21 | } | 28 | } |
| 22 | const io = std.Io.Threaded.global_single_threaded.io(); | 29 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 23 | #expect_stdout="Hello, World!\n" | 30 | #} |
| 31 | #update { | ||
| 32 | make hello pub#} | ||
| 33 | #check stdout { | ||
| 34 | Hello, World! | ||
| 35 | #} |
test/incremental/modify_inline_fn+18-6| ... | @@ -1,5 +1,8 @@ | ... | @@ -1,5 +1,8 @@ |
| 1 | #update=initial version | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | const std = @import("std"); | 6 | const std = @import("std"); |
| 4 | pub fn main() !void { | 7 | pub fn main() !void { |
| 5 | const str = getStr(); | 8 | const str = getStr(); |
| ... | @@ -9,9 +12,13 @@ inline fn getStr() []const u8 { | ... | @@ -9,9 +12,13 @@ inline fn getStr() []const u8 { |
| 9 | return "foo\n"; | 12 | return "foo\n"; |
| 10 | } | 13 | } |
| 11 | const io = std.Io.Threaded.global_single_threaded.io(); | 14 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 12 | #expect_stdout="foo\n" | 15 | #} |
| 13 | #update=change the string | 16 | #update |
| 14 | #file=main.zig | 17 | #check stdout { |
| 18 | foo | ||
| 19 | #} | ||
| 20 | |||
| 21 | #write main.zig { | ||
| 15 | const std = @import("std"); | 22 | const std = @import("std"); |
| 16 | pub fn main() !void { | 23 | pub fn main() !void { |
| 17 | const str = getStr(); | 24 | const str = getStr(); |
| ... | @@ -21,4 +28,9 @@ inline fn getStr() []const u8 { | ... | @@ -21,4 +28,9 @@ inline fn getStr() []const u8 { |
| 21 | return "bar\n"; | 28 | return "bar\n"; |
| 22 | } | 29 | } |
| 23 | const io = std.Io.Threaded.global_single_threaded.io(); | 30 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 24 | #expect_stdout="bar\n" | 31 | #} |
| 32 | #update { | ||
| 33 | change the string#} | ||
| 34 | #check stdout { | ||
| 35 | bar | ||
| 36 | #} |
test/incremental/move_src+17-6| ... | @@ -1,5 +1,8 @@ | ... | @@ -1,5 +1,8 @@ |
| 1 | #update=initial version | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | const std = @import("std"); | 6 | const std = @import("std"); |
| 4 | pub fn main() !void { | 7 | pub fn main() !void { |
| 5 | var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); | 8 | var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); |
| ... | @@ -12,10 +15,13 @@ fn bar() u32 { | ... | @@ -12,10 +15,13 @@ fn bar() u32 { |
| 12 | return 123; | 15 | return 123; |
| 13 | } | 16 | } |
| 14 | const io = std.Io.Threaded.global_single_threaded.io(); | 17 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 15 | #expect_stdout="7 123\n" | 18 | #} |
| 19 | #update | ||
| 20 | #check stdout { | ||
| 21 | 7 123 | ||
| 22 | #} | ||
| 16 | 23 | ||
| 17 | #update=add newline | 24 | #write main.zig { |
| 18 | #file=main.zig | ||
| 19 | const std = @import("std"); | 25 | const std = @import("std"); |
| 20 | pub fn main() !void { | 26 | pub fn main() !void { |
| 21 | var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); | 27 | var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); |
| ... | @@ -29,4 +35,9 @@ fn bar() u32 { | ... | @@ -29,4 +35,9 @@ fn bar() u32 { |
| 29 | return 123; | 35 | return 123; |
| 30 | } | 36 | } |
| 31 | const io = std.Io.Threaded.global_single_threaded.io(); | 37 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 32 | #expect_stdout="8 123\n" | 38 | #} |
| 39 | #update { | ||
| 40 | add newline#} | ||
| 41 | #check stdout { | ||
| 42 | 8 123 | ||
| 43 | #} |
test/incremental/pointer_to_decl_with_astgen_error+22-9| ... | @@ -1,23 +1,36 @@ | ... | @@ -1,23 +1,36 @@ |
| 1 | #update=initial version | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | const foo = {}; | 6 | const foo = {}; |
| 4 | pub fn main() void { | 7 | pub fn main() void { |
| 5 | _ = &foo; | 8 | _ = &foo; |
| 6 | } | 9 | } |
| 7 | #expect_stdout="" | 10 | #} |
| 11 | #update | ||
| 12 | #check stdout { | ||
| 13 | #} | ||
| 8 | 14 | ||
| 9 | #update=introduce use of undeclared identifier | 15 | #write main.zig { |
| 10 | #file=main.zig | ||
| 11 | const foo = something; | 16 | const foo = something; |
| 12 | pub fn main() void { | 17 | pub fn main() void { |
| 13 | _ = &foo; | 18 | _ = &foo; |
| 14 | } | 19 | } |
| 15 | #expect_error=main.zig:1:13: error: use of undeclared identifier 'something' | 20 | #} |
| 21 | #update { | ||
| 22 | introduce use of undeclared identifier#} | ||
| 23 | #check errors { | ||
| 24 | main.zig:1:13: error: use of undeclared identifier 'something' | ||
| 25 | #} | ||
| 16 | 26 | ||
| 17 | #update=revert use of undeclared identifier | 27 | #write main.zig { |
| 18 | #file=main.zig | ||
| 19 | const foo = {}; | 28 | const foo = {}; |
| 20 | pub fn main() void { | 29 | pub fn main() void { |
| 21 | _ = &foo; | 30 | _ = &foo; |
| 22 | } | 31 | } |
| 23 | #expect_stdout="" | 32 | #} |
| 33 | #update { | ||
| 34 | revert use of undeclared identifier#} | ||
| 35 | #check stdout { | ||
| 36 | #} |
test/incremental/recursive_function_becomes_non_recursive+17-6| ... | @@ -1,5 +1,8 @@ | ... | @@ -1,5 +1,8 @@ |
| 1 | #update=initial version | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | pub fn main() !void { | 6 | pub fn main() !void { |
| 4 | try foo(false); | 7 | try foo(false); |
| 5 | } | 8 | } |
| ... | @@ -10,10 +13,13 @@ fn foo(recurse: bool) !void { | ... | @@ -10,10 +13,13 @@ fn foo(recurse: bool) !void { |
| 10 | } | 13 | } |
| 11 | const std = @import("std"); | 14 | const std = @import("std"); |
| 12 | const io = std.Io.Threaded.global_single_threaded.io(); | 15 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 13 | #expect_stdout="non-recursive path\n" | 16 | #} |
| 17 | #update | ||
| 18 | #check stdout { | ||
| 19 | non-recursive path | ||
| 20 | #} | ||
| 14 | 21 | ||
| 15 | #update=eliminate recursion and change argument | 22 | #write main.zig { |
| 16 | #file=main.zig | ||
| 17 | pub fn main() !void { | 23 | pub fn main() !void { |
| 18 | try foo(true); | 24 | try foo(true); |
| 19 | } | 25 | } |
| ... | @@ -24,4 +30,9 @@ fn foo(recurse: bool) !void { | ... | @@ -24,4 +30,9 @@ fn foo(recurse: bool) !void { |
| 24 | } | 30 | } |
| 25 | const std = @import("std"); | 31 | const std = @import("std"); |
| 26 | const io = std.Io.Threaded.global_single_threaded.io(); | 32 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 27 | #expect_stdout="x==1\n" | 33 | #} |
| 34 | #update { | ||
| 35 | eliminate recursion and change argument#} | ||
| 36 | #check stdout { | ||
| 37 | x==1 | ||
| 38 | #} |
test/incremental/remove_enum_field+21-9| ... | @@ -1,27 +1,39 @@ | ... | @@ -1,27 +1,39 @@ |
| 1 | #update=initial version | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | const MyEnum = enum(u8) { | 6 | const MyEnum = enum(u8) { |
| 4 | foo = 1, | 7 | foo = 1, |
| 5 | bar = 2, | 8 | bar = 2, |
| 6 | }; | 9 | }; |
| 7 | pub fn main() !void { | 10 | pub fn main() !void { |
| 8 | var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); | 11 | var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); |
| 9 | try stdout_writer.interface.print("{}\n", .{@intFromEnum(MyEnum.foo)}); | 12 | try stdout_writer.interface.print("{}\n", .{@backingInt(MyEnum.foo)}); |
| 10 | } | 13 | } |
| 11 | const std = @import("std"); | 14 | const std = @import("std"); |
| 12 | const io = std.Io.Threaded.global_single_threaded.io(); | 15 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 13 | #expect_stdout="1\n" | 16 | #} |
| 14 | #update=remove enum field | 17 | #update |
| 15 | #file=main.zig | 18 | #check stdout { |
| 19 | 1 | ||
| 20 | #} | ||
| 21 | |||
| 22 | #write main.zig { | ||
| 16 | const MyEnum = enum(u8) { | 23 | const MyEnum = enum(u8) { |
| 17 | //foo = 1, | 24 | //foo = 1, |
| 18 | bar = 2, | 25 | bar = 2, |
| 19 | }; | 26 | }; |
| 20 | pub fn main() !void { | 27 | pub fn main() !void { |
| 21 | var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); | 28 | var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); |
| 22 | try stdout_writer.interface.print("{}\n", .{@intFromEnum(MyEnum.foo)}); | 29 | try stdout_writer.interface.print("{}\n", .{@backingInt(MyEnum.foo)}); |
| 23 | } | 30 | } |
| 24 | const std = @import("std"); | 31 | const std = @import("std"); |
| 25 | const io = std.Io.Threaded.global_single_threaded.io(); | 32 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 26 | #expect_error=main.zig:7:69: error: enum 'main.MyEnum' has no member named 'foo' | 33 | #} |
| 27 | #expect_error=main.zig:1:16: note: enum declared here | 34 | #update { |
| 35 | remove enum field#} | ||
| 36 | #check errors { | ||
| 37 | main.zig:7:68: error: enum 'main.MyEnum' has no member named 'foo' | ||
| 38 | main.zig:1:16: note: enum declared here | ||
| 39 | #} |
test/incremental/remove_function_with_changed_callee+16-6| ... | @@ -1,5 +1,8 @@ | ... | @@ -1,5 +1,8 @@ |
| 1 | #update=initial version | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | const std = @import("std"); | 6 | const std = @import("std"); |
| 4 | const io = std.Io.Threaded.global_single_threaded.io(); | 7 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 5 | 8 | ||
| ... | @@ -23,9 +26,12 @@ fn bar(a: A) !void { | ... | @@ -23,9 +26,12 @@ fn bar(a: A) !void { |
| 23 | pub fn main() !void { | 26 | pub fn main() !void { |
| 24 | try foo(); | 27 | try foo(); |
| 25 | } | 28 | } |
| 26 | #expect_stdout="0" | 29 | #} |
| 27 | #update=remove foo and change bar wasm function type | 30 | #update |
| 28 | #file=main.zig | 31 | #check stdout { |
| 32 | 0#} | ||
| 33 | |||
| 34 | #write main.zig { | ||
| 29 | //! This update must preserve `bar` `InternPool.Index` value, while changing its wasm function type. | 35 | //! This update must preserve `bar` `InternPool.Index` value, while changing its wasm function type. |
| 30 | //! If `foo` code is preserved in the binary without any changes, wasm type checking will fail. | 36 | //! If `foo` code is preserved in the binary without any changes, wasm type checking will fail. |
| 31 | const std = @import("std"); | 37 | const std = @import("std"); |
| ... | @@ -47,4 +53,8 @@ fn bar(a: A) !void { | ... | @@ -47,4 +53,8 @@ fn bar(a: A) !void { |
| 47 | pub fn main() !void { | 53 | pub fn main() !void { |
| 48 | try bar(.one); | 54 | try bar(.one); |
| 49 | } | 55 | } |
| 50 | #expect_stdout="1" | 56 | #} |
| 57 | #update { | ||
| 58 | remove foo and change bar wasm function type#} | ||
| 59 | #check stdout { | ||
| 60 | 1#} |
test/incremental/remove_invalid_union_backing_enum+18-7| ... | @@ -1,5 +1,8 @@ | ... | @@ -1,5 +1,8 @@ |
| 1 | #update=initial version | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | const E = enum { a, b, c }; | 6 | const E = enum { a, b, c }; |
| 4 | const U = union(E) { | 7 | const U = union(E) { |
| 5 | a: i32, | 8 | a: i32, |
| ... | @@ -11,10 +14,14 @@ pub fn main() void { | ... | @@ -11,10 +14,14 @@ pub fn main() void { |
| 11 | const u: U = .{ .a = 123 }; | 14 | const u: U = .{ .a = 123 }; |
| 12 | _ = u; | 15 | _ = u; |
| 13 | } | 16 | } |
| 14 | #expect_error=main.zig:6:5: error: no field named 'd' in enum 'main.E' | 17 | #} |
| 15 | #expect_error=main.zig:1:11: note: enum declared here | 18 | #update |
| 16 | #update=remove invalid backing enum | 19 | #check errors { |
| 17 | #file=main.zig | 20 | main.zig:6:5: error: no field named 'd' in enum 'main.E' |
| 21 | main.zig:1:11: note: enum declared here | ||
| 22 | #} | ||
| 23 | |||
| 24 | #write main.zig { | ||
| 18 | const U = union { | 25 | const U = union { |
| 19 | a: i32, | 26 | a: i32, |
| 20 | b: f64, | 27 | b: f64, |
| ... | @@ -25,4 +32,8 @@ pub fn main() void { | ... | @@ -25,4 +32,8 @@ pub fn main() void { |
| 25 | const u: U = .{ .a = 123 }; | 32 | const u: U = .{ .a = 123 }; |
| 26 | _ = u; | 33 | _ = u; |
| 27 | } | 34 | } |
| 28 | #expect_stdout="" | 35 | #} |
| 36 | #update { | ||
| 37 | remove invalid backing enum#} | ||
| 38 | #check stdout { | ||
| 39 | #} |
test/incremental/struct_reification_becomes_anon_init+17-6| ... | @@ -1,19 +1,30 @@ | ... | @@ -1,19 +1,30 @@ |
| 1 | #update=initial version | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | const Foo = @Struct(.auto, null, &.{"reified_field"}, &.{void}, &.{.{}}); | 6 | const Foo = @Struct(.auto, null, &.{"reified_field"}, &.{void}, &.{.{}}); |
| 4 | pub fn main(init: std.process.Init) !void { | 7 | pub fn main(init: std.process.Init) !void { |
| 5 | const field_name = @typeInfo(Foo).@"struct".field_names[0]; | 8 | const field_name = @typeInfo(Foo).@"struct".field_names[0]; |
| 6 | try std.Io.File.stdout().writeStreamingAll(init.io, field_name ++ "\n"); | 9 | try std.Io.File.stdout().writeStreamingAll(init.io, field_name ++ "\n"); |
| 7 | } | 10 | } |
| 8 | const std = @import("std"); | 11 | const std = @import("std"); |
| 9 | #expect_stdout="reified_field\n" | 12 | #} |
| 13 | #update | ||
| 14 | #check stdout { | ||
| 15 | reified_field | ||
| 16 | #} | ||
| 10 | 17 | ||
| 11 | #update=change to `@TypeOf` anonymous init | 18 | #write main.zig { |
| 12 | #file=main.zig | ||
| 13 | const Foo = @TypeOf(.{ .anon_field = 123 }); | 19 | const Foo = @TypeOf(.{ .anon_field = 123 }); |
| 14 | pub fn main(init: std.process.Init) !void { | 20 | pub fn main(init: std.process.Init) !void { |
| 15 | const field_name = @typeInfo(Foo).@"struct".field_names[0]; | 21 | const field_name = @typeInfo(Foo).@"struct".field_names[0]; |
| 16 | try std.Io.File.stdout().writeStreamingAll(init.io, field_name ++ "\n"); | 22 | try std.Io.File.stdout().writeStreamingAll(init.io, field_name ++ "\n"); |
| 17 | } | 23 | } |
| 18 | const std = @import("std"); | 24 | const std = @import("std"); |
| 19 | #expect_stdout="anon_field\n" | 25 | #} |
| 26 | #update { | ||
| 27 | change to `@TypeOf` anonymous init#} | ||
| 28 | #check stdout { | ||
| 29 | anon_field | ||
| 30 | #} |
test/incremental/tag_name+23-9| ... | @@ -1,27 +1,41 @@ | ... | @@ -1,27 +1,41 @@ |
| 1 | #update=initial version | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | const std = @import("std"); | 6 | const std = @import("std"); |
| 4 | var some_enum: enum { first, second } = .first; | 7 | var some_enum: enum { first, second } = .first; |
| 5 | const io = std.Io.Threaded.global_single_threaded.io(); | 8 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 6 | pub fn main() !void { | 9 | pub fn main() !void { |
| 7 | try std.Io.File.stdout().writeStreamingAll(io, @tagName(some_enum)); | 10 | try std.Io.File.stdout().writeStreamingAll(io, @tagName(some_enum)); |
| 8 | } | 11 | } |
| 9 | #expect_stdout="first" | 12 | #} |
| 10 | #update=no change | 13 | #update |
| 11 | #file=main.zig | 14 | #check stdout { |
| 15 | first#} | ||
| 16 | |||
| 17 | #write main.zig { | ||
| 12 | const std = @import("std"); | 18 | const std = @import("std"); |
| 13 | var some_enum: enum { first, second } = .first; | 19 | var some_enum: enum { first, second } = .first; |
| 14 | const io = std.Io.Threaded.global_single_threaded.io(); | 20 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 15 | pub fn main() !void { | 21 | pub fn main() !void { |
| 16 | try std.Io.File.stdout().writeStreamingAll(io, @tagName(some_enum)); | 22 | try std.Io.File.stdout().writeStreamingAll(io, @tagName(some_enum)); |
| 17 | } | 23 | } |
| 18 | #expect_stdout="first" | 24 | #} |
| 19 | #update=swap fields | 25 | #update { |
| 20 | #file=main.zig | 26 | no change#} |
| 27 | #check stdout { | ||
| 28 | first#} | ||
| 29 | |||
| 30 | #write main.zig { | ||
| 21 | const std = @import("std"); | 31 | const std = @import("std"); |
| 22 | var some_enum: enum { second, first } = .first; | 32 | var some_enum: enum { second, first } = .first; |
| 23 | const io = std.Io.Threaded.global_single_threaded.io(); | 33 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 24 | pub fn main() !void { | 34 | pub fn main() !void { |
| 25 | try std.Io.File.stdout().writeStreamingAll(io, @tagName(some_enum)); | 35 | try std.Io.File.stdout().writeStreamingAll(io, @tagName(some_enum)); |
| 26 | } | 36 | } |
| 27 | #expect_stdout="first" | 37 | #} |
| 38 | #update { | ||
| 39 | swap fields#} | ||
| 40 | #check stdout { | ||
| 41 | first#} |
test/incremental/temporary_analysis_error_in_generic_signature+25-10| ... | @@ -1,5 +1,8 @@ | ... | @@ -1,5 +1,8 @@ |
| 1 | #update=initial version | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | //! The original repro here depends on re-analysis order, which depends on | 6 | //! The original repro here depends on re-analysis order, which depends on |
| 4 | //! declaration order, so this exact declaration order must be used. | 7 | //! declaration order, so this exact declaration order must be used. |
| 5 | const Foo = struct { x: u8 }; | 8 | const Foo = struct { x: u8 }; |
| ... | @@ -11,10 +14,13 @@ fn bar(comptime x: u8) @This().Foo { | ... | @@ -11,10 +14,13 @@ fn bar(comptime x: u8) @This().Foo { |
| 11 | return .{ .x = x }; | 14 | return .{ .x = x }; |
| 12 | } | 15 | } |
| 13 | const std = @import("std"); | 16 | const std = @import("std"); |
| 14 | #expect_stdout="Z\n" | 17 | #} |
| 18 | #update | ||
| 19 | #check stdout { | ||
| 20 | Z | ||
| 21 | #} | ||
| 15 | 22 | ||
| 16 | #update=change generic signature to use non-existent member | 23 | #write main.zig { |
| 17 | #file=main.zig | ||
| 18 | //! The original repro here depends on re-analysis order, which depends on | 24 | //! The original repro here depends on re-analysis order, which depends on |
| 19 | //! declaration order, so this exact declaration order must be used. | 25 | //! declaration order, so this exact declaration order must be used. |
| 20 | const Foo = struct { x: u8 }; | 26 | const Foo = struct { x: u8 }; |
| ... | @@ -26,11 +32,15 @@ fn bar(comptime x: u8) @This().FooAlias { | ... | @@ -26,11 +32,15 @@ fn bar(comptime x: u8) @This().FooAlias { |
| 26 | return .{ .x = x }; | 32 | return .{ .x = x }; |
| 27 | } | 33 | } |
| 28 | const std = @import("std"); | 34 | const std = @import("std"); |
| 29 | #expect_error=main.zig:8:31: error: root source file struct 'main' has no member named 'FooAlias' | 35 | #} |
| 30 | #expect_error=main.zig:1:1: note: struct declared here | 36 | #update { |
| 37 | change generic signature to use non-existent member#} | ||
| 38 | #check errors { | ||
| 39 | main.zig:8:31: error: root source file struct 'main' has no member named 'FooAlias' | ||
| 40 | main.zig:1:1: note: struct declared here | ||
| 41 | #} | ||
| 31 | 42 | ||
| 32 | #update=add that member, fixing the error | 43 | #write main.zig { |
| 33 | #file=main.zig | ||
| 34 | //! The original repro here depends on re-analysis order, which depends on | 44 | //! The original repro here depends on re-analysis order, which depends on |
| 35 | //! declaration order, so this exact declaration order must be used. | 45 | //! declaration order, so this exact declaration order must be used. |
| 36 | const Foo = struct { x: u8 }; | 46 | const Foo = struct { x: u8 }; |
| ... | @@ -43,4 +53,9 @@ fn bar(comptime x: u8) @This().FooAlias { | ... | @@ -43,4 +53,9 @@ fn bar(comptime x: u8) @This().FooAlias { |
| 43 | return .{ .x = x }; | 53 | return .{ .x = x }; |
| 44 | } | 54 | } |
| 45 | const std = @import("std"); | 55 | const std = @import("std"); |
| 46 | #expect_stdout="Z\n" | 56 | #} |
| 57 | #update { | ||
| 58 | add that member, fixing the error#} | ||
| 59 | #check stdout { | ||
| 60 | Z | ||
| 61 | #} |
test/incremental/temporary_parse_error+22-9| ... | @@ -1,15 +1,28 @@ | ... | @@ -1,15 +1,28 @@ |
| 1 | #update=initial version | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | const std = @import("std"); | 6 | const std = @import("std"); |
| 4 | pub fn main() !void {} | 7 | pub fn main() !void {} |
| 5 | #expect_stdout="" | 8 | #} |
| 9 | #update | ||
| 10 | #check stdout { | ||
| 11 | #} | ||
| 6 | 12 | ||
| 7 | #update=introduce parse error | 13 | #write main.zig { |
| 8 | #file=main.zig | ||
| 9 | pub fn main() !void { | 14 | pub fn main() !void { |
| 10 | #expect_error=main.zig:2:1: error: expected statement, found 'EOF' | 15 | #} |
| 16 | #update { | ||
| 17 | introduce parse error#} | ||
| 18 | #check errors { | ||
| 19 | main.zig:2:1: error: expected statement, found 'EOF' | ||
| 20 | #} | ||
| 11 | 21 | ||
| 12 | #update=fix parse error | 22 | #write main.zig { |
| 13 | #file=main.zig | ||
| 14 | pub fn main() !void {} | 23 | pub fn main() !void {} |
| 15 | #expect_stdout="" | 24 | #} |
| 25 | #update { | ||
| 26 | fix parse error#} | ||
| 27 | #check stdout { | ||
| 28 | #} |
test/incremental/type_becomes_comptime_only+21-9| ... | @@ -1,5 +1,8 @@ | ... | @@ -1,5 +1,8 @@ |
| 1 | #update=initial version | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | const SomeType = u32; | 6 | const SomeType = u32; |
| 4 | const S = struct { | 7 | const S = struct { |
| 5 | x: SomeType, | 8 | x: SomeType, |
| ... | @@ -9,10 +12,12 @@ pub fn main() void { | ... | @@ -9,10 +12,12 @@ pub fn main() void { |
| 9 | const s: S = .{ .x = 456 }; | 12 | const s: S = .{ .x = 456 }; |
| 10 | s.foo(); | 13 | s.foo(); |
| 11 | } | 14 | } |
| 12 | #expect_stdout="" | 15 | #} |
| 16 | #update | ||
| 17 | #check stdout { | ||
| 18 | #} | ||
| 13 | 19 | ||
| 14 | #update=make S comptime-only | 20 | #write main.zig { |
| 15 | #file=main.zig | ||
| 16 | const SomeType = comptime_int; | 21 | const SomeType = comptime_int; |
| 17 | const S = struct { | 22 | const S = struct { |
| 18 | x: SomeType, | 23 | x: SomeType, |
| ... | @@ -22,10 +27,13 @@ pub fn main() void { | ... | @@ -22,10 +27,13 @@ pub fn main() void { |
| 22 | const s: S = .{ .x = 456 }; | 27 | const s: S = .{ .x = 456 }; |
| 23 | s.foo(); | 28 | s.foo(); |
| 24 | } | 29 | } |
| 25 | #expect_stdout="" | 30 | #} |
| 31 | #update { | ||
| 32 | make S comptime-only#} | ||
| 33 | #check stdout { | ||
| 34 | #} | ||
| 26 | 35 | ||
| 27 | #update=make S runtime again | 36 | #write main.zig { |
| 28 | #file=main.zig | ||
| 29 | const SomeType = u16; | 37 | const SomeType = u16; |
| 30 | const S = struct { | 38 | const S = struct { |
| 31 | x: SomeType, | 39 | x: SomeType, |
| ... | @@ -35,4 +43,8 @@ pub fn main() void { | ... | @@ -35,4 +43,8 @@ pub fn main() void { |
| 35 | const s: S = .{ .x = 456 }; | 43 | const s: S = .{ .x = 456 }; |
| 36 | s.foo(); | 44 | s.foo(); |
| 37 | } | 45 | } |
| 38 | #expect_stdout="" | 46 | #} |
| 47 | #update { | ||
| 48 | make S runtime again#} | ||
| 49 | #check stdout { | ||
| 50 | #} |
test/incremental/type_dependency_loop+41-21| ... | @@ -1,50 +1,70 @@ | ... | @@ -1,50 +1,70 @@ |
| 1 | #update=initial version | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | pub const A = struct { b: B }; | 6 | pub const A = struct { b: B }; |
| 4 | pub const B = struct { a: A }; | 7 | pub const B = struct { a: A }; |
| 5 | pub fn main() void { | 8 | pub fn main() void { |
| 6 | _ = @as(B, undefined); | 9 | _ = @as(B, undefined); |
| 7 | } | 10 | } |
| 8 | #expect_error=:error: dependency loop with length 2 | 11 | #} |
| 9 | #expect_error=main.zig:2:27: note: type 'main.B' depends on type 'main.A' for field declared here | 12 | #update |
| 10 | #expect_error=main.zig:1:27: note: type 'main.A' depends on type 'main.B' for field declared here | 13 | #check errors { |
| 11 | #expect_error=:note: eliminate any one of these dependencies to break the loop | 14 | error: dependency loop with length 2 |
| 15 | main.zig:2:27: note: type 'main.B' depends on type 'main.A' for field declared here | ||
| 16 | main.zig:1:27: note: type 'main.A' depends on type 'main.B' for field declared here | ||
| 17 | note: eliminate any one of these dependencies to break the loop | ||
| 18 | #} | ||
| 12 | 19 | ||
| 13 | #update=remove reference to dependency loop | 20 | #write main.zig { |
| 14 | #file=main.zig | ||
| 15 | pub const A = struct { b: B }; | 21 | pub const A = struct { b: B }; |
| 16 | pub const B = struct { a: A }; | 22 | pub const B = struct { a: A }; |
| 17 | pub fn main() void { | 23 | pub fn main() void { |
| 18 | _ = B; | 24 | _ = B; |
| 19 | } | 25 | } |
| 20 | #expect_stdout="" | 26 | #} |
| 27 | #update { | ||
| 28 | remove reference to dependency loop#} | ||
| 29 | #check stdout { | ||
| 30 | #} | ||
| 21 | 31 | ||
| 22 | #update=change dependency loop without fixing it | 32 | #write main.zig { |
| 23 | #file=main.zig | ||
| 24 | pub const A = struct { b: B }; | 33 | pub const A = struct { b: B }; |
| 25 | pub const B = struct { a: *align(@alignOf(A)) A }; | 34 | pub const B = struct { a: *align(@alignOf(A)) A }; |
| 26 | pub fn main() void { | 35 | pub fn main() void { |
| 27 | _ = B; | 36 | _ = B; |
| 28 | } | 37 | } |
| 29 | #expect_stdout="" | 38 | #} |
| 39 | #update { | ||
| 40 | change dependency loop without fixing it#} | ||
| 41 | #check stdout { | ||
| 42 | #} | ||
| 30 | 43 | ||
| 31 | #update=reference dependency loop again | 44 | #write main.zig { |
| 32 | #file=main.zig | ||
| 33 | pub const A = struct { b: B }; | 45 | pub const A = struct { b: B }; |
| 34 | pub const B = struct { a: *align(@alignOf(A)) A }; | 46 | pub const B = struct { a: *align(@alignOf(A)) A }; |
| 35 | pub fn main() void { | 47 | pub fn main() void { |
| 36 | _ = @as(B, undefined); | 48 | _ = @as(B, undefined); |
| 37 | } | 49 | } |
| 38 | #expect_error=:error: dependency loop with length 2 | 50 | #} |
| 39 | #expect_error=main.zig:2:43: note: type 'main.B' depends on type 'main.A' for alignment query here | 51 | #update { |
| 40 | #expect_error=main.zig:1:27: note: type 'main.A' depends on type 'main.B' for field declared here | 52 | reference dependency loop again#} |
| 41 | #expect_error=:note: eliminate any one of these dependencies to break the loop | 53 | #check errors { |
| 54 | error: dependency loop with length 2 | ||
| 55 | main.zig:2:43: note: type 'main.B' depends on type 'main.A' for alignment query here | ||
| 56 | main.zig:1:27: note: type 'main.A' depends on type 'main.B' for field declared here | ||
| 57 | note: eliminate any one of these dependencies to break the loop | ||
| 58 | #} | ||
| 42 | 59 | ||
| 43 | #update=fix dependency loop | 60 | #write main.zig { |
| 44 | #file=main.zig | ||
| 45 | pub const A = struct { b: B }; | 61 | pub const A = struct { b: B }; |
| 46 | pub const B = struct { a: *A }; | 62 | pub const B = struct { a: *A }; |
| 47 | pub fn main() void { | 63 | pub fn main() void { |
| 48 | _ = @as(B, undefined); | 64 | _ = @as(B, undefined); |
| 49 | } | 65 | } |
| 50 | #expect_stdout="" | 66 | #} |
| 67 | #update { | ||
| 68 | fix dependency loop#} | ||
| 69 | #check stdout { | ||
| 70 | #} |
test/incremental/unreferenced_error+31-12| ... | @@ -1,25 +1,35 @@ | ... | @@ -1,25 +1,35 @@ |
| 1 | #update=initial version | 1 | #exe { |
| 2 | #file=main.zig | 2 | -Mroot=main.zig |
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 3 | const std = @import("std"); | 6 | const std = @import("std"); |
| 4 | pub fn main() !void { | 7 | pub fn main() !void { |
| 5 | try std.Io.File.stdout().writeStreamingAll(io, a); | 8 | try std.Io.File.stdout().writeStreamingAll(io, a); |
| 6 | } | 9 | } |
| 7 | const a = "Hello, World!\n"; | 10 | const a = "Hello, World!\n"; |
| 8 | const io = std.Io.Threaded.global_single_threaded.io(); | 11 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 9 | #expect_stdout="Hello, World!\n" | 12 | #} |
| 13 | #update | ||
| 14 | #check stdout { | ||
| 15 | Hello, World! | ||
| 16 | #} | ||
| 10 | 17 | ||
| 11 | #update=introduce compile error | 18 | #write main.zig { |
| 12 | #file=main.zig | ||
| 13 | const std = @import("std"); | 19 | const std = @import("std"); |
| 14 | pub fn main() !void { | 20 | pub fn main() !void { |
| 15 | try std.Io.File.stdout().writeStreamingAll(io, a); | 21 | try std.Io.File.stdout().writeStreamingAll(io, a); |
| 16 | } | 22 | } |
| 17 | const a = @compileError("bad a"); | 23 | const a = @compileError("bad a"); |
| 18 | const io = std.Io.Threaded.global_single_threaded.io(); | 24 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 19 | #expect_error=main.zig:5:11: error: bad a | 25 | #} |
| 26 | #update { | ||
| 27 | introduce compile error#} | ||
| 28 | #check errors { | ||
| 29 | main.zig:5:11: error: bad a | ||
| 30 | #} | ||
| 20 | 31 | ||
| 21 | #update=remove error reference | 32 | #write main.zig { |
| 22 | #file=main.zig | ||
| 23 | const std = @import("std"); | 33 | const std = @import("std"); |
| 24 | pub fn main() !void { | 34 | pub fn main() !void { |
| 25 | try std.Io.File.stdout().writeStreamingAll(io, b); | 35 | try std.Io.File.stdout().writeStreamingAll(io, b); |
| ... | @@ -27,10 +37,14 @@ pub fn main() !void { | ... | @@ -27,10 +37,14 @@ pub fn main() !void { |
| 27 | const a = @compileError("bad a"); | 37 | const a = @compileError("bad a"); |
| 28 | const b = "Hi there!\n"; | 38 | const b = "Hi there!\n"; |
| 29 | const io = std.Io.Threaded.global_single_threaded.io(); | 39 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 30 | #expect_stdout="Hi there!\n" | 40 | #} |
| 41 | #update { | ||
| 42 | remove error reference#} | ||
| 43 | #check stdout { | ||
| 44 | Hi there! | ||
| 45 | #} | ||
| 31 | 46 | ||
| 32 | #update=introduce and remove reference to error | 47 | #write main.zig { |
| 33 | #file=main.zig | ||
| 34 | const std = @import("std"); | 48 | const std = @import("std"); |
| 35 | pub fn main() !void { | 49 | pub fn main() !void { |
| 36 | try std.Io.File.stdout().writeStreamingAll(io, a); | 50 | try std.Io.File.stdout().writeStreamingAll(io, a); |
| ... | @@ -38,4 +52,9 @@ pub fn main() !void { | ... | @@ -38,4 +52,9 @@ pub fn main() !void { |
| 38 | const a = "Back to a\n"; | 52 | const a = "Back to a\n"; |
| 39 | const b = @compileError("bad b"); | 53 | const b = @compileError("bad b"); |
| 40 | const io = std.Io.Threaded.global_single_threaded.io(); | 54 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 41 | #expect_stdout="Back to a\n" | 55 | #} |
| 56 | #update { | ||
| 57 | introduce and remove reference to error#} | ||
| 58 | #check stdout { | ||
| 59 | Back to a | ||
| 60 | #} |
test/incremental2/bad_import deleted-48| ... | @@ -1,48 +0,0 @@ | ||
| 1 | #exe { | ||
| 2 | -Mroot=main.zig | ||
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 6 | pub fn main() !void { | ||
| 7 | _ = @import("foo.zig"); | ||
| 8 | try std.Io.File.stdout().writeStreamingAll(io, "success\n"); | ||
| 9 | } | ||
| 10 | const std = @import("std"); | ||
| 11 | const io = std.Io.Threaded.global_single_threaded.io(); | ||
| 12 | #} | ||
| 13 | #write foo.zig { | ||
| 14 | comptime { | ||
| 15 | _ = @import("bad.zig"); | ||
| 16 | } | ||
| 17 | #} | ||
| 18 | #update | ||
| 19 | #check errors { | ||
| 20 | bad.zig:1:1: error: unable to load "bad.zig": FileNotFound | ||
| 21 | foo.zig:2:17: note: file imported here | ||
| 22 | #} | ||
| 23 | |||
| 24 | #write foo.zig { | ||
| 25 | comptime { | ||
| 26 | _ = @import("this_is/not_real.zig"); | ||
| 27 | } | ||
| 28 | #} | ||
| 29 | #update { | ||
| 30 | change bad import#} | ||
| 31 | #check errors { | ||
| 32 | this_is/not_real.zig:1:1: error: unable to load "not_real.zig": FileNotFound | ||
| 33 | foo.zig:2:17: note: file imported here | ||
| 34 | #} | ||
| 35 | |||
| 36 | #write main.zig { | ||
| 37 | pub fn main() !void { | ||
| 38 | //_ = @import("foo.zig"); | ||
| 39 | try std.Io.File.stdout().writeStreamingAll(io, "success\n"); | ||
| 40 | } | ||
| 41 | const std = @import("std"); | ||
| 42 | const io = std.Io.Threaded.global_single_threaded.io(); | ||
| 43 | #} | ||
| 44 | #update { | ||
| 45 | remove import of 'foo.zig'#} | ||
| 46 | #check stdout { | ||
| 47 | success | ||
| 48 | #} | ||
test/incremental2/change_panic_handler_explicit/0/main.zig deleted-46| ... | @@ -1,46 +0,0 @@ | ||
| 1 | pub fn main() !u8 { | ||
| 2 | var a: u8 = undefined; | ||
| 3 | a = 255; | ||
| 4 | _ = a + 1; | ||
| 5 | return 1; | ||
| 6 | } | ||
| 7 | const no_panic = std.debug.no_panic; | ||
| 8 | pub const panic = struct { | ||
| 9 | pub const call = myPanic; | ||
| 10 | pub fn integerOverflow() noreturn { | ||
| 11 | @panic("integer overflow"); | ||
| 12 | } | ||
| 13 | pub const sentinelMismatch = no_panic.sentinelMismatch; | ||
| 14 | pub const unwrapError = no_panic.unwrapError; | ||
| 15 | pub const outOfBounds = no_panic.outOfBounds; | ||
| 16 | pub const startGreaterThanEnd = no_panic.startGreaterThanEnd; | ||
| 17 | pub const inactiveUnionField = no_panic.inactiveUnionField; | ||
| 18 | pub const sliceCastLenRemainder = no_panic.sliceCastLenRemainder; | ||
| 19 | pub const reachedUnreachable = no_panic.reachedUnreachable; | ||
| 20 | pub const unwrapNull = no_panic.unwrapNull; | ||
| 21 | pub const castToNull = no_panic.castToNull; | ||
| 22 | pub const incorrectAlignment = no_panic.incorrectAlignment; | ||
| 23 | pub const invalidErrorCode = no_panic.invalidErrorCode; | ||
| 24 | pub const unexpectedErrorCode = no_panic.unexpectedErrorCode; | ||
| 25 | pub const integerOutOfBounds = no_panic.integerOutOfBounds; | ||
| 26 | pub const shlOverflow = no_panic.shlOverflow; | ||
| 27 | pub const shrOverflow = no_panic.shrOverflow; | ||
| 28 | pub const divideByZero = no_panic.divideByZero; | ||
| 29 | pub const exactDivisionRemainder = no_panic.exactDivisionRemainder; | ||
| 30 | pub const integerPartOutOfBounds = no_panic.integerPartOutOfBounds; | ||
| 31 | pub const corruptSwitch = no_panic.corruptSwitch; | ||
| 32 | pub const shiftRhsTooBig = no_panic.shiftRhsTooBig; | ||
| 33 | pub const invalidEnumValue = no_panic.invalidEnumValue; | ||
| 34 | pub const forLenMismatch = no_panic.forLenMismatch; | ||
| 35 | pub const copyLenMismatch = no_panic.copyLenMismatch; | ||
| 36 | pub const memcpyAlias = no_panic.memcpyAlias; | ||
| 37 | pub const noreturnReturned = no_panic.noreturnReturned; | ||
| 38 | pub const loadUninstantiableType = no_panic.loadUninstantiableType; | ||
| 39 | }; | ||
| 40 | fn myPanic(msg: []const u8, _: ?usize) noreturn { | ||
| 41 | var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); | ||
| 42 | stdout_writer.interface.print("panic message: {s}\n", .{msg}) catch {}; | ||
| 43 | std.process.exit(0); | ||
| 44 | } | ||
| 45 | const std = @import("std"); | ||
| 46 | const io = std.Io.Threaded.global_single_threaded.io(); | ||
test/incremental2/change_panic_handler_explicit/1/main.zig deleted-46| ... | @@ -1,46 +0,0 @@ | ||
| 1 | pub fn main() !u8 { | ||
| 2 | var a: u8 = undefined; | ||
| 3 | a = 255; | ||
| 4 | _ = a + 1; | ||
| 5 | return 1; | ||
| 6 | } | ||
| 7 | const no_panic = std.debug.no_panic; | ||
| 8 | pub const panic = struct { | ||
| 9 | pub const call = myPanic; | ||
| 10 | pub fn integerOverflow() noreturn { | ||
| 11 | @panic("integer overflow"); | ||
| 12 | } | ||
| 13 | pub const sentinelMismatch = no_panic.sentinelMismatch; | ||
| 14 | pub const unwrapError = no_panic.unwrapError; | ||
| 15 | pub const outOfBounds = no_panic.outOfBounds; | ||
| 16 | pub const startGreaterThanEnd = no_panic.startGreaterThanEnd; | ||
| 17 | pub const inactiveUnionField = no_panic.inactiveUnionField; | ||
| 18 | pub const sliceCastLenRemainder = no_panic.sliceCastLenRemainder; | ||
| 19 | pub const reachedUnreachable = no_panic.reachedUnreachable; | ||
| 20 | pub const unwrapNull = no_panic.unwrapNull; | ||
| 21 | pub const castToNull = no_panic.castToNull; | ||
| 22 | pub const incorrectAlignment = no_panic.incorrectAlignment; | ||
| 23 | pub const invalidErrorCode = no_panic.invalidErrorCode; | ||
| 24 | pub const unexpectedErrorCode = no_panic.unexpectedErrorCode; | ||
| 25 | pub const integerOutOfBounds = no_panic.integerOutOfBounds; | ||
| 26 | pub const shlOverflow = no_panic.shlOverflow; | ||
| 27 | pub const shrOverflow = no_panic.shrOverflow; | ||
| 28 | pub const divideByZero = no_panic.divideByZero; | ||
| 29 | pub const exactDivisionRemainder = no_panic.exactDivisionRemainder; | ||
| 30 | pub const integerPartOutOfBounds = no_panic.integerPartOutOfBounds; | ||
| 31 | pub const corruptSwitch = no_panic.corruptSwitch; | ||
| 32 | pub const shiftRhsTooBig = no_panic.shiftRhsTooBig; | ||
| 33 | pub const invalidEnumValue = no_panic.invalidEnumValue; | ||
| 34 | pub const forLenMismatch = no_panic.forLenMismatch; | ||
| 35 | pub const copyLenMismatch = no_panic.copyLenMismatch; | ||
| 36 | pub const memcpyAlias = no_panic.memcpyAlias; | ||
| 37 | pub const noreturnReturned = no_panic.noreturnReturned; | ||
| 38 | pub const loadUninstantiableType = no_panic.loadUninstantiableType; | ||
| 39 | }; | ||
| 40 | fn myPanic(msg: []const u8, _: ?usize) noreturn { | ||
| 41 | var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); | ||
| 42 | stdout_writer.interface.print("new panic message: {s}\n", .{msg}) catch {}; | ||
| 43 | std.process.exit(0); | ||
| 44 | } | ||
| 45 | const std = @import("std"); | ||
| 46 | const io = std.Io.Threaded.global_single_threaded.io(); | ||
test/incremental2/change_panic_handler_explicit/2/main.zig deleted-46| ... | @@ -1,46 +0,0 @@ | ||
| 1 | pub fn main() !u8 { | ||
| 2 | var a: u8 = undefined; | ||
| 3 | a = 255; | ||
| 4 | _ = a + 1; | ||
| 5 | return 1; | ||
| 6 | } | ||
| 7 | const no_panic = std.debug.no_panic; | ||
| 8 | pub const panic = struct { | ||
| 9 | pub const call = myPanicNew; | ||
| 10 | pub fn integerOverflow() noreturn { | ||
| 11 | @panic("integer overflow"); | ||
| 12 | } | ||
| 13 | pub const sentinelMismatch = no_panic.sentinelMismatch; | ||
| 14 | pub const unwrapError = no_panic.unwrapError; | ||
| 15 | pub const outOfBounds = no_panic.outOfBounds; | ||
| 16 | pub const startGreaterThanEnd = no_panic.startGreaterThanEnd; | ||
| 17 | pub const inactiveUnionField = no_panic.inactiveUnionField; | ||
| 18 | pub const sliceCastLenRemainder = no_panic.sliceCastLenRemainder; | ||
| 19 | pub const reachedUnreachable = no_panic.reachedUnreachable; | ||
| 20 | pub const unwrapNull = no_panic.unwrapNull; | ||
| 21 | pub const castToNull = no_panic.castToNull; | ||
| 22 | pub const incorrectAlignment = no_panic.incorrectAlignment; | ||
| 23 | pub const invalidErrorCode = no_panic.invalidErrorCode; | ||
| 24 | pub const unexpectedErrorCode = no_panic.unexpectedErrorCode; | ||
| 25 | pub const integerOutOfBounds = no_panic.integerOutOfBounds; | ||
| 26 | pub const shlOverflow = no_panic.shlOverflow; | ||
| 27 | pub const shrOverflow = no_panic.shrOverflow; | ||
| 28 | pub const divideByZero = no_panic.divideByZero; | ||
| 29 | pub const exactDivisionRemainder = no_panic.exactDivisionRemainder; | ||
| 30 | pub const integerPartOutOfBounds = no_panic.integerPartOutOfBounds; | ||
| 31 | pub const corruptSwitch = no_panic.corruptSwitch; | ||
| 32 | pub const shiftRhsTooBig = no_panic.shiftRhsTooBig; | ||
| 33 | pub const invalidEnumValue = no_panic.invalidEnumValue; | ||
| 34 | pub const forLenMismatch = no_panic.forLenMismatch; | ||
| 35 | pub const copyLenMismatch = no_panic.copyLenMismatch; | ||
| 36 | pub const memcpyAlias = no_panic.memcpyAlias; | ||
| 37 | pub const noreturnReturned = no_panic.noreturnReturned; | ||
| 38 | pub const loadUninstantiableType = no_panic.loadUninstantiableType; | ||
| 39 | }; | ||
| 40 | fn myPanicNew(msg: []const u8, _: ?usize) noreturn { | ||
| 41 | var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); | ||
| 42 | stdout_writer.interface.print("third panic message: {s}\n", .{msg}) catch {}; | ||
| 43 | std.process.exit(0); | ||
| 44 | } | ||
| 45 | const std = @import("std"); | ||
| 46 | const io = std.Io.Threaded.global_single_threaded.io(); | ||
test/incremental2/change_panic_handler_explicit/manifest deleted-23| ... | @@ -1,23 +0,0 @@ | ||
| 1 | #exe { | ||
| 2 | -Mroot=main.zig | ||
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig 0/main.zig | ||
| 6 | #update | ||
| 7 | #check stdout { | ||
| 8 | panic message: integer overflow | ||
| 9 | #} | ||
| 10 | |||
| 11 | #write main.zig 1/main.zig | ||
| 12 | #update { | ||
| 13 | change the panic handler body#} | ||
| 14 | #check stdout { | ||
| 15 | new panic message: integer overflow | ||
| 16 | #} | ||
| 17 | |||
| 18 | #write main.zig 2/main.zig | ||
| 19 | #update { | ||
| 20 | change the panic handler function value#} | ||
| 21 | #check stdout { | ||
| 22 | third panic message: integer overflow | ||
| 23 | #} | ||
test/incremental2/hello deleted-28| ... | @@ -1,28 +0,0 @@ | ||
| 1 | #exe { | ||
| 2 | -Mroot=main.zig | ||
| 3 | #} | ||
| 4 | |||
| 5 | #write main.zig { | ||
| 6 | const std = @import("std"); | ||
| 7 | const io = std.Io.Threaded.global_single_threaded.io(); | ||
| 8 | pub fn main() !void { | ||
| 9 | try std.Io.File.stdout().writeStreamingAll(io, "good morning\n"); | ||
| 10 | } | ||
| 11 | #} | ||
| 12 | #update | ||
| 13 | #check stdout { | ||
| 14 | good morning | ||
| 15 | #} | ||
| 16 | |||
| 17 | #write main.zig { | ||
| 18 | const std = @import("std"); | ||
| 19 | const io = std.Io.Threaded.global_single_threaded.io(); | ||
| 20 | pub fn main() !void { | ||
| 21 | try std.Io.File.stdout().writeStreamingAll(io, "おはようございます\n"); | ||
| 22 | } | ||
| 23 | #} | ||
| 24 | #update { | ||
| 25 | change the string#} | ||
| 26 | #check stdout { | ||
| 27 | おはようございます | ||
| 28 | #} | ||
test/src/runner.zig+14-5| ... | @@ -471,7 +471,7 @@ fn runTest( | ... | @@ -471,7 +471,7 @@ fn runTest( |
| 471 | continue; | 471 | continue; |
| 472 | } | 472 | } |
| 473 | const cmd = std.meta.stringToEnum( | 473 | const cmd = std.meta.stringToEnum( |
| 474 | enum { skip, exe, lib, obj, write, delete, update, check }, | 474 | enum { todo, skip, exe, lib, obj, write, delete, update, check }, |
| 475 | cmd_str, | 475 | cmd_str, |
| 476 | ) orelse return error.UnknownCommand; | 476 | ) orelse return error.UnknownCommand; |
| 477 | var maybe_arg = line_it.next(); | 477 | var maybe_arg = line_it.next(); |
| ... | @@ -525,6 +525,7 @@ fn runTest( | ... | @@ -525,6 +525,7 @@ fn runTest( |
| 525 | }; | 525 | }; |
| 526 | defer cmd_prog_node.end(); | 526 | defer cmd_prog_node.end(); |
| 527 | cmd: switch (cmd) { | 527 | cmd: switch (cmd) { |
| 528 | .todo => _ = try contents_r.discardRemaining(), | ||
| 528 | .skip => if (!allow_skip) | 529 | .skip => if (!allow_skip) |
| 529 | return error.NonInitialSkipCommand // #skip must appear first | 530 | return error.NonInitialSkipCommand // #skip must appear first |
| 530 | else if (std.mem.eql(u8, target_string, maybe_arg orelse return error.MissingArg)) | 531 | else if (std.mem.eql(u8, target_string, maybe_arg orelse return error.MissingArg)) |
| ... | @@ -646,12 +647,12 @@ fn runTest( | ... | @@ -646,12 +647,12 @@ fn runTest( |
| 646 | update_num += 1; | 647 | update_num += 1; |
| 647 | }, | 648 | }, |
| 648 | .check => { | 649 | .check => { |
| 649 | const expected = try contents_r.allocRemaining(gpa, .unlimited); | ||
| 650 | defer gpa.free(expected); | ||
| 651 | const check = std.meta.stringToEnum( | 650 | const check = std.meta.stringToEnum( |
| 652 | enum { errors, stdout, exit, lldb }, | 651 | enum { errors, stdout, exit, lldb }, |
| 653 | maybe_arg orelse return error.MissingCheckArg, | 652 | maybe_arg orelse return error.MissingCheckArg, |
| 654 | ) orelse return error.UnknownCheck; | 653 | ) orelse return error.UnknownCheck; |
| 654 | const expected = try contents_r.allocRemaining(gpa, .unlimited); | ||
| 655 | defer gpa.free(expected); | ||
| 655 | 656 | ||
| 656 | const comp = &(compiler orelse return error.MissingCompiler); | 657 | const comp = &(compiler orelse return error.MissingCompiler); |
| 657 | if (comp.state != .update) return error.MissingUpdate; | 658 | if (comp.state != .update) return error.MissingUpdate; |
| ... | @@ -753,7 +754,9 @@ fn runTest( | ... | @@ -753,7 +754,9 @@ fn runTest( |
| 753 | var error_aw: std.Io.Writer.Allocating = .init(gpa); | 754 | var error_aw: std.Io.Writer.Allocating = .init(gpa); |
| 754 | defer error_aw.deinit(); | 755 | defer error_aw.deinit(); |
| 755 | try error_bundle.renderToWriter(.{ | 756 | try error_bundle.renderToWriter(.{ |
| 757 | .include_reference_trace = false, | ||
| 756 | .include_source_line = false, | 758 | .include_source_line = false, |
| 759 | .include_log_text = true, | ||
| 757 | }, &error_aw.writer); | 760 | }, &error_aw.writer); |
| 758 | try std.testing.expectEqualStrings(expected, error_aw.written()); | 761 | try std.testing.expectEqualStrings(expected, error_aw.written()); |
| 759 | }, | 762 | }, |
| ... | @@ -783,12 +786,18 @@ fn runTest( | ... | @@ -783,12 +786,18 @@ fn runTest( |
| 783 | }, | 786 | }, |
| 784 | } | 787 | } |
| 785 | std.debug.assert(try contents_r.discardRemaining() == 0); | 788 | std.debug.assert(try contents_r.discardRemaining() == 0); |
| 786 | if (cmd != .skip) allow_skip = false; | 789 | switch (cmd) { |
| 790 | .todo, .skip => {}, | ||
| 791 | else => allow_skip = false, | ||
| 792 | } | ||
| 787 | } else |err| switch (err) { | 793 | } else |err| switch (err) { |
| 788 | else => |e| return e, | 794 | else => |e| return e, |
| 789 | error.EndOfStream => if (skip_delimiter) return error.MissingDelimiter, | 795 | error.EndOfStream => if (skip_delimiter) return error.MissingDelimiter, |
| 790 | } | 796 | } |
| 791 | if (compiler) |*comp| try comp.exit(io); | 797 | if (compiler) |*comp| { |
| 798 | if (comp.state != .idle) return error.MissingCheck; | ||
| 799 | try comp.exit(io); | ||
| 800 | } | ||
| 792 | } | 801 | } |
| 793 | const DelimitedReader = struct { | 802 | const DelimitedReader = struct { |
| 794 | const Io = std.Io; | 803 | const Io = std.Io; |
test/tests.zig+3-96| ... | @@ -3343,109 +3343,16 @@ const IncrementalTestOptions = struct { | ... | @@ -3343,109 +3343,16 @@ const IncrementalTestOptions = struct { |
| 3343 | }; | 3343 | }; |
| 3344 | 3344 | ||
| 3345 | pub fn addIncrementalTests( | 3345 | pub fn addIncrementalTests( |
| 3346 | b: *std.Build, | ||
| 3347 | test_step: *Step, | ||
| 3348 | options: IncrementalTestOptions, | ||
| 3349 | ) !void { | ||
| 3350 | const io = b.graph.io; | ||
| 3351 | |||
| 3352 | const incr_check = b.addExecutable(.{ | ||
| 3353 | .name = "incr-check", | ||
| 3354 | .root_module = b.createModule(.{ | ||
| 3355 | .root_source_file = b.path("tools/incr-check.zig"), | ||
| 3356 | .target = b.graph.host, | ||
| 3357 | .optimize = .debug, | ||
| 3358 | }), | ||
| 3359 | }); | ||
| 3360 | |||
| 3361 | b.dependOnDirectoryContents(b.path("test/incremental")); | ||
| 3362 | |||
| 3363 | var dir = try b.root.openDir(io, "test/incremental", .{ .iterate = true }); | ||
| 3364 | defer dir.close(io); | ||
| 3365 | |||
| 3366 | var it = try dir.walk(b.graph.arena); | ||
| 3367 | while (try it.next(io)) |entry| { | ||
| 3368 | if (isEditorFileName(entry.basename)) continue; | ||
| 3369 | |||
| 3370 | for (options.test_filters) |test_filter| { | ||
| 3371 | if (std.mem.find(u8, entry.path, test_filter)) |_| break; | ||
| 3372 | } else if (options.test_filters.len > 0) continue; | ||
| 3373 | |||
| 3374 | switch (entry.kind) { | ||
| 3375 | .file => {}, | ||
| 3376 | .directory => { | ||
| 3377 | b.dependOnDirectoryContents(b.path(b.pathJoin(&.{ "test", "incremental", entry.path }))); | ||
| 3378 | }, | ||
| 3379 | else => continue, | ||
| 3380 | } | ||
| 3381 | b.dependOnFileContents(b.path(b.pathJoin(&.{ "test", "incremental", entry.path }))); | ||
| 3382 | |||
| 3383 | for (incremental_targets) |test_target| { | ||
| 3384 | const resolved_target = b.resolveTargetQuery(test_target.target); | ||
| 3385 | |||
| 3386 | if (options.skip_non_native and !isNative(&resolved_target, &b.graph.host.result)) | ||
| 3387 | continue; | ||
| 3388 | |||
| 3389 | const target = &resolved_target.result; | ||
| 3390 | |||
| 3391 | if (options.skip_wasm and target.cpu.arch.isWasm()) continue; | ||
| 3392 | |||
| 3393 | if (options.skip_freebsd and target.os.tag == .freebsd) continue; | ||
| 3394 | if (options.skip_netbsd and target.os.tag == .netbsd) continue; | ||
| 3395 | if (options.skip_openbsd and target.os.tag == .openbsd) continue; | ||
| 3396 | if (options.skip_windows and target.os.tag == .windows) continue; | ||
| 3397 | if (options.skip_darwin and target.os.tag.isDarwin()) continue; | ||
| 3398 | if (options.skip_linux and target.os.tag == .linux) continue; | ||
| 3399 | |||
| 3400 | if (options.skip_llvm and test_target.backend == .llvm) continue; | ||
| 3401 | |||
| 3402 | const target_str = b.fmt("{s}-{t}", .{ | ||
| 3403 | resolved_target.query.zigTriple(b.allocator) catch @panic("OOM"), | ||
| 3404 | test_target.backend, | ||
| 3405 | }); | ||
| 3406 | |||
| 3407 | if (options.test_target_filters.len > 0) { | ||
| 3408 | for (options.test_target_filters) |filter| { | ||
| 3409 | if (std.mem.find(u8, target_str, filter) != null) break; | ||
| 3410 | } else continue; | ||
| 3411 | } | ||
| 3412 | |||
| 3413 | const run = b.addRunArtifact(incr_check); | ||
| 3414 | run.setName(b.fmt("incr-check {s} '{s}'", .{ target_str, entry.basename })); | ||
| 3415 | |||
| 3416 | run.addArg(b.graph.zig_exe); | ||
| 3417 | run.addFileArg(b.path("test/incremental/").path(b, entry.path)); | ||
| 3418 | |||
| 3419 | run.addArg("--zig-lib-dir"); | ||
| 3420 | run.addDirectoryArg(.zig_lib); | ||
| 3421 | |||
| 3422 | run.addArgs(&.{ "--target", target_str }); | ||
| 3423 | |||
| 3424 | run.addArg("--quiet"); // don't fill stderr telling us about skipped tests etc | ||
| 3425 | |||
| 3426 | run.addThirdPartyEnabledArgDarling(.{ .enabled = "-fdarling" }); | ||
| 3427 | run.addThirdPartyEnabledArgQemu(.{ .enabled = "-fqemu" }); | ||
| 3428 | run.addThirdPartyEnabledArgRosetta(.{ .enabled = "-frosetta" }); | ||
| 3429 | run.addThirdPartyEnabledArgWasmtime(.{ .enabled = "-fwasmtime" }); | ||
| 3430 | run.addThirdPartyEnabledArgWine(.{ .enabled = "-fwine" }); | ||
| 3431 | |||
| 3432 | run.addCheck(.{ .expect_term = .{ .exited = 0 } }); | ||
| 3433 | test_step.dependOn(&run.step); | ||
| 3434 | } | ||
| 3435 | } | ||
| 3436 | } | ||
| 3437 | |||
| 3438 | pub fn addNewIncrementalTests( | ||
| 3439 | b: *std.Build, | 3346 | b: *std.Build, |
| 3440 | runner: *std.Build.Step.Compile, | 3347 | runner: *std.Build.Step.Compile, |
| 3441 | options: IncrementalTestOptions, | 3348 | options: IncrementalTestOptions, |
| 3442 | ) !*Step { | 3349 | ) !*Step { |
| 3443 | const tests_step = b.step("test-new-incremental", "Run the new incremental compilation test cases"); | 3350 | const tests_step = b.step("test-incremental", "Run the new incremental compilation test cases"); |
| 3444 | 3351 | ||
| 3445 | const tests_path = b.path("test/incremental2"); | 3352 | const tests_path = b.path("test/incremental"); |
| 3446 | b.dependOnDirectoryContents(tests_path); | 3353 | b.dependOnDirectoryContents(tests_path); |
| 3447 | 3354 | ||
| 3448 | var tests_dir = try b.root.openDir(b.graph.io, "test/incremental2", .{ .iterate = true }); | 3355 | var tests_dir = try b.root.openDir(b.graph.io, "test/incremental", .{ .iterate = true }); |
| 3449 | defer tests_dir.close(b.graph.io); | 3356 | defer tests_dir.close(b.graph.io); |
| 3450 | var test_it = tests_dir.iterate(); | 3357 | var test_it = tests_dir.iterate(); |
| 3451 | while (try test_it.next(b.graph.io)) |@"test"| { | 3358 | while (try test_it.next(b.graph.io)) |@"test"| { |
tools/incr-check.zig deleted-1032| ... | @@ -1,1032 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const Io = std.Io; | ||
| 3 | const Dir = std.Io.Dir; | ||
| 4 | const Allocator = std.mem.Allocator; | ||
| 5 | const Cache = std.Build.Cache; | ||
| 6 | |||
| 7 | const usage = | ||
| 8 | \\Usage: incr-check <zig binary path> <input file> [options] | ||
| 9 | \\Options: | ||
| 10 | \\ --target triple-backend | ||
| 11 | \\ --quiet | ||
| 12 | \\ --zig-lib-dir /path/to/zig/lib | ||
| 13 | \\ --zig-cc-binary /path/to/zig | ||
| 14 | \\ -fqemu | ||
| 15 | \\ -fwine | ||
| 16 | \\ -fwasmtime | ||
| 17 | \\Debug Options: | ||
| 18 | \\ --preserve-tmp | ||
| 19 | \\ --debug-log foo | ||
| 20 | \\ --debug-link-snapshot | ||
| 21 | ; | ||
| 22 | |||
| 23 | pub const std_options: std.Options = .{ | ||
| 24 | .logFn = logImpl, | ||
| 25 | }; | ||
| 26 | var log_cur_update: ?*const Case.Update = null; | ||
| 27 | fn logImpl( | ||
| 28 | comptime level: std.log.Level, | ||
| 29 | comptime scope: @EnumLiteral(), | ||
| 30 | comptime format: []const u8, | ||
| 31 | args: anytype, | ||
| 32 | ) void { | ||
| 33 | const update = log_cur_update orelse { | ||
| 34 | return std.log.defaultLog(level, scope, format, args); | ||
| 35 | }; | ||
| 36 | std.log.defaultLog( | ||
| 37 | level, | ||
| 38 | scope, | ||
| 39 | "['{s}'] " ++ format, | ||
| 40 | .{update.name} ++ args, | ||
| 41 | ); | ||
| 42 | } | ||
| 43 | |||
| 44 | pub fn main(init: std.process.Init) !void { | ||
| 45 | const gpa = init.gpa; | ||
| 46 | const arena = init.arena.allocator(); | ||
| 47 | const io = init.io; | ||
| 48 | const environ_map = init.environ_map; | ||
| 49 | const cwd_path = try std.process.currentPathAlloc(io, arena); | ||
| 50 | |||
| 51 | var opt_zig_exe: ?[]const u8 = null; | ||
| 52 | var opt_input_file_name: ?[]const u8 = null; | ||
| 53 | var opt_lib_dir: ?[]const u8 = null; | ||
| 54 | var opt_cc_zig: ?[]const u8 = null; | ||
| 55 | var opt_target: ?struct { std.Target.Query, Backend } = null; | ||
| 56 | var preserve_tmp = false; | ||
| 57 | var enable_qemu: bool = false; | ||
| 58 | var enable_wine: bool = false; | ||
| 59 | var enable_wasmtime: bool = false; | ||
| 60 | var enable_darling: bool = false; | ||
| 61 | var quiet: bool = false; | ||
| 62 | |||
| 63 | var debug_log_args: std.ArrayList([]const u8) = .empty; | ||
| 64 | var debug_link_snapshot = false; | ||
| 65 | |||
| 66 | var arg_it = try init.minimal.args.iterateAllocator(arena); | ||
| 67 | _ = arg_it.skip(); | ||
| 68 | while (arg_it.next()) |arg| { | ||
| 69 | if (arg.len > 0 and arg[0] == '-') { | ||
| 70 | if (std.mem.eql(u8, arg, "--zig-lib-dir")) { | ||
| 71 | opt_lib_dir = arg_it.next() orelse badUsage("expected arg after --zig-lib-dir", .{}); | ||
| 72 | } else if (std.mem.eql(u8, arg, "--target")) { | ||
| 73 | const str = arg_it.next() orelse badUsage("expected arg after --zig-cc-binary", .{}); | ||
| 74 | opt_target = parseTargetQueryAndBackend(str, ""); | ||
| 75 | } else if (std.mem.eql(u8, arg, "--quiet")) { | ||
| 76 | quiet = true; | ||
| 77 | } else if (std.mem.eql(u8, arg, "--debug-log")) { | ||
| 78 | try debug_log_args.append( | ||
| 79 | arena, | ||
| 80 | arg_it.next() orelse badUsage("expected arg after --debug-log", .{}), | ||
| 81 | ); | ||
| 82 | } else if (std.mem.eql(u8, arg, "--debug-link-snapshot")) { | ||
| 83 | debug_link_snapshot = true; | ||
| 84 | } else if (std.mem.eql(u8, arg, "--preserve-tmp")) { | ||
| 85 | preserve_tmp = true; | ||
| 86 | } else if (std.mem.eql(u8, arg, "-fqemu")) { | ||
| 87 | enable_qemu = true; | ||
| 88 | } else if (std.mem.eql(u8, arg, "-fwine")) { | ||
| 89 | enable_wine = true; | ||
| 90 | } else if (std.mem.eql(u8, arg, "-fwasmtime")) { | ||
| 91 | enable_wasmtime = true; | ||
| 92 | } else if (std.mem.eql(u8, arg, "-fdarling")) { | ||
| 93 | enable_darling = true; | ||
| 94 | } else if (std.mem.eql(u8, arg, "--zig-cc-binary")) { | ||
| 95 | opt_cc_zig = arg_it.next() orelse badUsage("expected arg after --zig-cc-binary", .{}); | ||
| 96 | } else { | ||
| 97 | badUsage("unknown option '{s}'", .{arg}); | ||
| 98 | } | ||
| 99 | continue; | ||
| 100 | } | ||
| 101 | if (opt_zig_exe == null) { | ||
| 102 | opt_zig_exe = arg; | ||
| 103 | } else if (opt_input_file_name == null) { | ||
| 104 | opt_input_file_name = arg; | ||
| 105 | } else { | ||
| 106 | badUsage("unknown argument '{s}'\n{s}", .{ arg, usage }); | ||
| 107 | } | ||
| 108 | } | ||
| 109 | const zig_exe = opt_zig_exe orelse badUsage("missing path to zig", .{}); | ||
| 110 | const input_file_name = opt_input_file_name orelse badUsage("missing input file", .{}); | ||
| 111 | const target_query, const backend = opt_target orelse badUsage("missing required option '--target'", .{}); | ||
| 112 | |||
| 113 | if (backend == .cbe and opt_lib_dir == null) { | ||
| 114 | std.process.fatal("'--zig-lib-dir' required when using backend 'cbe'", .{}); | ||
| 115 | } | ||
| 116 | |||
| 117 | const input_file_bytes = try Dir.cwd().readFileAlloc(io, input_file_name, arena, .limited(std.math.maxInt(u32))); | ||
| 118 | const case: Case = try .parse(arena, input_file_bytes); | ||
| 119 | |||
| 120 | for (case.skip_targets) |skip| { | ||
| 121 | if (target_query.eql(skip.query) and backend == skip.backend) { | ||
| 122 | if (!quiet) std.log.warn("skipping test because of a 'skip_target' match", .{}); | ||
| 123 | return; | ||
| 124 | } | ||
| 125 | } | ||
| 126 | |||
| 127 | const target = try std.zig.system.resolveTargetQuery(io, target_query); | ||
| 128 | |||
| 129 | const prog_node = std.Progress.start(io, .{}); | ||
| 130 | defer prog_node.end(); | ||
| 131 | |||
| 132 | const rand_int = rand64(io); | ||
| 133 | const tmp_dir_path = "tmp_" ++ std.fmt.hex(rand_int); | ||
| 134 | var tmp_dir = try Dir.cwd().createDirPathOpen(io, tmp_dir_path, .{}); | ||
| 135 | defer { | ||
| 136 | tmp_dir.close(io); | ||
| 137 | if (!preserve_tmp) { | ||
| 138 | Dir.cwd().deleteTree(io, tmp_dir_path) catch |err| { | ||
| 139 | std.log.warn("failed to delete tree '{s}': {t}", .{ tmp_dir_path, err }); | ||
| 140 | }; | ||
| 141 | } | ||
| 142 | } | ||
| 143 | |||
| 144 | // Convert paths to be relative to the cwd of the subprocess. | ||
| 145 | const resolved_zig_exe = try Dir.path.relative(arena, cwd_path, environ_map, tmp_dir_path, zig_exe); | ||
| 146 | const opt_resolved_lib_dir = if (opt_lib_dir) |lib_dir| | ||
| 147 | try Dir.path.relative(arena, cwd_path, environ_map, tmp_dir_path, lib_dir) | ||
| 148 | else | ||
| 149 | null; | ||
| 150 | |||
| 151 | const host = try std.zig.system.resolveTargetQuery(io, .{}); | ||
| 152 | |||
| 153 | var child_args: std.ArrayList([]const u8) = .empty; | ||
| 154 | try child_args.appendSlice(arena, &.{ | ||
| 155 | resolved_zig_exe, "build-exe", | ||
| 156 | "-fincremental", "-fno-ubsan-rt", | ||
| 157 | "-target", try target_query.zigTriple(arena), | ||
| 158 | "--cache-dir", ".local-cache", | ||
| 159 | "--global-cache-dir", ".global-cache", | ||
| 160 | }); | ||
| 161 | |||
| 162 | if (opt_resolved_lib_dir) |resolved_lib_dir| { | ||
| 163 | try child_args.appendSlice(arena, &.{ "--zig-lib-dir", resolved_lib_dir }); | ||
| 164 | } | ||
| 165 | switch (backend) { | ||
| 166 | .sema => try child_args.append(arena, "-fno-emit-bin"), | ||
| 167 | .selfhosted => try child_args.appendSlice(arena, &.{ "-fno-llvm", "-fno-lld" }), | ||
| 168 | .llvm => try child_args.appendSlice(arena, &.{ "-fllvm", "-flld" }), | ||
| 169 | .cbe => try child_args.appendSlice(arena, &.{ "-ofmt=c", "-lc" }), | ||
| 170 | } | ||
| 171 | for (debug_log_args.items) |arg| { | ||
| 172 | try child_args.appendSlice(arena, &.{ "--debug-log", arg }); | ||
| 173 | } | ||
| 174 | if (debug_link_snapshot) { | ||
| 175 | try child_args.append(arena, "--debug-link-snapshot"); | ||
| 176 | } | ||
| 177 | for (case.modules) |mod| { | ||
| 178 | try child_args.appendSlice(arena, &.{ "--dep", mod.name }); | ||
| 179 | } | ||
| 180 | try child_args.append(arena, try std.fmt.allocPrint(arena, "-Mroot={s}", .{case.root_source_file})); | ||
| 181 | for (case.modules) |mod| { | ||
| 182 | try child_args.append(arena, try std.fmt.allocPrint(arena, "-M{s}={s}", .{ mod.name, mod.file })); | ||
| 183 | } | ||
| 184 | try child_args.append(arena, "--listen=-"); | ||
| 185 | |||
| 186 | const zig_prog_node = prog_node.start("zig", 0); | ||
| 187 | defer zig_prog_node.end(); | ||
| 188 | |||
| 189 | var cc_child_args: std.ArrayList([]const u8) = .empty; | ||
| 190 | if (backend == .cbe) { | ||
| 191 | const resolved_cc_zig_exe = if (opt_cc_zig) |cc_zig_exe| | ||
| 192 | try Dir.path.relative(arena, cwd_path, environ_map, tmp_dir_path, cc_zig_exe) | ||
| 193 | else | ||
| 194 | resolved_zig_exe; | ||
| 195 | |||
| 196 | try cc_child_args.appendSlice(arena, &.{ | ||
| 197 | resolved_cc_zig_exe, "build-exe", | ||
| 198 | "-target", try target_query.zigTriple(arena), | ||
| 199 | "--cache-dir", ".local-cache", | ||
| 200 | "--global-cache-dir", ".global-cache", | ||
| 201 | "-I", opt_resolved_lib_dir.?, // verified earlier | ||
| 202 | "-lc", | ||
| 203 | }); | ||
| 204 | } | ||
| 205 | |||
| 206 | const allow_compiler_stderr = debug_log_args.items.len != 0; | ||
| 207 | |||
| 208 | if (allow_compiler_stderr) { | ||
| 209 | const cmd: std.zig.SubprocessCommand = .{ | ||
| 210 | .argv = child_args.items, | ||
| 211 | .cwd = tmp_dir_path, | ||
| 212 | }; | ||
| 213 | std.log.scoped(.spawn).info("{f}", .{cmd}); | ||
| 214 | } | ||
| 215 | |||
| 216 | var child = try std.process.spawn(io, .{ | ||
| 217 | .argv = child_args.items, | ||
| 218 | .stdin = .pipe, | ||
| 219 | .stdout = .pipe, | ||
| 220 | .stderr = .pipe, | ||
| 221 | .progress_node = zig_prog_node, | ||
| 222 | .cwd = .{ .path = tmp_dir_path }, | ||
| 223 | }); | ||
| 224 | defer child.kill(io); | ||
| 225 | |||
| 226 | const updates_prog_node = prog_node.start("updates", case.updates.len); | ||
| 227 | defer updates_prog_node.end(); | ||
| 228 | |||
| 229 | var eval: Eval = .{ | ||
| 230 | .arena = arena, | ||
| 231 | .io = io, | ||
| 232 | .case = case, | ||
| 233 | .host = host, | ||
| 234 | .target = target, | ||
| 235 | .backend = backend, | ||
| 236 | .tmp_dir = tmp_dir, | ||
| 237 | .tmp_dir_path = tmp_dir_path, | ||
| 238 | .child = &child, | ||
| 239 | .allow_compiler_stderr = allow_compiler_stderr, | ||
| 240 | .quiet = quiet, | ||
| 241 | .preserve_tmp_on_fatal = preserve_tmp, | ||
| 242 | .cc_child_args = &cc_child_args, | ||
| 243 | .enable_qemu = enable_qemu, | ||
| 244 | .enable_wine = enable_wine, | ||
| 245 | .enable_wasmtime = enable_wasmtime, | ||
| 246 | .enable_darling = enable_darling, | ||
| 247 | }; | ||
| 248 | |||
| 249 | var multi_reader_buffer: Io.File.MultiReader.Buffer(2) = undefined; | ||
| 250 | var multi_reader: Io.File.MultiReader = undefined; | ||
| 251 | multi_reader.init(gpa, io, multi_reader_buffer.toStreams(), &.{ child.stdout.?, child.stderr.? }); | ||
| 252 | defer multi_reader.deinit(); | ||
| 253 | |||
| 254 | var update_mtime = Io.Clock.real.now(io); | ||
| 255 | for (case.updates) |update| { | ||
| 256 | var update_prog_node = updates_prog_node.start(update.name, 0); | ||
| 257 | defer update_prog_node.end(); | ||
| 258 | |||
| 259 | if (debug_log_args.items.len != 0) { | ||
| 260 | // Print a line separating the debug logs from the compiler in the stderr output. | ||
| 261 | std.log.scoped(.status).info("update: '{s}'", .{update.name}); | ||
| 262 | } | ||
| 263 | |||
| 264 | log_cur_update = &update; | ||
| 265 | defer log_cur_update = null; | ||
| 266 | |||
| 267 | eval.write(update, update_mtime); | ||
| 268 | update_mtime = update_mtime.addDuration(.fromSeconds(5)); | ||
| 269 | try eval.requestUpdate(); | ||
| 270 | try eval.check(&multi_reader, update, update_prog_node); | ||
| 271 | } | ||
| 272 | |||
| 273 | try eval.end(&multi_reader); | ||
| 274 | |||
| 275 | waitChild(&child, &eval); | ||
| 276 | } | ||
| 277 | |||
| 278 | const Eval = struct { | ||
| 279 | arena: Allocator, | ||
| 280 | io: Io, | ||
| 281 | case: Case, | ||
| 282 | host: std.Target, | ||
| 283 | target: std.Target, | ||
| 284 | backend: Backend, | ||
| 285 | tmp_dir: Dir, | ||
| 286 | tmp_dir_path: []const u8, | ||
| 287 | child: *std.process.Child, | ||
| 288 | allow_compiler_stderr: bool, | ||
| 289 | quiet: bool, | ||
| 290 | preserve_tmp_on_fatal: bool, | ||
| 291 | /// When `backend == .cbe`, this contains the first few arguments to `zig cc` to build the generated binary. | ||
| 292 | /// The arguments `out.c in.c` must be appended before spawning the subprocess. | ||
| 293 | cc_child_args: *std.ArrayList([]const u8), | ||
| 294 | |||
| 295 | enable_qemu: bool, | ||
| 296 | enable_wine: bool, | ||
| 297 | enable_wasmtime: bool, | ||
| 298 | enable_darling: bool, | ||
| 299 | |||
| 300 | /// Currently this function assumes the previous updates have already been written. | ||
| 301 | fn write(eval: *Eval, update: Case.Update, mtime: Io.Timestamp) void { | ||
| 302 | const io = eval.io; | ||
| 303 | for (update.changes) |full_contents| { | ||
| 304 | var update_file = eval.tmp_dir.createFile(io, full_contents.name, .{}) catch |err| { | ||
| 305 | eval.fatal("failed to create update '{s}': {t}", .{ full_contents.name, err }); | ||
| 306 | }; | ||
| 307 | defer update_file.close(io); | ||
| 308 | update_file.writeStreamingAll(io, full_contents.bytes) catch |err| { | ||
| 309 | eval.fatal("failed to write update '{s}': {t}", .{ full_contents.name, err }); | ||
| 310 | }; | ||
| 311 | update_file.setTimestamps(io, .{ .modify_timestamp = .{ .new = mtime } }) catch |err| { | ||
| 312 | eval.fatal("failed to set mtime for '{s}': {t}", .{ full_contents.name, err }); | ||
| 313 | }; | ||
| 314 | } | ||
| 315 | for (update.deletes) |doomed_name| { | ||
| 316 | eval.tmp_dir.deleteFile(io, doomed_name) catch |err| { | ||
| 317 | eval.fatal("failed to delete '{s}': {t}", .{ doomed_name, err }); | ||
| 318 | }; | ||
| 319 | } | ||
| 320 | } | ||
| 321 | |||
| 322 | fn check(eval: *Eval, mr: *Io.File.MultiReader, update: Case.Update, prog_node: std.Progress.Node) !void { | ||
| 323 | const arena = eval.arena; | ||
| 324 | const stdout = mr.reader(0); | ||
| 325 | const stderr = mr.reader(1); | ||
| 326 | |||
| 327 | var client: std.zig.Client = .{ | ||
| 328 | .in = stdout, | ||
| 329 | .out = undefined, | ||
| 330 | }; | ||
| 331 | |||
| 332 | while (true) { | ||
| 333 | const header = client.receiveMessageWithMultiReader(mr, .none) catch |err| switch (err) { | ||
| 334 | error.Timeout => unreachable, | ||
| 335 | error.EndOfStream => break, | ||
| 336 | else => |e| return e, | ||
| 337 | }; | ||
| 338 | const body = client.in.take(header.bytes_len) catch unreachable; | ||
| 339 | |||
| 340 | switch (header.tag) { | ||
| 341 | .error_bundle => { | ||
| 342 | const result_error_bundle = try std.zig.Server.allocErrorBundle(arena, body); | ||
| 343 | if (stderr.bufferedLen() > 0) { | ||
| 344 | if (eval.allow_compiler_stderr) { | ||
| 345 | std.log.info("error_bundle stderr:\n{s}", .{stderr.buffered()}); | ||
| 346 | } else { | ||
| 347 | eval.fatal("error_bundle unexpected stderr:\n{s}", .{stderr.buffered()}); | ||
| 348 | } | ||
| 349 | stderr.tossBuffered(); | ||
| 350 | } | ||
| 351 | if (result_error_bundle.errorMessageCount() != 0) { | ||
| 352 | try eval.checkErrorOutcome(update, result_error_bundle); | ||
| 353 | } | ||
| 354 | // This message indicates the end of the update. | ||
| 355 | return; | ||
| 356 | }, | ||
| 357 | .emit_digest => { | ||
| 358 | var r: std.Io.Reader = .fixed(body); | ||
| 359 | _ = r.takeStruct(std.zig.Server.Message.EmitDigest, .little) catch unreachable; | ||
| 360 | |||
| 361 | if (stderr.bufferedLen() > 0) { | ||
| 362 | if (eval.allow_compiler_stderr) { | ||
| 363 | std.log.info("emit_digest stderr:\n{s}", .{stderr.buffered()}); | ||
| 364 | } else { | ||
| 365 | eval.fatal("emit_digest unexpected stderr:\n{s}", .{stderr.buffered()}); | ||
| 366 | } | ||
| 367 | stderr.tossBuffered(); | ||
| 368 | } | ||
| 369 | if (eval.backend == .sema) { | ||
| 370 | try eval.checkSuccessOutcome(update, null, prog_node); | ||
| 371 | continue; | ||
| 372 | } | ||
| 373 | |||
| 374 | const digest = r.takeArray(Cache.bin_digest_len) catch unreachable; | ||
| 375 | const result_dir = ".local-cache" ++ Dir.path.sep_str ++ "o" ++ Dir.path.sep_str ++ Cache.binToHex(digest.*); | ||
| 376 | |||
| 377 | const bin_name = try std.zig.EmitArtifact.bin.cacheName(arena, .{ | ||
| 378 | .root_name = "root", // corresponds to the module name "root" | ||
| 379 | .cpu_arch = eval.target.cpu.arch, | ||
| 380 | .os_tag = eval.target.os.tag, | ||
| 381 | .ofmt = eval.target.ofmt, | ||
| 382 | .abi = eval.target.abi, | ||
| 383 | .output_mode = .Exe, | ||
| 384 | }); | ||
| 385 | const bin_path = try Dir.path.join(arena, &.{ result_dir, bin_name }); | ||
| 386 | |||
| 387 | try eval.checkSuccessOutcome(update, bin_path, prog_node); | ||
| 388 | }, | ||
| 389 | else => { | ||
| 390 | // Ignore other messages. | ||
| 391 | }, | ||
| 392 | } | ||
| 393 | } | ||
| 394 | |||
| 395 | const buffered_stderr = stderr.buffered(); | ||
| 396 | if (buffered_stderr.len > 0) { | ||
| 397 | if (eval.allow_compiler_stderr) { | ||
| 398 | std.log.info("stderr:\n{s}", .{buffered_stderr}); | ||
| 399 | } else { | ||
| 400 | eval.fatal("unexpected stderr:\n{s}", .{buffered_stderr}); | ||
| 401 | } | ||
| 402 | } | ||
| 403 | |||
| 404 | waitChild(eval.child, eval); | ||
| 405 | eval.fatal("compiler failed to send terminating error_bundle", .{}); | ||
| 406 | } | ||
| 407 | |||
| 408 | fn checkErrorOutcome(eval: *Eval, update: Case.Update, error_bundle: std.zig.ErrorBundle) !void { | ||
| 409 | const io = eval.io; | ||
| 410 | const expected = switch (update.outcome) { | ||
| 411 | .unknown => return, | ||
| 412 | .compile_errors => |ce| ce, | ||
| 413 | .stdout, .exit_code => { | ||
| 414 | try error_bundle.renderToStderr(io, .{}, .auto); | ||
| 415 | eval.fatal("unexpected compile errors", .{}); | ||
| 416 | }, | ||
| 417 | }; | ||
| 418 | |||
| 419 | var expected_idx: usize = 0; | ||
| 420 | |||
| 421 | for (error_bundle.getMessages()) |err_idx| { | ||
| 422 | if (expected_idx == expected.errors.len) { | ||
| 423 | try error_bundle.renderToStderr(io, .{}, .auto); | ||
| 424 | eval.fatal("more errors than expected", .{}); | ||
| 425 | } | ||
| 426 | try eval.checkOneError(error_bundle, expected.errors[expected_idx], false, err_idx); | ||
| 427 | expected_idx += 1; | ||
| 428 | |||
| 429 | for (error_bundle.getNotes(err_idx)) |note_idx| { | ||
| 430 | if (expected_idx == expected.errors.len) { | ||
| 431 | try error_bundle.renderToStderr(io, .{}, .auto); | ||
| 432 | eval.fatal("more error notes than expected", .{}); | ||
| 433 | } | ||
| 434 | try eval.checkOneError(error_bundle, expected.errors[expected_idx], true, note_idx); | ||
| 435 | expected_idx += 1; | ||
| 436 | } | ||
| 437 | } | ||
| 438 | |||
| 439 | if (!std.mem.eql(u8, error_bundle.getCompileLogOutput(), expected.compile_log_output)) { | ||
| 440 | try error_bundle.renderToStderr(io, .{}, .auto); | ||
| 441 | eval.fatal("unexpected compile log output", .{}); | ||
| 442 | } | ||
| 443 | } | ||
| 444 | |||
| 445 | fn checkOneError( | ||
| 446 | eval: *Eval, | ||
| 447 | eb: std.zig.ErrorBundle, | ||
| 448 | expected: Case.ExpectedError, | ||
| 449 | is_note: bool, | ||
| 450 | err_idx: std.zig.ErrorBundle.MessageIndex, | ||
| 451 | ) Allocator.Error!void { | ||
| 452 | const io = eval.io; | ||
| 453 | const err = eb.getErrorMessage(err_idx); | ||
| 454 | if (err.count != 1) @panic("TODO error message with count>1"); | ||
| 455 | const msg = eb.nullTerminatedString(err.msg); | ||
| 456 | const matches = matches: { | ||
| 457 | if (expected.is_note != is_note) break :matches false; | ||
| 458 | if (!std.mem.eql(u8, expected.msg, msg)) break :matches false; | ||
| 459 | if (err.src_loc == .none) { | ||
| 460 | break :matches expected.src == null; | ||
| 461 | } | ||
| 462 | const expected_src = expected.src orelse break :matches false; | ||
| 463 | const src = eb.getSourceLocation(err.src_loc); | ||
| 464 | const raw_filename = eb.nullTerminatedString(src.src_path); | ||
| 465 | // We need to replace backslashes for consistency between platforms. | ||
| 466 | const filename = name: { | ||
| 467 | if (std.mem.findScalar(u8, raw_filename, '\\') == null) break :name raw_filename; | ||
| 468 | const copied = try eval.arena.dupe(u8, raw_filename); | ||
| 469 | std.mem.replaceScalar(u8, copied, '\\', '/'); | ||
| 470 | break :name copied; | ||
| 471 | }; | ||
| 472 | if (!std.mem.eql(u8, expected_src.filename, filename)) break :matches false; | ||
| 473 | if (expected_src.line != src.line + 1) break :matches false; | ||
| 474 | if (expected_src.column != src.column + 1) break :matches false; | ||
| 475 | break :matches true; | ||
| 476 | }; | ||
| 477 | if (!matches) { | ||
| 478 | eb.renderToStderr(io, .{}, .auto) catch {}; | ||
| 479 | eval.fatal("compile error did not match expected error", .{}); | ||
| 480 | } | ||
| 481 | } | ||
| 482 | |||
| 483 | fn checkSuccessOutcome(eval: *Eval, update: Case.Update, opt_emitted_path: ?[]const u8, prog_node: std.Progress.Node) !void { | ||
| 484 | switch (update.outcome) { | ||
| 485 | .unknown => return, | ||
| 486 | .compile_errors => eval.fatal("expected compile errors but compilation incorrectly succeeded", .{}), | ||
| 487 | .stdout, .exit_code => {}, | ||
| 488 | } | ||
| 489 | const emitted_path = opt_emitted_path orelse { | ||
| 490 | std.debug.assert(eval.backend == .sema); | ||
| 491 | return; | ||
| 492 | }; | ||
| 493 | const io = eval.io; | ||
| 494 | |||
| 495 | const binary_path = switch (eval.backend) { | ||
| 496 | .sema => unreachable, | ||
| 497 | .selfhosted, .llvm => emitted_path, | ||
| 498 | .cbe => bin: { | ||
| 499 | const rand_int = rand64(io); | ||
| 500 | const out_bin_name = "./out_" ++ std.fmt.hex(rand_int); | ||
| 501 | try eval.buildCOutput(emitted_path, out_bin_name, prog_node); | ||
| 502 | break :bin out_bin_name; | ||
| 503 | }, | ||
| 504 | }; | ||
| 505 | |||
| 506 | var argv_buf: [2][]const u8 = undefined; | ||
| 507 | const argv: []const []const u8, const is_foreign: bool = sw: switch (std.zig.system.getExternalExecutor( | ||
| 508 | io, | ||
| 509 | &eval.target, | ||
| 510 | .{ | ||
| 511 | .link_libc = eval.backend == .cbe, | ||
| 512 | .host_cpu_arch = eval.host.cpu.arch, | ||
| 513 | .host_os_tag = eval.host.os.tag, | ||
| 514 | }, | ||
| 515 | )) { | ||
| 516 | .bad_dl, .bad_os_or_cpu => { | ||
| 517 | // This binary cannot be executed on this host. | ||
| 518 | if (!eval.quiet) { | ||
| 519 | std.log.warn("skipping execution because host '{s}' cannot execute binaries for foreign target '{s}'", .{ | ||
| 520 | try eval.host.zigTriple(eval.arena), | ||
| 521 | try eval.target.zigTriple(eval.arena), | ||
| 522 | }); | ||
| 523 | } | ||
| 524 | return; | ||
| 525 | }, | ||
| 526 | .native, .rosetta => argv: { | ||
| 527 | argv_buf[0] = binary_path; | ||
| 528 | break :argv .{ argv_buf[0..1], false }; | ||
| 529 | }, | ||
| 530 | .qemu => |executor_cmd| argv: { | ||
| 531 | if (eval.enable_qemu) { | ||
| 532 | argv_buf[0] = executor_cmd; | ||
| 533 | argv_buf[1] = binary_path; | ||
| 534 | break :argv .{ argv_buf[0..2], true }; | ||
| 535 | } else { | ||
| 536 | continue :sw .bad_os_or_cpu; | ||
| 537 | } | ||
| 538 | }, | ||
| 539 | .wine => |executor_cmd| argv: { | ||
| 540 | if (eval.enable_wine) { | ||
| 541 | argv_buf[0] = executor_cmd; | ||
| 542 | argv_buf[1] = binary_path; | ||
| 543 | break :argv .{ argv_buf[0..2], true }; | ||
| 544 | } else { | ||
| 545 | continue :sw .bad_os_or_cpu; | ||
| 546 | } | ||
| 547 | }, | ||
| 548 | .wasmtime => |executor_cmd| argv: { | ||
| 549 | if (eval.enable_wasmtime) { | ||
| 550 | argv_buf[0] = executor_cmd; | ||
| 551 | argv_buf[1] = binary_path; | ||
| 552 | break :argv .{ argv_buf[0..2], true }; | ||
| 553 | } else { | ||
| 554 | continue :sw .bad_os_or_cpu; | ||
| 555 | } | ||
| 556 | }, | ||
| 557 | .darling => |executor_cmd| argv: { | ||
| 558 | if (eval.enable_darling) { | ||
| 559 | argv_buf[0] = executor_cmd; | ||
| 560 | argv_buf[1] = binary_path; | ||
| 561 | break :argv .{ argv_buf[0..2], true }; | ||
| 562 | } else { | ||
| 563 | continue :sw .bad_os_or_cpu; | ||
| 564 | } | ||
| 565 | }, | ||
| 566 | }; | ||
| 567 | |||
| 568 | const run_prog_node = prog_node.start("run generated executable", 0); | ||
| 569 | defer run_prog_node.end(); | ||
| 570 | |||
| 571 | const result = std.process.run(eval.arena, io, .{ | ||
| 572 | .argv = argv, | ||
| 573 | .cwd = .{ .path = eval.tmp_dir_path }, | ||
| 574 | }) catch |err| { | ||
| 575 | if (is_foreign) { | ||
| 576 | // Chances are the foreign executor isn't available. Skip this evaluation. | ||
| 577 | if (!eval.quiet) { | ||
| 578 | std.log.warn("skipping execution of '{s}' via executor for foreign target '{s}': {t}", .{ | ||
| 579 | binary_path, | ||
| 580 | try eval.target.zigTriple(eval.arena), | ||
| 581 | err, | ||
| 582 | }); | ||
| 583 | } | ||
| 584 | return; | ||
| 585 | } | ||
| 586 | eval.fatal("failed to run the generated executable '{s}': {t}", .{ binary_path, err }); | ||
| 587 | }; | ||
| 588 | |||
| 589 | // Some executors (looking at you, Wine) like throwing some stderr in, just for fun. | ||
| 590 | // Therefore, we'll ignore stderr when using a foreign executor. | ||
| 591 | if (!is_foreign and result.stderr.len != 0) { | ||
| 592 | std.log.err("generated executable '{s}' had unexpected stderr:\n{s}", .{ | ||
| 593 | binary_path, result.stderr, | ||
| 594 | }); | ||
| 595 | } | ||
| 596 | |||
| 597 | switch (result.term) { | ||
| 598 | .exited => |code| switch (update.outcome) { | ||
| 599 | .unknown, .compile_errors => unreachable, | ||
| 600 | .stdout => |expected_stdout| { | ||
| 601 | if (code != 0) { | ||
| 602 | eval.fatal("generated executable '{s}' failed with code {d}", .{ binary_path, code }); | ||
| 603 | } | ||
| 604 | try std.testing.expectEqualStrings(expected_stdout, result.stdout); | ||
| 605 | }, | ||
| 606 | .exit_code => |expected_code| try std.testing.expectEqual(expected_code, code), | ||
| 607 | }, | ||
| 608 | .signal => |sig| { | ||
| 609 | eval.fatal("generated executable '{s}' terminated with signal {t}", .{ binary_path, sig }); | ||
| 610 | }, | ||
| 611 | .stopped => |sig| { | ||
| 612 | eval.fatal("generated executable '{s}' stopped with signal {t}", .{ binary_path, sig }); | ||
| 613 | }, | ||
| 614 | .unknown => { | ||
| 615 | eval.fatal("generated executable '{s}' terminated unexpectedly", .{binary_path}); | ||
| 616 | }, | ||
| 617 | } | ||
| 618 | |||
| 619 | if (!is_foreign and result.stderr.len != 0) std.process.exit(1); | ||
| 620 | } | ||
| 621 | |||
| 622 | fn requestUpdate(eval: *Eval) !void { | ||
| 623 | const io = eval.io; | ||
| 624 | |||
| 625 | var w = eval.child.stdin.?.writerStreaming(io, &.{}); | ||
| 626 | var client: std.zig.Client = .{ | ||
| 627 | .in = undefined, | ||
| 628 | .out = &w.interface, | ||
| 629 | }; | ||
| 630 | client.serveBodylessMessage(.update) catch |err| switch (err) { | ||
| 631 | error.WriteFailed => return w.err.?, | ||
| 632 | }; | ||
| 633 | } | ||
| 634 | |||
| 635 | fn end(eval: *Eval, mr: *Io.File.MultiReader) !void { | ||
| 636 | requestExit(eval.child, eval); | ||
| 637 | |||
| 638 | var client: std.zig.Client = .{ | ||
| 639 | .in = mr.reader(0), | ||
| 640 | .out = undefined, | ||
| 641 | }; | ||
| 642 | |||
| 643 | while (true) { | ||
| 644 | const header = client.receiveMessageWithMultiReader(mr, .none) catch |err| switch (err) { | ||
| 645 | error.Timeout => unreachable, | ||
| 646 | error.EndOfStream => |e| { | ||
| 647 | if (client.in.bufferedLen() == 0) break; | ||
| 648 | return e; | ||
| 649 | }, | ||
| 650 | else => |e| return e, | ||
| 651 | }; | ||
| 652 | try client.in.discardAll(header.bytes_len); | ||
| 653 | } | ||
| 654 | |||
| 655 | const stderr = mr.reader(1).buffered(); | ||
| 656 | if (stderr.len > 0) eval.fatal("unexpected stderr:\n{s}", .{stderr}); | ||
| 657 | } | ||
| 658 | |||
| 659 | fn buildCOutput(eval: *Eval, c_path: []const u8, out_path: []const u8, prog_node: std.Progress.Node) !void { | ||
| 660 | std.debug.assert(eval.cc_child_args.items.len > 0); | ||
| 661 | |||
| 662 | const child_prog_node = prog_node.start("build cbe output", 0); | ||
| 663 | defer child_prog_node.end(); | ||
| 664 | |||
| 665 | try eval.cc_child_args.append(eval.arena, try std.fmt.allocPrint(eval.arena, "-femit-bin={s}", .{out_path})); | ||
| 666 | try eval.cc_child_args.append(eval.arena, c_path); | ||
| 667 | defer eval.cc_child_args.items.len -= 2; | ||
| 668 | |||
| 669 | if (eval.allow_compiler_stderr) { | ||
| 670 | const cmd: std.zig.SubprocessCommand = .{ | ||
| 671 | .argv = eval.cc_child_args.items, | ||
| 672 | .cwd = eval.tmp_dir_path, | ||
| 673 | }; | ||
| 674 | std.log.scoped(.spawn).info("{f}", .{cmd}); | ||
| 675 | } | ||
| 676 | |||
| 677 | const result = std.process.run(eval.arena, eval.io, .{ | ||
| 678 | .argv = eval.cc_child_args.items, | ||
| 679 | .cwd = .{ .path = eval.tmp_dir_path }, | ||
| 680 | .progress_node = child_prog_node, | ||
| 681 | }) catch |err| { | ||
| 682 | eval.fatal("failed to spawn zig cc for '{s}': {t}", .{ c_path, err }); | ||
| 683 | }; | ||
| 684 | |||
| 685 | if (result.term == .exited and result.term.exited == 0) return; | ||
| 686 | |||
| 687 | if (result.stderr.len != 0) { | ||
| 688 | std.log.err("zig cc stderr:\n{s}", .{result.stderr}); | ||
| 689 | } | ||
| 690 | switch (result.term) { | ||
| 691 | .exited => |code| eval.fatal("zig cc for '{s}' failed with code {d}", .{ c_path, code }), | ||
| 692 | .signal => |sig| eval.fatal("zig cc for '{s}' terminated unexpectedly with signal {t}", .{ c_path, sig }), | ||
| 693 | .stopped => |sig| eval.fatal("zig cc for '{s}' stopped unexpectedly with signal {t}", .{ c_path, sig }), | ||
| 694 | .unknown => eval.fatal("zig cc for '{s}' terminated unexpectedly", .{c_path}), | ||
| 695 | } | ||
| 696 | } | ||
| 697 | |||
| 698 | fn fatal(eval: *Eval, comptime fmt: []const u8, args: anytype) noreturn { | ||
| 699 | const io = eval.io; | ||
| 700 | eval.tmp_dir.close(io); | ||
| 701 | if (!eval.preserve_tmp_on_fatal) { | ||
| 702 | // Kill the child since it holds an open handle to its CWD which is the tmp dir path | ||
| 703 | eval.child.kill(io); | ||
| 704 | Dir.cwd().deleteTree(io, eval.tmp_dir_path) catch |err| { | ||
| 705 | std.log.warn("failed to delete tree '{s}': {t}", .{ eval.tmp_dir_path, err }); | ||
| 706 | }; | ||
| 707 | } | ||
| 708 | std.process.fatal(fmt, args); | ||
| 709 | } | ||
| 710 | }; | ||
| 711 | |||
| 712 | const Backend = enum { | ||
| 713 | /// Run semantic analysis only. Runtime output will not be tested, but we still verify | ||
| 714 | /// that compilation succeeds. Corresponds to `-fno-emit-bin`. | ||
| 715 | sema, | ||
| 716 | /// Use the self-hosted code generation backend for this target. | ||
| 717 | /// Corresponds to `-fno-llvm -fno-lld`. | ||
| 718 | selfhosted, | ||
| 719 | /// Use the LLVM backend. | ||
| 720 | /// Corresponds to `-fllvm -flld`. | ||
| 721 | llvm, | ||
| 722 | /// Use the C backend. The output is compiled with `zig cc`. | ||
| 723 | /// Corresponds to `-ofmt=c`. | ||
| 724 | cbe, | ||
| 725 | }; | ||
| 726 | |||
| 727 | const Case = struct { | ||
| 728 | updates: []Update, | ||
| 729 | root_source_file: []const u8, | ||
| 730 | skip_targets: []const SkipTarget, | ||
| 731 | modules: []const Module, | ||
| 732 | |||
| 733 | const SkipTarget = struct { | ||
| 734 | query: std.Target.Query, | ||
| 735 | backend: Backend, | ||
| 736 | }; | ||
| 737 | |||
| 738 | const Module = struct { | ||
| 739 | name: []const u8, | ||
| 740 | file: []const u8, | ||
| 741 | }; | ||
| 742 | |||
| 743 | const Update = struct { | ||
| 744 | name: []const u8, | ||
| 745 | outcome: Outcome, | ||
| 746 | changes: []const FullContents = &.{}, | ||
| 747 | deletes: []const []const u8 = &.{}, | ||
| 748 | }; | ||
| 749 | |||
| 750 | const FullContents = struct { | ||
| 751 | name: []const u8, | ||
| 752 | bytes: []const u8, | ||
| 753 | }; | ||
| 754 | |||
| 755 | const Outcome = union(enum) { | ||
| 756 | unknown, | ||
| 757 | compile_errors: struct { | ||
| 758 | errors: []const ExpectedError, | ||
| 759 | compile_log_output: []const u8, | ||
| 760 | }, | ||
| 761 | stdout: []const u8, | ||
| 762 | exit_code: u8, | ||
| 763 | }; | ||
| 764 | |||
| 765 | const ExpectedError = struct { | ||
| 766 | is_note: bool, | ||
| 767 | msg: []const u8, | ||
| 768 | src: ?struct { | ||
| 769 | filename: []const u8, | ||
| 770 | line: u32, | ||
| 771 | column: u32, | ||
| 772 | }, | ||
| 773 | }; | ||
| 774 | |||
| 775 | fn parse(arena: Allocator, bytes: []const u8) !Case { | ||
| 776 | const fatal = std.process.fatal; | ||
| 777 | |||
| 778 | var skip_targets: std.ArrayList(SkipTarget) = .empty; | ||
| 779 | var modules: std.ArrayList(Module) = .empty; | ||
| 780 | var updates: std.ArrayList(Update) = .empty; | ||
| 781 | var changes: std.ArrayList(FullContents) = .empty; | ||
| 782 | var deletes: std.ArrayList([]const u8) = .empty; | ||
| 783 | var it = std.mem.splitScalar(u8, bytes, '\n'); | ||
| 784 | var line_n: usize = 1; | ||
| 785 | var root_source_file: ?[]const u8 = null; | ||
| 786 | while (it.next()) |line| : (line_n += 1) { | ||
| 787 | if (std.mem.startsWith(u8, line, "#")) { | ||
| 788 | var line_it = std.mem.splitScalar(u8, line, '='); | ||
| 789 | const key = line_it.first()[1..]; | ||
| 790 | const val = std.mem.trimEnd(u8, line_it.rest(), "\r"); // windows moment | ||
| 791 | if (val.len == 0) { | ||
| 792 | fatal("line {d}: missing value", .{line_n}); | ||
| 793 | } else if (std.mem.eql(u8, key, "skip_target")) { | ||
| 794 | const query, const backend = parseTargetQueryAndBackend( | ||
| 795 | val, | ||
| 796 | try std.fmt.allocPrint(arena, "line {d}: ", .{line_n}), | ||
| 797 | ); | ||
| 798 | try skip_targets.append(arena, .{ | ||
| 799 | .query = query, | ||
| 800 | .backend = backend, | ||
| 801 | }); | ||
| 802 | } else if (std.mem.eql(u8, key, "module")) { | ||
| 803 | const split_idx = std.mem.findScalar(u8, val, '=') orelse | ||
| 804 | fatal("line {d}: module does not include file", .{line_n}); | ||
| 805 | const name = val[0..split_idx]; | ||
| 806 | const file = val[split_idx + 1 ..]; | ||
| 807 | try modules.append(arena, .{ | ||
| 808 | .name = name, | ||
| 809 | .file = file, | ||
| 810 | }); | ||
| 811 | } else if (std.mem.eql(u8, key, "update")) { | ||
| 812 | if (updates.items.len > 0) { | ||
| 813 | const last_update = &updates.items[updates.items.len - 1]; | ||
| 814 | last_update.changes = try changes.toOwnedSlice(arena); | ||
| 815 | last_update.deletes = try deletes.toOwnedSlice(arena); | ||
| 816 | } | ||
| 817 | try updates.append(arena, .{ | ||
| 818 | .name = val, | ||
| 819 | .outcome = .unknown, | ||
| 820 | }); | ||
| 821 | } else if (std.mem.eql(u8, key, "file")) { | ||
| 822 | if (updates.items.len == 0) fatal("line {d}: file directive before update", .{line_n}); | ||
| 823 | |||
| 824 | if (root_source_file == null) | ||
| 825 | root_source_file = val; | ||
| 826 | |||
| 827 | // Because Windows is so excellent, we need to convert CRLF to LF, so | ||
| 828 | // can't just slice into the input here. How delightful! | ||
| 829 | var src: std.ArrayList(u8) = .empty; | ||
| 830 | |||
| 831 | while (true) { | ||
| 832 | const next_line_raw = it.peek() orelse fatal("line {d}: unexpected EOF", .{line_n}); | ||
| 833 | const next_line = std.mem.trimEnd(u8, next_line_raw, "\r"); | ||
| 834 | if (std.mem.startsWith(u8, next_line, "#")) break; | ||
| 835 | |||
| 836 | _ = it.next(); | ||
| 837 | line_n += 1; | ||
| 838 | |||
| 839 | try src.ensureUnusedCapacity(arena, next_line.len + 1); | ||
| 840 | src.appendSliceAssumeCapacity(next_line); | ||
| 841 | src.appendAssumeCapacity('\n'); | ||
| 842 | } | ||
| 843 | |||
| 844 | try changes.append(arena, .{ | ||
| 845 | .name = val, | ||
| 846 | .bytes = src.items, | ||
| 847 | }); | ||
| 848 | } else if (std.mem.eql(u8, key, "rm_file")) { | ||
| 849 | if (updates.items.len == 0) fatal("line {d}: rm_file directive before update", .{line_n}); | ||
| 850 | try deletes.append(arena, val); | ||
| 851 | } else if (std.mem.eql(u8, key, "expect_stdout")) { | ||
| 852 | if (updates.items.len == 0) fatal("line {d}: expect directive before update", .{line_n}); | ||
| 853 | const last_update = &updates.items[updates.items.len - 1]; | ||
| 854 | if (last_update.outcome != .unknown) fatal("line {d}: conflicting expect directive", .{line_n}); | ||
| 855 | last_update.outcome = .{ | ||
| 856 | .stdout = std.zig.string_literal.parseAlloc(arena, val) catch |err| { | ||
| 857 | fatal("line {d}: bad string literal: {t}", .{ line_n, err }); | ||
| 858 | }, | ||
| 859 | }; | ||
| 860 | } else if (std.mem.eql(u8, key, "expect_error")) { | ||
| 861 | if (updates.items.len == 0) fatal("line {d}: expect directive before update", .{line_n}); | ||
| 862 | const last_update = &updates.items[updates.items.len - 1]; | ||
| 863 | if (last_update.outcome != .unknown) fatal("line {d}: conflicting expect directive", .{line_n}); | ||
| 864 | |||
| 865 | var errors: std.ArrayList(ExpectedError) = .empty; | ||
| 866 | try errors.append(arena, parseExpectedError(val, line_n)); | ||
| 867 | while (true) { | ||
| 868 | const next_line = it.peek() orelse break; | ||
| 869 | if (!std.mem.startsWith(u8, next_line, "#")) break; | ||
| 870 | var new_line_it = std.mem.splitScalar(u8, next_line, '='); | ||
| 871 | const new_key = new_line_it.first()[1..]; | ||
| 872 | const new_val = std.mem.trimEnd(u8, new_line_it.rest(), "\r"); | ||
| 873 | if (new_val.len == 0) break; | ||
| 874 | if (!std.mem.eql(u8, new_key, "expect_error")) break; | ||
| 875 | |||
| 876 | _ = it.next(); | ||
| 877 | line_n += 1; | ||
| 878 | try errors.append(arena, parseExpectedError(new_val, line_n)); | ||
| 879 | } | ||
| 880 | |||
| 881 | var compile_log_output: std.ArrayList(u8) = .empty; | ||
| 882 | while (true) { | ||
| 883 | const next_line = it.peek() orelse break; | ||
| 884 | if (!std.mem.startsWith(u8, next_line, "#")) break; | ||
| 885 | var new_line_it = std.mem.splitScalar(u8, next_line, '='); | ||
| 886 | const new_key = new_line_it.first()[1..]; | ||
| 887 | const new_val = std.mem.trimEnd(u8, new_line_it.rest(), "\r"); | ||
| 888 | if (new_val.len == 0) break; | ||
| 889 | if (!std.mem.eql(u8, new_key, "expect_compile_log")) break; | ||
| 890 | |||
| 891 | _ = it.next(); | ||
| 892 | line_n += 1; | ||
| 893 | try compile_log_output.ensureUnusedCapacity(arena, new_val.len + 1); | ||
| 894 | compile_log_output.appendSliceAssumeCapacity(new_val); | ||
| 895 | compile_log_output.appendAssumeCapacity('\n'); | ||
| 896 | } | ||
| 897 | |||
| 898 | last_update.outcome = .{ .compile_errors = .{ | ||
| 899 | .errors = errors.items, | ||
| 900 | .compile_log_output = compile_log_output.items, | ||
| 901 | } }; | ||
| 902 | } else if (std.mem.eql(u8, key, "expect_compile_log")) { | ||
| 903 | fatal("line {d}: 'expect_compile_log' must immediately follow 'expect_error'", .{line_n}); | ||
| 904 | } else { | ||
| 905 | fatal("line {d}: unrecognized key '{s}'", .{ line_n, key }); | ||
| 906 | } | ||
| 907 | } | ||
| 908 | } | ||
| 909 | |||
| 910 | if (changes.items.len > 0) { | ||
| 911 | const last_update = &updates.items[updates.items.len - 1]; | ||
| 912 | last_update.changes = changes.items; // arena so no need for toOwnedSlice | ||
| 913 | last_update.deletes = deletes.items; | ||
| 914 | } | ||
| 915 | |||
| 916 | return .{ | ||
| 917 | .updates = updates.items, | ||
| 918 | .root_source_file = root_source_file orelse fatal("missing root source file", .{}), | ||
| 919 | .skip_targets = skip_targets.items, // arena so no need for toOwnedSlice | ||
| 920 | .modules = modules.items, | ||
| 921 | }; | ||
| 922 | } | ||
| 923 | }; | ||
| 924 | |||
| 925 | fn requestExit(child: *std.process.Child, eval: *Eval) void { | ||
| 926 | if (child.stdin == null) return; | ||
| 927 | const io = eval.io; | ||
| 928 | |||
| 929 | var w = eval.child.stdin.?.writerStreaming(io, &.{}); | ||
| 930 | var client: std.zig.Client = .{ | ||
| 931 | .in = undefined, | ||
| 932 | .out = &w.interface, | ||
| 933 | }; | ||
| 934 | client.serveBodylessMessage(.exit) catch |err| switch (err) { | ||
| 935 | error.WriteFailed => switch (w.err.?) { | ||
| 936 | error.BrokenPipe => {}, | ||
| 937 | else => |e| eval.fatal("failed to send exit: {t}", .{e}), | ||
| 938 | }, | ||
| 939 | }; | ||
| 940 | |||
| 941 | // Send EOF to stdin. | ||
| 942 | child.stdin.?.close(io); | ||
| 943 | child.stdin = null; | ||
| 944 | } | ||
| 945 | |||
| 946 | fn waitChild(child: *std.process.Child, eval: *Eval) void { | ||
| 947 | const io = eval.io; | ||
| 948 | requestExit(child, eval); | ||
| 949 | const term = child.wait(io) catch |err| eval.fatal("child process failed: {t}", .{err}); | ||
| 950 | switch (term) { | ||
| 951 | .exited => |code| if (code != 0) eval.fatal("compiler failed with code {d}", .{code}), | ||
| 952 | .signal => |sig| eval.fatal("compiler terminated with signal {t}", .{sig}), | ||
| 953 | .stopped => |sig| eval.fatal("compiler stopped unexpectedly with signal {t}", .{sig}), | ||
| 954 | .unknown => eval.fatal("compiler terminated unexpectedly", .{}), | ||
| 955 | } | ||
| 956 | } | ||
| 957 | |||
| 958 | fn parseExpectedError(str: []const u8, l: usize) Case.ExpectedError { | ||
| 959 | // #expect_error=foo.zig:1:2: error: the error message | ||
| 960 | // #expect_error=foo.zig:1:2: note: and a note | ||
| 961 | |||
| 962 | const fatal = std.process.fatal; | ||
| 963 | |||
| 964 | var it = std.mem.splitScalar(u8, str, ':'); | ||
| 965 | const filename = it.first(); | ||
| 966 | const line_str, const column_str = if (filename.len > 0) .{ | ||
| 967 | it.next() orelse fatal("line {d}: incomplete error specification", .{l}), | ||
| 968 | it.next() orelse fatal("line {d}: incomplete error specification", .{l}), | ||
| 969 | } else .{ undefined, undefined }; | ||
| 970 | const error_or_note_str = std.mem.trim( | ||
| 971 | u8, | ||
| 972 | it.next() orelse fatal("line {d}: incomplete error specification", .{l}), | ||
| 973 | " ", | ||
| 974 | ); | ||
| 975 | |||
| 976 | const is_note = if (std.mem.eql(u8, error_or_note_str, "error")) | ||
| 977 | false | ||
| 978 | else if (std.mem.eql(u8, error_or_note_str, "note")) | ||
| 979 | true | ||
| 980 | else | ||
| 981 | fatal("line {d}: expeted 'error' or 'note', found '{s}'", .{ l, error_or_note_str }); | ||
| 982 | |||
| 983 | const message = std.mem.trim(u8, it.rest(), " "); | ||
| 984 | if (message.len == 0) fatal("line {d}: empty error message", .{l}); | ||
| 985 | |||
| 986 | return .{ | ||
| 987 | .is_note = is_note, | ||
| 988 | .msg = message, | ||
| 989 | .src = if (filename.len == 0) null else .{ | ||
| 990 | .filename = filename, | ||
| 991 | .line = std.fmt.parseInt(u32, line_str, 10) catch | ||
| 992 | fatal("line {d}: invalid line number '{s}'", .{ l, line_str }), | ||
| 993 | .column = std.fmt.parseInt(u32, column_str, 10) catch | ||
| 994 | fatal("line {d}: invalid column number '{s}'", .{ l, column_str }), | ||
| 995 | }, | ||
| 996 | }; | ||
| 997 | } | ||
| 998 | |||
| 999 | fn rand64(io: Io) u64 { | ||
| 1000 | var x: u64 = undefined; | ||
| 1001 | io.random(@ptrCast(&x)); | ||
| 1002 | return x; | ||
| 1003 | } | ||
| 1004 | |||
| 1005 | /// Calls `std.process.fatal` on error. The error messages are prefixed with `err_prefix`. | ||
| 1006 | fn parseTargetQueryAndBackend(input_str: []const u8, err_prefix: []const u8) struct { std.Target.Query, Backend } { | ||
| 1007 | const fatal = std.process.fatal; | ||
| 1008 | |||
| 1009 | const split_idx = std.mem.findScalarLast(u8, input_str, '-') orelse | ||
| 1010 | fatal("{s}target does not include backend", .{err_prefix}); | ||
| 1011 | |||
| 1012 | const query = input_str[0..split_idx]; | ||
| 1013 | |||
| 1014 | const backend_str = input_str[split_idx + 1 ..]; | ||
| 1015 | const backend: Backend = std.meta.stringToEnum(Backend, backend_str) orelse | ||
| 1016 | fatal("{s}invalid backend '{s}'", .{ err_prefix, backend_str }); | ||
| 1017 | |||
| 1018 | const parsed_query = std.Build.parseTargetQuery(.{ | ||
| 1019 | .arch_os_abi = query, | ||
| 1020 | .object_format = switch (backend) { | ||
| 1021 | .sema, .selfhosted, .llvm => null, | ||
| 1022 | .cbe => "c", | ||
| 1023 | }, | ||
| 1024 | }) catch fatal("{s}invalid target query '{s}'", .{ err_prefix, query }); | ||
| 1025 | |||
| 1026 | return .{ parsed_query, backend }; | ||
| 1027 | } | ||
| 1028 | |||
| 1029 | fn badUsage(comptime fmt: []const u8, args: anytype) noreturn { | ||
| 1030 | std.log.err(fmt ++ "\n{s}", args ++ .{usage}); | ||
| 1031 | std.process.exit(1); | ||
| 1032 | } | ||