diff options
| author | Andrea Orru <andrea@orru.io> | 2018-08-06 01:43:19 -0400 |
|---|---|---|
| committer | Andrea Orru <andrea@orru.io> | 2018-08-06 01:43:19 -0400 |
| commit | d2f5e57b68da0b16e5789ca19045ccbcb4ecfa8d (patch) | |
| tree | e9fa3caec533a0d1e2b434868b2fde1f9240e5c8 /test | |
| parent | 06614b3fa09954464c2e2f32756cacedc178a282 (diff) | |
| parent | 63a23e848a62d5f167f8d5478de9766cb24aa6eb (diff) | |
| download | zig-d2f5e57b68da0b16e5789ca19045ccbcb4ecfa8d.tar.gz zig-d2f5e57b68da0b16e5789ca19045ccbcb4ecfa8d.zip | |
Merge branch 'master' into zen_stdlib
Diffstat (limited to 'test')
85 files changed, 6120 insertions, 2114 deletions
diff --git a/test/assemble_and_link.zig b/test/assemble_and_link.zig index 2593f3306a..8c727e87b5 100644 --- a/test/assemble_and_link.zig +++ b/test/assemble_and_link.zig @@ -1,7 +1,7 @@ const builtin = @import("builtin"); const tests = @import("tests.zig"); -pub fn addCases(cases: &tests.CompareOutputContext) void { +pub fn addCases(cases: *tests.CompareOutputContext) void { if (builtin.os == builtin.Os.linux and builtin.arch == builtin.Arch.x86_64) { cases.addAsm("hello world linux x86_64", \\.text diff --git a/test/behavior.zig b/test/behavior.zig index de39b20dad..e993d7e0dc 100644 --- a/test/behavior.zig +++ b/test/behavior.zig @@ -8,12 +8,18 @@ comptime { _ = @import("cases/atomics.zig"); _ = @import("cases/bitcast.zig"); _ = @import("cases/bool.zig"); + _ = @import("cases/bugs/1111.zig"); + _ = @import("cases/bugs/1230.zig"); _ = @import("cases/bugs/394.zig"); _ = @import("cases/bugs/655.zig"); _ = @import("cases/bugs/656.zig"); _ = @import("cases/bugs/828.zig"); + _ = @import("cases/bugs/920.zig"); + _ = @import("cases/byval_arg_var.zig"); + _ = @import("cases/cancel.zig"); _ = @import("cases/cast.zig"); _ = @import("cases/const_slice_child.zig"); + _ = @import("cases/coroutine_await_struct.zig"); _ = @import("cases/coroutines.zig"); _ = @import("cases/defer.zig"); _ = @import("cases/enum.zig"); @@ -22,6 +28,7 @@ comptime { _ = @import("cases/eval.zig"); _ = @import("cases/field_parent_ptr.zig"); _ = @import("cases/fn.zig"); + _ = @import("cases/fn_in_struct_in_comptime.zig"); _ = @import("cases/for.zig"); _ = @import("cases/generics.zig"); _ = @import("cases/if.zig"); @@ -29,9 +36,14 @@ comptime { _ = @import("cases/incomplete_struct_param_tld.zig"); _ = @import("cases/ir_block_deps.zig"); _ = @import("cases/math.zig"); + _ = @import("cases/merge_error_sets.zig"); _ = @import("cases/misc.zig"); _ = @import("cases/namespace_depends_on_compile_var/index.zig"); + _ = @import("cases/new_stack_call.zig"); _ = @import("cases/null.zig"); + _ = @import("cases/optional.zig"); + _ = @import("cases/pointers.zig"); + _ = @import("cases/popcount.zig"); _ = @import("cases/pub_enum/index.zig"); _ = @import("cases/ref_var_in_if_after_if_2nd_switch_prong.zig"); _ = @import("cases/reflection.zig"); @@ -46,9 +58,12 @@ comptime { _ = @import("cases/syntax.zig"); _ = @import("cases/this.zig"); _ = @import("cases/try.zig"); + _ = @import("cases/type_info.zig"); _ = @import("cases/undefined.zig"); + _ = @import("cases/underscore.zig"); _ = @import("cases/union.zig"); _ = @import("cases/var_args.zig"); _ = @import("cases/void.zig"); _ = @import("cases/while.zig"); + _ = @import("cases/widening.zig"); } diff --git a/test/build_examples.zig b/test/build_examples.zig index a3b44b9136..79192c3e9a 100644 --- a/test/build_examples.zig +++ b/test/build_examples.zig @@ -2,20 +2,30 @@ const tests = @import("tests.zig"); const builtin = @import("builtin"); const is_windows = builtin.os == builtin.Os.windows; -pub fn addCases(cases: &tests.BuildExamplesContext) void { +pub fn addCases(cases: *tests.BuildExamplesContext) void { cases.add("example/hello_world/hello.zig"); cases.addC("example/hello_world/hello_libc.zig"); cases.add("example/cat/main.zig"); cases.add("example/guess_number/main.zig"); if (!is_windows) { // TODO get this test passing on windows - // See https://github.com/zig-lang/zig/issues/538 + // See https://github.com/ziglang/zig/issues/538 cases.addBuildFile("example/shared_library/build.zig"); cases.addBuildFile("example/mix_o_files/build.zig"); } - cases.addBuildFile("test/standalone/issue_339/build.zig"); + if (builtin.os != builtin.Os.macosx) { + // TODO https://github.com/ziglang/zig/issues/1126 + cases.addBuildFile("test/standalone/issue_339/build.zig"); + } cases.addBuildFile("test/standalone/issue_794/build.zig"); cases.addBuildFile("test/standalone/pkg_import/build.zig"); cases.addBuildFile("test/standalone/use_alias/build.zig"); cases.addBuildFile("test/standalone/brace_expansion/build.zig"); + if (false) { + // TODO this test is disabled because it is failing on the CI server's linux. when this is fixed + // enable it for at least linux + // TODO hook up the DynLib API for windows using LoadLibraryA + // TODO figure out how to make this work on darwin - probably libSystem has dlopen/dlsym in it + cases.addBuildFile("test/standalone/load_dynamic_library/build.zig"); + } } diff --git a/test/cases/align.zig b/test/cases/align.zig index ad3a66a2e0..64f0788efc 100644 --- a/test/cases/align.zig +++ b/test/cases/align.zig @@ -5,34 +5,34 @@ var foo: u8 align(4) = 100; test "global variable alignment" { assert(@typeOf(&foo).alignment == 4); - assert(@typeOf(&foo) == &align(4) u8); - const slice = (&foo)[0..1]; + assert(@typeOf(&foo) == *align(4) u8); + const slice = (*[1]u8)(&foo)[0..]; assert(@typeOf(slice) == []align(4) u8); } -fn derp() align(@sizeOf(usize) * 2) i32 { return 1234; } +fn derp() align(@sizeOf(usize) * 2) i32 { + return 1234; +} fn noop1() align(1) void {} fn noop4() align(4) void {} test "function alignment" { assert(derp() == 1234); - assert(@typeOf(noop1) == fn() align(1) void); - assert(@typeOf(noop4) == fn() align(4) void); + assert(@typeOf(noop1) == fn () align(1) void); + assert(@typeOf(noop4) == fn () align(4) void); noop1(); noop4(); } - var baz: packed struct { a: u32, b: u32, } = undefined; test "packed struct alignment" { - assert(@typeOf(&baz.b) == &align(1) u32); + assert(@typeOf(&baz.b) == *align(1) u32); } - const blah: packed struct { a: u3, b: u3, @@ -40,11 +40,11 @@ const blah: packed struct { } = undefined; test "bit field alignment" { - assert(@typeOf(&blah.b) == &align(1:3:6) const u3); + assert(@typeOf(&blah.b) == *align(1:3:6) const u3); } test "default alignment allows unspecified in type syntax" { - assert(&u32 == &align(@alignOf(u32)) u32); + assert(*u32 == *align(@alignOf(u32)) u32); } test "implicitly decreasing pointer alignment" { @@ -53,30 +53,44 @@ test "implicitly decreasing pointer alignment" { assert(addUnaligned(&a, &b) == 7); } -fn addUnaligned(a: &align(1) const u32, b: &align(1) const u32) u32 { return *a + *b; } +fn addUnaligned(a: *align(1) const u32, b: *align(1) const u32) u32 { + return a.* + b.*; +} test "implicitly decreasing slice alignment" { const a: u32 align(4) = 3; const b: u32 align(8) = 4; - assert(addUnalignedSlice((&a)[0..1], (&b)[0..1]) == 7); + assert(addUnalignedSlice((*[1]u32)(&a)[0..], (*[1]u32)(&b)[0..]) == 7); +} +fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 { + return a[0] + b[0]; } -fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 { return a[0] + b[0]; } test "specifying alignment allows pointer cast" { testBytesAlign(0x33); } fn testBytesAlign(b: u8) void { - var bytes align(4) = []u8{b, b, b, b}; - const ptr = @ptrCast(&u32, &bytes[0]); - assert(*ptr == 0x33333333); + var bytes align(4) = []u8{ + b, + b, + b, + b, + }; + const ptr = @ptrCast(*u32, &bytes[0]); + assert(ptr.* == 0x33333333); } test "specifying alignment allows slice cast" { testBytesAlignSlice(0x33); } fn testBytesAlignSlice(b: u8) void { - var bytes align(4) = []u8{b, b, b, b}; - const slice = ([]u32)(bytes[0..]); + var bytes align(4) = []u8{ + b, + b, + b, + b, + }; + const slice: []u32 = @bytesToSlice(u32, bytes[0..]); assert(slice[0] == 0x33333333); } @@ -85,15 +99,18 @@ test "@alignCast pointers" { expectsOnly1(&x); assert(x == 2); } -fn expectsOnly1(x: &align(1) u32) void { +fn expectsOnly1(x: *align(1) u32) void { expects4(@alignCast(4, x)); } -fn expects4(x: &align(4) u32) void { - *x += 1; +fn expects4(x: *align(4) u32) void { + x.* += 1; } test "@alignCast slices" { - var array align(4) = []u32{1, 1}; + var array align(4) = []u32{ + 1, + 1, + }; const slice = array[0..]; sliceExpectsOnly1(slice); assert(slice[0] == 2); @@ -105,7 +122,6 @@ fn sliceExpects4(slice: []align(4) u32) void { slice[0] += 1; } - test "implicitly decreasing fn alignment" { testImplicitlyDecreaseFnAlign(alignedSmall, 1234); testImplicitlyDecreaseFnAlign(alignedBig, 5678); @@ -115,21 +131,25 @@ fn testImplicitlyDecreaseFnAlign(ptr: fn () align(1) i32, answer: i32) void { assert(ptr() == answer); } -fn alignedSmall() align(8) i32 { return 1234; } -fn alignedBig() align(16) i32 { return 5678; } - +fn alignedSmall() align(8) i32 { + return 1234; +} +fn alignedBig() align(16) i32 { + return 5678; +} test "@alignCast functions" { assert(fnExpectsOnly1(simple4) == 0x19); } -fn fnExpectsOnly1(ptr: fn()align(1) i32) i32 { +fn fnExpectsOnly1(ptr: fn () align(1) i32) i32 { return fnExpects4(@alignCast(4, ptr)); } -fn fnExpects4(ptr: fn()align(4) i32) i32 { +fn fnExpects4(ptr: fn () align(4) i32) i32 { return ptr(); } -fn simple4() align(4) i32 { return 0x19; } - +fn simple4() align(4) i32 { + return 0x19; +} test "generic function with align param" { assert(whyWouldYouEverDoThis(1) == 0x1); @@ -137,52 +157,53 @@ test "generic function with align param" { assert(whyWouldYouEverDoThis(8) == 0x1); } -fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 { return 0x1; } - +fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 { + return 0x1; +} test "@ptrCast preserves alignment of bigger source" { var x: u32 align(16) = 1234; - const ptr = @ptrCast(&u8, &x); - assert(@typeOf(ptr) == &align(16) u8); + const ptr = @ptrCast(*u8, &x); + assert(@typeOf(ptr) == *align(16) u8); } - -test "compile-time known array index has best alignment possible" { +test "runtime known array index has best alignment possible" { // take full advantage of over-alignment - var array align(4) = []u8 {1, 2, 3, 4}; - assert(@typeOf(&array[0]) == &align(4) u8); - assert(@typeOf(&array[1]) == &u8); - assert(@typeOf(&array[2]) == &align(2) u8); - assert(@typeOf(&array[3]) == &u8); + var array align(4) = []u8{ 1, 2, 3, 4 }; + assert(@typeOf(&array[0]) == *align(4) u8); + assert(@typeOf(&array[1]) == *u8); + assert(@typeOf(&array[2]) == *align(2) u8); + assert(@typeOf(&array[3]) == *u8); // because align is too small but we still figure out to use 2 - var bigger align(2) = []u64{1, 2, 3, 4}; - assert(@typeOf(&bigger[0]) == &align(2) u64); - assert(@typeOf(&bigger[1]) == &align(2) u64); - assert(@typeOf(&bigger[2]) == &align(2) u64); - assert(@typeOf(&bigger[3]) == &align(2) u64); + var bigger align(2) = []u64{ 1, 2, 3, 4 }; + assert(@typeOf(&bigger[0]) == *align(2) u64); + assert(@typeOf(&bigger[1]) == *align(2) u64); + assert(@typeOf(&bigger[2]) == *align(2) u64); + assert(@typeOf(&bigger[3]) == *align(2) u64); // because pointer is align 2 and u32 align % 2 == 0 we can assume align 2 - var smaller align(2) = []u32{1, 2, 3, 4}; - testIndex(&smaller[0], 0, &align(2) u32); - testIndex(&smaller[0], 1, &align(2) u32); - testIndex(&smaller[0], 2, &align(2) u32); - testIndex(&smaller[0], 3, &align(2) u32); + var smaller align(2) = []u32{ 1, 2, 3, 4 }; + comptime assert(@typeOf(smaller[0..]) == []align(2) u32); + comptime assert(@typeOf(smaller[0..].ptr) == [*]align(2) u32); + testIndex(smaller[0..].ptr, 0, *align(2) u32); + testIndex(smaller[0..].ptr, 1, *align(2) u32); + testIndex(smaller[0..].ptr, 2, *align(2) u32); + testIndex(smaller[0..].ptr, 3, *align(2) u32); // has to use ABI alignment because index known at runtime only - testIndex2(&array[0], 0, &u8); - testIndex2(&array[0], 1, &u8); - testIndex2(&array[0], 2, &u8); - testIndex2(&array[0], 3, &u8); + testIndex2(array[0..].ptr, 0, *u8); + testIndex2(array[0..].ptr, 1, *u8); + testIndex2(array[0..].ptr, 2, *u8); + testIndex2(array[0..].ptr, 3, *u8); } -fn testIndex(smaller: &align(2) u32, index: usize, comptime T: type) void { - assert(@typeOf(&smaller[index]) == T); +fn testIndex(smaller: [*]align(2) u32, index: usize, comptime T: type) void { + comptime assert(@typeOf(&smaller[index]) == T); } -fn testIndex2(ptr: &align(4) u8, index: usize, comptime T: type) void { - assert(@typeOf(&ptr[index]) == T); +fn testIndex2(ptr: [*]align(4) u8, index: usize, comptime T: type) void { + comptime assert(@typeOf(&ptr[index]) == T); } - test "alignstack" { assert(fnWithAlignedStack() == 1234); } diff --git a/test/cases/alignof.zig b/test/cases/alignof.zig index 27b95c7fdc..130a2a5b44 100644 --- a/test/cases/alignof.zig +++ b/test/cases/alignof.zig @@ -1,7 +1,11 @@ const assert = @import("std").debug.assert; const builtin = @import("builtin"); -const Foo = struct { x: u32, y: u32, z: u32, }; +const Foo = struct { + x: u32, + y: u32, + z: u32, +}; test "@alignOf(T) before referencing T" { comptime assert(@alignOf(Foo) != @maxValue(usize)); diff --git a/test/cases/array.zig b/test/cases/array.zig index 577161dd16..b72491bcc0 100644 --- a/test/cases/array.zig +++ b/test/cases/array.zig @@ -2,9 +2,9 @@ const assert = @import("std").debug.assert; const mem = @import("std").mem; test "arrays" { - var array : [5]u32 = undefined; + var array: [5]u32 = undefined; - var i : u32 = 0; + var i: u32 = 0; while (i < 5) { array[i] = i + 1; i = array[i]; @@ -34,24 +34,41 @@ test "void arrays" { } test "array literal" { - const hex_mult = []u16{4096, 256, 16, 1}; + const hex_mult = []u16{ + 4096, + 256, + 16, + 1, + }; assert(hex_mult.len == 4); assert(hex_mult[1] == 256); } test "array dot len const expr" { - assert(comptime x: {break :x some_array.len == 4;}); + assert(comptime x: { + break :x some_array.len == 4; + }); } const ArrayDotLenConstExpr = struct { y: [some_array.len]u8, }; -const some_array = []u8 {0, 1, 2, 3}; - +const some_array = []u8{ + 0, + 1, + 2, + 3, +}; test "nested arrays" { - const array_of_strings = [][]const u8 {"hello", "this", "is", "my", "thing"}; + const array_of_strings = [][]const u8{ + "hello", + "this", + "is", + "my", + "thing", + }; for (array_of_strings) |s, i| { if (i == 0) assert(mem.eql(u8, s, "hello")); if (i == 1) assert(mem.eql(u8, s, "this")); @@ -61,7 +78,6 @@ test "nested arrays" { } } - var s_array: [8]Sub = undefined; const Sub = struct { b: u8, @@ -70,7 +86,7 @@ const Str = struct { a: []Sub, }; test "set global var array via slice embedded in struct" { - var s = Str { .a = s_array[0..]}; + var s = Str{ .a = s_array[0..] }; s.a[0].b = 1; s.a[1].b = 2; @@ -82,7 +98,10 @@ test "set global var array via slice embedded in struct" { } test "array literal with specified size" { - var array = [2]u8{1, 2}; + var array = [2]u8{ + 1, + 2, + }; assert(array[0] == 1); assert(array[1] == 2); } @@ -96,3 +115,48 @@ test "array len property" { var x: [5]i32 = undefined; assert(@typeOf(x).len == 5); } + +test "array len field" { + var arr = [4]u8{ 0, 0, 0, 0 }; + var ptr = &arr; + assert(arr.len == 4); + comptime assert(arr.len == 4); + assert(ptr.len == 4); + comptime assert(ptr.len == 4); +} + +test "single-item pointer to array indexing and slicing" { + testSingleItemPtrArrayIndexSlice(); + comptime testSingleItemPtrArrayIndexSlice(); +} + +fn testSingleItemPtrArrayIndexSlice() void { + var array = "aaaa"; + doSomeMangling(&array); + assert(mem.eql(u8, "azya", array)); +} + +fn doSomeMangling(array: *[4]u8) void { + array[1] = 'z'; + array[2..3][0] = 'y'; +} + +test "implicit cast single-item pointer" { + testImplicitCastSingleItemPtr(); + comptime testImplicitCastSingleItemPtr(); +} + +fn testImplicitCastSingleItemPtr() void { + var byte: u8 = 100; + const slice = (*[1]u8)(&byte)[0..]; + slice[0] += 1; + assert(byte == 101); +} + +fn testArrayByValAtComptime(b: [2]u8) u8 { return b[0]; } + +test "comptime evalutating function that takes array by value" { + const arr = []u8{0,1}; + _ = comptime testArrayByValAtComptime(arr); + _ = comptime testArrayByValAtComptime(arr); +} diff --git a/test/cases/atomics.zig b/test/cases/atomics.zig index e8e81b76e6..67c9ab3dd1 100644 --- a/test/cases/atomics.zig +++ b/test/cases/atomics.zig @@ -1,12 +1,24 @@ -const assert = @import("std").debug.assert; +const std = @import("std"); +const assert = std.debug.assert; const builtin = @import("builtin"); const AtomicRmwOp = builtin.AtomicRmwOp; const AtomicOrder = builtin.AtomicOrder; test "cmpxchg" { var x: i32 = 1234; - while (!@cmpxchg(&x, 1234, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) {} + if (@cmpxchgWeak(i32, &x, 99, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| { + assert(x1 == 1234); + } else { + @panic("cmpxchg should have failed"); + } + + while (@cmpxchgWeak(i32, &x, 1234, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| { + assert(x1 == 1234); + } assert(x == 5678); + + assert(@cmpxchgStrong(i32, &x, 5678, 42, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null); + assert(x == 42); } test "fence" { @@ -15,13 +27,45 @@ test "fence" { x = 5678; } -test "atomicrmw" { +test "atomicrmw and atomicload" { var data: u8 = 200; testAtomicRmw(&data); assert(data == 42); + testAtomicLoad(&data); } -fn testAtomicRmw(ptr: &u8) void { +fn testAtomicRmw(ptr: *u8) void { const prev_value = @atomicRmw(u8, ptr, AtomicRmwOp.Xchg, 42, AtomicOrder.SeqCst); assert(prev_value == 200); + comptime { + var x: i32 = 1234; + const y: i32 = 12345; + assert(@atomicLoad(i32, &x, AtomicOrder.SeqCst) == 1234); + assert(@atomicLoad(i32, &y, AtomicOrder.SeqCst) == 12345); + } +} + +fn testAtomicLoad(ptr: *u8) void { + const x = @atomicLoad(u8, ptr, AtomicOrder.SeqCst); + assert(x == 42); +} + +test "cmpxchg with ptr" { + var data1: i32 = 1234; + var data2: i32 = 5678; + var data3: i32 = 9101; + var x: *i32 = &data1; + if (@cmpxchgWeak(*i32, &x, &data2, &data3, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| { + assert(x1 == &data1); + } else { + @panic("cmpxchg should have failed"); + } + + while (@cmpxchgWeak(*i32, &x, &data1, &data3, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| { + assert(x1 == &data1); + } + assert(x == &data3); + + assert(@cmpxchgStrong(*i32, &x, &data3, &data2, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null); + assert(x == &data2); } diff --git a/test/cases/bitcast.zig b/test/cases/bitcast.zig index f1f2ccd672..878140954a 100644 --- a/test/cases/bitcast.zig +++ b/test/cases/bitcast.zig @@ -10,5 +10,9 @@ fn testBitCast_i32_u32() void { assert(conv2(@maxValue(u32)) == -1); } -fn conv(x: i32) u32 { return @bitCast(u32, x); } -fn conv2(x: u32) i32 { return @bitCast(i32, x); } +fn conv(x: i32) u32 { + return @bitCast(u32, x); +} +fn conv2(x: u32) i32 { + return @bitCast(i32, x); +} diff --git a/test/cases/bool.zig b/test/cases/bool.zig index 07d30454ee..3e4ac9c1cf 100644 --- a/test/cases/bool.zig +++ b/test/cases/bool.zig @@ -8,14 +8,14 @@ test "bool literals" { test "cast bool to int" { const t = true; const f = false; - assert(i32(t) == i32(1)); - assert(i32(f) == i32(0)); + assert(@boolToInt(t) == u32(1)); + assert(@boolToInt(f) == u32(0)); nonConstCastBoolToInt(t, f); } fn nonConstCastBoolToInt(t: bool, f: bool) void { - assert(i32(t) == i32(1)); - assert(i32(f) == i32(0)); + assert(@boolToInt(t) == u32(1)); + assert(@boolToInt(f) == u32(0)); } test "bool cmp" { diff --git a/test/cases/bugs/1111.zig b/test/cases/bugs/1111.zig new file mode 100644 index 0000000000..f62107f9a3 --- /dev/null +++ b/test/cases/bugs/1111.zig @@ -0,0 +1,12 @@ +const Foo = extern enum { + Bar = -1, +}; + +test "issue 1111 fixed" { + const v = Foo.Bar; + + switch (v) { + Foo.Bar => return, + else => return, + } +} diff --git a/test/cases/bugs/1230.zig b/test/cases/bugs/1230.zig new file mode 100644 index 0000000000..b782a77f0b --- /dev/null +++ b/test/cases/bugs/1230.zig @@ -0,0 +1,14 @@ +const assert = @import("std").debug.assert; + +const S = extern struct { + x: i32, +}; + +extern fn ret_struct() S { + return S{ .x = 42 }; +} + +test "extern return small struct (bug 1230)" { + const s = ret_struct(); + assert(s.x == 42); +} diff --git a/test/cases/bugs/394.zig b/test/cases/bugs/394.zig index 071619d59c..b0afec2357 100644 --- a/test/cases/bugs/394.zig +++ b/test/cases/bugs/394.zig @@ -1,9 +1,18 @@ -const E = union(enum) { A: [9]u8, B: u64, }; -const S = struct { x: u8, y: E, }; +const E = union(enum) { + A: [9]u8, + B: u64, +}; +const S = struct { + x: u8, + y: E, +}; const assert = @import("std").debug.assert; test "bug 394 fixed" { - const x = S { .x = 3, .y = E {.B = 1 } }; + const x = S{ + .x = 3, + .y = E{ .B = 1 }, + }; assert(x.x == 3); } diff --git a/test/cases/bugs/655.zig b/test/cases/bugs/655.zig index e6a275004c..50374d4e6d 100644 --- a/test/cases/bugs/655.zig +++ b/test/cases/bugs/655.zig @@ -3,10 +3,10 @@ const other_file = @import("655_other_file.zig"); test "function with &const parameter with type dereferenced by namespace" { const x: other_file.Integer = 1234; - comptime std.debug.assert(@typeOf(&x) == &const other_file.Integer); + comptime std.debug.assert(@typeOf(&x) == *const other_file.Integer); foo(x); } -fn foo(x: &const other_file.Integer) void { - std.debug.assert(*x == 1234); +fn foo(x: *const other_file.Integer) void { + std.debug.assert(x.* == 1234); } diff --git a/test/cases/bugs/656.zig b/test/cases/bugs/656.zig index ce3eec8046..f93f0ac4d5 100644 --- a/test/cases/bugs/656.zig +++ b/test/cases/bugs/656.zig @@ -9,17 +9,18 @@ const Value = struct { align_expr: ?u32, }; -test "nullable if after an if in a switch prong of a switch with 2 prongs in an else" { +test "optional if after an if in a switch prong of a switch with 2 prongs in an else" { foo(false, true); } fn foo(a: bool, b: bool) void { - var prefix_op = PrefixOp { .AddrOf = Value { .align_expr = 1234 } }; - if (a) { - } else { + var prefix_op = PrefixOp{ + .AddrOf = Value{ .align_expr = 1234 }, + }; + if (a) {} else { switch (prefix_op) { PrefixOp.AddrOf => |addr_of_info| { - if (b) { } + if (b) {} if (addr_of_info.align_expr) |align_expr| { assert(align_expr == 1234); } diff --git a/test/cases/bugs/828.zig b/test/cases/bugs/828.zig index c46548cb7a..50ae0fd279 100644 --- a/test/cases/bugs/828.zig +++ b/test/cases/bugs/828.zig @@ -1,31 +1,27 @@ const CountBy = struct { a: usize, - - const One = CountBy { - .a = 1, - }; - - pub fn counter(self: &const CountBy) Counter { - return Counter { - .i = 0, - }; + + const One = CountBy{ .a = 1 }; + + pub fn counter(self: *const CountBy) Counter { + return Counter{ .i = 0 }; } }; const Counter = struct { i: usize, - - pub fn count(self: &Counter) bool { + + pub fn count(self: *Counter) bool { self.i += 1; return self.i <= 10; } }; -fn constCount(comptime cb: &const CountBy, comptime unused: u32) void { +fn constCount(comptime cb: *const CountBy, comptime unused: u32) void { comptime { var cnt = cb.counter(); - if(cnt.i != 0) @compileError("Counter instance reused!"); - while(cnt.count()){} + if (cnt.i != 0) @compileError("Counter instance reused!"); + while (cnt.count()) {} } } diff --git a/test/cases/bugs/920.zig b/test/cases/bugs/920.zig new file mode 100644 index 0000000000..2903f05a29 --- /dev/null +++ b/test/cases/bugs/920.zig @@ -0,0 +1,65 @@ +const std = @import("std"); +const math = std.math; +const Random = std.rand.Random; + +const ZigTable = struct { + r: f64, + x: [257]f64, + f: [257]f64, + + pdf: fn (f64) f64, + is_symmetric: bool, + zero_case: fn (*Random, f64) f64, +}; + +fn ZigTableGen(comptime is_symmetric: bool, comptime r: f64, comptime v: f64, comptime f: fn (f64) f64, comptime f_inv: fn (f64) f64, comptime zero_case: fn (*Random, f64) f64) ZigTable { + var tables: ZigTable = undefined; + + tables.is_symmetric = is_symmetric; + tables.r = r; + tables.pdf = f; + tables.zero_case = zero_case; + + tables.x[0] = v / f(r); + tables.x[1] = r; + + for (tables.x[2..256]) |*entry, i| { + const last = tables.x[2 + i - 1]; + entry.* = f_inv(v / last + f(last)); + } + tables.x[256] = 0; + + for (tables.f[0..]) |*entry, i| { + entry.* = f(tables.x[i]); + } + + return tables; +} + +const norm_r = 3.6541528853610088; +const norm_v = 0.00492867323399; + +fn norm_f(x: f64) f64 { + return math.exp(-x * x / 2.0); +} +fn norm_f_inv(y: f64) f64 { + return math.sqrt(-2.0 * math.ln(y)); +} +fn norm_zero_case(random: *Random, u: f64) f64 { + return 0.0; +} + +const NormalDist = blk: { + @setEvalBranchQuota(30000); + break :blk ZigTableGen(true, norm_r, norm_v, norm_f, norm_f_inv, norm_zero_case); +}; + +test "bug 920 fixed" { + const NormalDist1 = blk: { + break :blk ZigTableGen(true, norm_r, norm_v, norm_f, norm_f_inv, norm_zero_case); + }; + + for (NormalDist1.f) |_, i| { + std.debug.assert(NormalDist1.f[i] == NormalDist.f[i]); + } +} diff --git a/test/cases/byval_arg_var.zig b/test/cases/byval_arg_var.zig new file mode 100644 index 0000000000..826b9cc9e5 --- /dev/null +++ b/test/cases/byval_arg_var.zig @@ -0,0 +1,27 @@ +const std = @import("std"); + +var result: []const u8 = "wrong"; + +test "aoeu" { + start(); + blowUpStack(10); + + std.debug.assert(std.mem.eql(u8, result, "string literal")); +} + +fn start() void { + foo("string literal"); +} + +fn foo(x: var) void { + bar(x); +} + +fn bar(x: var) void { + result = x; +} + +fn blowUpStack(x: u32) void { + if (x == 0) return; + blowUpStack(x - 1); +} diff --git a/test/cases/cancel.zig b/test/cases/cancel.zig new file mode 100644 index 0000000000..c0f74fd34f --- /dev/null +++ b/test/cases/cancel.zig @@ -0,0 +1,92 @@ +const std = @import("std"); + +var defer_f1: bool = false; +var defer_f2: bool = false; +var defer_f3: bool = false; + +test "cancel forwards" { + var da = std.heap.DirectAllocator.init(); + defer da.deinit(); + + const p = async<&da.allocator> f1() catch unreachable; + cancel p; + std.debug.assert(defer_f1); + std.debug.assert(defer_f2); + std.debug.assert(defer_f3); +} + +async fn f1() void { + defer { + defer_f1 = true; + } + await (async f2() catch unreachable); +} + +async fn f2() void { + defer { + defer_f2 = true; + } + await (async f3() catch unreachable); +} + +async fn f3() void { + defer { + defer_f3 = true; + } + suspend; +} + +var defer_b1: bool = false; +var defer_b2: bool = false; +var defer_b3: bool = false; +var defer_b4: bool = false; + +test "cancel backwards" { + var da = std.heap.DirectAllocator.init(); + defer da.deinit(); + + const p = async<&da.allocator> b1() catch unreachable; + cancel p; + std.debug.assert(defer_b1); + std.debug.assert(defer_b2); + std.debug.assert(defer_b3); + std.debug.assert(defer_b4); +} + +async fn b1() void { + defer { + defer_b1 = true; + } + await (async b2() catch unreachable); +} + +var b4_handle: promise = undefined; + +async fn b2() void { + const b3_handle = async b3() catch unreachable; + resume b4_handle; + cancel b4_handle; + defer { + defer_b2 = true; + } + const value = await b3_handle; + @panic("unreachable"); +} + +async fn b3() i32 { + defer { + defer_b3 = true; + } + await (async b4() catch unreachable); + return 1234; +} + +async fn b4() void { + defer { + defer_b4 = true; + } + suspend { + b4_handle = @handle(); + } + suspend; +} diff --git a/test/cases/cast.zig b/test/cases/cast.zig index 024ece0055..63cc6313e1 100644 --- a/test/cases/cast.zig +++ b/test/cases/cast.zig @@ -1,23 +1,24 @@ -const assert = @import("std").debug.assert; -const mem = @import("std").mem; +const std = @import("std"); +const assert = std.debug.assert; +const mem = std.mem; test "int to ptr cast" { const x = usize(13); - const y = @intToPtr(&u8, x); + const y = @intToPtr(*u8, x); const z = @ptrToInt(y); assert(z == 13); } test "integer literal to pointer cast" { - const vga_mem = @intToPtr(&u16, 0xB8000); + const vga_mem = @intToPtr(*u16, 0xB8000); assert(@ptrToInt(vga_mem) == 0xB8000); } test "pointer reinterpret const float to int" { const float: f64 = 5.99999999999994648725e-01; const float_ptr = &float; - const int_ptr = @ptrCast(&const i32, float_ptr); - const int_val = *int_ptr; + const int_ptr = @ptrCast(*const i32, float_ptr); + const int_val = int_ptr.*; assert(int_val == 858993411); } @@ -28,26 +29,26 @@ test "implicitly cast a pointer to a const pointer of it" { assert(x == 2); } -fn funcWithConstPtrPtr(x: &const &i32) void { - **x += 1; +fn funcWithConstPtrPtr(x: *const *i32) void { + x.*.* += 1; } test "implicitly cast a container to a const pointer of it" { - const z = Struct(void) { .x = void{} }; + const z = Struct(void){ .x = void{} }; assert(0 == @sizeOf(@typeOf(z))); assert(void{} == Struct(void).pointer(z).x); assert(void{} == Struct(void).pointer(&z).x); assert(void{} == Struct(void).maybePointer(z).x); assert(void{} == Struct(void).maybePointer(&z).x); assert(void{} == Struct(void).maybePointer(null).x); - const s = Struct(u8) { .x = 42 }; + const s = Struct(u8){ .x = 42 }; assert(0 != @sizeOf(@typeOf(s))); assert(42 == Struct(u8).pointer(s).x); assert(42 == Struct(u8).pointer(&s).x); assert(42 == Struct(u8).maybePointer(s).x); assert(42 == Struct(u8).maybePointer(&s).x); assert(0 == Struct(u8).maybePointer(null).x); - const u = Union { .x = 42 }; + const u = Union{ .x = 42 }; assert(42 == Union.pointer(u).x); assert(42 == Union.pointer(&u).x); assert(42 == Union.maybePointer(u).x); @@ -66,13 +67,13 @@ fn Struct(comptime T: type) type { const Self = this; x: T, - fn pointer(self: &const Self) Self { - return *self; + fn pointer(self: *const Self) Self { + return self.*; } - fn maybePointer(self: ?&const Self) Self { - const none = Self { .x = if (T == void) void{} else 0 }; - return *(self ?? &none); + fn maybePointer(self: ?*const Self) Self { + const none = Self{ .x = if (T == void) void{} else 0 }; + return (self orelse &none).*; } }; } @@ -80,13 +81,13 @@ fn Struct(comptime T: type) type { const Union = union { x: u8, - fn pointer(self: &const Union) Union { - return *self; + fn pointer(self: *const Union) Union { + return self.*; } - fn maybePointer(self: ?&const Union) Union { - const none = Union { .x = 0 }; - return *(self ?? &none); + fn maybePointer(self: ?*const Union) Union { + const none = Union{ .x = 0 }; + return (self orelse &none).*; } }; @@ -94,12 +95,12 @@ const Enum = enum { None, Some, - fn pointer(self: &const Enum) Enum { - return *self; + fn pointer(self: *const Enum) Enum { + return self.*; } - fn maybePointer(self: ?&const Enum) Enum { - return *(self ?? &Enum.None); + fn maybePointer(self: ?*const Enum) Enum { + return (self orelse &Enum.None).*; } }; @@ -107,20 +108,20 @@ test "implicitly cast indirect pointer to maybe-indirect pointer" { const S = struct { const Self = this; x: u8, - fn constConst(p: &const &const Self) u8 { - return (*p).x; + fn constConst(p: *const *const Self) u8 { + return p.*.x; } - fn maybeConstConst(p: ?&const &const Self) u8 { - return (*??p).x; + fn maybeConstConst(p: ?*const *const Self) u8 { + return p.?.*.x; } - fn constConstConst(p: &const &const &const Self) u8 { - return (**p).x; + fn constConstConst(p: *const *const *const Self) u8 { + return p.*.*.x; } - fn maybeConstConstConst(p: ?&const &const &const Self) u8 { - return (**??p).x; + fn maybeConstConstConst(p: ?*const *const *const Self) u8 { + return p.?.*.*.x; } }; - const s = S { .x = 42 }; + const s = S{ .x = 42 }; const p = &s; const q = &p; const r = &q; @@ -139,8 +140,8 @@ test "explicit cast from integer to error type" { comptime testCastIntToErr(error.ItBroke); } fn testCastIntToErr(err: error) void { - const x = usize(err); - const y = error(x); + const x = @errorToInt(err); + const y = @intToError(x); assert(error.ItBroke == y); } @@ -154,7 +155,6 @@ fn boolToStr(b: bool) []const u8 { return if (b) "true" else "false"; } - test "peer resolve array and const slice" { testPeerResolveArrayConstSlice(true); comptime testPeerResolveArrayConstSlice(true); @@ -167,67 +167,66 @@ fn testPeerResolveArrayConstSlice(b: bool) void { } test "integer literal to &const int" { - const x: &const i32 = 3; - assert(*x == 3); + const x: *const i32 = 3; + assert(x.* == 3); } test "string literal to &const []const u8" { - const x: &const []const u8 = "hello"; - assert(mem.eql(u8, *x, "hello")); + const x: *const []const u8 = "hello"; + assert(mem.eql(u8, x.*, "hello")); } test "implicitly cast from T to error!?T" { - castToMaybeTypeError(1); - comptime castToMaybeTypeError(1); + castToOptionalTypeError(1); + comptime castToOptionalTypeError(1); } const A = struct { a: i32, }; -fn castToMaybeTypeError(z: i32) void { +fn castToOptionalTypeError(z: i32) void { const x = i32(1); const y: error!?i32 = x; - assert(??(try y) == 1); + assert((try y).? == 1); const f = z; const g: error!?i32 = f; const a = A{ .a = z }; const b: error!?A = a; - assert((??(b catch unreachable)).a == 1); + assert((b catch unreachable).?.a == 1); } test "implicitly cast from int to error!?T" { - implicitIntLitToMaybe(); - comptime implicitIntLitToMaybe(); + implicitIntLitToOptional(); + comptime implicitIntLitToOptional(); } -fn implicitIntLitToMaybe() void { +fn implicitIntLitToOptional() void { const f: ?i32 = 1; const g: error!?i32 = 1; } - test "return null from fn() error!?&T" { - const a = returnNullFromMaybeTypeErrorRef(); - const b = returnNullLitFromMaybeTypeErrorRef(); + const a = returnNullFromOptionalTypeErrorRef(); + const b = returnNullLitFromOptionalTypeErrorRef(); assert((try a) == null and (try b) == null); } -fn returnNullFromMaybeTypeErrorRef() error!?&A { - const a: ?&A = null; +fn returnNullFromOptionalTypeErrorRef() error!?*A { + const a: ?*A = null; return a; } -fn returnNullLitFromMaybeTypeErrorRef() error!?&A { +fn returnNullLitFromOptionalTypeErrorRef() error!?*A { return null; } test "peer type resolution: ?T and T" { - assert(??peerTypeTAndMaybeT(true, false) == 0); - assert(??peerTypeTAndMaybeT(false, false) == 3); + assert(peerTypeTAndOptionalT(true, false).? == 0); + assert(peerTypeTAndOptionalT(false, false).? == 3); comptime { - assert(??peerTypeTAndMaybeT(true, false) == 0); - assert(??peerTypeTAndMaybeT(false, false) == 3); + assert(peerTypeTAndOptionalT(true, false).? == 0); + assert(peerTypeTAndOptionalT(false, false).? == 3); } } -fn peerTypeTAndMaybeT(c: bool, b: bool) ?usize { +fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize { if (c) { return if (b) null else usize(0); } @@ -235,7 +234,6 @@ fn peerTypeTAndMaybeT(c: bool, b: bool) ?usize { return usize(3); } - test "peer type resolution: [0]u8 and []const u8" { assert(peerTypeEmptyArrayAndSlice(true, "hi").len == 0); assert(peerTypeEmptyArrayAndSlice(false, "hi").len == 1); @@ -246,22 +244,21 @@ test "peer type resolution: [0]u8 and []const u8" { } fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 { if (a) { - return []const u8 {}; + return []const u8{}; } return slice[0..1]; } test "implicitly cast from [N]T to ?[]const T" { - assert(mem.eql(u8, ??castToMaybeSlice(), "hi")); - comptime assert(mem.eql(u8, ??castToMaybeSlice(), "hi")); + assert(mem.eql(u8, castToOptionalSlice().?, "hi")); + comptime assert(mem.eql(u8, castToOptionalSlice().?, "hi")); } -fn castToMaybeSlice() ?[]const u8 { +fn castToOptionalSlice() ?[]const u8 { return "hi"; } - test "implicitly cast from [0]T to error![]T" { testCastZeroArrayToErrSliceMut(); comptime testCastZeroArrayToErrSliceMut(); @@ -316,25 +313,15 @@ test "implicit cast from &const [N]T to []const T" { fn testCastConstArrayRefToConstSlice() void { const blah = "aoeu"; const const_array_ref = &blah; - assert(@typeOf(const_array_ref) == &const [4]u8); + assert(@typeOf(const_array_ref) == *const [4]u8); const slice: []const u8 = const_array_ref; assert(mem.eql(u8, slice, "aoeu")); } -test "var args implicitly casts by value arg to const ref" { - foo("hello"); -} - -fn foo(args: ...) void { - assert(@typeOf(args[0]) == &const [5]u8); -} - - test "peer type resolution: error and [N]T" { // TODO: implicit error!T to error!U where T can implicitly cast to U //assert(mem.eql(u8, try testPeerErrorAndArray(0), "OK")); //comptime assert(mem.eql(u8, try testPeerErrorAndArray(0), "OK")); - assert(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK")); comptime assert(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK")); } @@ -353,11 +340,26 @@ fn testPeerErrorAndArray2(x: u8) error![]const u8 { }; } -test "explicit cast float number literal to integer if no fraction component" { +test "@floatToInt" { + testFloatToInts(); + comptime testFloatToInts(); +} + +fn testFloatToInts() void { const x = i32(1e4); assert(x == 10000); - const y = i32(f32(1e4)); + const y = @floatToInt(i32, f32(1e4)); assert(y == 10000); + expectFloatToInt(f16, 255.1, u8, 255); + expectFloatToInt(f16, 127.2, i8, 127); + expectFloatToInt(f16, -128.2, i8, -128); + expectFloatToInt(f32, 255.1, u8, 255); + expectFloatToInt(f32, 127.2, i8, 127); + expectFloatToInt(f32, -128.2, i8, -128); +} + +fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) void { + assert(@floatToInt(I, f) == i); } test "cast u128 to f128 and back" { @@ -378,10 +380,108 @@ fn cast128Float(x: u128) f128 { } test "const slice widen cast" { - const bytes align(4) = []u8{0x12, 0x12, 0x12, 0x12}; + const bytes align(4) = []u8{ + 0x12, + 0x12, + 0x12, + 0x12, + }; - const u32_value = ([]const u32)(bytes[0..])[0]; + const u32_value = @bytesToSlice(u32, bytes[0..])[0]; assert(u32_value == 0x12121212); assert(@bitCast(u32, bytes) == 0x12121212); } + +test "single-item pointer of array to slice and to unknown length pointer" { + testCastPtrOfArrayToSliceAndPtr(); + comptime testCastPtrOfArrayToSliceAndPtr(); +} + +fn testCastPtrOfArrayToSliceAndPtr() void { + var array = "ao" ++ "eu"; // TODO https://github.com/ziglang/zig/issues/1076 + const x: [*]u8 = &array; + x[0] += 1; + assert(mem.eql(u8, array[0..], "boeu")); + const y: []u8 = &array; + y[0] += 1; + assert(mem.eql(u8, array[0..], "coeu")); +} + +test "cast *[1][*]const u8 to [*]const ?[*]const u8" { + const window_name = [1][*]const u8{c"window name"}; + const x: [*]const ?[*]const u8 = &window_name; + assert(mem.eql(u8, std.cstr.toSliceConst(x[0].?), "window name")); +} + +test "@intCast comptime_int" { + const result = @intCast(i32, 1234); + assert(@typeOf(result) == i32); + assert(result == 1234); +} + +test "@floatCast comptime_int and comptime_float" { + { + const result = @floatCast(f16, 1234); + assert(@typeOf(result) == f16); + assert(result == 1234.0); + } + { + const result = @floatCast(f16, 1234.0); + assert(@typeOf(result) == f16); + assert(result == 1234.0); + } + { + const result = @floatCast(f32, 1234); + assert(@typeOf(result) == f32); + assert(result == 1234.0); + } + { + const result = @floatCast(f32, 1234.0); + assert(@typeOf(result) == f32); + assert(result == 1234.0); + } +} + +test "comptime_int @intToFloat" { + { + const result = @intToFloat(f16, 1234); + assert(@typeOf(result) == f16); + assert(result == 1234.0); + } + { + const result = @intToFloat(f32, 1234); + assert(@typeOf(result) == f32); + assert(result == 1234.0); + } +} + +test "@bytesToSlice keeps pointer alignment" { + var bytes = []u8{ 0x01, 0x02, 0x03, 0x04 }; + const numbers = @bytesToSlice(u32, bytes[0..]); + comptime assert(@typeOf(numbers) == []align(@alignOf(@typeOf(bytes))) u32); +} + +test "@intCast i32 to u7" { + var x: u128 = @maxValue(u128); + var y: i32 = 120; + var z = x >> @intCast(u7, y); + assert(z == 0xff); +} + +test "implicit cast undefined to optional" { + assert(MakeType(void).getNull() == null); + assert(MakeType(void).getNonNull() != null); +} + +fn MakeType(comptime T: type) type { + return struct { + fn getNull() ?T { + return null; + } + + fn getNonNull() ?T { + return T(undefined); + } + }; +} diff --git a/test/cases/const_slice_child.zig b/test/cases/const_slice_child.zig index 456b115234..07d02d5df0 100644 --- a/test/cases/const_slice_child.zig +++ b/test/cases/const_slice_child.zig @@ -1,15 +1,16 @@ const debug = @import("std").debug; const assert = debug.assert; -var argv: &const &const u8 = undefined; +var argv: [*]const [*]const u8 = undefined; test "const slice child" { - const strs = ([]&const u8) { + const strs = ([][*]const u8){ c"one", c"two", c"three", }; - argv = &strs[0]; + // TODO this should implicitly cast + argv = @ptrCast([*]const [*]const u8, &strs); bar(strs.len); } @@ -29,7 +30,7 @@ fn bar(argc: usize) void { foo(args); } -fn strlen(ptr: &const u8) usize { +fn strlen(ptr: [*]const u8) usize { var count: usize = 0; while (ptr[count] != 0) : (count += 1) {} return count; diff --git a/test/cases/coroutine_await_struct.zig b/test/cases/coroutine_await_struct.zig new file mode 100644 index 0000000000..79168715d8 --- /dev/null +++ b/test/cases/coroutine_await_struct.zig @@ -0,0 +1,47 @@ +const std = @import("std"); +const builtin = @import("builtin"); +const assert = std.debug.assert; + +const Foo = struct { + x: i32, +}; + +var await_a_promise: promise = undefined; +var await_final_result = Foo{ .x = 0 }; + +test "coroutine await struct" { + var da = std.heap.DirectAllocator.init(); + defer da.deinit(); + + await_seq('a'); + const p = async<&da.allocator> await_amain() catch unreachable; + await_seq('f'); + resume await_a_promise; + await_seq('i'); + assert(await_final_result.x == 1234); + assert(std.mem.eql(u8, await_points, "abcdefghi")); +} +async fn await_amain() void { + await_seq('b'); + const p = async await_another() catch unreachable; + await_seq('e'); + await_final_result = await p; + await_seq('h'); +} +async fn await_another() Foo { + await_seq('c'); + suspend { + await_seq('d'); + await_a_promise = @handle(); + } + await_seq('g'); + return Foo{ .x = 1234 }; +} + +var await_points = []u8{0} ** "abcdefghi".len; +var await_seq_index: usize = 0; + +fn await_seq(c: u8) void { + await_points[await_seq_index] = c; + await_seq_index += 1; +} diff --git a/test/cases/coroutines.zig b/test/cases/coroutines.zig index 6d28b98c9d..bd6b6abf6f 100644 --- a/test/cases/coroutines.zig +++ b/test/cases/coroutines.zig @@ -5,12 +5,14 @@ const assert = std.debug.assert; var x: i32 = 1; test "create a coroutine and cancel it" { - const p = try async<std.debug.global_allocator> simpleAsyncFn(); + var da = std.heap.DirectAllocator.init(); + defer da.deinit(); + + const p = try async<&da.allocator> simpleAsyncFn(); comptime assert(@typeOf(p) == promise->void); cancel p; assert(x == 2); } - async fn simpleAsyncFn() void { x += 1; suspend; @@ -18,8 +20,11 @@ async fn simpleAsyncFn() void { } test "coroutine suspend, resume, cancel" { + var da = std.heap.DirectAllocator.init(); + defer da.deinit(); + seq('a'); - const p = try async<std.debug.global_allocator> testAsyncSeq(); + const p = try async<&da.allocator> testAsyncSeq(); seq('c'); resume p; seq('f'); @@ -28,7 +33,6 @@ test "coroutine suspend, resume, cancel" { assert(std.mem.eql(u8, points, "abcdefg")); } - async fn testAsyncSeq() void { defer seq('e'); @@ -45,7 +49,10 @@ fn seq(c: u8) void { } test "coroutine suspend with block" { - const p = try async<std.debug.global_allocator> testSuspendBlock(); + var da = std.heap.DirectAllocator.init(); + defer da.deinit(); + + const p = try async<&da.allocator> testSuspendBlock(); std.debug.assert(!result); resume a_promise; std.debug.assert(result); @@ -54,12 +61,16 @@ test "coroutine suspend with block" { var a_promise: promise = undefined; var result = false; - async fn testSuspendBlock() void { - suspend |p| { - comptime assert(@typeOf(p) == promise->void); - a_promise = p; + suspend { + comptime assert(@typeOf(@handle()) == promise->void); + a_promise = @handle(); } + + //Test to make sure that @handle() works as advertised (issue #1296) + //var our_handle: promise = @handle(); + assert( a_promise == @handle() ); + result = true; } @@ -67,15 +78,17 @@ var await_a_promise: promise = undefined; var await_final_result: i32 = 0; test "coroutine await" { + var da = std.heap.DirectAllocator.init(); + defer da.deinit(); + await_seq('a'); - const p = async<std.debug.global_allocator> await_amain() catch unreachable; + const p = async<&da.allocator> await_amain() catch unreachable; await_seq('f'); resume await_a_promise; await_seq('i'); assert(await_final_result == 1234); assert(std.mem.eql(u8, await_points, "abcdefghi")); } - async fn await_amain() void { await_seq('b'); const p = async await_another() catch unreachable; @@ -83,12 +96,11 @@ async fn await_amain() void { await_final_result = await p; await_seq('h'); } - async fn await_another() i32 { await_seq('c'); - suspend |p| { + suspend { await_seq('d'); - await_a_promise = p; + await_a_promise = @handle(); } await_seq('g'); return 1234; @@ -102,25 +114,25 @@ fn await_seq(c: u8) void { await_seq_index += 1; } - var early_final_result: i32 = 0; test "coroutine await early return" { + var da = std.heap.DirectAllocator.init(); + defer da.deinit(); + early_seq('a'); - const p = async<std.debug.global_allocator> early_amain() catch unreachable; + const p = async<&da.allocator> early_amain() catch @panic("out of memory"); early_seq('f'); assert(early_final_result == 1234); assert(std.mem.eql(u8, early_points, "abcdef")); } - async fn early_amain() void { early_seq('b'); - const p = async early_another() catch unreachable; + const p = async early_another() catch @panic("out of memory"); early_seq('d'); early_final_result = await p; early_seq('e'); } - async fn early_another() i32 { early_seq('c'); return 1234; @@ -142,7 +154,6 @@ test "coro allocation failure" { error.OutOfMemory => {}, } } - async fn asyncFuncThatNeverGetsRun() void { @panic("coro frame allocation should fail"); } @@ -155,7 +166,9 @@ test "async function with dot syntax" { suspend; } }; - const p = try async<std.debug.global_allocator> S.foo(); + var da = std.heap.DirectAllocator.init(); + defer da.deinit(); + const p = try async<&da.allocator> S.foo(); cancel p; assert(S.y == 2); } @@ -163,29 +176,29 @@ test "async function with dot syntax" { test "async fn pointer in a struct field" { var data: i32 = 1; const Foo = struct { - bar: async<&std.mem.Allocator> fn(&i32) void, + bar: async<*std.mem.Allocator> fn (*i32) void, }; - var foo = Foo { - .bar = simpleAsyncFn2, - }; - const p = (async<std.debug.global_allocator> foo.bar(&data)) catch unreachable; + var foo = Foo{ .bar = simpleAsyncFn2 }; + var da = std.heap.DirectAllocator.init(); + defer da.deinit(); + const p = (async<&da.allocator> foo.bar(&data)) catch unreachable; assert(data == 2); cancel p; assert(data == 4); } - -async<&std.mem.Allocator> fn simpleAsyncFn2(y: &i32) void { - defer *y += 2; - *y += 1; +async<*std.mem.Allocator> fn simpleAsyncFn2(y: *i32) void { + defer y.* += 2; + y.* += 1; suspend; } test "async fn with inferred error set" { - const p = (async<std.debug.global_allocator> failing()) catch unreachable; + var da = std.heap.DirectAllocator.init(); + defer da.deinit(); + const p = (async<&da.allocator> failing()) catch unreachable; resume p; cancel p; } - async fn failing() !void { suspend; return error.Fail; @@ -194,7 +207,9 @@ async fn failing() !void { test "error return trace across suspend points - early return" { const p = nonFailing(); resume p; - const p2 = try async<std.debug.global_allocator> printTrace(p); + var da = std.heap.DirectAllocator.init(); + defer da.deinit(); + const p2 = try async<&da.allocator> printTrace(p); cancel p2; } @@ -205,22 +220,39 @@ test "error return trace across suspend points - async return" { cancel p2; } -fn nonFailing() promise->error!void { +// TODO https://github.com/ziglang/zig/issues/760 +fn nonFailing() (promise->error!void) { return async<std.debug.global_allocator> suspendThenFail() catch unreachable; } - async fn suspendThenFail() error!void { suspend; return error.Fail; } - async fn printTrace(p: promise->error!void) void { (await p) catch |e| { std.debug.assert(e == error.Fail); if (@errorReturnTrace()) |trace| { assert(trace.index == 1); - } else if (builtin.mode != builtin.Mode.ReleaseFast) { - @panic("expected return trace"); + } else switch (builtin.mode) { + builtin.Mode.Debug, builtin.Mode.ReleaseSafe => @panic("expected return trace"), + builtin.Mode.ReleaseFast, builtin.Mode.ReleaseSmall => {}, } }; } + +test "break from suspend" { + var buf: [500]u8 = undefined; + var a = &std.heap.FixedBufferAllocator.init(buf[0..]).allocator; + var my_result: i32 = 1; + const p = try async<a> testBreakFromSuspend(&my_result); + cancel p; + std.debug.assert(my_result == 2); +} +async fn testBreakFromSuspend(my_result: *i32) void { + suspend { + resume @handle(); + } + my_result.* += 1; + suspend; + my_result.* += 1; +} diff --git a/test/cases/defer.zig b/test/cases/defer.zig index a989af18c2..7d4d1bc3d8 100644 --- a/test/cases/defer.zig +++ b/test/cases/defer.zig @@ -5,9 +5,18 @@ var index: usize = undefined; fn runSomeErrorDefers(x: bool) !bool { index = 0; - defer {result[index] = 'a'; index += 1;} - errdefer {result[index] = 'b'; index += 1;} - defer {result[index] = 'c'; index += 1;} + defer { + result[index] = 'a'; + index += 1; + } + errdefer { + result[index] = 'b'; + index += 1; + } + defer { + result[index] = 'c'; + index += 1; + } return if (x) x else error.FalseNotAllowed; } @@ -41,3 +50,29 @@ fn testBreakContInDefer(x: usize) void { assert(i == 5); } } + +test "defer and labeled break" { + var i = usize(0); + + blk: { + defer i += 1; + break :blk; + } + + assert(i == 1); +} + +test "errdefer does not apply to fn inside fn" { + if (testNestedFnErrDefer()) |_| @panic("expected error") else |e| assert(e == error.Bad); +} + +fn testNestedFnErrDefer() error!void { + var a: i32 = 0; + errdefer a += 1; + const S = struct { + fn baz() error { + return error.Bad; + } + }; + return S.baz(); +} diff --git a/test/cases/enum.zig b/test/cases/enum.zig index 644c989b04..50edfda536 100644 --- a/test/cases/enum.zig +++ b/test/cases/enum.zig @@ -2,8 +2,13 @@ const assert = @import("std").debug.assert; const mem = @import("std").mem; test "enum type" { - const foo1 = Foo{ .One = 13}; - const foo2 = Foo{. Two = Point { .x = 1234, .y = 5678, }}; + const foo1 = Foo{ .One = 13 }; + const foo2 = Foo{ + .Two = Point{ + .x = 1234, + .y = 5678, + }, + }; const bar = Bar.B; assert(bar == Bar.B); @@ -41,26 +46,25 @@ const Bar = enum { }; fn returnAnInt(x: i32) Foo { - return Foo { .One = x }; + return Foo{ .One = x }; } - test "constant enum with payload" { - var empty = AnEnumWithPayload {.Empty = {}}; - var full = AnEnumWithPayload {.Full = 13}; + var empty = AnEnumWithPayload{ .Empty = {} }; + var full = AnEnumWithPayload{ .Full = 13 }; shouldBeEmpty(empty); shouldBeNotEmpty(full); } -fn shouldBeEmpty(x: &const AnEnumWithPayload) void { - switch (*x) { +fn shouldBeEmpty(x: *const AnEnumWithPayload) void { + switch (x.*) { AnEnumWithPayload.Empty => {}, else => unreachable, } } -fn shouldBeNotEmpty(x: &const AnEnumWithPayload) void { - switch (*x) { +fn shouldBeNotEmpty(x: *const AnEnumWithPayload) void { + switch (x.*) { AnEnumWithPayload.Empty => unreachable, else => {}, } @@ -71,8 +75,6 @@ const AnEnumWithPayload = union(enum) { Full: i32, }; - - const Number = enum { Zero, One, @@ -90,15 +92,14 @@ test "enum to int" { } fn shouldEqual(n: Number, expected: u3) void { - assert(u3(n) == expected); + assert(@enumToInt(n) == expected); } - test "int to enum" { testIntToEnumEval(3); } fn testIntToEnumEval(x: i32) void { - assert(IntToEnumNumber(u3(x)) == IntToEnumNumber.Three); + assert(@intToEnum(IntToEnumNumber, @intCast(u3, x)) == IntToEnumNumber.Three); } const IntToEnumNumber = enum { Zero, @@ -108,7 +109,6 @@ const IntToEnumNumber = enum { Four, }; - test "@tagName" { assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three")); comptime assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three")); @@ -124,7 +124,6 @@ const BareNumber = enum { Three, }; - test "enum alignment" { comptime { assert(@alignOf(AlignTestEnum) >= @alignOf([9]u8)); @@ -137,47 +136,529 @@ const AlignTestEnum = union(enum) { B: u64, }; -const ValueCount1 = enum { I0 }; -const ValueCount2 = enum { I0, I1 }; +const ValueCount1 = enum { + I0, +}; +const ValueCount2 = enum { + I0, + I1, +}; const ValueCount256 = enum { - I0, I1, I2, I3, I4, I5, I6, I7, I8, I9, I10, I11, I12, I13, I14, I15, - I16, I17, I18, I19, I20, I21, I22, I23, I24, I25, I26, I27, I28, I29, I30, I31, - I32, I33, I34, I35, I36, I37, I38, I39, I40, I41, I42, I43, I44, I45, I46, I47, - I48, I49, I50, I51, I52, I53, I54, I55, I56, I57, I58, I59, I60, I61, I62, I63, - I64, I65, I66, I67, I68, I69, I70, I71, I72, I73, I74, I75, I76, I77, I78, I79, - I80, I81, I82, I83, I84, I85, I86, I87, I88, I89, I90, I91, I92, I93, I94, I95, - I96, I97, I98, I99, I100, I101, I102, I103, I104, I105, I106, I107, I108, I109, - I110, I111, I112, I113, I114, I115, I116, I117, I118, I119, I120, I121, I122, I123, - I124, I125, I126, I127, I128, I129, I130, I131, I132, I133, I134, I135, I136, I137, - I138, I139, I140, I141, I142, I143, I144, I145, I146, I147, I148, I149, I150, I151, - I152, I153, I154, I155, I156, I157, I158, I159, I160, I161, I162, I163, I164, I165, - I166, I167, I168, I169, I170, I171, I172, I173, I174, I175, I176, I177, I178, I179, - I180, I181, I182, I183, I184, I185, I186, I187, I188, I189, I190, I191, I192, I193, - I194, I195, I196, I197, I198, I199, I200, I201, I202, I203, I204, I205, I206, I207, - I208, I209, I210, I211, I212, I213, I214, I215, I216, I217, I218, I219, I220, I221, - I222, I223, I224, I225, I226, I227, I228, I229, I230, I231, I232, I233, I234, I235, - I236, I237, I238, I239, I240, I241, I242, I243, I244, I245, I246, I247, I248, I249, - I250, I251, I252, I253, I254, I255 + I0, + I1, + I2, + I3, + I4, + I5, + I6, + I7, + I8, + I9, + I10, + I11, + I12, + I13, + I14, + I15, + I16, + I17, + I18, + I19, + I20, + I21, + I22, + I23, + I24, + I25, + I26, + I27, + I28, + I29, + I30, + I31, + I32, + I33, + I34, + I35, + I36, + I37, + I38, + I39, + I40, + I41, + I42, + I43, + I44, + I45, + I46, + I47, + I48, + I49, + I50, + I51, + I52, + I53, + I54, + I55, + I56, + I57, + I58, + I59, + I60, + I61, + I62, + I63, + I64, + I65, + I66, + I67, + I68, + I69, + I70, + I71, + I72, + I73, + I74, + I75, + I76, + I77, + I78, + I79, + I80, + I81, + I82, + I83, + I84, + I85, + I86, + I87, + I88, + I89, + I90, + I91, + I92, + I93, + I94, + I95, + I96, + I97, + I98, + I99, + I100, + I101, + I102, + I103, + I104, + I105, + I106, + I107, + I108, + I109, + I110, + I111, + I112, + I113, + I114, + I115, + I116, + I117, + I118, + I119, + I120, + I121, + I122, + I123, + I124, + I125, + I126, + I127, + I128, + I129, + I130, + I131, + I132, + I133, + I134, + I135, + I136, + I137, + I138, + I139, + I140, + I141, + I142, + I143, + I144, + I145, + I146, + I147, + I148, + I149, + I150, + I151, + I152, + I153, + I154, + I155, + I156, + I157, + I158, + I159, + I160, + I161, + I162, + I163, + I164, + I165, + I166, + I167, + I168, + I169, + I170, + I171, + I172, + I173, + I174, + I175, + I176, + I177, + I178, + I179, + I180, + I181, + I182, + I183, + I184, + I185, + I186, + I187, + I188, + I189, + I190, + I191, + I192, + I193, + I194, + I195, + I196, + I197, + I198, + I199, + I200, + I201, + I202, + I203, + I204, + I205, + I206, + I207, + I208, + I209, + I210, + I211, + I212, + I213, + I214, + I215, + I216, + I217, + I218, + I219, + I220, + I221, + I222, + I223, + I224, + I225, + I226, + I227, + I228, + I229, + I230, + I231, + I232, + I233, + I234, + I235, + I236, + I237, + I238, + I239, + I240, + I241, + I242, + I243, + I244, + I245, + I246, + I247, + I248, + I249, + I250, + I251, + I252, + I253, + I254, + I255, }; const ValueCount257 = enum { - I0, I1, I2, I3, I4, I5, I6, I7, I8, I9, I10, I11, I12, I13, I14, I15, - I16, I17, I18, I19, I20, I21, I22, I23, I24, I25, I26, I27, I28, I29, I30, I31, - I32, I33, I34, I35, I36, I37, I38, I39, I40, I41, I42, I43, I44, I45, I46, I47, - I48, I49, I50, I51, I52, I53, I54, I55, I56, I57, I58, I59, I60, I61, I62, I63, - I64, I65, I66, I67, I68, I69, I70, I71, I72, I73, I74, I75, I76, I77, I78, I79, - I80, I81, I82, I83, I84, I85, I86, I87, I88, I89, I90, I91, I92, I93, I94, I95, - I96, I97, I98, I99, I100, I101, I102, I103, I104, I105, I106, I107, I108, I109, - I110, I111, I112, I113, I114, I115, I116, I117, I118, I119, I120, I121, I122, I123, - I124, I125, I126, I127, I128, I129, I130, I131, I132, I133, I134, I135, I136, I137, - I138, I139, I140, I141, I142, I143, I144, I145, I146, I147, I148, I149, I150, I151, - I152, I153, I154, I155, I156, I157, I158, I159, I160, I161, I162, I163, I164, I165, - I166, I167, I168, I169, I170, I171, I172, I173, I174, I175, I176, I177, I178, I179, - I180, I181, I182, I183, I184, I185, I186, I187, I188, I189, I190, I191, I192, I193, - I194, I195, I196, I197, I198, I199, I200, I201, I202, I203, I204, I205, I206, I207, - I208, I209, I210, I211, I212, I213, I214, I215, I216, I217, I218, I219, I220, I221, - I222, I223, I224, I225, I226, I227, I228, I229, I230, I231, I232, I233, I234, I235, - I236, I237, I238, I239, I240, I241, I242, I243, I244, I245, I246, I247, I248, I249, - I250, I251, I252, I253, I254, I255, I256 + I0, + I1, + I2, + I3, + I4, + I5, + I6, + I7, + I8, + I9, + I10, + I11, + I12, + I13, + I14, + I15, + I16, + I17, + I18, + I19, + I20, + I21, + I22, + I23, + I24, + I25, + I26, + I27, + I28, + I29, + I30, + I31, + I32, + I33, + I34, + I35, + I36, + I37, + I38, + I39, + I40, + I41, + I42, + I43, + I44, + I45, + I46, + I47, + I48, + I49, + I50, + I51, + I52, + I53, + I54, + I55, + I56, + I57, + I58, + I59, + I60, + I61, + I62, + I63, + I64, + I65, + I66, + I67, + I68, + I69, + I70, + I71, + I72, + I73, + I74, + I75, + I76, + I77, + I78, + I79, + I80, + I81, + I82, + I83, + I84, + I85, + I86, + I87, + I88, + I89, + I90, + I91, + I92, + I93, + I94, + I95, + I96, + I97, + I98, + I99, + I100, + I101, + I102, + I103, + I104, + I105, + I106, + I107, + I108, + I109, + I110, + I111, + I112, + I113, + I114, + I115, + I116, + I117, + I118, + I119, + I120, + I121, + I122, + I123, + I124, + I125, + I126, + I127, + I128, + I129, + I130, + I131, + I132, + I133, + I134, + I135, + I136, + I137, + I138, + I139, + I140, + I141, + I142, + I143, + I144, + I145, + I146, + I147, + I148, + I149, + I150, + I151, + I152, + I153, + I154, + I155, + I156, + I157, + I158, + I159, + I160, + I161, + I162, + I163, + I164, + I165, + I166, + I167, + I168, + I169, + I170, + I171, + I172, + I173, + I174, + I175, + I176, + I177, + I178, + I179, + I180, + I181, + I182, + I183, + I184, + I185, + I186, + I187, + I188, + I189, + I190, + I191, + I192, + I193, + I194, + I195, + I196, + I197, + I198, + I199, + I200, + I201, + I202, + I203, + I204, + I205, + I206, + I207, + I208, + I209, + I210, + I211, + I212, + I213, + I214, + I215, + I216, + I217, + I218, + I219, + I220, + I221, + I222, + I223, + I224, + I225, + I226, + I227, + I228, + I229, + I230, + I231, + I232, + I233, + I234, + I235, + I236, + I237, + I238, + I239, + I240, + I241, + I242, + I243, + I244, + I245, + I246, + I247, + I248, + I249, + I250, + I251, + I252, + I253, + I254, + I255, + I256, }; test "enum sizes" { @@ -189,11 +670,11 @@ test "enum sizes" { } } -const Small2 = enum (u2) { +const Small2 = enum(u2) { One, Two, }; -const Small = enum (u2) { +const Small = enum(u2) { One, Two, Three, @@ -213,8 +694,7 @@ test "set enum tag type" { } } - -const A = enum (u3) { +const A = enum(u3) { One, Two, Three, @@ -225,7 +705,7 @@ const A = enum (u3) { Four2, }; -const B = enum (u3) { +const B = enum(u3) { One3, Two3, Three3, @@ -236,7 +716,7 @@ const B = enum (u3) { Four23, }; -const C = enum (u2) { +const C = enum(u2) { One4, Two4, Three4, @@ -249,7 +729,7 @@ const BitFieldOfEnums = packed struct { c: C, }; -const bit_field_1 = BitFieldOfEnums { +const bit_field_1 = BitFieldOfEnums{ .a = A.Two, .b = B.Three3, .c = C.Four4, @@ -270,15 +750,15 @@ test "bit field access with enum fields" { assert(data.b == B.Four3); } -fn getA(data: &const BitFieldOfEnums) A { +fn getA(data: *const BitFieldOfEnums) A { return data.a; } -fn getB(data: &const BitFieldOfEnums) B { +fn getB(data: *const BitFieldOfEnums) B { return data.b; } -fn getC(data: &const BitFieldOfEnums) C { +fn getC(data: *const BitFieldOfEnums) C { return data.c; } @@ -288,7 +768,7 @@ test "casting enum to its tag type" { } fn testCastEnumToTagType(value: Small2) void { - assert(u2(value) == 1); + assert(@enumToInt(value) == 1); } const MultipleChoice = enum(u32) { @@ -304,7 +784,7 @@ test "enum with specified tag values" { } fn testEnumWithSpecifiedTagValues(x: MultipleChoice) void { - assert(u32(x) == 60); + assert(@enumToInt(x) == 60); assert(1234 == switch (x) { MultipleChoice.A => 1, MultipleChoice.B => 2, @@ -331,7 +811,7 @@ test "enum with specified and unspecified tag values" { } fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void { - assert(u32(x) == 1000); + assert(@enumToInt(x) == 1000); assert(1234 == switch (x) { MultipleChoice2.A => 1, MultipleChoice2.B => 2, @@ -346,8 +826,8 @@ fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void { } test "cast integer literal to enum" { - assert(MultipleChoice2(0) == MultipleChoice2.Unspecified1); - assert(MultipleChoice2(40) == MultipleChoice2.B); + assert(@intToEnum(MultipleChoice2, 0) == MultipleChoice2.Unspecified1); + assert(@intToEnum(MultipleChoice2, 40) == MultipleChoice2.B); } const EnumWithOneMember = enum { @@ -385,10 +865,30 @@ const EnumWithTagValues = enum(u4) { D = 1 << 3, }; test "enum with tag values don't require parens" { - assert(u4(EnumWithTagValues.C) == 0b0100); + assert(@enumToInt(EnumWithTagValues.C) == 0b0100); } test "enum with 1 field but explicit tag type should still have the tag type" { - const Enum = enum(u8) { B = 2 }; + const Enum = enum(u8) { + B = 2, + }; comptime @import("std").debug.assert(@sizeOf(Enum) == @sizeOf(u8)); } + +test "empty extern enum with members" { + const E = extern enum { + A, + B, + C, + }; + assert(@sizeOf(E) == @sizeOf(c_int)); +} + +test "aoeu" { + const LocalFoo = enum { + A = 1, + B = 0, + }; + var b = LocalFoo.B; + assert(mem.eql(u8, @tagName(b), "B")); +} diff --git a/test/cases/enum_with_members.zig b/test/cases/enum_with_members.zig index 0c2ae1c383..18174186a9 100644 --- a/test/cases/enum_with_members.zig +++ b/test/cases/enum_with_members.zig @@ -6,8 +6,8 @@ const ET = union(enum) { SINT: i32, UINT: u32, - pub fn print(a: &const ET, buf: []u8) error!usize { - return switch (*a) { + pub fn print(a: *const ET, buf: []u8) error!usize { + return switch (a.*) { ET.SINT => |x| fmt.formatIntBuf(buf, x, 10, false, 0), ET.UINT => |x| fmt.formatIntBuf(buf, x, 10, false, 0), }; @@ -15,8 +15,8 @@ const ET = union(enum) { }; test "enum with members" { - const a = ET { .SINT = -42 }; - const b = ET { .UINT = 42 }; + const a = ET{ .SINT = -42 }; + const b = ET{ .UINT = 42 }; var buf: [20]u8 = undefined; assert((a.print(buf[0..]) catch unreachable) == 3); diff --git a/test/cases/error.zig b/test/cases/error.zig index e64bf02c91..45971fd40d 100644 --- a/test/cases/error.zig +++ b/test/cases/error.zig @@ -30,14 +30,12 @@ test "@errorName" { assert(mem.eql(u8, @errorName(error.ALongerErrorName), "ALongerErrorName")); } - test "error values" { - const a = i32(error.err1); - const b = i32(error.err2); + const a = @errorToInt(error.err1); + const b = @errorToInt(error.err2); assert(a != b); } - test "redefinition of error values allowed" { shouldBeNotEqual(error.AnError, error.SecondError); } @@ -45,7 +43,6 @@ fn shouldBeNotEqual(a: error, b: error) void { if (a == b) unreachable; } - test "error binary operator" { const a = errBinaryOperatorG(true) catch 3; const b = errBinaryOperatorG(false) catch 3; @@ -56,20 +53,20 @@ fn errBinaryOperatorG(x: bool) error!isize { return if (x) error.ItBroke else isize(10); } - test "unwrap simple value from error" { const i = unwrapSimpleValueFromErrorDo() catch unreachable; assert(i == 13); } -fn unwrapSimpleValueFromErrorDo() error!isize { return 13; } - +fn unwrapSimpleValueFromErrorDo() error!isize { + return 13; +} test "error return in assignment" { doErrReturnInAssignment() catch unreachable; } fn doErrReturnInAssignment() error!void { - var x : i32 = undefined; + var x: i32 = undefined; x = try makeANonErr(); } @@ -95,7 +92,10 @@ test "error set type " { comptime testErrorSetType(); } -const MyErrSet = error {OutOfMemory, FileNotFound}; +const MyErrSet = error{ + OutOfMemory, + FileNotFound, +}; fn testErrorSetType() void { assert(@memberCount(MyErrSet) == 2); @@ -109,18 +109,23 @@ fn testErrorSetType() void { } } - test "explicit error set cast" { testExplicitErrorSetCast(Set1.A); comptime testExplicitErrorSetCast(Set1.A); } -const Set1 = error{A, B}; -const Set2 = error{A, C}; +const Set1 = error{ + A, + B, +}; +const Set2 = error{ + A, + C, +}; fn testExplicitErrorSetCast(set1: Set1) void { - var x = Set2(set1); - var y = Set1(x); + var x = @errSetCast(Set2, set1); + var y = @errSetCast(Set1, x); assert(y == error.A); } @@ -129,24 +134,27 @@ test "comptime test error for empty error set" { comptime testComptimeTestErrorEmptySet(1234); } -const EmptyErrorSet = error {}; +const EmptyErrorSet = error{}; fn testComptimeTestErrorEmptySet(x: EmptyErrorSet!i32) void { if (x) |v| assert(v == 1234) else |err| @compileError("bad"); } -test "syntax: nullable operator in front of error union operator" { +test "syntax: optional operator in front of error union operator" { comptime { assert(?error!i32 == ?(error!i32)); } } test "comptime err to int of error set with only 1 possible value" { - testErrToIntWithOnePossibleValue(error.A, u32(error.A)); - comptime testErrToIntWithOnePossibleValue(error.A, u32(error.A)); -} -fn testErrToIntWithOnePossibleValue(x: error{A}, comptime value: u32) void { - if (u32(x) != value) { + testErrToIntWithOnePossibleValue(error.A, @errorToInt(error.A)); + comptime testErrToIntWithOnePossibleValue(error.A, @errorToInt(error.A)); +} +fn testErrToIntWithOnePossibleValue( + x: error{A}, + comptime value: u32, +) void { + if (@errorToInt(x) != value) { @compileError("bad"); } } @@ -175,3 +183,63 @@ fn baz_1() !i32 { fn quux_1() !i32 { return error.C; } + +test "error: fn returning empty error set can be passed as fn returning any error" { + entry(); + comptime entry(); +} + +fn entry() void { + foo2(bar2); +} + +fn foo2(f: fn () error!void) void { + const x = f(); +} + +fn bar2() (error{}!void) {} + +test "error: Zero sized error set returned with value payload crash" { + _ = foo3(0); + _ = comptime foo3(0); +} + +const Error = error{}; +fn foo3(b: usize) Error!usize { + return b; +} + +test "error: Infer error set from literals" { + _ = nullLiteral("n") catch |err| handleErrors(err); + _ = floatLiteral("n") catch |err| handleErrors(err); + _ = intLiteral("n") catch |err| handleErrors(err); + _ = comptime nullLiteral("n") catch |err| handleErrors(err); + _ = comptime floatLiteral("n") catch |err| handleErrors(err); + _ = comptime intLiteral("n") catch |err| handleErrors(err); +} + +fn handleErrors(err: var) noreturn { + switch (err) { + error.T => {}, + } + + unreachable; +} + +fn nullLiteral(str: []const u8) !?i64 { + if (str[0] == 'n') return null; + + return error.T; +} + +fn floatLiteral(str: []const u8) !?f64 { + if (str[0] == 'n') return 1.0; + + return error.T; +} + +fn intLiteral(str: []const u8) !?i64 { + if (str[0] == 'n') return 1; + + return error.T; +} diff --git a/test/cases/eval.zig b/test/cases/eval.zig index d6f7afe864..9da475994d 100644 --- a/test/cases/eval.zig +++ b/test/cases/eval.zig @@ -5,16 +5,14 @@ const builtin = @import("builtin"); test "compile time recursion" { assert(some_data.len == 21); } -var some_data: [usize(fibonacci(7))]u8 = undefined; +var some_data: [@intCast(usize, fibonacci(7))]u8 = undefined; fn fibonacci(x: i32) i32 { if (x <= 1) return 1; return fibonacci(x - 1) + fibonacci(x - 2); } - - fn unwrapAndAddOne(blah: ?i32) i32 { - return ??blah + 1; + return blah.? + 1; } const should_be_1235 = unwrapAndAddOne(1234); test "static add one" { @@ -40,13 +38,13 @@ test "inline variable gets result of const if" { assert(gimme1or2(false) == 2); } - test "static function evaluation" { assert(statically_added_number == 3); } const statically_added_number = staticAdd(1, 2); -fn staticAdd(a: i32, b: i32) i32 { return a + b; } - +fn staticAdd(a: i32, b: i32) i32 { + return a + b; +} test "const expr eval on single expr blocks" { assert(constExprEvalOnSingleExprBlocksFn(1, true) == 3); @@ -64,9 +62,6 @@ fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) i32 { return result; } - - - test "statically initialized list" { assert(static_point_list[0].x == 1); assert(static_point_list[0].y == 2); @@ -77,15 +72,17 @@ const Point = struct { x: i32, y: i32, }; -const static_point_list = []Point { makePoint(1, 2), makePoint(3, 4) }; +const static_point_list = []Point{ + makePoint(1, 2), + makePoint(3, 4), +}; fn makePoint(x: i32, y: i32) Point { - return Point { + return Point{ .x = x, .y = y, }; } - test "static eval list init" { assert(static_vec3.data[2] == 1.0); assert(vec3(0.0, 0.0, 3.0).data[2] == 3.0); @@ -95,18 +92,18 @@ pub const Vec3 = struct { data: [3]f32, }; pub fn vec3(x: f32, y: f32, z: f32) Vec3 { - return Vec3 { - .data = []f32 { x, y, z, }, - }; + return Vec3{ .data = []f32{ + x, + y, + z, + } }; } - test "constant expressions" { - var array : [array_size]u8 = undefined; + var array: [array_size]u8 = undefined; assert(@sizeOf(@typeOf(array)) == 20); } -const array_size : u8 = 20; - +const array_size: u8 = 20; test "constant struct with negation" { assert(vertices[0].x == -0.6); @@ -118,13 +115,30 @@ const Vertex = struct { g: f32, b: f32, }; -const vertices = []Vertex { - Vertex { .x = -0.6, .y = -0.4, .r = 1.0, .g = 0.0, .b = 0.0 }, - Vertex { .x = 0.6, .y = -0.4, .r = 0.0, .g = 1.0, .b = 0.0 }, - Vertex { .x = 0.0, .y = 0.6, .r = 0.0, .g = 0.0, .b = 1.0 }, +const vertices = []Vertex{ + Vertex{ + .x = -0.6, + .y = -0.4, + .r = 1.0, + .g = 0.0, + .b = 0.0, + }, + Vertex{ + .x = 0.6, + .y = -0.4, + .r = 0.0, + .g = 1.0, + .b = 0.0, + }, + Vertex{ + .x = 0.0, + .y = 0.6, + .r = 0.0, + .g = 0.0, + .b = 1.0, + }, }; - test "statically initialized struct" { st_init_str_foo.x += 1; assert(st_init_str_foo.x == 14); @@ -133,15 +147,21 @@ const StInitStrFoo = struct { x: i32, y: bool, }; -var st_init_str_foo = StInitStrFoo { .x = 13, .y = true, }; - +var st_init_str_foo = StInitStrFoo{ + .x = 13, + .y = true, +}; test "statically initalized array literal" { - const y : [4]u8 = st_init_arr_lit_x; + const y: [4]u8 = st_init_arr_lit_x; assert(y[3] == 4); } -const st_init_arr_lit_x = []u8{1,2,3,4}; - +const st_init_arr_lit_x = []u8{ + 1, + 2, + 3, + 4, +}; test "const slice" { comptime { @@ -195,17 +215,32 @@ test "inlined block and runtime block phi" { const CmdFn = struct { name: []const u8, - func: fn(i32) i32, + func: fn (i32) i32, }; const cmd_fns = []CmdFn{ - CmdFn {.name = "one", .func = one}, - CmdFn {.name = "two", .func = two}, - CmdFn {.name = "three", .func = three}, + CmdFn{ + .name = "one", + .func = one, + }, + CmdFn{ + .name = "two", + .func = two, + }, + CmdFn{ + .name = "three", + .func = three, + }, }; -fn one(value: i32) i32 { return value + 1; } -fn two(value: i32) i32 { return value + 2; } -fn three(value: i32) i32 { return value + 3; } +fn one(value: i32) i32 { + return value + 1; +} +fn two(value: i32) i32 { + return value + 2; +} +fn three(value: i32) i32 { + return value + 3; +} fn performFn(comptime prefix_char: u8, start_value: i32) i32 { var result: i32 = start_value; @@ -229,7 +264,7 @@ test "eval @setRuntimeSafety at compile-time" { assert(result == 1234); } -fn fnWithSetRuntimeSafety() i32{ +fn fnWithSetRuntimeSafety() i32 { @setRuntimeSafety(true); return 1234; } @@ -244,16 +279,15 @@ fn fnWithFloatMode() f32 { return 1234.0; } - const SimpleStruct = struct { field: i32, - fn method(self: &const SimpleStruct) i32 { + fn method(self: *const SimpleStruct) i32 { return self.field + 3; } }; -var simple_struct = SimpleStruct{ .field = 1234, }; +var simple_struct = SimpleStruct{ .field = 1234 }; const bound_fn = simple_struct.method; @@ -261,8 +295,6 @@ test "call method on bound fn referring to var instance" { assert(bound_fn() == 1237); } - - test "ptr to local array argument at comptime" { comptime { var bytes: [10]u8 = undefined; @@ -277,7 +309,6 @@ fn modifySomeBytes(bytes: []u8) void { bytes[9] = 'b'; } - test "comparisons 0 <= uint and 0 > uint should be comptime" { testCompTimeUIntComparisons(1234); } @@ -296,8 +327,6 @@ fn testCompTimeUIntComparisons(x: u32) void { } } - - test "const ptr to variable data changes at runtime" { assert(foo_ref.name[0] == 'a'); foo_ref.name = "b"; @@ -308,11 +337,9 @@ const Foo = struct { name: []const u8, }; -var foo_contents = Foo { .name = "a", }; +var foo_contents = Foo{ .name = "a" }; const foo_ref = &foo_contents; - - test "create global array with for loop" { assert(global_array[5] == 5 * 5); assert(global_array[9] == 9 * 9); @@ -321,7 +348,7 @@ test "create global array with for loop" { const global_array = x: { var result: [10]usize = undefined; for (result) |*item, index| { - *item = index * index; + item.* = index * index; } break :x result; }; @@ -329,7 +356,7 @@ const global_array = x: { test "compile-time downcast when the bits fit" { comptime { const spartan_count: u16 = 255; - const byte = u8(spartan_count); + const byte = @intCast(u8, spartan_count); assert(byte == 255); } } @@ -340,7 +367,7 @@ test "const global shares pointer with other same one" { assertEqualPtrs(&hi1[0], &hi2[0]); comptime assert(&hi1[0] == &hi2[0]); } -fn assertEqualPtrs(ptr1: &const u8, ptr2: &const u8) void { +fn assertEqualPtrs(ptr1: *const u8, ptr2: *const u8) void { assert(ptr1 == ptr2); } @@ -379,7 +406,7 @@ test "f128 at compile time is lossy" { pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) type { return struct { - pub const Node = struct { }; + pub const Node = struct {}; }; } @@ -391,9 +418,9 @@ test "string literal used as comptime slice is memoized" { } test "comptime slice of undefined pointer of length 0" { - const slice1 = (&i32)(undefined)[0..0]; + const slice1 = ([*]i32)(undefined)[0..0]; assert(slice1.len == 0); - const slice2 = (&i32)(undefined)[100..100]; + const slice2 = ([*]i32)(undefined)[100..100]; assert(slice2.len == 0); } @@ -401,10 +428,10 @@ fn copyWithPartialInline(s: []u32, b: []u8) void { comptime var i: usize = 0; inline while (i < 4) : (i += 1) { s[i] = 0; - s[i] |= u32(b[i*4+0]) << 24; - s[i] |= u32(b[i*4+1]) << 16; - s[i] |= u32(b[i*4+2]) << 8; - s[i] |= u32(b[i*4+3]) << 0; + s[i] |= u32(b[i * 4 + 0]) << 24; + s[i] |= u32(b[i * 4 + 1]) << 16; + s[i] |= u32(b[i * 4 + 2]) << 8; + s[i] |= u32(b[i * 4 + 3]) << 0; } } @@ -413,7 +440,7 @@ test "binary math operator in partially inlined function" { var b: [16]u8 = undefined; for (b) |*r, i| - *r = u8(i + 1); + r.* = @intCast(u8, i + 1); copyWithPartialInline(s[0..], b[0..]); assert(s[0] == 0x1020304); @@ -422,7 +449,6 @@ test "binary math operator in partially inlined function" { assert(s[3] == 0xd0e0f10); } - test "comptime function with the same args is memoized" { comptime { assert(MakeType(i32) == MakeType(i32)); @@ -446,15 +472,15 @@ test "comptime function with mutable pointer is not memoized" { } } -fn increment(value: &i32) void { - *value += 1; +fn increment(value: *i32) void { + value.* += 1; } fn generateTable(comptime T: type) [1010]T { - var res : [1010]T = undefined; - var i : usize = 0; + var res: [1010]T = undefined; + var i: usize = 0; while (i < 1010) : (i += 1) { - res[i] = T(i); + res[i] = @intCast(T, i); } return res; } @@ -482,7 +508,7 @@ test "comptime slice of slice preserves comptime var" { test "comptime slice of pointer preserves comptime var" { comptime { var buff: [10]u8 = undefined; - var a = &buff[0]; + var a = buff[0..].ptr; a[0..1][0] = 1; assert(buff[0..][0..][0] == 1); } @@ -491,14 +517,13 @@ test "comptime slice of pointer preserves comptime var" { const SingleFieldStruct = struct { x: i32, - fn read_x(self: &const SingleFieldStruct) i32 { + fn read_x(self: *const SingleFieldStruct) i32 { return self.x; } }; test "const ptr to comptime mutable data is not memoized" { - comptime { - var foo = SingleFieldStruct {.x = 1}; + var foo = SingleFieldStruct{ .x = 1 }; assert(foo.read_x() == 1); foo.x = 2; assert(foo.read_x() == 2); @@ -513,3 +538,117 @@ test "array concat of slices gives slice" { assert(std.mem.eql(u8, c, "aoeuasdf")); } } + +test "comptime shlWithOverflow" { + const ct_shifted: u64 = comptime amt: { + var amt = u64(0); + _ = @shlWithOverflow(u64, ~u64(0), 16, &amt); + break :amt amt; + }; + + const rt_shifted: u64 = amt: { + var amt = u64(0); + _ = @shlWithOverflow(u64, ~u64(0), 16, &amt); + break :amt amt; + }; + + assert(ct_shifted == rt_shifted); +} + +test "runtime 128 bit integer division" { + var a: u128 = 152313999999999991610955792383; + var b: u128 = 10000000000000000000; + var c = a / b; + assert(c == 15231399999); +} + +pub const Info = struct { + version: u8, +}; + +pub const diamond_info = Info{ .version = 0 }; + +test "comptime modification of const struct field" { + comptime { + var res = diamond_info; + res.version = 1; + assert(diamond_info.version == 0); + assert(res.version == 1); + } +} + +test "pointer to type" { + comptime { + var T: type = i32; + assert(T == i32); + var ptr = &T; + assert(@typeOf(ptr) == *type); + ptr.* = f32; + assert(T == f32); + assert(*T == *f32); + } +} + +test "slice of type" { + comptime { + var types_array = []type{ i32, f64, type }; + for (types_array) |T, i| { + switch (i) { + 0 => assert(T == i32), + 1 => assert(T == f64), + 2 => assert(T == type), + else => unreachable, + } + } + for (types_array[0..]) |T, i| { + switch (i) { + 0 => assert(T == i32), + 1 => assert(T == f64), + 2 => assert(T == type), + else => unreachable, + } + } + } +} + +const Wrapper = struct { + T: type, +}; + +fn wrap(comptime T: type) Wrapper { + return Wrapper{ .T = T }; +} + +test "function which returns struct with type field causes implicit comptime" { + const ty = wrap(i32).T; + assert(ty == i32); +} + +test "call method with comptime pass-by-non-copying-value self parameter" { + const S = struct { + a: u8, + + fn b(comptime s: this) u8 { + return s.a; + } + }; + + const s = S{ .a = 2 }; + var b = s.b(); + assert(b == 2); +} + +test "@tagName of @typeId" { + const str = @tagName(@typeId(u8)); + assert(std.mem.eql(u8, str, "Int")); +} + +test "setting backward branch quota just before a generic fn call" { + @setEvalBranchQuota(1001); + loopNTimes(1001); +} + +fn loopNTimes(comptime n: usize) void { + comptime var i = 0; + inline while (i < n) : (i += 1) {} +} diff --git a/test/cases/field_parent_ptr.zig b/test/cases/field_parent_ptr.zig index 2e519098cc..00d4e0f367 100644 --- a/test/cases/field_parent_ptr.zig +++ b/test/cases/field_parent_ptr.zig @@ -17,14 +17,14 @@ const Foo = struct { d: i32, }; -const foo = Foo { +const foo = Foo{ .a = true, .b = 0.123, .c = 1234, .d = -10, }; -fn testParentFieldPtr(c: &const i32) void { +fn testParentFieldPtr(c: *const i32) void { assert(c == &foo.c); const base = @fieldParentPtr(Foo, "c", c); @@ -32,7 +32,7 @@ fn testParentFieldPtr(c: &const i32) void { assert(&base.c == c); } -fn testParentFieldPtrFirst(a: &const bool) void { +fn testParentFieldPtrFirst(a: *const bool) void { assert(a == &foo.a); const base = @fieldParentPtr(Foo, "a", a); diff --git a/test/cases/fn.zig b/test/cases/fn.zig index 5388deac10..47f7d5e688 100644 --- a/test/cases/fn.zig +++ b/test/cases/fn.zig @@ -7,7 +7,6 @@ fn testParamsAdd(a: i32, b: i32) i32 { return a + b; } - test "local variables" { testLocVars(2); } @@ -16,7 +15,6 @@ fn testLocVars(b: i32) void { if (a + b != 3) unreachable; } - test "void parameters" { voidFun(1, void{}, 2, {}); } @@ -27,9 +25,8 @@ fn voidFun(a: i32, b: void, c: i32, d: void) void { return vv; } - test "mutable local variables" { - var zero : i32 = 0; + var zero: i32 = 0; assert(zero == 0); var i = i32(0); @@ -41,7 +38,7 @@ test "mutable local variables" { test "separate block scopes" { { - const no_conflict : i32 = 5; + const no_conflict: i32 = 5; assert(no_conflict == 5); } @@ -56,8 +53,7 @@ test "call function with empty string" { acceptsString(""); } -fn acceptsString(foo: []u8) void { } - +fn acceptsString(foo: []u8) void {} fn @"weird function name"() i32 { return 1234; @@ -70,31 +66,43 @@ test "implicit cast function unreachable return" { wantsFnWithVoid(fnWithUnreachable); } -fn wantsFnWithVoid(f: fn() void) void { } +fn wantsFnWithVoid(f: fn () void) void {} fn fnWithUnreachable() noreturn { unreachable; } - test "function pointers" { - const fns = []@typeOf(fn1) { fn1, fn2, fn3, fn4, }; + const fns = []@typeOf(fn1){ + fn1, + fn2, + fn3, + fn4, + }; for (fns) |f, i| { - assert(f() == u32(i) + 5); + assert(f() == @intCast(u32, i) + 5); } } -fn fn1() u32 {return 5;} -fn fn2() u32 {return 6;} -fn fn3() u32 {return 7;} -fn fn4() u32 {return 8;} - +fn fn1() u32 { + return 5; +} +fn fn2() u32 { + return 6; +} +fn fn3() u32 { + return 7; +} +fn fn4() u32 { + return 8; +} test "inline function call" { assert(@inlineCall(add, 3, 9) == 12); } -fn add(a: i32, b: i32) i32 { return a + b; } - +fn add(a: i32, b: i32) i32 { + return a + b; +} test "number literal as an argument" { numberLiteralArg(3); @@ -110,4 +118,61 @@ test "assign inline fn to const variable" { a(); } -inline fn inlineFn() void { } +inline fn inlineFn() void {} + +test "pass by non-copying value" { + assert(addPointCoords(Point{ .x = 1, .y = 2 }) == 3); +} + +const Point = struct { + x: i32, + y: i32, +}; + +fn addPointCoords(pt: Point) i32 { + return pt.x + pt.y; +} + +test "pass by non-copying value through var arg" { + assert(addPointCoordsVar(Point{ .x = 1, .y = 2 }) == 3); +} + +fn addPointCoordsVar(pt: var) i32 { + comptime assert(@typeOf(pt) == Point); + return pt.x + pt.y; +} + +test "pass by non-copying value as method" { + var pt = Point2{ .x = 1, .y = 2 }; + assert(pt.addPointCoords() == 3); +} + +const Point2 = struct { + x: i32, + y: i32, + + fn addPointCoords(self: Point2) i32 { + return self.x + self.y; + } +}; + +test "pass by non-copying value as method, which is generic" { + var pt = Point3{ .x = 1, .y = 2 }; + assert(pt.addPointCoords(i32) == 3); +} + +const Point3 = struct { + x: i32, + y: i32, + + fn addPointCoords(self: Point3, comptime T: type) i32 { + return self.x + self.y; + } +}; + +test "pass by non-copying value as method, at comptime" { + comptime { + var pt = Point2{ .x = 1, .y = 2 }; + assert(pt.addPointCoords() == 3); + } +} diff --git a/test/cases/fn_in_struct_in_comptime.zig b/test/cases/fn_in_struct_in_comptime.zig new file mode 100644 index 0000000000..fabb57e9cb --- /dev/null +++ b/test/cases/fn_in_struct_in_comptime.zig @@ -0,0 +1,17 @@ +const assert = @import("std").debug.assert; + +fn get_foo() fn (*u8) usize { + comptime { + return struct { + fn func(ptr: *u8) usize { + var u = @ptrToInt(ptr); + return u; + } + }.func; + } +} + +test "define a function in an anonymous struct in comptime" { + const foo = get_foo(); + assert(foo(@intToPtr(*u8, 12345)) == 12345); +} diff --git a/test/cases/for.zig b/test/cases/for.zig index 7bb0d7c9fa..59d90c1b85 100644 --- a/test/cases/for.zig +++ b/test/cases/for.zig @@ -3,8 +3,14 @@ const assert = std.debug.assert; const mem = std.mem; test "continue in for loop" { - const array = []i32 {1, 2, 3, 4, 5}; - var sum : i32 = 0; + const array = []i32{ + 1, + 2, + 3, + 4, + 5, + }; + var sum: i32 = 0; for (array) |x| { sum += x; if (x < 3) { @@ -24,23 +30,23 @@ test "for loop with pointer elem var" { } fn mangleString(s: []u8) void { for (s) |*c| { - *c += 1; + c.* += 1; } } test "basic for loop" { - const expected_result = []u8{9, 8, 7, 6, 0, 1, 2, 3, 9, 8, 7, 6, 0, 1, 2, 3 }; + const expected_result = []u8{ 9, 8, 7, 6, 0, 1, 2, 3, 9, 8, 7, 6, 0, 1, 2, 3 }; var buffer: [expected_result.len]u8 = undefined; var buf_index: usize = 0; - const array = []u8 {9, 8, 7, 6}; + const array = []u8{ 9, 8, 7, 6 }; for (array) |item| { buffer[buf_index] = item; buf_index += 1; } for (array) |item, index| { - buffer[buf_index] = u8(index); + buffer[buf_index] = @intCast(u8, index); buf_index += 1; } const unknown_size: []const u8 = array; @@ -49,7 +55,7 @@ test "basic for loop" { buf_index += 1; } for (unknown_size) |item, index| { - buffer[buf_index] = u8(index); + buffer[buf_index] = @intCast(u8, index); buf_index += 1; } @@ -65,7 +71,8 @@ fn testBreakOuter() void { var array = "aoeu"; var count: usize = 0; outer: for (array) |_| { - for (array) |_2| { // TODO shouldn't get error for redeclaring "_" + // TODO shouldn't get error for redeclaring "_" + for (array) |_2| { count += 1; break :outer; } @@ -82,7 +89,8 @@ fn testContinueOuter() void { var array = "aoeu"; var counter: usize = 0; outer: for (array) |_| { - for (array) |_2| { // TODO shouldn't get error for redeclaring "_" + // TODO shouldn't get error for redeclaring "_" + for (array) |_2| { counter += 1; continue :outer; } diff --git a/test/cases/generics.zig b/test/cases/generics.zig index 19b4a598d8..52aa013989 100644 --- a/test/cases/generics.zig +++ b/test/cases/generics.zig @@ -37,7 +37,6 @@ test "fn with comptime args" { assert(sameButWithFloats(0.43, 0.49) == 0.49); } - test "var params" { assert(max_i32(12, 34) == 34); assert(max_f64(1.2, 3.4) == 3.4); @@ -60,7 +59,6 @@ fn max_f64(a: f64, b: f64) f64 { return max_var(a, b); } - pub fn List(comptime T: type) type { return SmallList(T, 8); } @@ -82,10 +80,15 @@ test "function with return type type" { assert(list2.prealloc_items.len == 8); } - test "generic struct" { - var a1 = GenNode(i32) {.value = 13, .next = null,}; - var b1 = GenNode(bool) {.value = true, .next = null,}; + var a1 = GenNode(i32){ + .value = 13, + .next = null, + }; + var b1 = GenNode(bool){ + .value = true, + .next = null, + }; assert(a1.value == 13); assert(a1.value == a1.getVal()); assert(b1.getVal()); @@ -93,8 +96,10 @@ test "generic struct" { fn GenNode(comptime T: type) type { return struct { value: T, - next: ?&GenNode(T), - fn getVal(n: &const GenNode(T)) T { return n.value; } + next: ?*GenNode(T), + fn getVal(n: *const GenNode(T)) T { + return n.value; + } }; } @@ -107,7 +112,6 @@ fn GenericDataThing(comptime count: isize) type { }; } - test "use generic param in generic param" { assert(aGenericFn(i32, 3, 4) == 7); } @@ -115,21 +119,31 @@ fn aGenericFn(comptime T: type, comptime a: T, b: T) T { return a + b; } - test "generic fn with implicit cast" { - assert(getFirstByte(u8, []u8 {13}) == 13); - assert(getFirstByte(u16, []u16 {0, 13}) == 0); + assert(getFirstByte(u8, []u8{13}) == 13); + assert(getFirstByte(u16, []u16{ + 0, + 13, + }) == 0); +} +fn getByte(ptr: ?*const u8) u8 { + return ptr.?.*; } -fn getByte(ptr: ?&const u8) u8 {return *??ptr;} fn getFirstByte(comptime T: type, mem: []const T) u8 { - return getByte(@ptrCast(&const u8, &mem[0])); + return getByte(@ptrCast(*const u8, &mem[0])); } +const foos = []fn (var) bool{ + foo1, + foo2, +}; -const foos = []fn(var) bool { foo1, foo2 }; - -fn foo1(arg: var) bool { return arg; } -fn foo2(arg: var) bool { return !arg; } +fn foo1(arg: var) bool { + return arg; +} +fn foo2(arg: var) bool { + return !arg; +} test "array of generic fns" { assert(foos[0](true)); diff --git a/test/cases/if.zig b/test/cases/if.zig index 2caae7448c..808936bfa5 100644 --- a/test/cases/if.zig +++ b/test/cases/if.zig @@ -23,7 +23,6 @@ fn firstEqlThird(a: i32, b: i32, c: i32) void { } } - test "else if expression" { assert(elseIfExpressionF(1) == 1); } diff --git a/test/cases/import/a_namespace.zig b/test/cases/import/a_namespace.zig index 5cf906cf91..042f1867a5 100644 --- a/test/cases/import/a_namespace.zig +++ b/test/cases/import/a_namespace.zig @@ -1 +1,3 @@ -pub fn foo() i32 { return 1234; } +pub fn foo() i32 { + return 1234; +} diff --git a/test/cases/incomplete_struct_param_tld.zig b/test/cases/incomplete_struct_param_tld.zig index a907ca748a..552d6ef185 100644 --- a/test/cases/incomplete_struct_param_tld.zig +++ b/test/cases/incomplete_struct_param_tld.zig @@ -11,21 +11,19 @@ const B = struct { const C = struct { x: i32, - fn d(c: &const C) i32 { + fn d(c: *const C) i32 { return c.x; } }; -fn foo(a: &const A) i32 { +fn foo(a: *const A) i32 { return a.b.c.d(); } test "incomplete struct param top level declaration" { - const a = A { - .b = B { - .c = C { - .x = 13, - }, + const a = A{ + .b = B{ + .c = C{ .x = 13 }, }, }; assert(foo(a) == 13); diff --git a/test/cases/ir_block_deps.zig b/test/cases/ir_block_deps.zig index 202df19f62..c017eca508 100644 --- a/test/cases/ir_block_deps.zig +++ b/test/cases/ir_block_deps.zig @@ -11,7 +11,9 @@ fn foo(id: u64) !i32 { }; } -fn getErrInt() error!i32 { return 0; } +fn getErrInt() error!i32 { + return 0; +} test "ir block deps" { assert((foo(1) catch unreachable) == 0); diff --git a/test/cases/math.zig b/test/cases/math.zig index 574aa39bb1..195ada15dd 100644 --- a/test/cases/math.zig +++ b/test/cases/math.zig @@ -6,15 +6,20 @@ test "division" { } fn testDivision() void { assert(div(u32, 13, 3) == 4); + assert(div(f16, 1.0, 2.0) == 0.5); assert(div(f32, 1.0, 2.0) == 0.5); assert(divExact(u32, 55, 11) == 5); assert(divExact(i32, -55, 11) == -5); + assert(divExact(f16, 55.0, 11.0) == 5.0); + assert(divExact(f16, -55.0, 11.0) == -5.0); assert(divExact(f32, 55.0, 11.0) == 5.0); assert(divExact(f32, -55.0, 11.0) == -5.0); assert(divFloor(i32, 5, 3) == 1); assert(divFloor(i32, -5, 3) == -2); + assert(divFloor(f16, 5.0, 3.0) == 1.0); + assert(divFloor(f16, -5.0, 3.0) == -2.0); assert(divFloor(f32, 5.0, 3.0) == 1.0); assert(divFloor(f32, -5.0, 3.0) == -2.0); assert(divFloor(i32, -0x80000000, -2) == 0x40000000); @@ -24,30 +29,35 @@ fn testDivision() void { assert(divTrunc(i32, 5, 3) == 1); assert(divTrunc(i32, -5, 3) == -1); + assert(divTrunc(f16, 5.0, 3.0) == 1.0); + assert(divTrunc(f16, -5.0, 3.0) == -1.0); assert(divTrunc(f32, 5.0, 3.0) == 1.0); assert(divTrunc(f32, -5.0, 3.0) == -1.0); + assert(divTrunc(f64, 5.0, 3.0) == 1.0); + assert(divTrunc(f64, -5.0, 3.0) == -1.0); comptime { assert( - 1194735857077236777412821811143690633098347576 % - 508740759824825164163191790951174292733114988 == - 177254337427586449086438229241342047632117600); - assert(@rem(-1194735857077236777412821811143690633098347576, - 508740759824825164163191790951174292733114988) == - -177254337427586449086438229241342047632117600); - assert(1194735857077236777412821811143690633098347576 / - 508740759824825164163191790951174292733114988 == - 2); - assert(@divTrunc(-1194735857077236777412821811143690633098347576, - 508740759824825164163191790951174292733114988) == - -2); - assert(@divTrunc(1194735857077236777412821811143690633098347576, - -508740759824825164163191790951174292733114988) == - -2); - assert(@divTrunc(-1194735857077236777412821811143690633098347576, - -508740759824825164163191790951174292733114988) == - 2); - assert(4126227191251978491697987544882340798050766755606969681711 % 10 == 1); + 1194735857077236777412821811143690633098347576 % 508740759824825164163191790951174292733114988 == 177254337427586449086438229241342047632117600, + ); + assert( + @rem(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -177254337427586449086438229241342047632117600, + ); + assert( + 1194735857077236777412821811143690633098347576 / 508740759824825164163191790951174292733114988 == 2, + ); + assert( + @divTrunc(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -2, + ); + assert( + @divTrunc(1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == -2, + ); + assert( + @divTrunc(-1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == 2, + ); + assert( + 4126227191251978491697987544882340798050766755606969681711 % 10 == 1, + ); } } fn div(comptime T: type, a: T, b: T) T { @@ -114,18 +124,28 @@ fn ctz(x: var) usize { test "assignment operators" { var i: u32 = 0; - i += 5; assert(i == 5); - i -= 2; assert(i == 3); - i *= 20; assert(i == 60); - i /= 3; assert(i == 20); - i %= 11; assert(i == 9); - i <<= 1; assert(i == 18); - i >>= 2; assert(i == 4); + i += 5; + assert(i == 5); + i -= 2; + assert(i == 3); + i *= 20; + assert(i == 60); + i /= 3; + assert(i == 20); + i %= 11; + assert(i == 9); + i <<= 1; + assert(i == 18); + i >>= 2; + assert(i == 4); i = 6; - i &= 5; assert(i == 4); - i ^= 6; assert(i == 2); + i &= 5; + assert(i == 4); + i ^= 6; + assert(i == 2); i = 6; - i |= 3; assert(i == 7); + i |= 3; + assert(i == 7); } test "three expr in a row" { @@ -138,7 +158,7 @@ fn testThreeExprInARow(f: bool, t: bool) void { assertFalse(1 | 2 | 4 != 7); assertFalse(3 ^ 6 ^ 8 != 13); assertFalse(7 & 14 & 28 != 4); - assertFalse(9 << 1 << 2 != 9 << 3); + assertFalse(9 << 1 << 2 != 9 << 3); assertFalse(90 >> 1 >> 2 != 90 >> 3); assertFalse(100 - 1 + 1000 != 1099); assertFalse(5 * 4 / 2 % 3 != 1); @@ -150,7 +170,6 @@ fn assertFalse(b: bool) void { assert(!b); } - test "const number literal" { const one = 1; const eleven = ten + one; @@ -159,8 +178,6 @@ test "const number literal" { } const ten = 10; - - test "unsigned wrapping" { testUnsignedWrappingEval(@maxValue(u32)); comptime testUnsignedWrappingEval(@maxValue(u32)); @@ -203,7 +220,7 @@ fn test_u64_div() void { assert(result.remainder == 100663296); } fn divWithResult(a: u64, b: u64) DivResult { - return DivResult { + return DivResult{ .quotient = a / b, .remainder = a % b, }; @@ -214,8 +231,12 @@ const DivResult = struct { }; test "binary not" { - assert(comptime x: {break :x ~u16(0b1010101010101010) == 0b0101010101010101;}); - assert(comptime x: {break :x ~u64(2147483647) == 18446744071562067968;}); + assert(comptime x: { + break :x ~u16(0b1010101010101010) == 0b0101010101010101; + }); + assert(comptime x: { + break :x ~u64(2147483647) == 18446744071562067968; + }); testBinaryNot(0b1010101010101010); } @@ -275,6 +296,14 @@ test "quad hex float literal parsing in range" { const d = 0x1.edcbff8ad76ab5bf46463233214fp-435; } +test "quad hex float literal parsing accurate" { + const a: f128 = 0x1.1111222233334444555566667777p+0; + + // implied 1 is dropped, with an exponent of 0 (0x3fff) after biasing. + const expected: u128 = 0x3fff1111222233334444555566667777; + assert(@bitCast(u128, a) == expected); +} + test "hex float literal within range" { const a = 0x1.0p16383; const b = 0x0.1p16387; @@ -317,38 +346,55 @@ fn testShrExact(x: u8) void { assert(shifted == 0b00101101); } -test "big number addition" { +test "comptime_int addition" { comptime { - assert( - 35361831660712422535336160538497375248 + - 101752735581729509668353361206450473702 == - 137114567242441932203689521744947848950); - assert( - 594491908217841670578297176641415611445982232488944558774612 + - 390603545391089362063884922208143568023166603618446395589768 == - 985095453608931032642182098849559179469148836107390954364380); + assert(35361831660712422535336160538497375248 + 101752735581729509668353361206450473702 == 137114567242441932203689521744947848950); + assert(594491908217841670578297176641415611445982232488944558774612 + 390603545391089362063884922208143568023166603618446395589768 == 985095453608931032642182098849559179469148836107390954364380); } } -test "big number multiplication" { +test "comptime_int multiplication" { comptime { assert( - 45960427431263824329884196484953148229 * - 128339149605334697009938835852565949723 == - 5898522172026096622534201617172456926982464453350084962781392314016180490567); + 45960427431263824329884196484953148229 * 128339149605334697009938835852565949723 == 5898522172026096622534201617172456926982464453350084962781392314016180490567, + ); assert( - 594491908217841670578297176641415611445982232488944558774612 * - 390603545391089362063884922208143568023166603618446395589768 == - 232210647056203049913662402532976186578842425262306016094292237500303028346593132411865381225871291702600263463125370016); + 594491908217841670578297176641415611445982232488944558774612 * 390603545391089362063884922208143568023166603618446395589768 == 232210647056203049913662402532976186578842425262306016094292237500303028346593132411865381225871291702600263463125370016, + ); } } -test "big number shifting" { +test "comptime_int shifting" { comptime { assert((u128(1) << 127) == 0x80000000000000000000000000000000); } } +test "comptime_int multi-limb shift and mask" { + comptime { + var a = 0xefffffffa0000001eeeeeeefaaaaaaab; + + assert(u32(a & 0xffffffff) == 0xaaaaaaab); + a >>= 32; + assert(u32(a & 0xffffffff) == 0xeeeeeeef); + a >>= 32; + assert(u32(a & 0xffffffff) == 0xa0000001); + a >>= 32; + assert(u32(a & 0xffffffff) == 0xefffffff); + a >>= 32; + + assert(a == 0); + } +} + +test "comptime_int multi-limb partial shift right" { + comptime { + var a = 0x1ffffffffeeeeeeee; + a >>= 16; + assert(a == 0x1ffffffffeeee); + } +} + test "xor" { test_xor(); comptime test_xor(); @@ -362,7 +408,7 @@ fn test_xor() void { assert(0xFF ^ 0xFF == 0x00); } -test "big number xor" { +test "comptime_int xor" { comptime { assert(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0x00000000000000000000000000000000 == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); assert(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0x0000000000000000FFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); @@ -380,7 +426,9 @@ test "f128" { comptime test_f128(); } -fn make_f128(x: f128) f128 { return x; } +fn make_f128(x: f128) f128 { + return x; +} fn test_f128() void { assert(@sizeOf(f128) == 16); @@ -402,3 +450,48 @@ test "comptime float rem int" { assert(x == 1.0); } } + +test "remainder division" { + comptime remdiv(f16); + comptime remdiv(f32); + comptime remdiv(f64); + comptime remdiv(f128); + remdiv(f16); + remdiv(f64); + remdiv(f128); +} + +fn remdiv(comptime T: type) void { + assert(T(1) == T(1) % T(2)); + assert(T(1) == T(7) % T(3)); +} + +test "@sqrt" { + testSqrt(f64, 12.0); + comptime testSqrt(f64, 12.0); + testSqrt(f32, 13.0); + comptime testSqrt(f32, 13.0); + testSqrt(f16, 13.0); + comptime testSqrt(f16, 13.0); + + const x = 14.0; + const y = x * x; + const z = @sqrt(@typeOf(y), y); + comptime assert(z == x); +} + +fn testSqrt(comptime T: type, x: T) void { + assert(@sqrt(T, x * x) == x); +} + +test "comptime_int param and return" { + const a = comptimeAdd(35361831660712422535336160538497375248, 101752735581729509668353361206450473702); + assert(a == 137114567242441932203689521744947848950); + + const b = comptimeAdd(594491908217841670578297176641415611445982232488944558774612, 390603545391089362063884922208143568023166603618446395589768); + assert(b == 985095453608931032642182098849559179469148836107390954364380); +} + +fn comptimeAdd(comptime a: comptime_int, comptime b: comptime_int) comptime_int { + return a + b; +} diff --git a/test/cases/merge_error_sets.zig b/test/cases/merge_error_sets.zig new file mode 100644 index 0000000000..189bd16a4d --- /dev/null +++ b/test/cases/merge_error_sets.zig @@ -0,0 +1,21 @@ +const A = error{ + PathNotFound, + NotDir, +}; +const B = error{OutOfMemory}; + +const C = A || B; + +fn foo() C!void { + return error.NotDir; +} + +test "merge error sets" { + if (foo()) { + @panic("unexpected"); + } else |err| switch (err) { + error.OutOfMemory => @panic("unexpected"), + error.PathNotFound => @panic("unexpected"), + error.NotDir => {}, + } +} diff --git a/test/cases/misc.zig b/test/cases/misc.zig index 95a9a46bff..1c0189571b 100644 --- a/test/cases/misc.zig +++ b/test/cases/misc.zig @@ -4,6 +4,7 @@ const cstr = @import("std").cstr; const builtin = @import("builtin"); // normal comment + /// this is a documentation comment /// doc comment line 2 fn emptyFunctionWithComments() void {} @@ -16,8 +17,7 @@ comptime { @export("disabledExternFn", disabledExternFn, builtin.GlobalLinkage.Internal); } -extern fn disabledExternFn() void { -} +extern fn disabledExternFn() void {} test "call disabled extern fn" { disabledExternFn(); @@ -53,15 +53,11 @@ test "@IntType builtin" { } test "floating point primitive bit counts" { + assert(f16.bit_count == 16); assert(f32.bit_count == 32); assert(f64.bit_count == 64); } -const u1 = @IntType(false, 1); -const u63 = @IntType(false, 63); -const i1 = @IntType(true, 1); -const i63 = @IntType(true, 63); - test "@minValue and @maxValue" { assert(@maxValue(u1) == 1); assert(@maxValue(u8) == 255); @@ -110,17 +106,29 @@ fn testShortCircuit(f: bool, t: bool) void { var hit_3 = f; var hit_4 = f; - if (t or x: {assert(f); break :x f;}) { + if (t or x: { + assert(f); + break :x f; + }) { hit_1 = t; } - if (f or x: { hit_2 = t; break :x f; }) { + if (f or x: { + hit_2 = t; + break :x f; + }) { assert(f); } - if (t and x: { hit_3 = t; break :x f; }) { + if (t and x: { + hit_3 = t; + break :x f; + }) { assert(f); } - if (f and x: {assert(f); break :x f;}) { + if (f and x: { + assert(f); + break :x f; + }) { assert(f); } else { hit_4 = t; @@ -146,8 +154,8 @@ test "return string from function" { assert(mem.eql(u8, first4KeysOfHomeRow(), "aoeu")); } -const g1 : i32 = 1233 + 1; -var g2 : i32 = 0; +const g1: i32 = 1233 + 1; +var g2: i32 = 0; test "global variables" { assert(g2 == 0); @@ -155,24 +163,25 @@ test "global variables" { assert(g2 == 1234); } - test "memcpy and memset intrinsics" { - var foo : [20]u8 = undefined; - var bar : [20]u8 = undefined; + var foo: [20]u8 = undefined; + var bar: [20]u8 = undefined; - @memset(&foo[0], 'A', foo.len); - @memcpy(&bar[0], &foo[0], bar.len); + @memset(foo[0..].ptr, 'A', foo.len); + @memcpy(bar[0..].ptr, foo[0..].ptr, bar.len); if (bar[11] != 'A') unreachable; } test "builtin static eval" { - const x : i32 = comptime x: {break :x 1 + 2 + 3;}; + const x: i32 = comptime x: { + break :x 1 + 2 + 3; + }; assert(x == comptime 6); } test "slicing" { - var array : [20]i32 = undefined; + var array: [20]i32 = undefined; array[5] = 1234; @@ -181,21 +190,21 @@ test "slicing" { if (slice.len != 5) unreachable; const ptr = &slice[0]; - if (ptr[0] != 1234) unreachable; + if (ptr.* != 1234) unreachable; var slice_rest = array[10..]; if (slice_rest.len != 10) unreachable; } - test "constant equal function pointers" { const alias = emptyFn; - assert(comptime x: {break :x emptyFn == alias;}); + assert(comptime x: { + break :x emptyFn == alias; + }); } fn emptyFn() void {} - test "hex escape" { assert(mem.eql(u8, "\x68\x65\x6c\x6c\x6f", "hello")); } @@ -238,35 +247,32 @@ test "multiline C string" { assert(cstr.cmp(s1, s2) == 0); } - test "type equality" { - assert(&const u8 != &u8); + assert(*const u8 != *u8); } - const global_a: i32 = 1234; -const global_b: &const i32 = &global_a; -const global_c: &const f32 = @ptrCast(&const f32, global_b); +const global_b: *const i32 = &global_a; +const global_c: *const f32 = @ptrCast(*const f32, global_b); test "compile time global reinterpret" { - const d = @ptrCast(&const i32, global_c); - assert(*d == 1234); + const d = @ptrCast(*const i32, global_c); + assert(d.* == 1234); } test "explicit cast maybe pointers" { - const a: ?&i32 = undefined; - const b: ?&f32 = @ptrCast(?&f32, a); + const a: ?*i32 = undefined; + const b: ?*f32 = @ptrCast(?*f32, a); } test "generic malloc free" { const a = memAlloc(u8, 10) catch unreachable; memFree(u8, a); } -var some_mem : [100]u8 = undefined; +var some_mem: [100]u8 = undefined; fn memAlloc(comptime T: type, n: usize) error![]T { - return @ptrCast(&T, &some_mem[0])[0..n]; + return @ptrCast([*]T, &some_mem[0])[0..n]; } -fn memFree(comptime T: type, memory: []T) void { } - +fn memFree(comptime T: type, memory: []T) void {} test "cast undefined" { const array: [100]u8 = undefined; @@ -275,32 +281,35 @@ test "cast undefined" { } fn testCastUndefined(x: []const u8) void {} - test "cast small unsigned to larger signed" { assert(castSmallUnsignedToLargerSigned1(200) == i16(200)); assert(castSmallUnsignedToLargerSigned2(9999) == i64(9999)); } -fn castSmallUnsignedToLargerSigned1(x: u8) i16 { return x; } -fn castSmallUnsignedToLargerSigned2(x: u16) i64 { return x; } - +fn castSmallUnsignedToLargerSigned1(x: u8) i16 { + return x; +} +fn castSmallUnsignedToLargerSigned2(x: u16) i64 { + return x; +} test "implicit cast after unreachable" { assert(outer() == 1234); } -fn inner() i32 { return 1234; } +fn inner() i32 { + return 1234; +} fn outer() i64 { return inner(); } - test "pointer dereferencing" { var x = i32(3); const y = &x; - *y += 1; + y.* += 1; assert(x == 4); - assert(*y == 4); + assert(y.* == 4); } test "call result of if else expression" { @@ -310,9 +319,12 @@ test "call result of if else expression" { fn f2(x: bool) []const u8 { return (if (x) fA else fB)(); } -fn fA() []const u8 { return "a"; } -fn fB() []const u8 { return "b"; } - +fn fA() []const u8 { + return "a"; +} +fn fB() []const u8 { + return "b"; +} test "const expression eval handling of variables" { var x = true; @@ -321,8 +333,6 @@ test "const expression eval handling of variables" { } } - - test "constant enum initialization with differing sizes" { test3_1(test3_foo); test3_2(test3_bar); @@ -336,10 +346,15 @@ const Test3Point = struct { x: i32, y: i32, }; -const test3_foo = Test3Foo { .Three = Test3Point {.x = 3, .y = 4}}; -const test3_bar = Test3Foo { .Two = 13}; -fn test3_1(f: &const Test3Foo) void { - switch (*f) { +const test3_foo = Test3Foo{ + .Three = Test3Point{ + .x = 3, + .y = 4, + }, +}; +const test3_bar = Test3Foo{ .Two = 13 }; +fn test3_1(f: *const Test3Foo) void { + switch (f.*) { Test3Foo.Three => |pt| { assert(pt.x == 3); assert(pt.y == 4); @@ -347,8 +362,8 @@ fn test3_1(f: &const Test3Foo) void { else => unreachable, } } -fn test3_2(f: &const Test3Foo) void { - switch (*f) { +fn test3_2(f: *const Test3Foo) void { + switch (f.*) { Test3Foo.Two => |x| { assert(x == 13); }, @@ -356,58 +371,61 @@ fn test3_2(f: &const Test3Foo) void { } } - test "character literals" { assert('\'' == single_quote); } const single_quote = '\''; - - test "take address of parameter" { testTakeAddressOfParameter(12.34); } fn testTakeAddressOfParameter(f: f32) void { const f_ptr = &f; - assert(*f_ptr == 12.34); + assert(f_ptr.* == 12.34); } - test "pointer comparison" { const a = ([]const u8)("a"); const b = &a; assert(ptrEql(b, b)); } -fn ptrEql(a: &const []const u8, b: &const []const u8) bool { +fn ptrEql(a: *const []const u8, b: *const []const u8) bool { return a == b; } - test "C string concatenation" { const a = c"OK" ++ c" IT " ++ c"WORKED"; const b = c"OK IT WORKED"; const len = cstr.len(b); const len_with_null = len + 1; - {var i: u32 = 0; while (i < len_with_null) : (i += 1) { - assert(a[i] == b[i]); - }} + { + var i: u32 = 0; + while (i < len_with_null) : (i += 1) { + assert(a[i] == b[i]); + } + } assert(a[len] == 0); assert(b[len] == 0); } test "cast slice to u8 slice" { assert(@sizeOf(i32) == 4); - var big_thing_array = []i32{1, 2, 3, 4}; + var big_thing_array = []i32{ + 1, + 2, + 3, + 4, + }; const big_thing_slice: []i32 = big_thing_array[0..]; - const bytes = ([]u8)(big_thing_slice); + const bytes = @sliceToBytes(big_thing_slice); assert(bytes.len == 4 * 4); bytes[4] = 0; bytes[5] = 0; bytes[6] = 0; bytes[7] = 0; assert(big_thing_slice[1] == 0); - const big_thing_again = ([]align(1) i32)(bytes); + const big_thing_again = @bytesToSlice(i32, bytes); assert(big_thing_again[2] == 3); big_thing_again[2] = -1; assert(bytes[8] == @maxValue(u8)); @@ -421,39 +439,48 @@ test "pointer to void return type" { } fn testPointerToVoidReturnType() error!void { const a = testPointerToVoidReturnType2(); - return *a; + return a.*; } const test_pointer_to_void_return_type_x = void{}; -fn testPointerToVoidReturnType2() &const void { +fn testPointerToVoidReturnType2() *const void { return &test_pointer_to_void_return_type_x; } - test "non const ptr to aliased type" { const int = i32; - assert(?&int == ?&i32); + assert(?*int == ?*i32); } - - test "array 2D const double ptr" { - const rect_2d_vertexes = [][1]f32 { + const rect_2d_vertexes = [][1]f32{ []f32{1.0}, []f32{2.0}, }; testArray2DConstDoublePtr(&rect_2d_vertexes[0][0]); } -fn testArray2DConstDoublePtr(ptr: &const f32) void { - assert(ptr[0] == 1.0); - assert(ptr[1] == 2.0); +fn testArray2DConstDoublePtr(ptr: *const f32) void { + const ptr2 = @ptrCast([*]const f32, ptr); + assert(ptr2[0] == 1.0); + assert(ptr2[1] == 2.0); } const Tid = builtin.TypeId; -const AStruct = struct { x: i32, }; -const AnEnum = enum { One, Two, }; -const AUnionEnum = union(enum) { One: i32, Two: void, }; -const AUnion = union { One: void, Two: void }; +const AStruct = struct { + x: i32, +}; +const AnEnum = enum { + One, + Two, +}; +const AUnionEnum = union(enum) { + One: i32, + Two: void, +}; +const AUnion = union { + One: void, + Two: void, +}; test "@typeId" { comptime { @@ -467,40 +494,33 @@ test "@typeId" { assert(@typeId(u64) == Tid.Int); assert(@typeId(f32) == Tid.Float); assert(@typeId(f64) == Tid.Float); - assert(@typeId(&f32) == Tid.Pointer); + assert(@typeId(*f32) == Tid.Pointer); assert(@typeId([2]u8) == Tid.Array); assert(@typeId(AStruct) == Tid.Struct); - assert(@typeId(@typeOf(1)) == Tid.IntLiteral); - assert(@typeId(@typeOf(1.0)) == Tid.FloatLiteral); - assert(@typeId(@typeOf(undefined)) == Tid.UndefinedLiteral); - assert(@typeId(@typeOf(null)) == Tid.NullLiteral); - assert(@typeId(?i32) == Tid.Nullable); + assert(@typeId(@typeOf(1)) == Tid.ComptimeInt); + assert(@typeId(@typeOf(1.0)) == Tid.ComptimeFloat); + assert(@typeId(@typeOf(undefined)) == Tid.Undefined); + assert(@typeId(@typeOf(null)) == Tid.Null); + assert(@typeId(?i32) == Tid.Optional); assert(@typeId(error!i32) == Tid.ErrorUnion); assert(@typeId(error) == Tid.ErrorSet); assert(@typeId(AnEnum) == Tid.Enum); assert(@typeId(@typeOf(AUnionEnum.One)) == Tid.Enum); assert(@typeId(AUnionEnum) == Tid.Union); assert(@typeId(AUnion) == Tid.Union); - assert(@typeId(fn()void) == Tid.Fn); + assert(@typeId(fn () void) == Tid.Fn); assert(@typeId(@typeOf(builtin)) == Tid.Namespace); - assert(@typeId(@typeOf(x: {break :x this;})) == Tid.Block); + assert(@typeId(@typeOf(x: { + break :x this; + })) == Tid.Block); // TODO bound fn // TODO arg tuple // TODO opaque } } -test "@canImplicitCast" { - comptime { - assert(@canImplicitCast(i64, i32(3))); - assert(!@canImplicitCast(i32, f32(1.234))); - assert(@canImplicitCast([]const u8, "aoeu")); - } -} - test "@typeName" { - const Struct = struct { - }; + const Struct = struct {}; const Union = union { unused: u8, }; @@ -509,8 +529,8 @@ test "@typeName" { }; comptime { assert(mem.eql(u8, @typeName(i64), "i64")); - assert(mem.eql(u8, @typeName(&usize), "&usize")); - // https://github.com/zig-lang/zig/issues/675 + assert(mem.eql(u8, @typeName(*usize), "*usize")); + // https://github.com/ziglang/zig/issues/675 assert(mem.eql(u8, @typeName(TypeFromFn(u8)), "TypeFromFn(u8)")); assert(mem.eql(u8, @typeName(Struct), "Struct")); assert(mem.eql(u8, @typeName(Union), "Union")); @@ -524,15 +544,20 @@ fn TypeFromFn(comptime T: type) type { test "volatile load and store" { var number: i32 = 1234; - const ptr = (&volatile i32)(&number); - *ptr += 1; - assert(*ptr == 1235); + const ptr = (*volatile i32)(&number); + ptr.* += 1; + assert(ptr.* == 1235); } test "slice string literal has type []const u8" { comptime { assert(@typeOf("aoeu"[0..]) == []const u8); - const array = []i32{1, 2, 3, 4}; + const array = []i32{ + 1, + 2, + 3, + 4, + }; assert(@typeOf(array[0..]) == []const i32); } } @@ -543,37 +568,36 @@ test "global variable initialized to global variable array element" { const GDTEntry = struct { field: i32, }; -var gdt = []GDTEntry { - GDTEntry {.field = 1}, - GDTEntry {.field = 2}, +var gdt = []GDTEntry{ + GDTEntry{ .field = 1 }, + GDTEntry{ .field = 2 }, }; var global_ptr = &gdt[0]; - // can't really run this test but we can make sure it has no compile error // and generates code -const vram = @intToPtr(&volatile u8, 0x20000000)[0..0x8000]; +const vram = @intToPtr([*]volatile u8, 0x20000000)[0..0x8000]; export fn writeToVRam() void { vram[0] = 'X'; } test "pointer child field" { - assert((&u32).Child == u32); + assert((*u32).Child == u32); } const OpaqueA = @OpaqueType(); const OpaqueB = @OpaqueType(); test "@OpaqueType" { - assert(&OpaqueA != &OpaqueB); + assert(*OpaqueA != *OpaqueB); assert(mem.eql(u8, @typeName(OpaqueA), "OpaqueA")); assert(mem.eql(u8, @typeName(OpaqueB), "OpaqueB")); } test "variable is allowed to be a pointer to an opaque type" { var x: i32 = 1234; - _ = hereIsAnOpaqueType(@ptrCast(&OpaqueA, &x)); + _ = hereIsAnOpaqueType(@ptrCast(*OpaqueA, &x)); } -fn hereIsAnOpaqueType(ptr: &OpaqueA) &OpaqueA { +fn hereIsAnOpaqueType(ptr: *OpaqueA) *OpaqueA { var a = ptr; return a; } @@ -584,7 +608,7 @@ test "comptime if inside runtime while which unconditionally breaks" { } fn testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(cond: bool) void { while (cond) { - if (false) { } + if (false) {} break; } } @@ -607,7 +631,7 @@ fn testStructInFn() void { kind: BlockKind, }; - var block = Block { .kind = 1234 }; + var block = Block{ .kind = 1234 }; block.kind += 1; @@ -617,7 +641,9 @@ fn testStructInFn() void { fn fnThatClosesOverLocalConst() type { const c = 1; return struct { - fn g() i32 { return c; } + fn g() i32 { + return c; + } }; } @@ -635,22 +661,27 @@ fn thisIsAColdFn() void { @setCold(true); } - -const PackedStruct = packed struct { a: u8, b: u8, }; -const PackedUnion = packed union { a: u8, b: u32, }; -const PackedEnum = packed enum { A, B, }; +const PackedStruct = packed struct { + a: u8, + b: u8, +}; +const PackedUnion = packed union { + a: u8, + b: u32, +}; +const PackedEnum = packed enum { + A, + B, +}; test "packed struct, enum, union parameters in extern function" { - testPackedStuff( - PackedStruct{.a = 1, .b = 2}, - PackedUnion{.a = 1}, - PackedEnum.A, - ); -} - -export fn testPackedStuff(a: &const PackedStruct, b: &const PackedUnion, c: PackedEnum) void { + testPackedStuff(PackedStruct{ + .a = 1, + .b = 2, + }, PackedUnion{ .a = 1 }, PackedEnum.A); } +export fn testPackedStuff(a: *const PackedStruct, b: *const PackedUnion, c: PackedEnum) void {} test "slicing zero length array" { const s1 = ""[0..]; @@ -661,9 +692,13 @@ test "slicing zero length array" { assert(mem.eql(u32, s2, []u32{})); } - -const addr1 = @ptrCast(&const u8, emptyFn); +const addr1 = @ptrCast(*const u8, emptyFn); test "comptime cast fn to ptr" { - const addr2 = @ptrCast(&const u8, emptyFn); + const addr2 = @ptrCast(*const u8, emptyFn); comptime assert(addr1 == addr2); } + +test "equality compare fn ptrs" { + var a = emptyFn; + assert(a == a); +} diff --git a/test/cases/namespace_depends_on_compile_var/index.zig b/test/cases/namespace_depends_on_compile_var/index.zig index 95209dcef3..ccc49d9367 100644 --- a/test/cases/namespace_depends_on_compile_var/index.zig +++ b/test/cases/namespace_depends_on_compile_var/index.zig @@ -8,7 +8,7 @@ test "namespace depends on compile var" { assert(!some_namespace.a_bool); } } -const some_namespace = switch(builtin.os) { +const some_namespace = switch (builtin.os) { builtin.Os.linux => @import("a.zig"), else => @import("b.zig"), }; diff --git a/test/cases/new_stack_call.zig b/test/cases/new_stack_call.zig new file mode 100644 index 0000000000..5912550d54 --- /dev/null +++ b/test/cases/new_stack_call.zig @@ -0,0 +1,26 @@ +const std = @import("std"); +const assert = std.debug.assert; + +var new_stack_bytes: [1024]u8 = undefined; + +test "calling a function with a new stack" { + const arg = 1234; + + const a = @newStackCall(new_stack_bytes[0..512], targetFunction, arg); + const b = @newStackCall(new_stack_bytes[512..], targetFunction, arg); + _ = targetFunction(arg); + + assert(arg == 1234); + assert(a < b); +} + +fn targetFunction(x: i32) usize { + assert(x == 1234); + + var local_variable: i32 = 42; + const ptr = &local_variable; + ptr.* += 1; + + assert(local_variable == 43); + return @ptrToInt(ptr); +} diff --git a/test/cases/null.zig b/test/cases/null.zig index 35d72b729c..c86dd34b06 100644 --- a/test/cases/null.zig +++ b/test/cases/null.zig @@ -1,7 +1,7 @@ const assert = @import("std").debug.assert; -test "nullable type" { - const x : ?bool = true; +test "optional type" { + const x: ?bool = true; if (x) |y| { if (y) { @@ -13,15 +13,15 @@ test "nullable type" { unreachable; } - const next_x : ?i32 = null; + const next_x: ?i32 = null; - const z = next_x ?? 1234; + const z = next_x orelse 1234; assert(z == 1234); - const final_x : ?i32 = 13; + const final_x: ?i32 = 13; - const num = final_x ?? unreachable; + const num = final_x orelse unreachable; assert(num == 13); } @@ -30,42 +30,43 @@ test "test maybe object and get a pointer to the inner value" { var maybe_bool: ?bool = true; if (maybe_bool) |*b| { - *b = false; + b.* = false; } - assert(??maybe_bool == false); + assert(maybe_bool.? == false); } - test "rhs maybe unwrap return" { const x: ?bool = true; - const y = x ?? return; + const y = x orelse return; } - test "maybe return" { maybeReturnImpl(); comptime maybeReturnImpl(); } fn maybeReturnImpl() void { - assert(??foo(1235)); - if (foo(null) != null) - unreachable; - assert(!??foo(1234)); + assert(foo(1235).?); + if (foo(null) != null) unreachable; + assert(!foo(1234).?); } fn foo(x: ?i32) ?bool { - const value = x ?? return null; + const value = x orelse return null; return value > 1234; } - test "if var maybe pointer" { - assert(shouldBeAPlus1(Particle {.a = 14, .b = 1, .c = 1, .d = 1}) == 15); -} -fn shouldBeAPlus1(p: &const Particle) u64 { - var maybe_particle: ?Particle = *p; + assert(shouldBeAPlus1(Particle{ + .a = 14, + .b = 1, + .c = 1, + .d = 1, + }) == 15); +} +fn shouldBeAPlus1(p: *const Particle) u64 { + var maybe_particle: ?Particle = p.*; if (maybe_particle) |*particle| { particle.a += 1; } @@ -81,7 +82,6 @@ const Particle = struct { d: u64, }; - test "null literal outside function" { const is_null = here_is_a_null_literal.context == null; assert(is_null); @@ -92,10 +92,7 @@ test "null literal outside function" { const SillyStruct = struct { context: ?i32, }; -const here_is_a_null_literal = SillyStruct { - .context = null, -}; - +const here_is_a_null_literal = SillyStruct{ .context = null }; test "test null runtime" { testTestNullRuntime(null); @@ -105,12 +102,12 @@ fn testTestNullRuntime(x: ?i32) void { assert(!(x != null)); } -test "nullable void" { - nullableVoidImpl(); - comptime nullableVoidImpl(); +test "optional void" { + optionalVoidImpl(); + comptime optionalVoidImpl(); } -fn nullableVoidImpl() void { +fn optionalVoidImpl() void { assert(bar(null) == null); assert(bar({}) != null); } @@ -123,21 +120,19 @@ fn bar(x: ?void) ?void { } } - - -const StructWithNullable = struct { +const StructWithOptional = struct { field: ?i32, }; -var struct_with_nullable: StructWithNullable = undefined; +var struct_with_optional: StructWithOptional = undefined; -test "unwrap nullable which is field of global var" { - struct_with_nullable.field = null; - if (struct_with_nullable.field) |payload| { +test "unwrap optional which is field of global var" { + struct_with_optional.field = null; + if (struct_with_optional.field) |payload| { unreachable; } - struct_with_nullable.field = 1234; - if (struct_with_nullable.field) |payload| { + struct_with_optional.field = 1234; + if (struct_with_optional.field) |payload| { assert(payload == 1234); } else { unreachable; @@ -145,6 +140,17 @@ test "unwrap nullable which is field of global var" { } test "null with default unwrap" { - const x: i32 = null ?? 1; + const x: i32 = null orelse 1; assert(x == 1); } + +test "optional types" { + comptime { + const opt_type_struct = StructWithOptionalType{ .t = u8 }; + assert(opt_type_struct.t != null and opt_type_struct.t.? == u8); + } +} + +const StructWithOptionalType = struct { + t: ?type, +}; diff --git a/test/cases/optional.zig b/test/cases/optional.zig new file mode 100644 index 0000000000..d43682bbec --- /dev/null +++ b/test/cases/optional.zig @@ -0,0 +1,30 @@ +const assert = @import("std").debug.assert; + +pub const EmptyStruct = struct {}; + +test "optional pointer to size zero struct" { + var e = EmptyStruct{}; + var o: ?*EmptyStruct = &e; + assert(o != null); +} + +test "equality compare nullable pointers" { + testNullPtrsEql(); + comptime testNullPtrsEql(); +} + +fn testNullPtrsEql() void { + var number: i32 = 1234; + + var x: ?*i32 = null; + var y: ?*i32 = null; + assert(x == y); + y = &number; + assert(x != y); + assert(x != &number); + assert(&number != x); + x = &number; + assert(x == y); + assert(x == &number); + assert(&number == x); +} diff --git a/test/cases/pointers.zig b/test/cases/pointers.zig new file mode 100644 index 0000000000..47afb60a2e --- /dev/null +++ b/test/cases/pointers.zig @@ -0,0 +1,44 @@ +const std = @import("std"); +const assert = std.debug.assert; + +test "dereference pointer" { + comptime testDerefPtr(); + testDerefPtr(); +} + +fn testDerefPtr() void { + var x: i32 = 1234; + var y = &x; + y.* += 1; + assert(x == 1235); +} + +test "pointer arithmetic" { + var ptr = c"abcd"; + + assert(ptr[0] == 'a'); + ptr += 1; + assert(ptr[0] == 'b'); + ptr += 1; + assert(ptr[0] == 'c'); + ptr += 1; + assert(ptr[0] == 'd'); + ptr += 1; + assert(ptr[0] == 0); + ptr -= 1; + assert(ptr[0] == 'd'); + ptr -= 1; + assert(ptr[0] == 'c'); + ptr -= 1; + assert(ptr[0] == 'b'); + ptr -= 1; + assert(ptr[0] == 'a'); +} + +test "double pointer parsing" { + comptime assert(PtrOf(PtrOf(i32)) == **i32); +} + +fn PtrOf(comptime T: type) type { + return *T; +} diff --git a/test/cases/popcount.zig b/test/cases/popcount.zig new file mode 100644 index 0000000000..7dc7f28c0e --- /dev/null +++ b/test/cases/popcount.zig @@ -0,0 +1,24 @@ +const assert = @import("std").debug.assert; + +test "@popCount" { + comptime testPopCount(); + testPopCount(); +} + +fn testPopCount() void { + { + var x: u32 = 0xaa; + assert(@popCount(x) == 4); + } + { + var x: u32 = 0xaaaaaaaa; + assert(@popCount(x) == 16); + } + { + var x: i16 = -1; + assert(@popCount(x) == 16); + } + comptime { + assert(@popCount(0b11111111000110001100010000100001000011000011100101010001) == 24); + } +} diff --git a/test/cases/ref_var_in_if_after_if_2nd_switch_prong.zig b/test/cases/ref_var_in_if_after_if_2nd_switch_prong.zig index 76cff3731a..3c94bb0d49 100644 --- a/test/cases/ref_var_in_if_after_if_2nd_switch_prong.zig +++ b/test/cases/ref_var_in_if_after_if_2nd_switch_prong.zig @@ -23,7 +23,7 @@ fn foo(c: bool, k: Num, c2: bool, b: []const u8) void { if (c) { const output_path = b; - if (c2) { } + if (c2) {} a(output_path); } diff --git a/test/cases/reflection.zig b/test/cases/reflection.zig index 18a766d9fc..3d3af3c889 100644 --- a/test/cases/reflection.zig +++ b/test/cases/reflection.zig @@ -1,10 +1,11 @@ const assert = @import("std").debug.assert; const mem = @import("std").mem; +const reflection = this; -test "reflection: array, pointer, nullable, error union type child" { +test "reflection: array, pointer, optional, error union type child" { comptime { assert(([10]u8).Child == u8); - assert((&u8).Child == u8); + assert((*u8).Child == u8); assert((error!u8).Payload == u8); assert((?u8).Child == u8); } @@ -22,7 +23,9 @@ test "reflection: function return type, var args, and param types" { } } -fn dummy(a: bool, b: i32, c: f32) i32 { return 1234; } +fn dummy(a: bool, b: i32, c: f32) i32 { + return 1234; +} fn dummy_varargs(args: ...) void {} test "reflection: struct member types and names" { @@ -53,10 +56,32 @@ test "reflection: enum member types and names" { assert(mem.eql(u8, @memberName(Bar, 2), "Three")); assert(mem.eql(u8, @memberName(Bar, 3), "Four")); } +} +test "reflection: @field" { + var f = Foo{ + .one = 42, + .two = true, + .three = void{}, + }; + + assert(f.one == f.one); + assert(@field(f, "o" ++ "ne") == f.one); + assert(@field(f, "t" ++ "wo") == f.two); + assert(@field(f, "th" ++ "ree") == f.three); + assert(@field(Foo, "const" ++ "ant") == Foo.constant); + assert(@field(Bar, "O" ++ "ne") == Bar.One); + assert(@field(Bar, "T" ++ "wo") == Bar.Two); + assert(@field(Bar, "Th" ++ "ree") == Bar.Three); + assert(@field(Bar, "F" ++ "our") == Bar.Four); + assert(@field(reflection, "dum" ++ "my")(true, 1, 2) == dummy(true, 1, 2)); + @field(f, "o" ++ "ne") = 4; + assert(f.one == 4); } const Foo = struct { + const constant = 52; + one: i32, two: bool, three: void, diff --git a/test/cases/slice.zig b/test/cases/slice.zig index ea708ba3b5..b4b43bdd19 100644 --- a/test/cases/slice.zig +++ b/test/cases/slice.zig @@ -1,7 +1,7 @@ const assert = @import("std").debug.assert; const mem = @import("std").mem; -const x = @intToPtr(&i32, 0x1000)[0..0x500]; +const x = @intToPtr([*]i32, 0x1000)[0..0x500]; const y = x[0x100..]; test "compile time slice of pointer to hard coded address" { assert(@ptrToInt(x.ptr) == 0x1000); @@ -18,7 +18,11 @@ test "slice child property" { } test "runtime safety lets us slice from len..len" { - var an_array = []u8{1, 2, 3}; + var an_array = []u8{ + 1, + 2, + 3, + }; assert(mem.eql(u8, sliceFromLenToLen(an_array[0..], 3, 3), "")); } @@ -27,7 +31,7 @@ fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 { } test "implicitly cast array of size 0 to slice" { - var msg = []u8 {}; + var msg = []u8{}; assertLenIsZero(msg); } diff --git a/test/cases/struct.zig b/test/cases/struct.zig index c3df97678b..20d46999d5 100644 --- a/test/cases/struct.zig +++ b/test/cases/struct.zig @@ -2,9 +2,11 @@ const assert = @import("std").debug.assert; const builtin = @import("builtin"); const StructWithNoFields = struct { - fn add(a: i32, b: i32) i32 { return a + b; } + fn add(a: i32, b: i32) i32 { + return a + b; + } }; -const empty_global_instance = StructWithNoFields {}; +const empty_global_instance = StructWithNoFields{}; test "call struct static method" { const result = StructWithNoFields.add(3, 4); @@ -25,7 +27,7 @@ test "invake static method in global scope" { } test "void struct fields" { - const foo = VoidStructFieldsFoo { + const foo = VoidStructFieldsFoo{ .a = void{}, .b = 1, .c = void{}, @@ -34,15 +36,14 @@ test "void struct fields" { assert(@sizeOf(VoidStructFieldsFoo) == 4); } const VoidStructFieldsFoo = struct { - a : void, - b : i32, - c : void, + a: void, + b: i32, + c: void, }; - test "structs" { var foo: StructFoo = undefined; - @memset(@ptrCast(&u8, &foo), 0, @sizeOf(StructFoo)); + @memset(@ptrCast([*]u8, &foo), 0, @sizeOf(StructFoo)); foo.a += 1; foo.b = foo.a == 1; testFoo(foo); @@ -50,21 +51,20 @@ test "structs" { assert(foo.c == 100); } const StructFoo = struct { - a : i32, - b : bool, - c : f32, + a: i32, + b: bool, + c: f32, }; -fn testFoo(foo: &const StructFoo) void { +fn testFoo(foo: *const StructFoo) void { assert(foo.b); } -fn testMutation(foo: &StructFoo) void { +fn testMutation(foo: *StructFoo) void { foo.c = 100; } - const Node = struct { val: Val, - next: &Node, + next: *Node, }; const Val = struct { @@ -72,10 +72,10 @@ const Val = struct { }; test "struct point to self" { - var root : Node = undefined; + var root: Node = undefined; root.val.x = 1; - var node : Node = undefined; + var node: Node = undefined; node.next = &root; node.val.x = 2; @@ -85,8 +85,8 @@ test "struct point to self" { } test "struct byval assign" { - var foo1 : StructFoo = undefined; - var foo2 : StructFoo = undefined; + var foo1: StructFoo = undefined; + var foo2: StructFoo = undefined; foo1.a = 1234; foo2.a = 0; @@ -96,51 +96,52 @@ test "struct byval assign" { } fn structInitializer() void { - const val = Val { .x = 42 }; + const val = Val{ .x = 42 }; assert(val.x == 42); } - test "fn call of struct field" { - assert(callStructField(Foo {.ptr = aFunc,}) == 13); + assert(callStructField(Foo{ .ptr = aFunc }) == 13); } const Foo = struct { - ptr: fn() i32, + ptr: fn () i32, }; -fn aFunc() i32 { return 13; } +fn aFunc() i32 { + return 13; +} -fn callStructField(foo: &const Foo) i32 { +fn callStructField(foo: *const Foo) i32 { return foo.ptr(); } - test "store member function in variable" { - const instance = MemberFnTestFoo { .x = 1234, }; + const instance = MemberFnTestFoo{ .x = 1234 }; const memberFn = MemberFnTestFoo.member; const result = memberFn(instance); assert(result == 1234); } const MemberFnTestFoo = struct { x: i32, - fn member(foo: &const MemberFnTestFoo) i32 { return foo.x; } + fn member(foo: *const MemberFnTestFoo) i32 { + return foo.x; + } }; - test "call member function directly" { - const instance = MemberFnTestFoo { .x = 1234, }; + const instance = MemberFnTestFoo{ .x = 1234 }; const result = MemberFnTestFoo.member(instance); assert(result == 1234); } test "member functions" { - const r = MemberFnRand {.seed = 1234}; + const r = MemberFnRand{ .seed = 1234 }; assert(r.getSeed() == 1234); } const MemberFnRand = struct { seed: u32, - pub fn getSeed(r: &const MemberFnRand) u32 { + pub fn getSeed(r: *const MemberFnRand) u32 { return r.seed; } }; @@ -154,7 +155,7 @@ const Bar = struct { y: i32, }; fn makeBar(x: i32, y: i32) Bar { - return Bar { + return Bar{ .x = x, .y = y, }; @@ -165,22 +166,21 @@ test "empty struct method call" { assert(es.method() == 1234); } const EmptyStruct = struct { - fn method(es: &const EmptyStruct) i32 { + fn method(es: *const EmptyStruct) i32 { return 1234; } }; - test "return empty struct from fn" { _ = testReturnEmptyStructFromFn(); } const EmptyStruct2 = struct {}; fn testReturnEmptyStructFromFn() EmptyStruct2 { - return EmptyStruct2 {}; + return EmptyStruct2{}; } test "pass slice of empty struct to fn" { - assert(testPassSliceOfEmptyStructToFn([]EmptyStruct2{ EmptyStruct2{} }) == 1); + assert(testPassSliceOfEmptyStructToFn([]EmptyStruct2{EmptyStruct2{}}) == 1); } fn testPassSliceOfEmptyStructToFn(slice: []const EmptyStruct2) usize { return slice.len; @@ -192,7 +192,7 @@ const APackedStruct = packed struct { }; test "packed struct" { - var foo = APackedStruct { + var foo = APackedStruct{ .x = 1, .y = 2, }; @@ -201,14 +201,13 @@ test "packed struct" { assert(four == 4); } - const BitField1 = packed struct { a: u3, b: u3, c: u2, }; -const bit_field_1 = BitField1 { +const bit_field_1 = BitField1{ .a = 1, .b = 2, .c = 3, @@ -229,19 +228,18 @@ test "bit field access" { assert(data.b == 3); } -fn getA(data: &const BitField1) u3 { +fn getA(data: *const BitField1) u3 { return data.a; } -fn getB(data: &const BitField1) u3 { +fn getB(data: *const BitField1) u3 { return data.b; } -fn getC(data: &const BitField1) u2 { +fn getC(data: *const BitField1) u2 { return data.c; } -const u24 = @IntType(false, 24); const Foo24Bits = packed struct { field: u24, }; @@ -258,7 +256,7 @@ test "packed struct 24bits" { assert(@sizeOf(Foo96Bits) == 12); } - var value = Foo96Bits { + var value = Foo96Bits{ .a = 0, .b = 0, .c = 0, @@ -303,7 +301,7 @@ test "packed array 24bits" { var bytes = []u8{0} ** (@sizeOf(FooArray24Bits) + 1); bytes[bytes.len - 1] = 0xaa; - const ptr = &([]FooArray24Bits)(bytes[0..bytes.len - 1])[0]; + const ptr = &@bytesToSlice(FooArray24Bits, bytes[0 .. bytes.len - 1])[0]; assert(ptr.a == 0); assert(ptr.b[0].field == 0); assert(ptr.b[1].field == 0); @@ -352,7 +350,7 @@ test "aligned array of packed struct" { } var bytes = []u8{0xbb} ** @sizeOf(FooArrayOfAligned); - const ptr = &([]FooArrayOfAligned)(bytes[0..bytes.len])[0]; + const ptr = &@bytesToSlice(FooArrayOfAligned, bytes[0..bytes.len])[0]; assert(ptr.a[0].a == 0xbb); assert(ptr.a[0].b == 0xbb); @@ -360,16 +358,20 @@ test "aligned array of packed struct" { assert(ptr.a[1].b == 0xbb); } - - test "runtime struct initialization of bitfield" { - const s1 = Nibbles { .x = x1, .y = x1 }; - const s2 = Nibbles { .x = u4(x2), .y = u4(x2) }; + const s1 = Nibbles{ + .x = x1, + .y = x1, + }; + const s2 = Nibbles{ + .x = @intCast(u4, x2), + .y = @intCast(u4, x2), + }; assert(s1.x == x1); assert(s1.y == x1); - assert(s2.x == u4(x2)); - assert(s2.y == u4(x2)); + assert(s2.x == @intCast(u4, x2)); + assert(s2.y == @intCast(u4, x2)); } var x1 = u4(1); @@ -393,8 +395,8 @@ const Bitfields = packed struct { test "native bit field understands endianness" { var all: u64 = 0x7765443322221111; var bytes: [8]u8 = undefined; - @memcpy(&bytes[0], @ptrCast(&u8, &all), 8); - var bitfields = *@ptrCast(&Bitfields, &bytes[0]); + @memcpy(bytes[0..].ptr, @ptrCast([*]u8, &all), 8); + var bitfields = @ptrCast(*Bitfields, bytes[0..].ptr).*; assert(bitfields.f1 == 0x1111); assert(bitfields.f2 == 0x2222); @@ -412,9 +414,26 @@ test "align 1 field before self referential align 8 field as slice return type" const Expr = union(enum) { Literal: u8, - Question: &Expr, + Question: *Expr, }; fn alloc(comptime T: type) []T { return []T{}; } + +test "call method with mutable reference to struct with no fields" { + const S = struct { + fn doC(s: *const this) bool { + return true; + } + fn do(s: *this) bool { + return true; + } + }; + + var s = S{}; + assert(S.doC(&s)); + assert(s.doC()); + assert(S.do(&s)); + assert(s.do()); +} diff --git a/test/cases/struct_contains_null_ptr_itself.zig b/test/cases/struct_contains_null_ptr_itself.zig index 5864ef4038..21175974b3 100644 --- a/test/cases/struct_contains_null_ptr_itself.zig +++ b/test/cases/struct_contains_null_ptr_itself.zig @@ -2,13 +2,13 @@ const std = @import("std"); const assert = std.debug.assert; test "struct contains null pointer which contains original struct" { - var x: ?&NodeLineComment = null; + var x: ?*NodeLineComment = null; assert(x == null); } pub const Node = struct { id: Id, - comment: ?&NodeLineComment, + comment: ?*NodeLineComment, pub const Id = enum { Root, @@ -19,4 +19,3 @@ pub const Node = struct { pub const NodeLineComment = struct { base: Node, }; - diff --git a/test/cases/struct_contains_slice_of_itself.zig b/test/cases/struct_contains_slice_of_itself.zig index 45ec56c1e2..07987ae32b 100644 --- a/test/cases/struct_contains_slice_of_itself.zig +++ b/test/cases/struct_contains_slice_of_itself.zig @@ -7,30 +7,30 @@ const Node = struct { test "struct contains slice of itself" { var other_nodes = []Node{ - Node { + Node{ .payload = 31, .children = []Node{}, }, - Node { + Node{ .payload = 32, .children = []Node{}, }, }; - var nodes = []Node { - Node { + var nodes = []Node{ + Node{ .payload = 1, .children = []Node{}, }, - Node { + Node{ .payload = 2, .children = []Node{}, }, - Node { + Node{ .payload = 3, .children = other_nodes[0..], }, }; - const root = Node { + const root = Node{ .payload = 1234, .children = nodes[0..], }; diff --git a/test/cases/switch.zig b/test/cases/switch.zig index a0ac646160..c6a4b60f09 100644 --- a/test/cases/switch.zig +++ b/test/cases/switch.zig @@ -6,7 +6,7 @@ test "switch with numbers" { fn testSwitchWithNumbers(x: u32) void { const result = switch (x) { - 1, 2, 3, 4 ... 8 => false, + 1, 2, 3, 4...8 => false, 13 => true, else => false, }; @@ -22,9 +22,9 @@ test "switch with all ranges" { fn testSwitchWithAllRanges(x: u32, y: u32) u32 { return switch (x) { - 0 ... 100 => 1, - 101 ... 200 => 2, - 201 ... 300 => 3, + 0...100 => 1, + 101...200 => 2, + 201...300 => 3, else => y, }; } @@ -61,7 +61,6 @@ fn nonConstSwitchOnEnum(fruit: Fruit) void { } } - test "switch statement" { nonConstSwitch(SwitchStatmentFoo.C); } @@ -81,19 +80,18 @@ const SwitchStatmentFoo = enum { D, }; - test "switch prong with variable" { - switchProngWithVarFn(SwitchProngWithVarEnum { .One = 13}); - switchProngWithVarFn(SwitchProngWithVarEnum { .Two = 13.0}); - switchProngWithVarFn(SwitchProngWithVarEnum { .Meh = {}}); + switchProngWithVarFn(SwitchProngWithVarEnum{ .One = 13 }); + switchProngWithVarFn(SwitchProngWithVarEnum{ .Two = 13.0 }); + switchProngWithVarFn(SwitchProngWithVarEnum{ .Meh = {} }); } const SwitchProngWithVarEnum = union(enum) { One: i32, Two: f32, Meh: void, }; -fn switchProngWithVarFn(a: &const SwitchProngWithVarEnum) void { - switch(*a) { +fn switchProngWithVarFn(a: *const SwitchProngWithVarEnum) void { + switch (a.*) { SwitchProngWithVarEnum.One => |x| { assert(x == 13); }, @@ -112,9 +110,9 @@ test "switch on enum using pointer capture" { } fn testSwitchEnumPtrCapture() void { - var value = SwitchProngWithVarEnum { .One = 1234 }; + var value = SwitchProngWithVarEnum{ .One = 1234 }; switch (value) { - SwitchProngWithVarEnum.One => |*x| *x += 1, + SwitchProngWithVarEnum.One => |*x| x.* += 1, else => unreachable, } switch (value) { @@ -135,14 +133,13 @@ fn returnsFive() i32 { return 5; } - const Number = union(enum) { One: u64, Two: u8, Three: f32, }; -const number = Number { .Three = 1.23 }; +const number = Number{ .Three = 1.23 }; fn returnsFalse() bool { switch (number) { @@ -196,11 +193,11 @@ fn testSwitchHandleAllCasesExhaustive(x: u2) u2 { fn testSwitchHandleAllCasesRange(x: u8) u8 { return switch (x) { - 0 ... 100 => u8(0), - 101 ... 200 => 1, + 0...100 => u8(0), + 101...200 => 1, 201, 203 => 2, 202 => 4, - 204 ... 255 => 3, + 204...255 => 3, }; } diff --git a/test/cases/switch_prong_err_enum.zig b/test/cases/switch_prong_err_enum.zig index 136e8834e6..f060ac2c57 100644 --- a/test/cases/switch_prong_err_enum.zig +++ b/test/cases/switch_prong_err_enum.zig @@ -14,14 +14,16 @@ const FormValue = union(enum) { fn doThing(form_id: u64) error!FormValue { return switch (form_id) { - 17 => FormValue { .Address = try readOnce() }, + 17 => FormValue{ .Address = try readOnce() }, else => error.InvalidDebugInfo, }; } test "switch prong returns error enum" { switch (doThing(17) catch unreachable) { - FormValue.Address => |payload| { assert(payload == 1); }, + FormValue.Address => |payload| { + assert(payload == 1); + }, else => unreachable, } assert(read_count == 1); diff --git a/test/cases/switch_prong_implicit_cast.zig b/test/cases/switch_prong_implicit_cast.zig index 335feeef43..56d37e290f 100644 --- a/test/cases/switch_prong_implicit_cast.zig +++ b/test/cases/switch_prong_implicit_cast.zig @@ -7,8 +7,8 @@ const FormValue = union(enum) { fn foo(id: u64) !FormValue { return switch (id) { - 2 => FormValue { .Two = true }, - 1 => FormValue { .One = {} }, + 2 => FormValue{ .Two = true }, + 1 => FormValue{ .One = {} }, else => return error.Whatever, }; } diff --git a/test/cases/syntax.zig b/test/cases/syntax.zig index 6c851c0ff3..b497b060c4 100644 --- a/test/cases/syntax.zig +++ b/test/cases/syntax.zig @@ -1,12 +1,11 @@ // Test trailing comma syntax +// zig fmt: off const struct_trailing_comma = struct { x: i32, y: i32, }; const struct_no_comma = struct { x: i32, y: i32 }; -const struct_no_comma_void_type = struct { x: i32, y }; const struct_fn_no_comma = struct { fn m() void {} y: i32 }; const enum_no_comma = enum { A, B }; -const enum_no_comma_type = enum { A, B: i32 }; fn container_init() void { const S = struct { x: i32, y: i32 }; @@ -36,16 +35,11 @@ fn switch_prongs(x: i32) void { const fn_no_comma = fn(i32, i32)void; const fn_trailing_comma = fn(i32, i32,)void; -const fn_vararg_trailing_comma = fn(i32, i32, ...,)void; fn fn_calls() void { fn add(x: i32, y: i32,) i32 { x + y }; _ = add(1, 2); _ = add(1, 2,); - - fn swallow(x: ...,) void {}; - _ = swallow(1,2,3,); - _ = swallow(); } fn asm_lists() void { diff --git a/test/cases/this.zig b/test/cases/this.zig index 8ed5e1ae1a..ba51d0ac90 100644 --- a/test/cases/this.zig +++ b/test/cases/this.zig @@ -8,7 +8,7 @@ fn Point(comptime T: type) type { x: T, y: T, - fn addOne(self: &Self) void { + fn addOne(self: *Self) void { self.x += 1; self.y += 1; } @@ -29,7 +29,7 @@ test "this refer to module call private fn" { } test "this refer to container" { - var pt = Point(i32) { + var pt = Point(i32){ .x = 12, .y = 34, }; diff --git a/test/cases/try.zig b/test/cases/try.zig index 4a0425e22e..cf5fa5862a 100644 --- a/test/cases/try.zig +++ b/test/cases/try.zig @@ -3,13 +3,10 @@ const assert = @import("std").debug.assert; test "try on error union" { tryOnErrorUnionImpl(); comptime tryOnErrorUnionImpl(); - } fn tryOnErrorUnionImpl() void { - const x = if (returnsTen()) |val| - val + 1 - else |err| switch (err) { + const x = if (returnsTen()) |val| val + 1 else |err| switch (err) { error.ItBroke, error.NoMem => 1, error.CrappedOut => i32(2), else => unreachable, diff --git a/test/cases/type_info.zig b/test/cases/type_info.zig new file mode 100644 index 0000000000..b8fc4cf14e --- /dev/null +++ b/test/cases/type_info.zig @@ -0,0 +1,259 @@ +const assert = @import("std").debug.assert; +const mem = @import("std").mem; +const TypeInfo = @import("builtin").TypeInfo; +const TypeId = @import("builtin").TypeId; + +test "type info: tag type, void info" { + testBasic(); + comptime testBasic(); +} + +fn testBasic() void { + assert(@TagType(TypeInfo) == TypeId); + const void_info = @typeInfo(void); + assert(TypeId(void_info) == TypeId.Void); + assert(void_info.Void == {}); +} + +test "type info: integer, floating point type info" { + testIntFloat(); + comptime testIntFloat(); +} + +fn testIntFloat() void { + const u8_info = @typeInfo(u8); + assert(TypeId(u8_info) == TypeId.Int); + assert(!u8_info.Int.is_signed); + assert(u8_info.Int.bits == 8); + + const f64_info = @typeInfo(f64); + assert(TypeId(f64_info) == TypeId.Float); + assert(f64_info.Float.bits == 64); +} + +test "type info: pointer type info" { + testPointer(); + comptime testPointer(); +} + +fn testPointer() void { + const u32_ptr_info = @typeInfo(*u32); + assert(TypeId(u32_ptr_info) == TypeId.Pointer); + assert(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.One); + assert(u32_ptr_info.Pointer.is_const == false); + assert(u32_ptr_info.Pointer.is_volatile == false); + assert(u32_ptr_info.Pointer.alignment == @alignOf(u32)); + assert(u32_ptr_info.Pointer.child == u32); +} + +test "type info: unknown length pointer type info" { + testUnknownLenPtr(); + comptime testUnknownLenPtr(); +} + +fn testUnknownLenPtr() void { + const u32_ptr_info = @typeInfo([*]const volatile f64); + assert(TypeId(u32_ptr_info) == TypeId.Pointer); + assert(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many); + assert(u32_ptr_info.Pointer.is_const == true); + assert(u32_ptr_info.Pointer.is_volatile == true); + assert(u32_ptr_info.Pointer.alignment == @alignOf(f64)); + assert(u32_ptr_info.Pointer.child == f64); +} + +test "type info: slice type info" { + testSlice(); + comptime testSlice(); +} + +fn testSlice() void { + const u32_slice_info = @typeInfo([]u32); + assert(TypeId(u32_slice_info) == TypeId.Pointer); + assert(u32_slice_info.Pointer.size == TypeInfo.Pointer.Size.Slice); + assert(u32_slice_info.Pointer.is_const == false); + assert(u32_slice_info.Pointer.is_volatile == false); + assert(u32_slice_info.Pointer.alignment == 4); + assert(u32_slice_info.Pointer.child == u32); +} + +test "type info: array type info" { + testArray(); + comptime testArray(); +} + +fn testArray() void { + const arr_info = @typeInfo([42]bool); + assert(TypeId(arr_info) == TypeId.Array); + assert(arr_info.Array.len == 42); + assert(arr_info.Array.child == bool); +} + +test "type info: optional type info" { + testOptional(); + comptime testOptional(); +} + +fn testOptional() void { + const null_info = @typeInfo(?void); + assert(TypeId(null_info) == TypeId.Optional); + assert(null_info.Optional.child == void); +} + +test "type info: promise info" { + testPromise(); + comptime testPromise(); +} + +fn testPromise() void { + const null_promise_info = @typeInfo(promise); + assert(TypeId(null_promise_info) == TypeId.Promise); + assert(null_promise_info.Promise.child == null); + + const promise_info = @typeInfo(promise->usize); + assert(TypeId(promise_info) == TypeId.Promise); + assert(promise_info.Promise.child.? == usize); +} + +test "type info: error set, error union info" { + testErrorSet(); + comptime testErrorSet(); +} + +fn testErrorSet() void { + const TestErrorSet = error{ + First, + Second, + Third, + }; + + const error_set_info = @typeInfo(TestErrorSet); + assert(TypeId(error_set_info) == TypeId.ErrorSet); + assert(error_set_info.ErrorSet.errors.len == 3); + assert(mem.eql(u8, error_set_info.ErrorSet.errors[0].name, "First")); + assert(error_set_info.ErrorSet.errors[2].value == @errorToInt(TestErrorSet.Third)); + + const error_union_info = @typeInfo(TestErrorSet!usize); + assert(TypeId(error_union_info) == TypeId.ErrorUnion); + assert(error_union_info.ErrorUnion.error_set == TestErrorSet); + assert(error_union_info.ErrorUnion.payload == usize); +} + +test "type info: enum info" { + testEnum(); + comptime testEnum(); +} + +fn testEnum() void { + const Os = @import("builtin").Os; + + const os_info = @typeInfo(Os); + assert(TypeId(os_info) == TypeId.Enum); + assert(os_info.Enum.layout == TypeInfo.ContainerLayout.Auto); + assert(os_info.Enum.fields.len == 32); + assert(mem.eql(u8, os_info.Enum.fields[1].name, "ananas")); + assert(os_info.Enum.fields[10].value == 10); + assert(os_info.Enum.tag_type == u5); + assert(os_info.Enum.defs.len == 0); +} + +test "type info: union info" { + testUnion(); + comptime testUnion(); +} + +fn testUnion() void { + const typeinfo_info = @typeInfo(TypeInfo); + assert(TypeId(typeinfo_info) == TypeId.Union); + assert(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto); + assert(typeinfo_info.Union.tag_type.? == TypeId); + assert(typeinfo_info.Union.fields.len == 25); + assert(typeinfo_info.Union.fields[4].enum_field != null); + assert(typeinfo_info.Union.fields[4].enum_field.?.value == 4); + assert(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int)); + assert(typeinfo_info.Union.defs.len == 20); + + const TestNoTagUnion = union { + Foo: void, + Bar: u32, + }; + + const notag_union_info = @typeInfo(TestNoTagUnion); + assert(TypeId(notag_union_info) == TypeId.Union); + assert(notag_union_info.Union.tag_type == null); + assert(notag_union_info.Union.layout == TypeInfo.ContainerLayout.Auto); + assert(notag_union_info.Union.fields.len == 2); + assert(notag_union_info.Union.fields[0].enum_field == null); + assert(notag_union_info.Union.fields[1].field_type == u32); + + const TestExternUnion = extern union { + foo: *c_void, + }; + + const extern_union_info = @typeInfo(TestExternUnion); + assert(extern_union_info.Union.layout == TypeInfo.ContainerLayout.Extern); + assert(extern_union_info.Union.tag_type == null); + assert(extern_union_info.Union.fields[0].enum_field == null); + assert(extern_union_info.Union.fields[0].field_type == *c_void); +} + +test "type info: struct info" { + testStruct(); + comptime testStruct(); +} + +fn testStruct() void { + const struct_info = @typeInfo(TestStruct); + assert(TypeId(struct_info) == TypeId.Struct); + assert(struct_info.Struct.layout == TypeInfo.ContainerLayout.Packed); + assert(struct_info.Struct.fields.len == 3); + assert(struct_info.Struct.fields[1].offset == null); + assert(struct_info.Struct.fields[2].field_type == *TestStruct); + assert(struct_info.Struct.defs.len == 2); + assert(struct_info.Struct.defs[0].is_pub); + assert(!struct_info.Struct.defs[0].data.Fn.is_extern); + assert(struct_info.Struct.defs[0].data.Fn.lib_name == null); + assert(struct_info.Struct.defs[0].data.Fn.return_type == void); + assert(struct_info.Struct.defs[0].data.Fn.fn_type == fn (*const TestStruct) void); +} + +const TestStruct = packed struct { + const Self = this; + + fieldA: usize, + fieldB: void, + fieldC: *Self, + + pub fn foo(self: *const Self) void {} +}; + +test "type info: function type info" { + testFunction(); + comptime testFunction(); +} + +fn testFunction() void { + const fn_info = @typeInfo(@typeOf(foo)); + assert(TypeId(fn_info) == TypeId.Fn); + assert(fn_info.Fn.calling_convention == TypeInfo.CallingConvention.Unspecified); + assert(fn_info.Fn.is_generic); + assert(fn_info.Fn.args.len == 2); + assert(fn_info.Fn.is_var_args); + assert(fn_info.Fn.return_type == null); + assert(fn_info.Fn.async_allocator_type == null); + + const test_instance: TestStruct = undefined; + const bound_fn_info = @typeInfo(@typeOf(test_instance.foo)); + assert(TypeId(bound_fn_info) == TypeId.BoundFn); + assert(bound_fn_info.BoundFn.args[0].arg_type.? == *const TestStruct); +} + +fn foo(comptime a: usize, b: bool, args: ...) usize { + return 0; +} + +test "typeInfo with comptime parameter in struct fn def" { + const S = struct { + pub fn func(comptime x: f32) void {} + }; + comptime var info = @typeInfo(S); +} diff --git a/test/cases/undefined.zig b/test/cases/undefined.zig index bc81f9cf84..83c620d211 100644 --- a/test/cases/undefined.zig +++ b/test/cases/undefined.zig @@ -27,12 +27,12 @@ test "init static array to undefined" { const Foo = struct { x: i32, - fn setFooXMethod(foo: &Foo) void { + fn setFooXMethod(foo: *Foo) void { foo.x = 3; } }; -fn setFooX(foo: &Foo) void { +fn setFooX(foo: *Foo) void { foo.x = 2; } @@ -63,6 +63,6 @@ test "assign undefined to struct with method" { } test "type name of undefined" { - const x = undefined; - assert(mem.eql(u8, @typeName(@typeOf(x)), "(undefined)")); + const x = undefined; + assert(mem.eql(u8, @typeName(@typeOf(x)), "(undefined)")); } diff --git a/test/cases/underscore.zig b/test/cases/underscore.zig new file mode 100644 index 0000000000..44451e3723 --- /dev/null +++ b/test/cases/underscore.zig @@ -0,0 +1,28 @@ +const std = @import("std"); +const assert = std.debug.assert; + +test "ignore lval with underscore" { + _ = false; +} + +test "ignore lval with underscore (for loop)" { + for ([]void{}) |_, i| { + for ([]void{}) |_, j| { + break; + } + break; + } +} + +test "ignore lval with underscore (while loop)" { + while (optionalReturnError()) |_| { + while (optionalReturnError()) |_| { + break; + } else |_| { } + break; + } else |_| { } +} + +fn optionalReturnError() !?u32 { + return error.optionalReturnError; +} diff --git a/test/cases/union.zig b/test/cases/union.zig index dc2a7c3414..08969e64fe 100644 --- a/test/cases/union.zig +++ b/test/cases/union.zig @@ -10,41 +10,54 @@ const Agg = struct { val2: Value, }; -const v1 = Value { .Int = 1234 }; -const v2 = Value { .Array = []u8{3} ** 9 }; +const v1 = Value{ .Int = 1234 }; +const v2 = Value{ .Array = []u8{3} ** 9 }; -const err = (error!Agg)(Agg { +const err = (error!Agg)(Agg{ .val1 = v1, .val2 = v2, }); -const array = []Value { v1, v2, v1, v2}; - +const array = []Value{ + v1, + v2, + v1, + v2, +}; test "unions embedded in aggregate types" { switch (array[1]) { Value.Array => |arr| assert(arr[4] == 3), else => unreachable, } - switch((err catch unreachable).val1) { + switch ((err catch unreachable).val1) { Value.Int => |x| assert(x == 1234), else => unreachable, } } - const Foo = union { float: f64, int: i32, }; test "basic unions" { - var foo = Foo { .int = 1 }; + var foo = Foo{ .int = 1 }; assert(foo.int == 1); - foo = Foo {.float = 12.34}; + foo = Foo{ .float = 12.34 }; assert(foo.float == 12.34); } +test "comptime union field access" { + comptime { + var foo = Foo{ .int = 0 }; + assert(foo.int == 0); + + foo = Foo{ .float = 42.42 }; + assert(foo.float == 42.42); + } +} + test "init union with runtime value" { var foo: Foo = undefined; @@ -55,12 +68,12 @@ test "init union with runtime value" { assert(foo.int == 42); } -fn setFloat(foo: &Foo, x: f64) void { - *foo = Foo { .float = x }; +fn setFloat(foo: *Foo, x: f64) void { + foo.* = Foo{ .float = x }; } -fn setInt(foo: &Foo, x: i32) void { - *foo = Foo { .int = x }; +fn setInt(foo: *Foo, x: i32) void { + foo.* = Foo{ .int = x }; } const FooExtern = extern union { @@ -69,13 +82,12 @@ const FooExtern = extern union { }; test "basic extern unions" { - var foo = FooExtern { .int = 1 }; + var foo = FooExtern{ .int = 1 }; assert(foo.int == 1); foo.float = 12.34; assert(foo.float == 12.34); } - const Letter = enum { A, B, @@ -93,12 +105,12 @@ test "union with specified enum tag" { } fn doTest() void { - assert(bar(Payload {.A = 1234}) == -10); + assert(bar(Payload{ .A = 1234 }) == -10); } -fn bar(value: &const Payload) i32 { - assert(Letter(*value) == Letter.A); - return switch (*value) { +fn bar(value: *const Payload) i32 { + assert(Letter(value.*) == Letter.A); + return switch (value.*) { Payload.A => |x| return x - 1244, Payload.B => |x| if (x == 12.34) i32(20) else 21, Payload.C => |x| if (x) i32(30) else 31, @@ -114,7 +126,7 @@ const MultipleChoice = union(enum(u32)) { test "simple union(enum(u32))" { var x = MultipleChoice.C; assert(x == MultipleChoice.C); - assert(u32(@TagType(MultipleChoice)(x)) == 60); + assert(@enumToInt(@TagType(MultipleChoice)(x)) == 60); } const MultipleChoice2 = union(enum(u32)) { @@ -131,13 +143,13 @@ const MultipleChoice2 = union(enum(u32)) { test "union(enum(u32)) with specified and unspecified tag values" { comptime assert(@TagType(@TagType(MultipleChoice2)) == u32); - testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2 {.C = 123}); - comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2 { .C = 123} ); + testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 }); + comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 }); } -fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: &const MultipleChoice2) void { - assert(u32(@TagType(MultipleChoice2)(*x)) == 60); - assert(1123 == switch (*x) { +fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: *const MultipleChoice2) void { + assert(@enumToInt(@TagType(MultipleChoice2)(x.*)) == 60); + assert(1123 == switch (x.*) { MultipleChoice2.A => 1, MultipleChoice2.B => 2, MultipleChoice2.C => |v| i32(1000) + v, @@ -150,18 +162,17 @@ fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: &const MultipleChoice2) void }); } - const ExternPtrOrInt = extern union { - ptr: &u8, - int: u64 + ptr: *u8, + int: u64, }; test "extern union size" { comptime assert(@sizeOf(ExternPtrOrInt) == 8); } const PackedPtrOrInt = packed union { - ptr: &u8, - int: u64 + ptr: *u8, + int: u64, }; test "extern union size" { comptime assert(@sizeOf(PackedPtrOrInt) == 8); @@ -174,8 +185,16 @@ test "union with only 1 field which is void should be zero bits" { comptime assert(@sizeOf(ZeroBits) == 0); } -const TheTag = enum {A, B, C}; -const TheUnion = union(TheTag) { A: i32, B: i32, C: i32 }; +const TheTag = enum { + A, + B, + C, +}; +const TheUnion = union(TheTag) { + A: i32, + B: i32, + C: i32, +}; test "union field access gives the enum values" { assert(TheUnion.A == TheTag.A); assert(TheUnion.B == TheTag.B); @@ -183,20 +202,28 @@ test "union field access gives the enum values" { } test "cast union to tag type of union" { - testCastUnionToTagType(TheUnion {.B = 1234}); - comptime testCastUnionToTagType(TheUnion {.B = 1234}); + testCastUnionToTagType(TheUnion{ .B = 1234 }); + comptime testCastUnionToTagType(TheUnion{ .B = 1234 }); } -fn testCastUnionToTagType(x: &const TheUnion) void { - assert(TheTag(*x) == TheTag.B); +fn testCastUnionToTagType(x: *const TheUnion) void { + assert(TheTag(x.*) == TheTag.B); } test "cast tag type of union to union" { var x: Value2 = Letter2.B; assert(Letter2(x) == Letter2.B); } -const Letter2 = enum { A, B, C }; -const Value2 = union(Letter2) { A: i32, B, C, }; +const Letter2 = enum { + A, + B, + C, +}; +const Value2 = union(Letter2) { + A: i32, + B, + C, +}; test "implicit cast union to its tag type" { var x: Value2 = Letter2.B; @@ -216,20 +243,17 @@ const TheUnion2 = union(enum) { Item2: i32, }; -fn assertIsTheUnion2Item1(value: &const TheUnion2) void { - assert(*value == TheUnion2.Item1); +fn assertIsTheUnion2Item1(value: *const TheUnion2) void { + assert(value.* == TheUnion2.Item1); } - pub const PackThis = union(enum) { Invalid: bool, StringLiteral: u2, }; test "constant packed union" { - testConstPackedUnion([]PackThis { - PackThis { .StringLiteral = 1 }, - }); + testConstPackedUnion([]PackThis{PackThis{ .StringLiteral = 1 }}); } fn testConstPackedUnion(expected_tokens: []const PackThis) void { @@ -242,7 +266,7 @@ test "switch on union with only 1 field" { switch (r) { PartialInst.Compiled => { var z: PartialInstWithPayload = undefined; - z = PartialInstWithPayload { .Compiled = 1234 }; + z = PartialInstWithPayload{ .Compiled = 1234 }; switch (z) { PartialInstWithPayload.Compiled => |x| { assert(x == 1234); @@ -262,3 +286,28 @@ const PartialInstWithPayload = union(enum) { Compiled: i32, }; +test "access a member of tagged union with conflicting enum tag name" { + const Bar = union(enum) { + A: A, + B: B, + + const A = u8; + const B = void; + }; + + comptime assert(Bar.A == u8); +} + +test "tagged union initialization with runtime void" { + assert(testTaggedUnionInit({})); +} + +const TaggedUnionWithAVoid = union(enum) { + A, + B: i32, +}; + +fn testTaggedUnionInit(x: var) bool { + const y = TaggedUnionWithAVoid{ .A = x }; + return @TagType(TaggedUnionWithAVoid)(y) == TaggedUnionWithAVoid.A; +} diff --git a/test/cases/var_args.zig b/test/cases/var_args.zig index cead9eb8bf..3eb6e30448 100644 --- a/test/cases/var_args.zig +++ b/test/cases/var_args.zig @@ -2,9 +2,12 @@ const assert = @import("std").debug.assert; fn add(args: ...) i32 { var sum = i32(0); - {comptime var i: usize = 0; inline while (i < args.len) : (i += 1) { - sum += args[i]; - }} + { + comptime var i: usize = 0; + inline while (i < args.len) : (i += 1) { + sum += args[i]; + } + } return sum; } @@ -55,31 +58,23 @@ fn extraFn(extra: u32, args: ...) usize { return args.len; } +const foos = []fn (...) bool{ + foo1, + foo2, +}; -const foos = []fn(...) bool { foo1, foo2 }; - -fn foo1(args: ...) bool { return true; } -fn foo2(args: ...) bool { return false; } +fn foo1(args: ...) bool { + return true; +} +fn foo2(args: ...) bool { + return false; +} test "array of var args functions" { assert(foos[0]()); assert(!foos[1]()); } - -test "pass array and slice of same array to var args should have same pointers" { - const array = "hi"; - const slice: []const u8 = array; - return assertSlicePtrsEql(array, slice); -} - -fn assertSlicePtrsEql(args: ...) void { - const s1 = ([]const u8)(args[0]); - const s2 = args[1]; - assert(s1.ptr == s2.ptr); -} - - test "pass zero length array to var args param" { doNothingWithFirstArg(""); } diff --git a/test/cases/void.zig b/test/cases/void.zig index f4d72209e4..7121ac664b 100644 --- a/test/cases/void.zig +++ b/test/cases/void.zig @@ -8,7 +8,7 @@ const Foo = struct { test "compare void with void compile time known" { comptime { - const foo = Foo { + const foo = Foo{ .a = {}, .b = 1, .c = {}, @@ -16,3 +16,15 @@ test "compare void with void compile time known" { assert(foo.a == {}); } } + +test "iterate over a void slice" { + var j: usize = 0; + for (times(10)) |_, i| { + assert(i == j); + j += 1; + } +} + +fn times(n: usize) []const void { + return ([*]void)(undefined)[0..n]; +} diff --git a/test/cases/while.zig b/test/cases/while.zig index 33d5a5623a..fe53522ea6 100644 --- a/test/cases/while.zig +++ b/test/cases/while.zig @@ -1,7 +1,7 @@ const assert = @import("std").debug.assert; test "while loop" { - var i : i32 = 0; + var i: i32 = 0; while (i < 4) { i += 1; } @@ -35,7 +35,7 @@ test "continue and break" { } var continue_and_break_counter: i32 = 0; fn runContinueAndBreakTest() void { - var i : i32 = 0; + var i: i32 = 0; while (true) { continue_and_break_counter += 2; i += 1; @@ -58,10 +58,13 @@ fn returnWithImplicitCastFromWhileLoopTest() error!void { test "while with continue expression" { var sum: i32 = 0; - {var i: i32 = 0; while (i < 10) : (i += 1) { - if (i == 5) continue; - sum += i; - }} + { + var i: i32 = 0; + while (i < 10) : (i += 1) { + if (i == 5) continue; + sum += i; + } + } assert(sum == 40); } @@ -78,7 +81,7 @@ test "while with else" { assert(got_else == 1); } -test "while with nullable as condition" { +test "while with optional as condition" { numbers_left = 10; var sum: i32 = 0; while (getNumberOrNull()) |value| { @@ -87,7 +90,7 @@ test "while with nullable as condition" { assert(sum == 45); } -test "while with nullable as condition with else" { +test "while with optional as condition with else" { numbers_left = 10; var sum: i32 = 0; var got_else: i32 = 0; @@ -117,61 +120,63 @@ test "while with error union condition" { var numbers_left: i32 = undefined; fn getNumberOrErr() error!i32 { - return if (numbers_left == 0) - error.OutOfNumbers - else x: { + return if (numbers_left == 0) error.OutOfNumbers else x: { numbers_left -= 1; break :x numbers_left; }; } fn getNumberOrNull() ?i32 { - return if (numbers_left == 0) - null - else x: { + return if (numbers_left == 0) null else x: { numbers_left -= 1; break :x numbers_left; }; } -test "while on nullable with else result follow else prong" { +test "while on optional with else result follow else prong" { const result = while (returnNull()) |value| { break value; - } else i32(2); + } else + i32(2); assert(result == 2); } -test "while on nullable with else result follow break prong" { - const result = while (returnMaybe(10)) |value| { +test "while on optional with else result follow break prong" { + const result = while (returnOptional(10)) |value| { break value; - } else i32(2); + } else + i32(2); assert(result == 10); } test "while on error union with else result follow else prong" { const result = while (returnError()) |value| { break value; - } else |err| i32(2); + } else |err| + i32(2); assert(result == 2); } test "while on error union with else result follow break prong" { const result = while (returnSuccess(10)) |value| { break value; - } else |err| i32(2); + } else |err| + i32(2); assert(result == 10); } test "while on bool with else result follow else prong" { const result = while (returnFalse()) { break i32(10); - } else i32(2); + } else + i32(2); assert(result == 2); } test "while on bool with else result follow break prong" { const result = while (returnTrue()) { break i32(10); - } else i32(2); + } else + i32(2); assert(result == 10); } @@ -202,9 +207,21 @@ fn testContinueOuter() void { } } -fn returnNull() ?i32 { return null; } -fn returnMaybe(x: i32) ?i32 { return x; } -fn returnError() error!i32 { return error.YouWantedAnError; } -fn returnSuccess(x: i32) error!i32 { return x; } -fn returnFalse() bool { return false; } -fn returnTrue() bool { return true; } +fn returnNull() ?i32 { + return null; +} +fn returnOptional(x: i32) ?i32 { + return x; +} +fn returnError() error!i32 { + return error.YouWantedAnError; +} +fn returnSuccess(x: i32) error!i32 { + return x; +} +fn returnFalse() bool { + return false; +} +fn returnTrue() bool { + return true; +} diff --git a/test/cases/widening.zig b/test/cases/widening.zig new file mode 100644 index 0000000000..cf6ab4ca0f --- /dev/null +++ b/test/cases/widening.zig @@ -0,0 +1,27 @@ +const std = @import("std"); +const assert = std.debug.assert; +const mem = std.mem; + +test "integer widening" { + var a: u8 = 250; + var b: u16 = a; + var c: u32 = b; + var d: u64 = c; + var e: u64 = d; + var f: u128 = e; + assert(f == a); +} + +test "implicit unsigned integer to signed integer" { + var a: u8 = 250; + var b: i16 = a; + assert(b == 250); +} + +test "float widening" { + var a: f16 = 12.34; + var b: f32 = a; + var c: f64 = b; + var d: f128 = c; + assert(d == a); +} diff --git a/test/compare_output.zig b/test/compare_output.zig index 9595bf8259..a18a78b419 100644 --- a/test/compare_output.zig +++ b/test/compare_output.zig @@ -3,10 +3,10 @@ const std = @import("std"); const os = std.os; const tests = @import("tests.zig"); -pub fn addCases(cases: &tests.CompareOutputContext) void { +pub fn addCases(cases: *tests.CompareOutputContext) void { cases.addC("hello world with libc", \\const c = @cImport(@cInclude("stdio.h")); - \\export fn main(argc: c_int, argv: &&u8) c_int { + \\export fn main(argc: c_int, argv: [*][*]u8) c_int { \\ _ = c.puts(c"Hello, world!"); \\ return 0; \\} @@ -131,7 +131,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void { \\const is_windows = builtin.os == builtin.Os.windows; \\const c = @cImport({ \\ if (is_windows) { - \\ // See https://github.com/zig-lang/zig/issues/515 + \\ // See https://github.com/ziglang/zig/issues/515 \\ @cDefine("_NO_CRT_STDIO_INLINE", "1"); \\ @cInclude("io.h"); \\ @cInclude("fcntl.h"); @@ -139,7 +139,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void { \\ @cInclude("stdio.h"); \\}); \\ - \\export fn main(argc: c_int, argv: &&u8) c_int { + \\export fn main(argc: c_int, argv: [*][*]u8) c_int { \\ if (is_windows) { \\ // we want actual \n, not \r\n \\ _ = c._setmode(1, c._O_BINARY); @@ -284,12 +284,12 @@ pub fn addCases(cases: &tests.CompareOutputContext) void { cases.addC("expose function pointer to C land", \\const c = @cImport(@cInclude("stdlib.h")); \\ - \\export fn compare_fn(a: ?&const c_void, b: ?&const c_void) c_int { - \\ const a_int = @ptrCast(&align(1) const i32, a ?? unreachable); - \\ const b_int = @ptrCast(&align(1) const i32, b ?? unreachable); - \\ if (*a_int < *b_int) { + \\export fn compare_fn(a: ?*const c_void, b: ?*const c_void) c_int { + \\ const a_int = @ptrCast(*const i32, @alignCast(@alignOf(i32), a)); + \\ const b_int = @ptrCast(*const i32, @alignCast(@alignOf(i32), b)); + \\ if (a_int.* < b_int.*) { \\ return -1; - \\ } else if (*a_int > *b_int) { + \\ } else if (a_int.* > b_int.*) { \\ return 1; \\ } else { \\ return 0; @@ -297,9 +297,9 @@ pub fn addCases(cases: &tests.CompareOutputContext) void { \\} \\ \\export fn main() c_int { - \\ var array = []u32 { 1, 7, 3, 2, 0, 9, 4, 8, 6, 5 }; + \\ var array = []u32{ 1, 7, 3, 2, 0, 9, 4, 8, 6, 5 }; \\ - \\ c.qsort(@ptrCast(&c_void, &array[0]), c_ulong(array.len), @sizeOf(i32), compare_fn); + \\ c.qsort(@ptrCast(?*c_void, array[0..].ptr), @intCast(c_ulong, array.len), @sizeOf(i32), compare_fn); \\ \\ for (array) |item, i| { \\ if (item != i) { @@ -316,7 +316,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void { \\const is_windows = builtin.os == builtin.Os.windows; \\const c = @cImport({ \\ if (is_windows) { - \\ // See https://github.com/zig-lang/zig/issues/515 + \\ // See https://github.com/ziglang/zig/issues/515 \\ @cDefine("_NO_CRT_STDIO_INLINE", "1"); \\ @cInclude("io.h"); \\ @cInclude("fcntl.h"); @@ -324,15 +324,15 @@ pub fn addCases(cases: &tests.CompareOutputContext) void { \\ @cInclude("stdio.h"); \\}); \\ - \\export fn main(argc: c_int, argv: &&u8) c_int { + \\export fn main(argc: c_int, argv: [*][*]u8) c_int { \\ if (is_windows) { \\ // we want actual \n, not \r\n \\ _ = c._setmode(1, c._O_BINARY); \\ } \\ const small: f32 = 3.25; \\ const x: f64 = small; - \\ const y = i32(x); - \\ const z = f64(y); + \\ const y = @floatToInt(i32, x); + \\ const z = @intToFloat(f64, y); \\ _ = c.printf(c"%.2f\n%d\n%.2f\n%.2f\n", x, y, z, f64(-0.4)); \\ return 0; \\} @@ -344,13 +344,13 @@ pub fn addCases(cases: &tests.CompareOutputContext) void { \\const Foo = struct { \\ field1: Bar, \\ - \\ fn method(a: &const Foo) bool { return true; } + \\ fn method(a: *const Foo) bool { return true; } \\}; \\ \\const Bar = struct { \\ field2: i32, \\ - \\ fn method(b: &const Bar) bool { return true; } + \\ fn method(b: *const Bar) bool { return true; } \\}; \\ \\pub fn main() void { @@ -475,7 +475,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void { \\ ); - tc.setCommandLineArgs([][]const u8 { + tc.setCommandLineArgs([][]const u8{ "first arg", "'a' 'b' \\", "bare", @@ -516,7 +516,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void { \\ ); - tc.setCommandLineArgs([][]const u8 { + tc.setCommandLineArgs([][]const u8{ "first arg", "'a' 'b' \\", "bare", diff --git a/test/compile_errors.zig b/test/compile_errors.zig index b22816a9a8..56b2c51d74 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -1,25 +1,484 @@ const tests = @import("tests.zig"); -pub fn addCases(cases: &tests.CompileErrorContext) void { - cases.add("assign inline fn to non-comptime var", +pub fn addCases(cases: *tests.CompileErrorContext) void { + cases.add( + "@handle() called outside of function definition", + \\var handle_undef: promise = undefined; + \\var handle_dummy: promise = @handle(); + \\export fn entry() bool { + \\ return handle_undef == handle_dummy; + \\} + , + ".tmp_source.zig:2:29: error: @handle() called outside of function definition", + ); + + cases.add( + "@handle() in non-async function", + \\export fn entry() bool { + \\ var handle_undef: promise = undefined; + \\ return handle_undef == @handle(); + \\} + , + ".tmp_source.zig:3:28: error: @handle() in non-async function", + ); + + cases.add( + "`_` is not a declarable symbol", + \\export fn f1() usize { + \\ var _: usize = 2; + \\ return _; + \\} + , + ".tmp_source.zig:2:5: error: `_` is not a declarable symbol", + ".tmp_source.zig:3:12: error: use of undeclared identifier '_'", + ); + + cases.add( + "`_` should not be usable inside for", + \\export fn returns() void { + \\ for ([]void{}) |_, i| { + \\ for ([]void{}) |_, j| { + \\ return _; + \\ } + \\ } + \\} + , + ".tmp_source.zig:4:20: error: use of undeclared identifier '_'", + ); + + cases.add( + "`_` should not be usable inside while", + \\export fn returns() void { + \\ while (optionalReturn()) |_| { + \\ while (optionalReturn()) |_| { + \\ return _; + \\ } + \\ } + \\} + \\fn optionalReturn() ?u32 { + \\ return 1; + \\} + , + ".tmp_source.zig:4:20: error: use of undeclared identifier '_'", + ); + + cases.add( + "`_` should not be usable inside while else", + \\export fn returns() void { + \\ while (optionalReturnError()) |_| { + \\ while (optionalReturnError()) |_| { + \\ return; + \\ } else |_| { + \\ if (_ == error.optionalReturnError) return; + \\ } + \\ } + \\} + \\fn optionalReturnError() !?u32 { + \\ return error.optionalReturnError; + \\} + , + ".tmp_source.zig:6:17: error: use of undeclared identifier '_'", + ); + + cases.add( + "while loop body expression ignored", + \\fn returns() usize { + \\ return 2; + \\} + \\export fn f1() void { + \\ while (true) returns(); + \\} + \\export fn f2() void { + \\ var x: ?i32 = null; + \\ while (x) |_| returns(); + \\} + \\export fn f3() void { + \\ var x: error!i32 = error.Bad; + \\ while (x) |_| returns() else |_| unreachable; + \\} + , + ".tmp_source.zig:5:25: error: expression value is ignored", + ".tmp_source.zig:9:26: error: expression value is ignored", + ".tmp_source.zig:13:26: error: expression value is ignored", + ); + + cases.add( + "missing parameter name of generic function", + \\fn dump(var) void {} + \\export fn entry() void { + \\ var a: u8 = 9; + \\ dump(a); + \\} + , + ".tmp_source.zig:1:9: error: missing parameter name", + ); + + cases.add( + "non-inline for loop on a type that requires comptime", + \\const Foo = struct { + \\ name: []const u8, + \\ T: type, + \\}; + \\export fn entry() void { + \\ const xx: [2]Foo = undefined; + \\ for (xx) |f| {} + \\} + , + ".tmp_source.zig:7:15: error: variable of type 'Foo' must be const or comptime", + ); + + cases.add( + "generic fn as parameter without comptime keyword", + \\fn f(_: fn (var) void) void {} + \\fn g(_: var) void {} + \\export fn entry() void { + \\ f(g); + \\} + , + ".tmp_source.zig:1:9: error: parameter of type 'fn(var)var' must be declared comptime", + ); + + cases.add( + "optional pointer to void in extern struct", + \\comptime { + \\ _ = @IntType(false, @maxValue(u32) + 1); + \\} + , + ".tmp_source.zig:2:40: error: integer value 4294967296 cannot be implicitly casted to type 'u32'", + ); + + cases.add( + "optional pointer to void in extern struct", + \\const Foo = extern struct { + \\ x: ?*const void, + \\}; + \\const Bar = extern struct { + \\ foo: Foo, + \\ y: i32, + \\}; + \\export fn entry(bar: *Bar) void {} + , + ".tmp_source.zig:2:5: error: extern structs cannot contain fields of type '?*const void'", + ); + + cases.add( + "use of comptime-known undefined function value", + \\const Cmd = struct { + \\ exec: fn () void, + \\}; + \\export fn entry() void { + \\ const command = Cmd{ .exec = undefined }; + \\ command.exec(); + \\} + , + ".tmp_source.zig:6:12: error: use of undefined value", + ); + + cases.add( + "use of comptime-known undefined function value", + \\const Cmd = struct { + \\ exec: fn () void, + \\}; + \\export fn entry() void { + \\ const command = Cmd{ .exec = undefined }; + \\ command.exec(); + \\} + , + ".tmp_source.zig:6:12: error: use of undefined value", + ); + + cases.add( + "bad @alignCast at comptime", + \\comptime { + \\ const ptr = @intToPtr(*i32, 0x1); + \\ const aligned = @alignCast(4, ptr); + \\} + , + ".tmp_source.zig:3:35: error: pointer address 0x1 is not aligned to 4 bytes", + ); + + cases.add( + "@ptrToInt on *void", + \\export fn entry() bool { + \\ return @ptrToInt(&{}) == @ptrToInt(&{}); + \\} + , + ".tmp_source.zig:2:23: error: pointer to size 0 type has no address", + ); + + cases.add( + "@popCount - non-integer", + \\export fn entry(x: f32) u32 { + \\ return @popCount(x); + \\} + , + ".tmp_source.zig:2:22: error: expected integer type, found 'f32'", + ); + + cases.add( + "@popCount - negative comptime_int", + \\comptime { + \\ _ = @popCount(-1); + \\} + , + ".tmp_source.zig:2:9: error: @popCount on negative comptime_int value -1", + ); + + cases.addCase(x: { + const tc = cases.create( + "wrong same named struct", + \\const a = @import("a.zig"); + \\const b = @import("b.zig"); + \\ + \\export fn entry() void { + \\ var a1: a.Foo = undefined; + \\ bar(&a1); + \\} + \\ + \\fn bar(x: *b.Foo) void {} + , + ".tmp_source.zig:6:10: error: expected type '*Foo', found '*Foo'", + ".tmp_source.zig:6:10: note: pointer type child 'Foo' cannot cast into pointer type child 'Foo'", + "a.zig:1:17: note: Foo declared here", + "b.zig:1:17: note: Foo declared here", + ); + + tc.addSourceFile("a.zig", + \\pub const Foo = struct { + \\ x: i32, + \\}; + ); + + tc.addSourceFile("b.zig", + \\pub const Foo = struct { + \\ z: f64, + \\}; + ); + + break :x tc; + }); + + cases.add( + "enum field value references enum", + \\pub const Foo = extern enum { + \\ A = Foo.B, + \\ C = D, + \\}; + \\export fn entry() void { + \\ var s: Foo = Foo.E; + \\} + , + ".tmp_source.zig:1:17: error: 'Foo' depends on itself", + ); + + cases.add( + "@floatToInt comptime safety", + \\comptime { + \\ _ = @floatToInt(i8, f32(-129.1)); + \\} + \\comptime { + \\ _ = @floatToInt(u8, f32(-1.1)); + \\} + \\comptime { + \\ _ = @floatToInt(u8, f32(256.1)); + \\} + , + ".tmp_source.zig:2:9: error: integer value '-129' cannot be stored in type 'i8'", + ".tmp_source.zig:5:9: error: integer value '-1' cannot be stored in type 'u8'", + ".tmp_source.zig:8:9: error: integer value '256' cannot be stored in type 'u8'", + ); + + cases.add( + "use c_void as return type of fn ptr", + \\export fn entry() void { + \\ const a: fn () c_void = undefined; + \\} + , + ".tmp_source.zig:2:20: error: return type cannot be opaque", + ); + + cases.add( + "non int passed to @intToFloat", + \\export fn entry() void { + \\ const x = @intToFloat(f32, 1.1); + \\} + , + ".tmp_source.zig:2:32: error: expected int type, found 'comptime_float'", + ); + + cases.add( + "use implicit casts to assign null to non-nullable pointer", + \\export fn entry() void { + \\ var x: i32 = 1234; + \\ var p: *i32 = &x; + \\ var pp: *?*i32 = &p; + \\ pp.* = null; + \\ var y = p.*; + \\} + , + ".tmp_source.zig:4:23: error: expected type '*?*i32', found '**i32'", + ); + + cases.add( + "attempted implicit cast from T to [*]const T", + \\export fn entry() void { + \\ const x: [*]const bool = true; + \\} + , + ".tmp_source.zig:2:30: error: expected type '[*]const bool', found 'bool'", + ); + + cases.add( + "dereference unknown length pointer", + \\export fn entry(x: [*]i32) i32 { + \\ return x.*; + \\} + , + ".tmp_source.zig:2:13: error: index syntax required for unknown-length pointer type '[*]i32'", + ); + + cases.add( + "field access of unknown length pointer", + \\const Foo = extern struct { + \\ a: i32, + \\}; + \\ + \\export fn entry(foo: [*]Foo) void { + \\ foo.a += 1; + \\} + , + ".tmp_source.zig:6:8: error: type '[*]Foo' does not support field access", + ); + + cases.add( + "unknown length pointer to opaque", + \\export const T = [*]@OpaqueType(); + , + ".tmp_source.zig:1:18: error: unknown-length pointer to opaque", + ); + + cases.add( + "error when evaluating return type", + \\const Foo = struct { + \\ map: i32(i32), + \\ + \\ fn init() Foo { + \\ return undefined; + \\ } + \\}; + \\export fn entry() void { + \\ var rule_set = try Foo.init(); + \\} + , + ".tmp_source.zig:2:13: error: expected type 'i32', found 'type'", + ); + + cases.add( + "slicing single-item pointer", + \\export fn entry(ptr: *i32) void { + \\ const slice = ptr[0..2]; + \\} + , + ".tmp_source.zig:2:22: error: slice of single-item pointer", + ); + + cases.add( + "indexing single-item pointer", + \\export fn entry(ptr: *i32) i32 { + \\ return ptr[1]; + \\} + , + ".tmp_source.zig:2:15: error: index of single-item pointer", + ); + + cases.add( + "nested error set mismatch", + \\const NextError = error{NextError}; + \\const OtherError = error{OutOfMemory}; + \\ + \\export fn entry() void { + \\ const a: ?NextError!i32 = foo(); + \\} + \\ + \\fn foo() ?OtherError!i32 { + \\ return null; + \\} + , + ".tmp_source.zig:5:34: error: expected type '?NextError!i32', found '?OtherError!i32'", + ".tmp_source.zig:5:34: note: optional type child 'OtherError!i32' cannot cast into optional type child 'NextError!i32'", + ".tmp_source.zig:5:34: note: error set 'OtherError' cannot cast into error set 'NextError'", + ".tmp_source.zig:2:26: note: 'error.OutOfMemory' not a member of destination error set", + ); + + cases.add( + "invalid deref on switch target", + \\comptime { + \\ var tile = Tile.Empty; + \\ switch (tile.*) { + \\ Tile.Empty => {}, + \\ Tile.Filled => {}, + \\ } + \\} + \\const Tile = enum { + \\ Empty, + \\ Filled, + \\}; + , + ".tmp_source.zig:3:17: error: invalid deref on switch target", + ); + + cases.add( + "invalid field access in comptime", + \\comptime { var x = doesnt_exist.whatever; } + , + ".tmp_source.zig:1:20: error: use of undeclared identifier 'doesnt_exist'", + ); + + cases.add( + "suspend inside suspend block", + \\const std = @import("std",); + \\ + \\export fn entry() void { + \\ var buf: [500]u8 = undefined; + \\ var a = &std.heap.FixedBufferAllocator.init(buf[0..]).allocator; + \\ const p = (async<a> foo()) catch unreachable; + \\ cancel p; + \\} + \\ + \\async fn foo() void { + \\ suspend { + \\ suspend { + \\ } + \\ } + \\} + , + ".tmp_source.zig:12:9: error: cannot suspend inside suspend block", + ".tmp_source.zig:11:5: note: other suspend block here", + ); + + cases.add( + "assign inline fn to non-comptime var", \\export fn entry() void { \\ var a = b; \\} \\inline fn b() void { } , ".tmp_source.zig:2:5: error: functions marked inline must be stored in const or comptime var", - ".tmp_source.zig:4:8: note: declared here"); + ".tmp_source.zig:4:8: note: declared here", + ); - cases.add("wrong type passed to @panic", + cases.add( + "wrong type passed to @panic", \\export fn entry() void { \\ var e = error.Foo; \\ @panic(e); \\} , - ".tmp_source.zig:3:12: error: expected type '[]const u8', found 'error{Foo}'"); - + ".tmp_source.zig:3:12: error: expected type '[]const u8', found 'error{Foo}'", + ); - cases.add("@tagName used on union with no associated enum tag", + cases.add( + "@tagName used on union with no associated enum tag", \\const FloatInt = extern union { \\ Float: f32, \\ Int: i32, @@ -30,10 +489,12 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\} , ".tmp_source.zig:7:19: error: union has no associated enum", - ".tmp_source.zig:1:18: note: declared here"); + ".tmp_source.zig:1:18: note: declared here", + ); - cases.add("returning error from void async function", - \\const std = @import("std"); + cases.add( + "returning error from void async function", + \\const std = @import("std",); \\export fn entry() void { \\ const p = async<std.debug.global_allocator> amain() catch unreachable; \\} @@ -41,32 +502,40 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ return error.ShouldBeCompileError; \\} , - ".tmp_source.zig:6:17: error: expected type 'void', found 'error{ShouldBeCompileError}'"); + ".tmp_source.zig:6:17: error: expected type 'void', found 'error{ShouldBeCompileError}'", + ); - cases.add("var not allowed in structs", + cases.add( + "var not allowed in structs", \\export fn entry() void { \\ var s = (struct{v: var}){.v=i32(10)}; \\} , - ".tmp_source.zig:2:23: error: invalid token: 'var'"); + ".tmp_source.zig:2:23: error: invalid token: 'var'", + ); - cases.add("@ptrCast discards const qualifier", + cases.add( + "@ptrCast discards const qualifier", \\export fn entry() void { \\ const x: i32 = 1234; - \\ const y = @ptrCast(&i32, &x); + \\ const y = @ptrCast(*i32, &x); \\} , - ".tmp_source.zig:3:15: error: cast discards const qualifier"); + ".tmp_source.zig:3:15: error: cast discards const qualifier", + ); - cases.add("comptime slice of undefined pointer non-zero len", + cases.add( + "comptime slice of undefined pointer non-zero len", \\export fn entry() void { - \\ const slice = (&i32)(undefined)[0..1]; + \\ const slice = ([*]i32)(undefined)[0..1]; \\} , - ".tmp_source.zig:2:36: error: non-zero length slice of undefined pointer"); + ".tmp_source.zig:2:38: error: non-zero length slice of undefined pointer", + ); - cases.add("type checking function pointers", - \\fn a(b: fn (&const u8) void) void { + cases.add( + "type checking function pointers", + \\fn a(b: fn (*const u8) void) void { \\ b('a'); \\} \\fn c(d: u8) void { @@ -76,9 +545,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ a(c); \\} , - ".tmp_source.zig:8:7: error: expected type 'fn(&const u8) void', found 'fn(u8) void'"); + ".tmp_source.zig:8:7: error: expected type 'fn(*const u8) void', found 'fn(u8) void'", + ); - cases.add("no else prong on switch on global error set", + cases.add( + "no else prong on switch on global error set", \\export fn entry() void { \\ foo(error.A); \\} @@ -88,18 +559,22 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ } \\} , - ".tmp_source.zig:5:5: error: else prong required when switching on type 'error'"); + ".tmp_source.zig:5:5: error: else prong required when switching on type 'error'", + ); - cases.add("inferred error set with no returned error", + cases.add( + "inferred error set with no returned error", \\export fn entry() void { \\ foo() catch unreachable; \\} \\fn foo() !void { \\} , - ".tmp_source.zig:4:11: error: function with inferred error set must return at least one possible error"); + ".tmp_source.zig:4:11: error: function with inferred error set must return at least one possible error", + ); - cases.add("error not handled in switch", + cases.add( + "error not handled in switch", \\export fn entry() void { \\ foo(452) catch |err| switch (err) { \\ error.Foo => {}, @@ -115,9 +590,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\} , ".tmp_source.zig:2:26: error: error.Baz not handled in switch", - ".tmp_source.zig:2:26: error: error.Bar not handled in switch"); + ".tmp_source.zig:2:26: error: error.Bar not handled in switch", + ); - cases.add("duplicate error in switch", + cases.add( + "duplicate error in switch", \\export fn entry() void { \\ foo(452) catch |err| switch (err) { \\ error.Foo => {}, @@ -135,9 +612,25 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\} , ".tmp_source.zig:5:14: error: duplicate switch value: '@typeOf(foo).ReturnType.ErrorSet.Foo'", - ".tmp_source.zig:3:14: note: other value is here"); + ".tmp_source.zig:3:14: note: other value is here", + ); + + cases.add("invalid cast from integral type to enum", + \\const E = enum(usize) { One, Two }; + \\ + \\export fn entry() void { + \\ foo(1); + \\} + \\ + \\fn foo(x: usize) void { + \\ switch (x) { + \\ E.One => {}, + \\ } + \\} + , ".tmp_source.zig:9:10: error: expected type 'usize', found 'E'"); - cases.add("range operator in switch used on error set", + cases.add( + "range operator in switch used on error set", \\export fn entry() void { \\ try foo(452) catch |err| switch (err) { \\ error.A ... error.B => {}, @@ -152,31 +645,39 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ } \\} , - ".tmp_source.zig:3:17: error: operator not allowed for errors"); + ".tmp_source.zig:3:17: error: operator not allowed for errors", + ); - cases.add("inferring error set of function pointer", + cases.add( + "inferring error set of function pointer", \\comptime { \\ const z: ?fn()!void = null; \\} , - ".tmp_source.zig:2:15: error: inferring error set of return type valid only for function definitions"); + ".tmp_source.zig:2:15: error: inferring error set of return type valid only for function definitions", + ); - cases.add("access non-existent member of error set", + cases.add( + "access non-existent member of error set", \\const Foo = error{A}; \\comptime { \\ const z = Foo.Bar; \\} , - ".tmp_source.zig:3:18: error: no error named 'Bar' in 'Foo'"); + ".tmp_source.zig:3:18: error: no error named 'Bar' in 'Foo'", + ); - cases.add("error union operator with non error set LHS", + cases.add( + "error union operator with non error set LHS", \\comptime { \\ const z = i32!i32; \\} , - ".tmp_source.zig:2:15: error: expected error set type, found type 'i32'"); + ".tmp_source.zig:2:15: error: expected error set type, found type 'i32'", + ); - cases.add("error equality but sets have no common members", + cases.add( + "error equality but sets have no common members", \\const Set1 = error{A, C}; \\const Set2 = error{B, D}; \\export fn entry() void { @@ -188,26 +689,32 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ } \\} , - ".tmp_source.zig:7:11: error: error sets 'Set1' and 'Set2' have no common errors"); + ".tmp_source.zig:7:11: error: error sets 'Set1' and 'Set2' have no common errors", + ); - cases.add("only equality binary operator allowed for error sets", + cases.add( + "only equality binary operator allowed for error sets", \\comptime { \\ const z = error.A > error.B; \\} , - ".tmp_source.zig:2:23: error: operator not allowed for errors"); + ".tmp_source.zig:2:23: error: operator not allowed for errors", + ); - cases.add("explicit error set cast known at comptime violates error sets", + cases.add( + "explicit error set cast known at comptime violates error sets", \\const Set1 = error {A, B}; \\const Set2 = error {A, C}; \\comptime { \\ var x = Set1.B; - \\ var y = Set2(x); + \\ var y = @errSetCast(Set2, x); \\} , - ".tmp_source.zig:5:17: error: error.B not a member of error set 'Set2'"); + ".tmp_source.zig:5:13: error: error.B not a member of error set 'Set2'", + ); - cases.add("cast error union of global error set to error union of smaller error set", + cases.add( + "cast error union of global error set to error union of smaller error set", \\const SmallErrorSet = error{A}; \\export fn entry() void { \\ var x: SmallErrorSet!i32 = foo(); @@ -216,10 +723,13 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ return error.B; \\} , - ".tmp_source.zig:3:35: error: expected 'SmallErrorSet!i32', found 'error!i32'", - ".tmp_source.zig:3:35: note: unable to cast global error set into smaller set"); + ".tmp_source.zig:3:35: error: expected type 'SmallErrorSet!i32', found 'error!i32'", + ".tmp_source.zig:3:35: note: error set 'error' cannot cast into error set 'SmallErrorSet'", + ".tmp_source.zig:3:35: note: cannot cast global error set into smaller set", + ); - cases.add("cast global error set to error set", + cases.add( + "cast global error set to error set", \\const SmallErrorSet = error{A}; \\export fn entry() void { \\ var x: SmallErrorSet = foo(); @@ -228,10 +738,12 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ return error.B; \\} , - ".tmp_source.zig:3:31: error: expected 'SmallErrorSet', found 'error'", - ".tmp_source.zig:3:31: note: unable to cast global error set into smaller set"); + ".tmp_source.zig:3:31: error: expected type 'SmallErrorSet', found 'error'", + ".tmp_source.zig:3:31: note: cannot cast global error set into smaller set", + ); - cases.add("recursive inferred error set", + cases.add( + "recursive inferred error set", \\export fn entry() void { \\ foo() catch unreachable; \\} @@ -239,9 +751,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ try foo(); \\} , - ".tmp_source.zig:5:5: error: cannot resolve inferred error set '@typeOf(foo).ReturnType.ErrorSet': function 'foo' not fully analyzed yet"); + ".tmp_source.zig:5:5: error: cannot resolve inferred error set '@typeOf(foo).ReturnType.ErrorSet': function 'foo' not fully analyzed yet", + ); - cases.add("implicit cast of error set not a subset", + cases.add( + "implicit cast of error set not a subset", \\const Set1 = error{A, B}; \\const Set2 = error{A, C}; \\export fn entry() void { @@ -251,36 +765,53 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ var x: Set2 = set1; \\} , - ".tmp_source.zig:7:19: error: expected 'Set2', found 'Set1'", - ".tmp_source.zig:1:23: note: 'error.B' not a member of destination error set"); + ".tmp_source.zig:7:19: error: expected type 'Set2', found 'Set1'", + ".tmp_source.zig:1:23: note: 'error.B' not a member of destination error set", + ); - cases.add("int to err global invalid number", - \\const Set1 = error{A, B}; + cases.add( + "int to err global invalid number", + \\const Set1 = error{ + \\ A, + \\ B, + \\}; \\comptime { - \\ var x: usize = 3; - \\ var y = error(x); + \\ var x: u16 = 3; + \\ var y = @intToError(x); \\} , - ".tmp_source.zig:4:18: error: integer value 3 represents no error"); + ".tmp_source.zig:7:13: error: integer value 3 represents no error", + ); - cases.add("int to err non global invalid number", - \\const Set1 = error{A, B}; - \\const Set2 = error{A, C}; + cases.add( + "int to err non global invalid number", + \\const Set1 = error{ + \\ A, + \\ B, + \\}; + \\const Set2 = error{ + \\ A, + \\ C, + \\}; \\comptime { - \\ var x = usize(Set1.B); - \\ var y = Set2(x); + \\ var x = @errorToInt(Set1.B); + \\ var y = @errSetCast(Set2, @intToError(x)); \\} , - ".tmp_source.zig:5:17: error: integer value 2 represents no error in 'Set2'"); + ".tmp_source.zig:11:13: error: error.B not a member of error set 'Set2'", + ); - cases.add("@memberCount of error", + cases.add( + "@memberCount of error", \\comptime { \\ _ = @memberCount(error); \\} , - ".tmp_source.zig:2:9: error: global error set member count not available at comptime"); + ".tmp_source.zig:2:9: error: global error set member count not available at comptime", + ); - cases.add("duplicate error value in error set", + cases.add( + "duplicate error value in error set", \\const Foo = error { \\ Bar, \\ Bar, @@ -290,22 +821,30 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\} , ".tmp_source.zig:3:5: error: duplicate error: 'Bar'", - ".tmp_source.zig:2:5: note: other error here"); + ".tmp_source.zig:2:5: note: other error here", + ); - cases.add("cast negative integer literal to usize", + cases.add( + "cast negative integer literal to usize", \\export fn entry() void { \\ const x = usize(-10); \\} - , ".tmp_source.zig:2:21: error: cannot cast negative value -10 to unsigned integer type 'usize'"); + , + ".tmp_source.zig:2:21: error: cannot cast negative value -10 to unsigned integer type 'usize'", + ); - cases.add("use invalid number literal as array index", + cases.add( + "use invalid number literal as array index", \\var v = 25; \\export fn entry() void { \\ var arr: [v]u8 = undefined; \\} - , ".tmp_source.zig:1:1: error: unable to infer variable type"); + , + ".tmp_source.zig:1:1: error: unable to infer variable type", + ); - cases.add("duplicate struct field", + cases.add( + "duplicate struct field", \\const Foo = struct { \\ Bar: i32, \\ Bar: usize, @@ -315,9 +854,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\} , ".tmp_source.zig:3:5: error: duplicate struct field: 'Bar'", - ".tmp_source.zig:2:5: note: other field here"); + ".tmp_source.zig:2:5: note: other field here", + ); - cases.add("duplicate union field", + cases.add( + "duplicate union field", \\const Foo = union { \\ Bar: i32, \\ Bar: usize, @@ -327,9 +868,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\} , ".tmp_source.zig:3:5: error: duplicate union field: 'Bar'", - ".tmp_source.zig:2:5: note: other field here"); + ".tmp_source.zig:2:5: note: other field here", + ); - cases.add("duplicate enum field", + cases.add( + "duplicate enum field", \\const Foo = enum { \\ Bar, \\ Bar, @@ -340,77 +883,108 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\} , ".tmp_source.zig:3:5: error: duplicate enum field: 'Bar'", - ".tmp_source.zig:2:5: note: other field here"); + ".tmp_source.zig:2:5: note: other field here", + ); - cases.add("calling function with naked calling convention", + cases.add( + "calling function with naked calling convention", \\export fn entry() void { \\ foo(); \\} \\nakedcc fn foo() void { } , ".tmp_source.zig:2:5: error: unable to call function with naked calling convention", - ".tmp_source.zig:4:9: note: declared here"); + ".tmp_source.zig:4:9: note: declared here", + ); - cases.add("function with invalid return type", + cases.add( + "function with invalid return type", \\export fn foo() boid {} - , ".tmp_source.zig:1:17: error: use of undeclared identifier 'boid'"); + , + ".tmp_source.zig:1:17: error: use of undeclared identifier 'boid'", + ); - cases.add("function with non-extern non-packed enum parameter", + cases.add( + "function with non-extern non-packed enum parameter", \\const Foo = enum { A, B, C }; \\export fn entry(foo: Foo) void { } - , ".tmp_source.zig:2:22: error: parameter of type 'Foo' not allowed in function with calling convention 'ccc'"); + , + ".tmp_source.zig:2:22: error: parameter of type 'Foo' not allowed in function with calling convention 'ccc'", + ); - cases.add("function with non-extern non-packed struct parameter", + cases.add( + "function with non-extern non-packed struct parameter", \\const Foo = struct { \\ A: i32, \\ B: f32, \\ C: bool, \\}; \\export fn entry(foo: Foo) void { } - , ".tmp_source.zig:6:22: error: parameter of type 'Foo' not allowed in function with calling convention 'ccc'"); + , + ".tmp_source.zig:6:22: error: parameter of type 'Foo' not allowed in function with calling convention 'ccc'", + ); - cases.add("function with non-extern non-packed union parameter", + cases.add( + "function with non-extern non-packed union parameter", \\const Foo = union { \\ A: i32, \\ B: f32, \\ C: bool, \\}; \\export fn entry(foo: Foo) void { } - , ".tmp_source.zig:6:22: error: parameter of type 'Foo' not allowed in function with calling convention 'ccc'"); + , + ".tmp_source.zig:6:22: error: parameter of type 'Foo' not allowed in function with calling convention 'ccc'", + ); - cases.add("switch on enum with 1 field with no prongs", + cases.add( + "switch on enum with 1 field with no prongs", \\const Foo = enum { M }; \\ \\export fn entry() void { \\ var f = Foo.M; \\ switch (f) {} \\} - , ".tmp_source.zig:5:5: error: enumeration value 'Foo.M' not handled in switch"); + , + ".tmp_source.zig:5:5: error: enumeration value 'Foo.M' not handled in switch", + ); - cases.add("shift by negative comptime integer", + cases.add( + "shift by negative comptime integer", \\comptime { \\ var a = 1 >> -1; \\} - , ".tmp_source.zig:2:18: error: shift by negative value -1"); + , + ".tmp_source.zig:2:18: error: shift by negative value -1", + ); - cases.add("@panic called at compile time", + cases.add( + "@panic called at compile time", \\export fn entry() void { \\ comptime { - \\ @panic("aoeu"); + \\ @panic("aoeu",); \\ } \\} - , ".tmp_source.zig:3:9: error: encountered @panic at compile-time"); + , + ".tmp_source.zig:3:9: error: encountered @panic at compile-time", + ); - cases.add("wrong return type for main", + cases.add( + "wrong return type for main", \\pub fn main() f32 { } - , "error: expected return type of main to be 'u8', 'noreturn', 'void', or '!void'"); + , + "error: expected return type of main to be 'u8', 'noreturn', 'void', or '!void'", + ); - cases.add("double ?? on main return value", + cases.add( + "double ?? on main return value", \\pub fn main() ??void { \\} - , "error: expected return type of main to be 'u8', 'noreturn', 'void', or '!void'"); + , + "error: expected return type of main to be 'u8', 'noreturn', 'void', or '!void'", + ); - cases.add("bad identifier in function with struct defined inside function which references local const", + cases.add( + "bad identifier in function with struct defined inside function which references local const", \\export fn entry() void { \\ const BlockKind = u32; \\ @@ -420,9 +994,12 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ \\ bogus; \\} - , ".tmp_source.zig:8:5: error: use of undeclared identifier 'bogus'"); + , + ".tmp_source.zig:8:5: error: use of undeclared identifier 'bogus'", + ); - cases.add("labeled break not found", + cases.add( + "labeled break not found", \\export fn entry() void { \\ blah: while (true) { \\ while (true) { @@ -430,9 +1007,12 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ } \\ } \\} - , ".tmp_source.zig:4:13: error: label not found: 'outer'"); + , + ".tmp_source.zig:4:13: error: label not found: 'outer'", + ); - cases.add("labeled continue not found", + cases.add( + "labeled continue not found", \\export fn entry() void { \\ var i: usize = 0; \\ blah: while (i < 10) : (i += 1) { @@ -441,400 +1021,554 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ } \\ } \\} - , ".tmp_source.zig:5:13: error: labeled loop not found: 'outer'"); + , + ".tmp_source.zig:5:13: error: labeled loop not found: 'outer'", + ); - cases.add("attempt to use 0 bit type in extern fn", - \\extern fn foo(ptr: extern fn(&void) void) void; + cases.add( + "attempt to use 0 bit type in extern fn", + \\extern fn foo(ptr: extern fn(*void) void) void; \\ \\export fn entry() void { \\ foo(bar); \\} \\ - \\extern fn bar(x: &void) void { } - , ".tmp_source.zig:7:18: error: parameter of type '&void' has 0 bits; not allowed in function with calling convention 'ccc'"); + \\extern fn bar(x: *void) void { } + , + ".tmp_source.zig:7:18: error: parameter of type '*void' has 0 bits; not allowed in function with calling convention 'ccc'", + ); - cases.add("implicit semicolon - block statement", + cases.add( + "implicit semicolon - block statement", \\export fn entry() void { \\ {} \\ var good = {}; \\ ({}) \\ var bad = {}; \\} - , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); + , + ".tmp_source.zig:5:5: error: expected token ';', found 'var'", + ); - cases.add("implicit semicolon - block expr", + cases.add( + "implicit semicolon - block expr", \\export fn entry() void { \\ _ = {}; \\ var good = {}; \\ _ = {} \\ var bad = {}; \\} - , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); + , + ".tmp_source.zig:5:5: error: expected token ';', found 'var'", + ); - cases.add("implicit semicolon - comptime statement", + cases.add( + "implicit semicolon - comptime statement", \\export fn entry() void { \\ comptime {} \\ var good = {}; \\ comptime ({}) \\ var bad = {}; \\} - , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); + , + ".tmp_source.zig:5:5: error: expected token ';', found 'var'", + ); - cases.add("implicit semicolon - comptime expression", + cases.add( + "implicit semicolon - comptime expression", \\export fn entry() void { \\ _ = comptime {}; \\ var good = {}; \\ _ = comptime {} \\ var bad = {}; \\} - , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); + , + ".tmp_source.zig:5:5: error: expected token ';', found 'var'", + ); - cases.add("implicit semicolon - defer", + cases.add( + "implicit semicolon - defer", \\export fn entry() void { \\ defer {} \\ var good = {}; \\ defer ({}) \\ var bad = {}; \\} - , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); + , + ".tmp_source.zig:5:5: error: expected token ';', found 'var'", + ); - cases.add("implicit semicolon - if statement", + cases.add( + "implicit semicolon - if statement", \\export fn entry() void { \\ if(true) {} \\ var good = {}; \\ if(true) ({}) \\ var bad = {}; \\} - , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); + , + ".tmp_source.zig:5:5: error: expected token ';', found 'var'", + ); - cases.add("implicit semicolon - if expression", + cases.add( + "implicit semicolon - if expression", \\export fn entry() void { \\ _ = if(true) {}; \\ var good = {}; \\ _ = if(true) {} \\ var bad = {}; \\} - , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); + , + ".tmp_source.zig:5:5: error: expected token ';', found 'var'", + ); - cases.add("implicit semicolon - if-else statement", + cases.add( + "implicit semicolon - if-else statement", \\export fn entry() void { \\ if(true) {} else {} \\ var good = {}; \\ if(true) ({}) else ({}) \\ var bad = {}; \\} - , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); + , + ".tmp_source.zig:5:5: error: expected token ';', found 'var'", + ); - cases.add("implicit semicolon - if-else expression", + cases.add( + "implicit semicolon - if-else expression", \\export fn entry() void { \\ _ = if(true) {} else {}; \\ var good = {}; \\ _ = if(true) {} else {} \\ var bad = {}; \\} - , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); + , + ".tmp_source.zig:5:5: error: expected token ';', found 'var'", + ); - cases.add("implicit semicolon - if-else-if statement", + cases.add( + "implicit semicolon - if-else-if statement", \\export fn entry() void { \\ if(true) {} else if(true) {} \\ var good = {}; \\ if(true) ({}) else if(true) ({}) \\ var bad = {}; \\} - , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); + , + ".tmp_source.zig:5:5: error: expected token ';', found 'var'", + ); - cases.add("implicit semicolon - if-else-if expression", + cases.add( + "implicit semicolon - if-else-if expression", \\export fn entry() void { \\ _ = if(true) {} else if(true) {}; \\ var good = {}; \\ _ = if(true) {} else if(true) {} \\ var bad = {}; \\} - , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); + , + ".tmp_source.zig:5:5: error: expected token ';', found 'var'", + ); - cases.add("implicit semicolon - if-else-if-else statement", + cases.add( + "implicit semicolon - if-else-if-else statement", \\export fn entry() void { \\ if(true) {} else if(true) {} else {} \\ var good = {}; \\ if(true) ({}) else if(true) ({}) else ({}) \\ var bad = {}; \\} - , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); + , + ".tmp_source.zig:5:5: error: expected token ';', found 'var'", + ); - cases.add("implicit semicolon - if-else-if-else expression", + cases.add( + "implicit semicolon - if-else-if-else expression", \\export fn entry() void { \\ _ = if(true) {} else if(true) {} else {}; \\ var good = {}; \\ _ = if(true) {} else if(true) {} else {} \\ var bad = {}; \\} - , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); + , + ".tmp_source.zig:5:5: error: expected token ';', found 'var'", + ); - cases.add("implicit semicolon - test statement", + cases.add( + "implicit semicolon - test statement", \\export fn entry() void { \\ if (foo()) |_| {} \\ var good = {}; \\ if (foo()) |_| ({}) \\ var bad = {}; \\} - , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); + , + ".tmp_source.zig:5:5: error: expected token ';', found 'var'", + ); - cases.add("implicit semicolon - test expression", + cases.add( + "implicit semicolon - test expression", \\export fn entry() void { \\ _ = if (foo()) |_| {}; \\ var good = {}; \\ _ = if (foo()) |_| {} \\ var bad = {}; \\} - , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); + , + ".tmp_source.zig:5:5: error: expected token ';', found 'var'", + ); - cases.add("implicit semicolon - while statement", + cases.add( + "implicit semicolon - while statement", \\export fn entry() void { \\ while(true) {} \\ var good = {}; \\ while(true) ({}) \\ var bad = {}; \\} - , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); + , + ".tmp_source.zig:5:5: error: expected token ';', found 'var'", + ); - cases.add("implicit semicolon - while expression", + cases.add( + "implicit semicolon - while expression", \\export fn entry() void { \\ _ = while(true) {}; \\ var good = {}; \\ _ = while(true) {} \\ var bad = {}; \\} - , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); + , + ".tmp_source.zig:5:5: error: expected token ';', found 'var'", + ); - cases.add("implicit semicolon - while-continue statement", + cases.add( + "implicit semicolon - while-continue statement", \\export fn entry() void { \\ while(true):({}) {} \\ var good = {}; \\ while(true):({}) ({}) \\ var bad = {}; \\} - , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); + , + ".tmp_source.zig:5:5: error: expected token ';', found 'var'", + ); - cases.add("implicit semicolon - while-continue expression", + cases.add( + "implicit semicolon - while-continue expression", \\export fn entry() void { \\ _ = while(true):({}) {}; \\ var good = {}; \\ _ = while(true):({}) {} \\ var bad = {}; \\} - , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); + , + ".tmp_source.zig:5:5: error: expected token ';', found 'var'", + ); - cases.add("implicit semicolon - for statement", + cases.add( + "implicit semicolon - for statement", \\export fn entry() void { \\ for(foo()) {} \\ var good = {}; \\ for(foo()) ({}) \\ var bad = {}; \\} - , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); + , + ".tmp_source.zig:5:5: error: expected token ';', found 'var'", + ); - cases.add("implicit semicolon - for expression", + cases.add( + "implicit semicolon - for expression", \\export fn entry() void { \\ _ = for(foo()) {}; \\ var good = {}; \\ _ = for(foo()) {} \\ var bad = {}; \\} - , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); + , + ".tmp_source.zig:5:5: error: expected token ';', found 'var'", + ); - cases.add("multiple function definitions", + cases.add( + "multiple function definitions", \\fn a() void {} \\fn a() void {} \\export fn entry() void { a(); } - , ".tmp_source.zig:2:1: error: redefinition of 'a'"); + , + ".tmp_source.zig:2:1: error: redefinition of 'a'", + ); - cases.add("unreachable with return", + cases.add( + "unreachable with return", \\fn a() noreturn {return;} \\export fn entry() void { a(); } - , ".tmp_source.zig:1:18: error: expected type 'noreturn', found 'void'"); + , + ".tmp_source.zig:1:18: error: expected type 'noreturn', found 'void'", + ); - cases.add("control reaches end of non-void function", + cases.add( + "control reaches end of non-void function", \\fn a() i32 {} \\export fn entry() void { _ = a(); } - , ".tmp_source.zig:1:12: error: expected type 'i32', found 'void'"); + , + ".tmp_source.zig:1:12: error: expected type 'i32', found 'void'", + ); - cases.add("undefined function call", + cases.add( + "undefined function call", \\export fn a() void { \\ b(); \\} - , ".tmp_source.zig:2:5: error: use of undeclared identifier 'b'"); + , + ".tmp_source.zig:2:5: error: use of undeclared identifier 'b'", + ); - cases.add("wrong number of arguments", + cases.add( + "wrong number of arguments", \\export fn a() void { \\ b(1); \\} \\fn b(a: i32, b: i32, c: i32) void { } - , ".tmp_source.zig:2:6: error: expected 3 arguments, found 1"); + , + ".tmp_source.zig:2:6: error: expected 3 arguments, found 1", + ); - cases.add("invalid type", + cases.add( + "invalid type", \\fn a() bogus {} \\export fn entry() void { _ = a(); } - , ".tmp_source.zig:1:8: error: use of undeclared identifier 'bogus'"); + , + ".tmp_source.zig:1:8: error: use of undeclared identifier 'bogus'", + ); - cases.add("pointer to noreturn", - \\fn a() &noreturn {} + cases.add( + "pointer to noreturn", + \\fn a() *noreturn {} \\export fn entry() void { _ = a(); } - , ".tmp_source.zig:1:9: error: pointer to noreturn not allowed"); + , + ".tmp_source.zig:1:8: error: pointer to noreturn not allowed", + ); - cases.add("unreachable code", + cases.add( + "unreachable code", \\export fn a() void { \\ return; \\ b(); \\} \\ \\fn b() void {} - , ".tmp_source.zig:3:5: error: unreachable code"); + , + ".tmp_source.zig:3:5: error: unreachable code", + ); - cases.add("bad import", - \\const bogus = @import("bogus-does-not-exist.zig"); + cases.add( + "bad import", + \\const bogus = @import("bogus-does-not-exist.zig",); \\export fn entry() void { bogus.bogo(); } - , ".tmp_source.zig:1:15: error: unable to find 'bogus-does-not-exist.zig'"); + , + ".tmp_source.zig:1:15: error: unable to find 'bogus-does-not-exist.zig'", + ); - cases.add("undeclared identifier", + cases.add( + "undeclared identifier", \\export fn a() void { \\ return \\ b + \\ c; \\} , - ".tmp_source.zig:3:5: error: use of undeclared identifier 'b'", - ".tmp_source.zig:4:5: error: use of undeclared identifier 'c'"); + ".tmp_source.zig:3:5: error: use of undeclared identifier 'b'", + ".tmp_source.zig:4:5: error: use of undeclared identifier 'c'", + ); - cases.add("parameter redeclaration", + cases.add( + "parameter redeclaration", \\fn f(a : i32, a : i32) void { \\} \\export fn entry() void { f(1, 2); } - , ".tmp_source.zig:1:15: error: redeclaration of variable 'a'"); + , + ".tmp_source.zig:1:15: error: redeclaration of variable 'a'", + ); - cases.add("local variable redeclaration", + cases.add( + "local variable redeclaration", \\export fn f() void { \\ const a : i32 = 0; \\ const a = 0; \\} - , ".tmp_source.zig:3:5: error: redeclaration of variable 'a'"); + , + ".tmp_source.zig:3:5: error: redeclaration of variable 'a'", + ); - cases.add("local variable redeclares parameter", + cases.add( + "local variable redeclares parameter", \\fn f(a : i32) void { \\ const a = 0; \\} \\export fn entry() void { f(1); } - , ".tmp_source.zig:2:5: error: redeclaration of variable 'a'"); + , + ".tmp_source.zig:2:5: error: redeclaration of variable 'a'", + ); - cases.add("variable has wrong type", + cases.add( + "variable has wrong type", \\export fn f() i32 { \\ const a = c"a"; \\ return a; \\} - , ".tmp_source.zig:3:12: error: expected type 'i32', found '&const u8'"); + , + ".tmp_source.zig:3:12: error: expected type 'i32', found '[*]const u8'", + ); - cases.add("if condition is bool, not int", + cases.add( + "if condition is bool, not int", \\export fn f() void { \\ if (0) {} \\} - , ".tmp_source.zig:2:9: error: integer value 0 cannot be implicitly casted to type 'bool'"); + , + ".tmp_source.zig:2:9: error: integer value 0 cannot be implicitly casted to type 'bool'", + ); - cases.add("assign unreachable", + cases.add( + "assign unreachable", \\export fn f() void { \\ const a = return; \\} - , ".tmp_source.zig:2:5: error: unreachable code"); + , + ".tmp_source.zig:2:5: error: unreachable code", + ); - cases.add("unreachable variable", + cases.add( + "unreachable variable", \\export fn f() void { \\ const a: noreturn = {}; \\} - , ".tmp_source.zig:2:14: error: variable of type 'noreturn' not allowed"); + , + ".tmp_source.zig:2:14: error: variable of type 'noreturn' not allowed", + ); - cases.add("unreachable parameter", + cases.add( + "unreachable parameter", \\fn f(a: noreturn) void {} \\export fn entry() void { f(); } - , ".tmp_source.zig:1:9: error: parameter of type 'noreturn' not allowed"); + , + ".tmp_source.zig:1:9: error: parameter of type 'noreturn' not allowed", + ); - cases.add("bad assignment target", + cases.add( + "bad assignment target", \\export fn f() void { \\ 3 = 3; \\} - , ".tmp_source.zig:2:7: error: cannot assign to constant"); + , + ".tmp_source.zig:2:7: error: cannot assign to constant", + ); - cases.add("assign to constant variable", + cases.add( + "assign to constant variable", \\export fn f() void { \\ const a = 3; \\ a = 4; \\} - , ".tmp_source.zig:3:7: error: cannot assign to constant"); + , + ".tmp_source.zig:3:7: error: cannot assign to constant", + ); - cases.add("use of undeclared identifier", + cases.add( + "use of undeclared identifier", \\export fn f() void { \\ b = 3; \\} - , ".tmp_source.zig:2:5: error: use of undeclared identifier 'b'"); + , + ".tmp_source.zig:2:5: error: use of undeclared identifier 'b'", + ); - cases.add("const is a statement, not an expression", + cases.add( + "const is a statement, not an expression", \\export fn f() void { \\ (const a = 0); \\} - , ".tmp_source.zig:2:6: error: invalid token: 'const'"); + , + ".tmp_source.zig:2:6: error: invalid token: 'const'", + ); - cases.add("array access of undeclared identifier", + cases.add( + "array access of undeclared identifier", \\export fn f() void { \\ i[i] = i[i]; \\} - , ".tmp_source.zig:2:5: error: use of undeclared identifier 'i'", - ".tmp_source.zig:2:12: error: use of undeclared identifier 'i'"); + , + ".tmp_source.zig:2:5: error: use of undeclared identifier 'i'", + ".tmp_source.zig:2:12: error: use of undeclared identifier 'i'", + ); - cases.add("array access of non array", + cases.add( + "array access of non array", \\export fn f() void { \\ var bad : bool = undefined; \\ bad[bad] = bad[bad]; \\} - , ".tmp_source.zig:3:8: error: array access of non-array type 'bool'", - ".tmp_source.zig:3:19: error: array access of non-array type 'bool'"); + , + ".tmp_source.zig:3:8: error: array access of non-array type 'bool'", + ".tmp_source.zig:3:19: error: array access of non-array type 'bool'", + ); - cases.add("array access with non integer index", + cases.add( + "array access with non integer index", \\export fn f() void { \\ var array = "aoeu"; \\ var bad = false; \\ array[bad] = array[bad]; \\} - , ".tmp_source.zig:4:11: error: expected type 'usize', found 'bool'", - ".tmp_source.zig:4:24: error: expected type 'usize', found 'bool'"); + , + ".tmp_source.zig:4:11: error: expected type 'usize', found 'bool'", + ".tmp_source.zig:4:24: error: expected type 'usize', found 'bool'", + ); - cases.add("write to const global variable", + cases.add( + "write to const global variable", \\const x : i32 = 99; \\fn f() void { \\ x = 1; \\} \\export fn entry() void { f(); } - , ".tmp_source.zig:3:7: error: cannot assign to constant"); - + , + ".tmp_source.zig:3:7: error: cannot assign to constant", + ); - cases.add("missing else clause", + cases.add( + "missing else clause", \\fn f(b: bool) void { \\ const x : i32 = if (b) h: { break :h 1; }; \\ const y = if (b) h: { break :h i32(1); }; \\} \\export fn entry() void { f(true); } - , ".tmp_source.zig:2:42: error: integer value 1 cannot be implicitly casted to type 'void'", - ".tmp_source.zig:3:15: error: incompatible types: 'i32' and 'void'"); + , + ".tmp_source.zig:2:42: error: integer value 1 cannot be implicitly casted to type 'void'", + ".tmp_source.zig:3:15: error: incompatible types: 'i32' and 'void'", + ); - cases.add("direct struct loop", + cases.add( + "direct struct loop", \\const A = struct { a : A, }; \\export fn entry() usize { return @sizeOf(A); } - , ".tmp_source.zig:1:11: error: struct 'A' contains itself"); + , + ".tmp_source.zig:1:11: error: struct 'A' contains itself", + ); - cases.add("indirect struct loop", + cases.add( + "indirect struct loop", \\const A = struct { b : B, }; \\const B = struct { c : C, }; \\const C = struct { a : A, }; \\export fn entry() usize { return @sizeOf(A); } - , ".tmp_source.zig:1:11: error: struct 'A' contains itself"); + , + ".tmp_source.zig:1:11: error: struct 'A' contains itself", + ); - cases.add("invalid struct field", + cases.add( + "invalid struct field", \\const A = struct { x : i32, }; \\export fn f() void { \\ var a : A = undefined; @@ -842,27 +1576,37 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ const y = a.bar; \\} , - ".tmp_source.zig:4:6: error: no member named 'foo' in struct 'A'", - ".tmp_source.zig:5:16: error: no member named 'bar' in struct 'A'"); + ".tmp_source.zig:4:6: error: no member named 'foo' in struct 'A'", + ".tmp_source.zig:5:16: error: no member named 'bar' in struct 'A'", + ); - cases.add("redefinition of struct", + cases.add( + "redefinition of struct", \\const A = struct { x : i32, }; \\const A = struct { y : i32, }; - , ".tmp_source.zig:2:1: error: redefinition of 'A'"); + , + ".tmp_source.zig:2:1: error: redefinition of 'A'", + ); - cases.add("redefinition of enums", + cases.add( + "redefinition of enums", \\const A = enum {}; \\const A = enum {}; - , ".tmp_source.zig:2:1: error: redefinition of 'A'"); + , + ".tmp_source.zig:2:1: error: redefinition of 'A'", + ); - cases.add("redefinition of global variables", + cases.add( + "redefinition of global variables", \\var a : i32 = 1; \\var a : i32 = 2; , - ".tmp_source.zig:2:1: error: redefinition of 'a'", - ".tmp_source.zig:1:1: note: previous definition is here"); + ".tmp_source.zig:2:1: error: redefinition of 'a'", + ".tmp_source.zig:1:1: note: previous definition is here", + ); - cases.add("duplicate field in struct value expression", + cases.add( + "duplicate field in struct value expression", \\const A = struct { \\ x : i32, \\ y : i32, @@ -876,9 +1620,12 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ .z = 4, \\ }; \\} - , ".tmp_source.zig:11:9: error: duplicate field"); + , + ".tmp_source.zig:11:9: error: duplicate field", + ); - cases.add("missing field in struct value expression", + cases.add( + "missing field in struct value expression", \\const A = struct { \\ x : i32, \\ y : i32, @@ -892,9 +1639,12 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ .y = 2, \\ }; \\} - , ".tmp_source.zig:9:17: error: missing field: 'x'"); + , + ".tmp_source.zig:9:17: error: missing field: 'x'", + ); - cases.add("invalid field in struct value expression", + cases.add( + "invalid field in struct value expression", \\const A = struct { \\ x : i32, \\ y : i32, @@ -907,66 +1657,95 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ .foo = 42, \\ }; \\} - , ".tmp_source.zig:10:9: error: no member named 'foo' in struct 'A'"); + , + ".tmp_source.zig:10:9: error: no member named 'foo' in struct 'A'", + ); - cases.add("invalid break expression", + cases.add( + "invalid break expression", \\export fn f() void { \\ break; \\} - , ".tmp_source.zig:2:5: error: break expression outside loop"); + , + ".tmp_source.zig:2:5: error: break expression outside loop", + ); - cases.add("invalid continue expression", + cases.add( + "invalid continue expression", \\export fn f() void { \\ continue; \\} - , ".tmp_source.zig:2:5: error: continue expression outside loop"); + , + ".tmp_source.zig:2:5: error: continue expression outside loop", + ); - cases.add("invalid maybe type", + cases.add( + "invalid maybe type", \\export fn f() void { \\ if (true) |x| { } \\} - , ".tmp_source.zig:2:9: error: expected nullable type, found 'bool'"); + , + ".tmp_source.zig:2:9: error: expected optional type, found 'bool'", + ); - cases.add("cast unreachable", + cases.add( + "cast unreachable", \\fn f() i32 { \\ return i32(return 1); \\} \\export fn entry() void { _ = f(); } - , ".tmp_source.zig:2:15: error: unreachable code"); + , + ".tmp_source.zig:2:15: error: unreachable code", + ); - cases.add("invalid builtin fn", + cases.add( + "invalid builtin fn", \\fn f() @bogus(foo) { \\} \\export fn entry() void { _ = f(); } - , ".tmp_source.zig:1:8: error: invalid builtin function: 'bogus'"); + , + ".tmp_source.zig:1:8: error: invalid builtin function: 'bogus'", + ); - cases.add("top level decl dependency loop", + cases.add( + "top level decl dependency loop", \\const a : @typeOf(b) = 0; \\const b : @typeOf(a) = 0; \\export fn entry() void { \\ const c = a + b; \\} - , ".tmp_source.zig:1:1: error: 'a' depends on itself"); + , + ".tmp_source.zig:1:1: error: 'a' depends on itself", + ); - cases.add("noalias on non pointer param", + cases.add( + "noalias on non pointer param", \\fn f(noalias x: i32) void {} \\export fn entry() void { f(1234); } - , ".tmp_source.zig:1:6: error: noalias on non-pointer parameter"); + , + ".tmp_source.zig:1:6: error: noalias on non-pointer parameter", + ); - cases.add("struct init syntax for array", + cases.add( + "struct init syntax for array", \\const foo = []u16{.x = 1024,}; \\export fn entry() usize { return @sizeOf(@typeOf(foo)); } - , ".tmp_source.zig:1:18: error: type '[]u16' does not support struct initialization syntax"); + , + ".tmp_source.zig:1:18: error: type '[]u16' does not support struct initialization syntax", + ); - cases.add("type variables must be constant", + cases.add( + "type variables must be constant", \\var foo = u8; \\export fn entry() foo { \\ return 1; \\} - , ".tmp_source.zig:1:1: error: variable of type 'type' must be constant"); - + , + ".tmp_source.zig:1:1: error: variable of type 'type' must be constant", + ); - cases.add("variables shadowing types", + cases.add( + "variables shadowing types", \\const Foo = struct {}; \\const Bar = struct {}; \\ @@ -978,12 +1757,14 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ f(1234); \\} , - ".tmp_source.zig:4:6: error: redefinition of 'Foo'", - ".tmp_source.zig:1:1: note: previous definition is here", - ".tmp_source.zig:5:5: error: redefinition of 'Bar'", - ".tmp_source.zig:2:1: note: previous definition is here"); + ".tmp_source.zig:4:6: error: redefinition of 'Foo'", + ".tmp_source.zig:1:1: note: previous definition is here", + ".tmp_source.zig:5:5: error: redefinition of 'Bar'", + ".tmp_source.zig:2:1: note: previous definition is here", + ); - cases.add("switch expression - missing enumeration prong", + cases.add( + "switch expression - missing enumeration prong", \\const Number = enum { \\ One, \\ Two, @@ -999,9 +1780,12 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\} \\ \\export fn entry() usize { return @sizeOf(@typeOf(f)); } - , ".tmp_source.zig:8:5: error: enumeration value 'Number.Four' not handled in switch"); + , + ".tmp_source.zig:8:5: error: enumeration value 'Number.Four' not handled in switch", + ); - cases.add("switch expression - duplicate enumeration prong", + cases.add( + "switch expression - duplicate enumeration prong", \\const Number = enum { \\ One, \\ Two, @@ -1019,10 +1803,13 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\} \\ \\export fn entry() usize { return @sizeOf(@typeOf(f)); } - , ".tmp_source.zig:13:15: error: duplicate switch value", - ".tmp_source.zig:10:15: note: other value is here"); + , + ".tmp_source.zig:13:15: error: duplicate switch value", + ".tmp_source.zig:10:15: note: other value is here", + ); - cases.add("switch expression - duplicate enumeration prong when else present", + cases.add( + "switch expression - duplicate enumeration prong when else present", \\const Number = enum { \\ One, \\ Two, @@ -1041,10 +1828,13 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\} \\ \\export fn entry() usize { return @sizeOf(@typeOf(f)); } - , ".tmp_source.zig:13:15: error: duplicate switch value", - ".tmp_source.zig:10:15: note: other value is here"); + , + ".tmp_source.zig:13:15: error: duplicate switch value", + ".tmp_source.zig:10:15: note: other value is here", + ); - cases.add("switch expression - multiple else prongs", + cases.add( + "switch expression - multiple else prongs", \\fn f(x: u32) void { \\ const value: bool = switch (x) { \\ 1234 => false, @@ -1055,9 +1845,12 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\export fn entry() void { \\ f(1234); \\} - , ".tmp_source.zig:5:9: error: multiple else prongs in switch expression"); + , + ".tmp_source.zig:5:9: error: multiple else prongs in switch expression", + ); - cases.add("switch expression - non exhaustive integer prongs", + cases.add( + "switch expression - non exhaustive integer prongs", \\fn foo(x: u8) void { \\ switch (x) { \\ 0 => {}, @@ -1065,9 +1858,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\} \\export fn entry() usize { return @sizeOf(@typeOf(foo)); } , - ".tmp_source.zig:2:5: error: switch must handle all possibilities"); + ".tmp_source.zig:2:5: error: switch must handle all possibilities", + ); - cases.add("switch expression - duplicate or overlapping integer value", + cases.add( + "switch expression - duplicate or overlapping integer value", \\fn foo(x: u8) u8 { \\ return switch (x) { \\ 0 ... 100 => u8(0), @@ -1079,10 +1874,12 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\export fn entry() usize { return @sizeOf(@typeOf(foo)); } , ".tmp_source.zig:6:9: error: duplicate switch value", - ".tmp_source.zig:5:14: note: previous value is here"); + ".tmp_source.zig:5:14: note: previous value is here", + ); - cases.add("switch expression - switch on pointer type with no else", - \\fn foo(x: &u8) void { + cases.add( + "switch expression - switch on pointer type with no else", + \\fn foo(x: *u8) void { \\ switch (x) { \\ &y => {}, \\ } @@ -1090,62 +1887,97 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\const y: u8 = 100; \\export fn entry() usize { return @sizeOf(@typeOf(foo)); } , - ".tmp_source.zig:2:5: error: else prong required when switching on type '&u8'"); + ".tmp_source.zig:2:5: error: else prong required when switching on type '*u8'", + ); - cases.add("global variable initializer must be constant expression", + cases.add( + "global variable initializer must be constant expression", \\extern fn foo() i32; \\const x = foo(); \\export fn entry() i32 { return x; } - , ".tmp_source.zig:2:11: error: unable to evaluate constant expression"); + , + ".tmp_source.zig:2:11: error: unable to evaluate constant expression", + ); - cases.add("array concatenation with wrong type", + cases.add( + "array concatenation with wrong type", \\const src = "aoeu"; \\const derp = usize(1234); \\const a = derp ++ "foo"; \\ \\export fn entry() usize { return @sizeOf(@typeOf(a)); } - , ".tmp_source.zig:3:11: error: expected array or C string literal, found 'usize'"); + , + ".tmp_source.zig:3:11: error: expected array or C string literal, found 'usize'", + ); - cases.add("non compile time array concatenation", + cases.add( + "non compile time array concatenation", \\fn f() []u8 { \\ return s ++ "foo"; \\} \\var s: [10]u8 = undefined; \\export fn entry() usize { return @sizeOf(@typeOf(f)); } - , ".tmp_source.zig:2:12: error: unable to evaluate constant expression"); + , + ".tmp_source.zig:2:12: error: unable to evaluate constant expression", + ); - cases.add("@cImport with bogus include", + cases.add( + "@cImport with bogus include", \\const c = @cImport(@cInclude("bogus.h")); \\export fn entry() usize { return @sizeOf(@typeOf(c.bogo)); } - , ".tmp_source.zig:1:11: error: C import failed", - ".h:1:10: note: 'bogus.h' file not found"); + , + ".tmp_source.zig:1:11: error: C import failed", + ".h:1:10: note: 'bogus.h' file not found", + ); - cases.add("address of number literal", + cases.add( + "address of number literal", \\const x = 3; \\const y = &x; - \\fn foo() &const i32 { return y; } + \\fn foo() *const i32 { return y; } \\export fn entry() usize { return @sizeOf(@typeOf(foo)); } - , ".tmp_source.zig:3:30: error: expected type '&const i32', found '&const (integer literal)'"); + , + ".tmp_source.zig:3:30: error: expected type '*const i32', found '*const comptime_int'", + ); - cases.add("integer overflow error", + cases.add( + "integer overflow error", \\const x : u8 = 300; \\export fn entry() usize { return @sizeOf(@typeOf(x)); } - , ".tmp_source.zig:1:16: error: integer value 300 cannot be implicitly casted to type 'u8'"); + , + ".tmp_source.zig:1:16: error: integer value 300 cannot be implicitly casted to type 'u8'", + ); - cases.add("incompatible number literals", + cases.add( + "invalid shift amount error", + \\const x : u8 = 2; + \\fn f() u16 { + \\ return x << 8; + \\} + \\export fn entry() u16 { return f(); } + , + ".tmp_source.zig:3:14: error: RHS of shift is too large for LHS type", + ".tmp_source.zig:3:17: note: value 8 cannot fit into type u3", + ); + + cases.add( + "incompatible number literals", \\const x = 2 == 2.0; \\export fn entry() usize { return @sizeOf(@typeOf(x)); } - , ".tmp_source.zig:1:11: error: integer value 2 cannot be implicitly casted to type '(float literal)'"); + , + ".tmp_source.zig:1:11: error: integer value 2 cannot be implicitly casted to type 'comptime_float'", + ); - cases.add("missing function call param", + cases.add( + "missing function call param", \\const Foo = struct { \\ a: i32, \\ b: i32, \\ - \\ fn member_a(foo: &const Foo) i32 { + \\ fn member_a(foo: *const Foo) i32 { \\ return foo.a; \\ } - \\ fn member_b(foo: &const Foo) i32 { + \\ fn member_b(foo: *const Foo) i32 { \\ return foo.b; \\ } \\}; @@ -1156,63 +1988,78 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ Foo.member_b, \\}; \\ - \\fn f(foo: &const Foo, index: usize) void { + \\fn f(foo: *const Foo, index: usize) void { \\ const result = members[index](); \\} \\ \\export fn entry() usize { return @sizeOf(@typeOf(f)); } - , ".tmp_source.zig:20:34: error: expected 1 arguments, found 0"); + , + ".tmp_source.zig:20:34: error: expected 1 arguments, found 0", + ); - cases.add("missing function name and param name", + cases.add( + "missing function name and param name", \\fn () void {} \\fn f(i32) void {} \\export fn entry() usize { return @sizeOf(@typeOf(f)); } , - ".tmp_source.zig:1:1: error: missing function name", - ".tmp_source.zig:2:6: error: missing parameter name"); + ".tmp_source.zig:1:1: error: missing function name", + ".tmp_source.zig:2:6: error: missing parameter name", + ); - cases.add("wrong function type", + cases.add( + "wrong function type", \\const fns = []fn() void { a, b, c }; \\fn a() i32 {return 0;} \\fn b() i32 {return 1;} \\fn c() i32 {return 2;} \\export fn entry() usize { return @sizeOf(@typeOf(fns)); } - , ".tmp_source.zig:1:27: error: expected type 'fn() void', found 'fn() i32'"); + , + ".tmp_source.zig:1:27: error: expected type 'fn() void', found 'fn() i32'", + ); - cases.add("extern function pointer mismatch", + cases.add( + "extern function pointer mismatch", \\const fns = [](fn(i32)i32) { a, b, c }; \\pub fn a(x: i32) i32 {return x + 0;} \\pub fn b(x: i32) i32 {return x + 1;} \\export fn c(x: i32) i32 {return x + 2;} \\ \\export fn entry() usize { return @sizeOf(@typeOf(fns)); } - , ".tmp_source.zig:1:36: error: expected type 'fn(i32) i32', found 'extern fn(i32) i32'"); - + , + ".tmp_source.zig:1:36: error: expected type 'fn(i32) i32', found 'extern fn(i32) i32'", + ); - cases.add("implicit cast from f64 to f32", + cases.add( + "implicit cast from f64 to f32", \\const x : f64 = 1.0; \\const y : f32 = x; \\ \\export fn entry() usize { return @sizeOf(@typeOf(y)); } - , ".tmp_source.zig:2:17: error: expected type 'f32', found 'f64'"); - + , + ".tmp_source.zig:2:17: error: expected type 'f32', found 'f64'", + ); - cases.add("colliding invalid top level functions", + cases.add( + "colliding invalid top level functions", \\fn func() bogus {} \\fn func() bogus {} \\export fn entry() usize { return @sizeOf(@typeOf(func)); } , - ".tmp_source.zig:2:1: error: redefinition of 'func'", - ".tmp_source.zig:1:11: error: use of undeclared identifier 'bogus'"); - + ".tmp_source.zig:2:1: error: redefinition of 'func'", + ".tmp_source.zig:1:11: error: use of undeclared identifier 'bogus'", + ); - cases.add("bogus compile var", + cases.add( + "bogus compile var", \\const x = @import("builtin").bogus; \\export fn entry() usize { return @sizeOf(@typeOf(x)); } - , ".tmp_source.zig:1:29: error: no member named 'bogus' in '"); - + , + ".tmp_source.zig:1:29: error: no member named 'bogus' in '", + ); - cases.add("non constant expression in array size outside function", + cases.add( + "non constant expression in array size outside function", \\const Foo = struct { \\ y: [get()]u8, \\}; @@ -1221,22 +2068,25 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ \\export fn entry() usize { return @sizeOf(@typeOf(Foo)); } , - ".tmp_source.zig:5:25: error: unable to evaluate constant expression", - ".tmp_source.zig:2:12: note: called from here", - ".tmp_source.zig:2:8: note: called from here"); - + ".tmp_source.zig:5:25: error: unable to evaluate constant expression", + ".tmp_source.zig:2:12: note: called from here", + ".tmp_source.zig:2:8: note: called from here", + ); - cases.add("addition with non numbers", + cases.add( + "addition with non numbers", \\const Foo = struct { \\ field: i32, \\}; \\const x = Foo {.field = 1} + Foo {.field = 2}; \\ \\export fn entry() usize { return @sizeOf(@typeOf(x)); } - , ".tmp_source.zig:4:28: error: invalid operands to binary expression: 'Foo' and 'Foo'"); - + , + ".tmp_source.zig:4:28: error: invalid operands to binary expression: 'Foo' and 'Foo'", + ); - cases.add("division by zero", + cases.add( + "division by zero", \\const lit_int_x = 1 / 0; \\const lit_float_x = 1.0 / 0.0; \\const int_x = u32(1) / u32(0); @@ -1247,49 +2097,65 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\export fn entry3() usize { return @sizeOf(@typeOf(int_x)); } \\export fn entry4() usize { return @sizeOf(@typeOf(float_x)); } , - ".tmp_source.zig:1:21: error: division by zero", - ".tmp_source.zig:2:25: error: division by zero", - ".tmp_source.zig:3:22: error: division by zero", - ".tmp_source.zig:4:26: error: division by zero"); - + ".tmp_source.zig:1:21: error: division by zero", + ".tmp_source.zig:2:25: error: division by zero", + ".tmp_source.zig:3:22: error: division by zero", + ".tmp_source.zig:4:26: error: division by zero", + ); - cases.add("normal string with newline", + cases.add( + "normal string with newline", \\const foo = "a \\b"; \\ \\export fn entry() usize { return @sizeOf(@typeOf(foo)); } - , ".tmp_source.zig:1:13: error: newline not allowed in string literal"); + , + ".tmp_source.zig:1:13: error: newline not allowed in string literal", + ); - cases.add("invalid comparison for function pointers", + cases.add( + "invalid comparison for function pointers", \\fn foo() void {} \\const invalid = foo > foo; \\ \\export fn entry() usize { return @sizeOf(@typeOf(invalid)); } - , ".tmp_source.zig:2:21: error: operator not allowed for type 'fn() void'"); + , + ".tmp_source.zig:2:21: error: operator not allowed for type 'fn() void'", + ); - cases.add("generic function instance with non-constant expression", + cases.add( + "generic function instance with non-constant expression", \\fn foo(comptime x: i32, y: i32) i32 { return x + y; } \\fn test1(a: i32, b: i32) i32 { \\ return foo(a, b); \\} \\ \\export fn entry() usize { return @sizeOf(@typeOf(test1)); } - , ".tmp_source.zig:3:16: error: unable to evaluate constant expression"); + , + ".tmp_source.zig:3:16: error: unable to evaluate constant expression", + ); - cases.add("assign null to non-nullable pointer", - \\const a: &u8 = null; + cases.add( + "assign null to non-optional pointer", + \\const a: *u8 = null; \\ \\export fn entry() usize { return @sizeOf(@typeOf(a)); } - , ".tmp_source.zig:1:16: error: expected type '&u8', found '(null)'"); + , + ".tmp_source.zig:1:16: error: expected type '*u8', found '(null)'", + ); - cases.add("indexing an array of size zero", + cases.add( + "indexing an array of size zero", \\const array = []u8{}; \\export fn foo() void { \\ const pointer = &array[0]; \\} - , ".tmp_source.zig:3:27: error: index 0 outside array of size 0"); + , + ".tmp_source.zig:3:27: error: index 0 outside array of size 0", + ); - cases.add("compile time division by zero", + cases.add( + "compile time division by zero", \\const y = foo(0); \\fn foo(x: u32) u32 { \\ return 1 / x; @@ -1297,17 +2163,431 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ \\export fn entry() usize { return @sizeOf(@typeOf(y)); } , - ".tmp_source.zig:3:14: error: division by zero", - ".tmp_source.zig:1:14: note: called from here"); + ".tmp_source.zig:3:14: error: division by zero", + ".tmp_source.zig:1:14: note: called from here", + ); - cases.add("branch on undefined value", + cases.add( + "branch on undefined value", \\const x = if (undefined) true else false; \\ \\export fn entry() usize { return @sizeOf(@typeOf(x)); } - , ".tmp_source.zig:1:15: error: use of undefined value"); + , + ".tmp_source.zig:1:15: error: use of undefined value", + ); + + cases.add( + "div on undefined value", + \\comptime { + \\ var a: i64 = undefined; + \\ _ = a / a; + \\} + , + ".tmp_source.zig:3:9: error: use of undefined value", + ); + + cases.add( + "div assign on undefined value", + \\comptime { + \\ var a: i64 = undefined; + \\ a /= a; + \\} + , + ".tmp_source.zig:3:5: error: use of undefined value", + ); + + cases.add( + "mod on undefined value", + \\comptime { + \\ var a: i64 = undefined; + \\ _ = a % a; + \\} + , + ".tmp_source.zig:3:9: error: use of undefined value", + ); + + cases.add( + "mod assign on undefined value", + \\comptime { + \\ var a: i64 = undefined; + \\ a %= a; + \\} + , + ".tmp_source.zig:3:5: error: use of undefined value", + ); + + cases.add( + "add on undefined value", + \\comptime { + \\ var a: i64 = undefined; + \\ _ = a + a; + \\} + , + ".tmp_source.zig:3:9: error: use of undefined value", + ); + + cases.add( + "add assign on undefined value", + \\comptime { + \\ var a: i64 = undefined; + \\ a += a; + \\} + , + ".tmp_source.zig:3:5: error: use of undefined value", + ); + + cases.add( + "add wrap on undefined value", + \\comptime { + \\ var a: i64 = undefined; + \\ _ = a +% a; + \\} + , + ".tmp_source.zig:3:9: error: use of undefined value", + ); + + cases.add( + "add wrap assign on undefined value", + \\comptime { + \\ var a: i64 = undefined; + \\ a +%= a; + \\} + , + ".tmp_source.zig:3:5: error: use of undefined value", + ); + + cases.add( + "sub on undefined value", + \\comptime { + \\ var a: i64 = undefined; + \\ _ = a - a; + \\} + , + ".tmp_source.zig:3:9: error: use of undefined value", + ); + + cases.add( + "sub assign on undefined value", + \\comptime { + \\ var a: i64 = undefined; + \\ a -= a; + \\} + , + ".tmp_source.zig:3:5: error: use of undefined value", + ); + + cases.add( + "sub wrap on undefined value", + \\comptime { + \\ var a: i64 = undefined; + \\ _ = a -% a; + \\} + , + ".tmp_source.zig:3:9: error: use of undefined value", + ); + + cases.add( + "sub wrap assign on undefined value", + \\comptime { + \\ var a: i64 = undefined; + \\ a -%= a; + \\} + , + ".tmp_source.zig:3:5: error: use of undefined value", + ); + + cases.add( + "mult on undefined value", + \\comptime { + \\ var a: i64 = undefined; + \\ _ = a * a; + \\} + , + ".tmp_source.zig:3:9: error: use of undefined value", + ); + + cases.add( + "mult assign on undefined value", + \\comptime { + \\ var a: i64 = undefined; + \\ a *= a; + \\} + , + ".tmp_source.zig:3:5: error: use of undefined value", + ); + + cases.add( + "mult wrap on undefined value", + \\comptime { + \\ var a: i64 = undefined; + \\ _ = a *% a; + \\} + , + ".tmp_source.zig:3:9: error: use of undefined value", + ); + + cases.add( + "mult wrap assign on undefined value", + \\comptime { + \\ var a: i64 = undefined; + \\ a *%= a; + \\} + , + ".tmp_source.zig:3:5: error: use of undefined value", + ); + + cases.add( + "shift left on undefined value", + \\comptime { + \\ var a: i64 = undefined; + \\ _ = a << 2; + \\} + , + ".tmp_source.zig:3:9: error: use of undefined value", + ); + + cases.add( + "shift left assign on undefined value", + \\comptime { + \\ var a: i64 = undefined; + \\ a <<= 2; + \\} + , + ".tmp_source.zig:3:5: error: use of undefined value", + ); + + cases.add( + "shift right on undefined value", + \\comptime { + \\ var a: i64 = undefined; + \\ _ = a >> 2; + \\} + , + ".tmp_source.zig:3:9: error: use of undefined value", + ); + + cases.add( + "shift left assign on undefined value", + \\comptime { + \\ var a: i64 = undefined; + \\ a >>= 2; + \\} + , + ".tmp_source.zig:3:5: error: use of undefined value", + ); + + cases.add( + "bin and on undefined value", + \\comptime { + \\ var a: i64 = undefined; + \\ _ = a & a; + \\} + , + ".tmp_source.zig:3:9: error: use of undefined value", + ); + + cases.add( + "bin and assign on undefined value", + \\comptime { + \\ var a: i64 = undefined; + \\ a &= a; + \\} + , + ".tmp_source.zig:3:5: error: use of undefined value", + ); + + cases.add( + "bin or on undefined value", + \\comptime { + \\ var a: i64 = undefined; + \\ _ = a | a; + \\} + , + ".tmp_source.zig:3:9: error: use of undefined value", + ); + + cases.add( + "bin or assign on undefined value", + \\comptime { + \\ var a: i64 = undefined; + \\ a |= a; + \\} + , + ".tmp_source.zig:3:5: error: use of undefined value", + ); + + cases.add( + "bin xor on undefined value", + \\comptime { + \\ var a: i64 = undefined; + \\ _ = a ^ a; + \\} + , + ".tmp_source.zig:3:9: error: use of undefined value", + ); + + cases.add( + "bin xor assign on undefined value", + \\comptime { + \\ var a: i64 = undefined; + \\ a ^= a; + \\} + , + ".tmp_source.zig:3:5: error: use of undefined value", + ); + + cases.add( + "equal on undefined value", + \\comptime { + \\ var a: i64 = undefined; + \\ _ = a == a; + \\} + , + ".tmp_source.zig:3:9: error: use of undefined value", + ); + + cases.add( + "not equal on undefined value", + \\comptime { + \\ var a: i64 = undefined; + \\ _ = a != a; + \\} + , + ".tmp_source.zig:3:9: error: use of undefined value", + ); + + cases.add( + "greater than on undefined value", + \\comptime { + \\ var a: i64 = undefined; + \\ _ = a > a; + \\} + , + ".tmp_source.zig:3:9: error: use of undefined value", + ); + + cases.add( + "greater than equal on undefined value", + \\comptime { + \\ var a: i64 = undefined; + \\ _ = a >= a; + \\} + , + ".tmp_source.zig:3:9: error: use of undefined value", + ); + cases.add( + "less than on undefined value", + \\comptime { + \\ var a: i64 = undefined; + \\ _ = a < a; + \\} + , + ".tmp_source.zig:3:9: error: use of undefined value", + ); + + cases.add( + "less than equal on undefined value", + \\comptime { + \\ var a: i64 = undefined; + \\ _ = a <= a; + \\} + , + ".tmp_source.zig:3:9: error: use of undefined value", + ); + + cases.add( + "and on undefined value", + \\comptime { + \\ var a: bool = undefined; + \\ _ = a and a; + \\} + , + ".tmp_source.zig:3:9: error: use of undefined value", + ); + + cases.add( + "or on undefined value", + \\comptime { + \\ var a: bool = undefined; + \\ _ = a or a; + \\} + , + ".tmp_source.zig:3:9: error: use of undefined value", + ); + + cases.add( + "negate on undefined value", + \\comptime { + \\ var a: i64 = undefined; + \\ _ = -a; + \\} + , + ".tmp_source.zig:3:10: error: use of undefined value", + ); + + cases.add( + "negate wrap on undefined value", + \\comptime { + \\ var a: i64 = undefined; + \\ _ = -%a; + \\} + , + ".tmp_source.zig:3:11: error: use of undefined value", + ); + + cases.add( + "bin not on undefined value", + \\comptime { + \\ var a: i64 = undefined; + \\ _ = ~a; + \\} + , + ".tmp_source.zig:3:10: error: use of undefined value", + ); + + cases.add( + "bool not on undefined value", + \\comptime { + \\ var a: bool = undefined; + \\ _ = !a; + \\} + , + ".tmp_source.zig:3:10: error: use of undefined value", + ); + + cases.add( + "orelse on undefined value", + \\comptime { + \\ var a: ?bool = undefined; + \\ _ = a orelse false; + \\} + , + ".tmp_source.zig:3:11: error: use of undefined value", + ); + + cases.add( + "catch on undefined value", + \\comptime { + \\ var a: error!bool = undefined; + \\ _ = a catch |err| false; + \\} + , + ".tmp_source.zig:3:11: error: use of undefined value", + ); - cases.add("endless loop in function evaluation", + cases.add( + "deref on undefined value", + \\comptime { + \\ var a: *u8 = undefined; + \\ _ = a.*; + \\} + , + ".tmp_source.zig:3:9: error: use of undefined value", + ); + + cases.add( + "endless loop in function evaluation", \\const seventh_fib_number = fibbonaci(7); \\fn fibbonaci(x: i32) i32 { \\ return fibbonaci(x - 1) + fibbonaci(x - 2); @@ -1315,16 +2595,22 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ \\export fn entry() usize { return @sizeOf(@typeOf(seventh_fib_number)); } , - ".tmp_source.zig:3:21: error: evaluation exceeded 1000 backwards branches", - ".tmp_source.zig:3:21: note: called from here"); + ".tmp_source.zig:3:21: error: evaluation exceeded 1000 backwards branches", + ".tmp_source.zig:3:21: note: called from here", + ); - cases.add("@embedFile with bogus file", - \\const resource = @embedFile("bogus.txt"); + cases.add( + "@embedFile with bogus file", + \\const resource = @embedFile("bogus.txt",); \\ \\export fn entry() usize { return @sizeOf(@typeOf(resource)); } - , ".tmp_source.zig:1:29: error: unable to find '", "bogus.txt'"); + , + ".tmp_source.zig:1:29: error: unable to find '", + "bogus.txt'", + ); - cases.add("non-const expression in struct literal outside function", + cases.add( + "non-const expression in struct literal outside function", \\const Foo = struct { \\ x: i32, \\}; @@ -1332,9 +2618,12 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\extern fn get_it() i32; \\ \\export fn entry() usize { return @sizeOf(@typeOf(a)); } - , ".tmp_source.zig:4:21: error: unable to evaluate constant expression"); + , + ".tmp_source.zig:4:21: error: unable to evaluate constant expression", + ); - cases.add("non-const expression function call with struct return value outside function", + cases.add( + "non-const expression function call with struct return value outside function", \\const Foo = struct { \\ x: i32, \\}; @@ -1347,19 +2636,24 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ \\export fn entry() usize { return @sizeOf(@typeOf(a)); } , - ".tmp_source.zig:6:24: error: unable to evaluate constant expression", - ".tmp_source.zig:4:17: note: called from here"); + ".tmp_source.zig:6:24: error: unable to evaluate constant expression", + ".tmp_source.zig:4:17: note: called from here", + ); - cases.add("undeclared identifier error should mark fn as impure", + cases.add( + "undeclared identifier error should mark fn as impure", \\export fn foo() void { \\ test_a_thing(); \\} \\fn test_a_thing() void { \\ bad_fn_call(); \\} - , ".tmp_source.zig:5:5: error: use of undeclared identifier 'bad_fn_call'"); + , + ".tmp_source.zig:5:5: error: use of undeclared identifier 'bad_fn_call'", + ); - cases.add("illegal comparison of types", + cases.add( + "illegal comparison of types", \\fn bad_eql_1(a: []u8, b: []u8) bool { \\ return a == b; \\} @@ -1367,17 +2661,19 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ One: void, \\ Two: i32, \\}; - \\fn bad_eql_2(a: &const EnumWithData, b: &const EnumWithData) bool { - \\ return *a == *b; + \\fn bad_eql_2(a: *const EnumWithData, b: *const EnumWithData) bool { + \\ return a.* == b.*; \\} \\ \\export fn entry1() usize { return @sizeOf(@typeOf(bad_eql_1)); } \\export fn entry2() usize { return @sizeOf(@typeOf(bad_eql_2)); } , - ".tmp_source.zig:2:14: error: operator not allowed for type '[]u8'", - ".tmp_source.zig:9:15: error: operator not allowed for type 'EnumWithData'"); + ".tmp_source.zig:2:14: error: operator not allowed for type '[]u8'", + ".tmp_source.zig:9:16: error: operator not allowed for type 'EnumWithData'", + ); - cases.add("non-const switch number literal", + cases.add( + "non-const switch number literal", \\export fn foo() void { \\ const x = switch (bar()) { \\ 1, 2 => 1, @@ -1388,25 +2684,34 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\fn bar() i32 { \\ return 2; \\} - , ".tmp_source.zig:2:15: error: unable to infer expression type"); + , + ".tmp_source.zig:2:15: error: unable to infer expression type", + ); - cases.add("atomic orderings of cmpxchg - failure stricter than success", + cases.add( + "atomic orderings of cmpxchg - failure stricter than success", \\const AtomicOrder = @import("builtin").AtomicOrder; \\export fn f() void { \\ var x: i32 = 1234; - \\ while (!@cmpxchg(&x, 1234, 5678, AtomicOrder.Monotonic, AtomicOrder.SeqCst)) {} + \\ while (!@cmpxchgWeak(i32, &x, 1234, 5678, AtomicOrder.Monotonic, AtomicOrder.SeqCst)) {} \\} - , ".tmp_source.zig:4:72: error: failure atomic ordering must be no stricter than success"); + , + ".tmp_source.zig:4:81: error: failure atomic ordering must be no stricter than success", + ); - cases.add("atomic orderings of cmpxchg - success Monotonic or stricter", + cases.add( + "atomic orderings of cmpxchg - success Monotonic or stricter", \\const AtomicOrder = @import("builtin").AtomicOrder; \\export fn f() void { \\ var x: i32 = 1234; - \\ while (!@cmpxchg(&x, 1234, 5678, AtomicOrder.Unordered, AtomicOrder.Unordered)) {} + \\ while (!@cmpxchgWeak(i32, &x, 1234, 5678, AtomicOrder.Unordered, AtomicOrder.Unordered)) {} \\} - , ".tmp_source.zig:4:49: error: success atomic ordering must be Monotonic or stricter"); + , + ".tmp_source.zig:4:58: error: success atomic ordering must be Monotonic or stricter", + ); - cases.add("negation overflow in function evaluation", + cases.add( + "negation overflow in function evaluation", \\const y = neg(-128); \\fn neg(x: i8) i8 { \\ return -x; @@ -1414,10 +2719,12 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ \\export fn entry() usize { return @sizeOf(@typeOf(y)); } , - ".tmp_source.zig:3:12: error: negation caused overflow", - ".tmp_source.zig:1:14: note: called from here"); + ".tmp_source.zig:3:12: error: negation caused overflow", + ".tmp_source.zig:1:14: note: called from here", + ); - cases.add("add overflow in function evaluation", + cases.add( + "add overflow in function evaluation", \\const y = add(65530, 10); \\fn add(a: u16, b: u16) u16 { \\ return a + b; @@ -1425,11 +2732,12 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ \\export fn entry() usize { return @sizeOf(@typeOf(y)); } , - ".tmp_source.zig:3:14: error: operation caused overflow", - ".tmp_source.zig:1:14: note: called from here"); - + ".tmp_source.zig:3:14: error: operation caused overflow", + ".tmp_source.zig:1:14: note: called from here", + ); - cases.add("sub overflow in function evaluation", + cases.add( + "sub overflow in function evaluation", \\const y = sub(10, 20); \\fn sub(a: u16, b: u16) u16 { \\ return a - b; @@ -1437,10 +2745,12 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ \\export fn entry() usize { return @sizeOf(@typeOf(y)); } , - ".tmp_source.zig:3:14: error: operation caused overflow", - ".tmp_source.zig:1:14: note: called from here"); + ".tmp_source.zig:3:14: error: operation caused overflow", + ".tmp_source.zig:1:14: note: called from here", + ); - cases.add("mul overflow in function evaluation", + cases.add( + "mul overflow in function evaluation", \\const y = mul(300, 6000); \\fn mul(a: u16, b: u16) u16 { \\ return a * b; @@ -1448,58 +2758,78 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ \\export fn entry() usize { return @sizeOf(@typeOf(y)); } , - ".tmp_source.zig:3:14: error: operation caused overflow", - ".tmp_source.zig:1:14: note: called from here"); + ".tmp_source.zig:3:14: error: operation caused overflow", + ".tmp_source.zig:1:14: note: called from here", + ); - cases.add("truncate sign mismatch", + cases.add( + "truncate sign mismatch", \\fn f() i8 { \\ const x: u32 = 10; \\ return @truncate(i8, x); \\} \\ \\export fn entry() usize { return @sizeOf(@typeOf(f)); } - , ".tmp_source.zig:3:26: error: expected signed integer type, found 'u32'"); + , + ".tmp_source.zig:3:26: error: expected signed integer type, found 'u32'", + ); - cases.add("try in function with non error return type", + cases.add( + "try in function with non error return type", \\export fn f() void { \\ try something(); \\} \\fn something() error!void { } , - ".tmp_source.zig:2:5: error: expected type 'void', found 'error'"); + ".tmp_source.zig:2:5: error: expected type 'void', found 'error'", + ); - cases.add("invalid pointer for var type", + cases.add( + "invalid pointer for var type", \\extern fn ext() usize; \\var bytes: [ext()]u8 = undefined; \\export fn f() void { \\ for (bytes) |*b, i| { - \\ *b = u8(i); + \\ b.* = u8(i); \\ } \\} - , ".tmp_source.zig:2:13: error: unable to evaluate constant expression"); + , + ".tmp_source.zig:2:13: error: unable to evaluate constant expression", + ); - cases.add("export function with comptime parameter", + cases.add( + "export function with comptime parameter", \\export fn foo(comptime x: i32, y: i32) i32{ \\ return x + y; \\} - , ".tmp_source.zig:1:15: error: comptime parameter not allowed in function with calling convention 'ccc'"); + , + ".tmp_source.zig:1:15: error: comptime parameter not allowed in function with calling convention 'ccc'", + ); - cases.add("extern function with comptime parameter", + cases.add( + "extern function with comptime parameter", \\extern fn foo(comptime x: i32, y: i32) i32; \\fn f() i32 { \\ return foo(1, 2); \\} \\export fn entry() usize { return @sizeOf(@typeOf(f)); } - , ".tmp_source.zig:1:15: error: comptime parameter not allowed in function with calling convention 'ccc'"); + , + ".tmp_source.zig:1:15: error: comptime parameter not allowed in function with calling convention 'ccc'", + ); - cases.add("convert fixed size array to slice with invalid size", + cases.add( + "convert fixed size array to slice with invalid size", \\export fn f() void { \\ var array: [5]u8 = undefined; - \\ var foo = ([]const u32)(array)[0]; + \\ var foo = @bytesToSlice(u32, array)[0]; \\} - , ".tmp_source.zig:3:28: error: unable to convert [5]u8 to []const u32: size mismatch"); + , + ".tmp_source.zig:3:15: error: unable to convert [5]u8 to []align(1) const u32: size mismatch", + ".tmp_source.zig:3:29: note: u32 has size 4; remaining bytes: 1", + ); - cases.add("non-pure function returns type", + cases.add( + "non-pure function returns type", \\var a: u32 = 0; \\pub fn List(comptime T: type) type { \\ a += 1; @@ -1518,56 +2848,77 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ var list: List(i32) = undefined; \\ list.length = 10; \\} - , ".tmp_source.zig:3:7: error: unable to evaluate constant expression", - ".tmp_source.zig:16:19: note: called from here"); + , + ".tmp_source.zig:3:7: error: unable to evaluate constant expression", + ".tmp_source.zig:16:19: note: called from here", + ); - cases.add("bogus method call on slice", + cases.add( + "bogus method call on slice", \\var self = "aoeu"; \\fn f(m: []const u8) void { \\ m.copy(u8, self[0..], m); \\} \\export fn entry() usize { return @sizeOf(@typeOf(f)); } - , ".tmp_source.zig:3:6: error: no member named 'copy' in '[]const u8'"); + , + ".tmp_source.zig:3:6: error: no member named 'copy' in '[]const u8'", + ); - cases.add("wrong number of arguments for method fn call", + cases.add( + "wrong number of arguments for method fn call", \\const Foo = struct { - \\ fn method(self: &const Foo, a: i32) void {} + \\ fn method(self: *const Foo, a: i32) void {} \\}; - \\fn f(foo: &const Foo) void { + \\fn f(foo: *const Foo) void { \\ \\ foo.method(1, 2); \\} \\export fn entry() usize { return @sizeOf(@typeOf(f)); } - , ".tmp_source.zig:6:15: error: expected 2 arguments, found 3"); + , + ".tmp_source.zig:6:15: error: expected 2 arguments, found 3", + ); - cases.add("assign through constant pointer", + cases.add( + "assign through constant pointer", \\export fn f() void { \\ var cstr = c"Hat"; \\ cstr[0] = 'W'; \\} - , ".tmp_source.zig:3:11: error: cannot assign to constant"); + , + ".tmp_source.zig:3:11: error: cannot assign to constant", + ); - cases.add("assign through constant slice", + cases.add( + "assign through constant slice", \\export fn f() void { \\ var cstr: []const u8 = "Hat"; \\ cstr[0] = 'W'; \\} - , ".tmp_source.zig:3:11: error: cannot assign to constant"); + , + ".tmp_source.zig:3:11: error: cannot assign to constant", + ); - cases.add("main function with bogus args type", + cases.add( + "main function with bogus args type", \\pub fn main(args: [][]bogus) !void {} - , ".tmp_source.zig:1:23: error: use of undeclared identifier 'bogus'"); + , + ".tmp_source.zig:1:23: error: use of undeclared identifier 'bogus'", + ); - cases.add("for loop missing element param", + cases.add( + "for loop missing element param", \\fn foo(blah: []u8) void { \\ for (blah) { } \\} \\export fn entry() usize { return @sizeOf(@typeOf(foo)); } - , ".tmp_source.zig:2:5: error: for loop expression missing element parameter"); + , + ".tmp_source.zig:2:5: error: for loop expression missing element parameter", + ); - cases.add("misspelled type with pointer only reference", + cases.add( + "misspelled type with pointer only reference", \\const JasonHM = u8; - \\const JasonList = &JsonNode; + \\const JasonList = *JsonNode; \\ \\const JsonOA = union(enum) { \\ JSONArray: JsonList, @@ -1596,9 +2947,12 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\} \\ \\export fn entry() usize { return @sizeOf(@typeOf(foo)); } - , ".tmp_source.zig:5:16: error: use of undeclared identifier 'JsonList'"); + , + ".tmp_source.zig:5:16: error: use of undeclared identifier 'JsonList'", + ); - cases.add("method call with first arg type primitive", + cases.add( + "method call with first arg type primitive", \\const Foo = struct { \\ x: i32, \\ @@ -1614,14 +2968,17 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ \\ derp.init(); \\} - , ".tmp_source.zig:14:5: error: expected type 'i32', found '&const Foo'"); + , + ".tmp_source.zig:14:5: error: expected type 'i32', found 'Foo'", + ); - cases.add("method call with first arg type wrong container", + cases.add( + "method call with first arg type wrong container", \\pub const List = struct { \\ len: usize, - \\ allocator: &Allocator, + \\ allocator: *Allocator, \\ - \\ pub fn init(allocator: &Allocator) List { + \\ pub fn init(allocator: *Allocator) List { \\ return List { \\ .len = 0, \\ .allocator = allocator, @@ -1641,26 +2998,33 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ var x = List.init(&global_allocator); \\ x.init(); \\} - , ".tmp_source.zig:23:5: error: expected type '&Allocator', found '&List'"); + , + ".tmp_source.zig:23:5: error: expected type '*Allocator', found '*List'", + ); - cases.add("binary not on number literal", + cases.add( + "binary not on number literal", \\const TINY_QUANTUM_SHIFT = 4; \\const TINY_QUANTUM_SIZE = 1 << TINY_QUANTUM_SHIFT; \\var block_aligned_stuff: usize = (4 + TINY_QUANTUM_SIZE) & ~(TINY_QUANTUM_SIZE - 1); \\ \\export fn entry() usize { return @sizeOf(@typeOf(block_aligned_stuff)); } - , ".tmp_source.zig:3:60: error: unable to perform binary not operation on type '(integer literal)'"); + , + ".tmp_source.zig:3:60: error: unable to perform binary not operation on type 'comptime_int'", + ); cases.addCase(x: { - const tc = cases.create("multiple files with private function error", - \\const foo = @import("foo.zig"); + const tc = cases.create( + "multiple files with private function error", + \\const foo = @import("foo.zig",); \\ \\export fn callPrivFunction() void { \\ foo.privateFunction(); \\} , ".tmp_source.zig:4:8: error: 'privateFunction' is private", - "foo.zig:1:1: note: declared here"); + "foo.zig:1:1: note: declared here", + ); tc.addSourceFile("foo.zig", \\fn privateFunction() void { } @@ -1669,14 +3033,18 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { break :x tc; }); - cases.add("container init with non-type", + cases.add( + "container init with non-type", \\const zero: i32 = 0; \\const a = zero{1}; \\ \\export fn entry() usize { return @sizeOf(@typeOf(a)); } - , ".tmp_source.zig:2:11: error: expected type, found 'i32'"); + , + ".tmp_source.zig:2:11: error: expected type, found 'i32'", + ); - cases.add("assign to constant field", + cases.add( + "assign to constant field", \\const Foo = struct { \\ field: i32, \\}; @@ -1684,15 +3052,18 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ const f = Foo {.field = 1234,}; \\ f.field = 0; \\} - , ".tmp_source.zig:6:13: error: cannot assign to constant"); + , + ".tmp_source.zig:6:13: error: cannot assign to constant", + ); - cases.add("return from defer expression", + cases.add( + "return from defer expression", \\pub fn testTrickyDefer() !void { \\ defer canFail() catch {}; \\ \\ defer try canFail(); \\ - \\ const a = maybeInt() ?? return; + \\ const a = maybeInt() orelse return; \\} \\ \\fn canFail() error!void { } @@ -1702,9 +3073,12 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\} \\ \\export fn entry() usize { return @sizeOf(@typeOf(testTrickyDefer)); } - , ".tmp_source.zig:4:11: error: cannot return from defer expression"); + , + ".tmp_source.zig:4:11: error: cannot return from defer expression", + ); - cases.add("attempt to access var args out of bounds", + cases.add( + "attempt to access var args out of bounds", \\fn add(args: ...) i32 { \\ return args[0] + args[1]; \\} @@ -1715,10 +3089,12 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ \\export fn entry() usize { return @sizeOf(@typeOf(foo)); } , - ".tmp_source.zig:2:26: error: index 1 outside argument list of size 1", - ".tmp_source.zig:6:15: note: called from here"); + ".tmp_source.zig:2:26: error: index 1 outside argument list of size 1", + ".tmp_source.zig:6:15: note: called from here", + ); - cases.add("pass integer literal to var args", + cases.add( + "pass integer literal to var args", \\fn add(args: ...) i32 { \\ var sum = i32(0); \\ {comptime var i: usize = 0; inline while (i < args.len) : (i += 1) { @@ -1732,32 +3108,44 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\} \\ \\export fn entry() usize { return @sizeOf(@typeOf(bar)); } - , ".tmp_source.zig:10:16: error: compiler bug: integer and float literals in var args function must be casted"); + , + ".tmp_source.zig:10:16: error: compiler bug: integer and float literals in var args function must be casted", + ); - cases.add("assign too big number to u16", + cases.add( + "assign too big number to u16", \\export fn foo() void { \\ var vga_mem: u16 = 0xB8000; \\} - , ".tmp_source.zig:2:24: error: integer value 753664 cannot be implicitly casted to type 'u16'"); + , + ".tmp_source.zig:2:24: error: integer value 753664 cannot be implicitly casted to type 'u16'", + ); - cases.add("global variable alignment non power of 2", + cases.add( + "global variable alignment non power of 2", \\const some_data: [100]u8 align(3) = undefined; \\export fn entry() usize { return @sizeOf(@typeOf(some_data)); } - , ".tmp_source.zig:1:32: error: alignment value 3 is not a power of 2"); + , + ".tmp_source.zig:1:32: error: alignment value 3 is not a power of 2", + ); - cases.add("function alignment non power of 2", + cases.add( + "function alignment non power of 2", \\extern fn foo() align(3) void; \\export fn entry() void { return foo(); } - , ".tmp_source.zig:1:23: error: alignment value 3 is not a power of 2"); + , + ".tmp_source.zig:1:23: error: alignment value 3 is not a power of 2", + ); - cases.add("compile log", + cases.add( + "compile log", \\export fn foo() void { - \\ comptime bar(12, "hi"); + \\ comptime bar(12, "hi",); \\} \\fn bar(a: i32, b: []const u8) void { - \\ @compileLog("begin"); + \\ @compileLog("begin",); \\ @compileLog("a", a, "b", b); - \\ @compileLog("end"); + \\ @compileLog("end",); \\} , ".tmp_source.zig:5:5: error: found compile log statement", @@ -1765,27 +3153,32 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { ".tmp_source.zig:6:5: error: found compile log statement", ".tmp_source.zig:2:17: note: called from here", ".tmp_source.zig:7:5: error: found compile log statement", - ".tmp_source.zig:2:17: note: called from here"); + ".tmp_source.zig:2:17: note: called from here", + ); - cases.add("casting bit offset pointer to regular pointer", + cases.add( + "casting bit offset pointer to regular pointer", \\const BitField = packed struct { \\ a: u3, \\ b: u3, \\ c: u2, \\}; \\ - \\fn foo(bit_field: &const BitField) u3 { + \\fn foo(bit_field: *const BitField) u3 { \\ return bar(&bit_field.b); \\} \\ - \\fn bar(x: &const u3) u3 { - \\ return *x; + \\fn bar(x: *const u3) u3 { + \\ return x.*; \\} \\ \\export fn entry() usize { return @sizeOf(@typeOf(foo)); } - , ".tmp_source.zig:8:26: error: expected type '&const u3', found '&align(1:3:6) const u3'"); + , + ".tmp_source.zig:8:26: error: expected type '*const u3', found '*align(1:3:6) const u3'", + ); - cases.add("referring to a struct that is invalid", + cases.add( + "referring to a struct that is invalid", \\const UsbDeviceRequest = struct { \\ Type: u8, \\}; @@ -1798,10 +3191,12 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ if (!ok) unreachable; \\} , - ".tmp_source.zig:10:14: error: unable to evaluate constant expression", - ".tmp_source.zig:6:20: note: called from here"); + ".tmp_source.zig:10:14: error: unable to evaluate constant expression", + ".tmp_source.zig:6:20: note: called from here", + ); - cases.add("control flow uses comptime var at runtime", + cases.add( + "control flow uses comptime var at runtime", \\export fn foo() void { \\ comptime var i = 0; \\ while (i < 5) : (i += 1) { @@ -1811,88 +3206,118 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ \\fn bar() void { } , - ".tmp_source.zig:3:5: error: control flow attempts to use compile-time variable at runtime", - ".tmp_source.zig:3:24: note: compile-time variable assigned here"); + ".tmp_source.zig:3:5: error: control flow attempts to use compile-time variable at runtime", + ".tmp_source.zig:3:24: note: compile-time variable assigned here", + ); - cases.add("ignored return value", + cases.add( + "ignored return value", \\export fn foo() void { \\ bar(); \\} \\fn bar() i32 { return 0; } - , ".tmp_source.zig:2:8: error: expression value is ignored"); + , + ".tmp_source.zig:2:8: error: expression value is ignored", + ); - cases.add("ignored assert-err-ok return value", + cases.add( + "ignored assert-err-ok return value", \\export fn foo() void { \\ bar() catch unreachable; \\} \\fn bar() error!i32 { return 0; } - , ".tmp_source.zig:2:11: error: expression value is ignored"); + , + ".tmp_source.zig:2:11: error: expression value is ignored", + ); - cases.add("ignored statement value", + cases.add( + "ignored statement value", \\export fn foo() void { \\ 1; \\} - , ".tmp_source.zig:2:5: error: expression value is ignored"); + , + ".tmp_source.zig:2:5: error: expression value is ignored", + ); - cases.add("ignored comptime statement value", + cases.add( + "ignored comptime statement value", \\export fn foo() void { \\ comptime {1;} \\} - , ".tmp_source.zig:2:15: error: expression value is ignored"); + , + ".tmp_source.zig:2:15: error: expression value is ignored", + ); - cases.add("ignored comptime value", + cases.add( + "ignored comptime value", \\export fn foo() void { \\ comptime 1; \\} - , ".tmp_source.zig:2:5: error: expression value is ignored"); + , + ".tmp_source.zig:2:5: error: expression value is ignored", + ); - cases.add("ignored defered statement value", + cases.add( + "ignored defered statement value", \\export fn foo() void { \\ defer {1;} \\} - , ".tmp_source.zig:2:12: error: expression value is ignored"); + , + ".tmp_source.zig:2:12: error: expression value is ignored", + ); - cases.add("ignored defered function call", + cases.add( + "ignored defered function call", \\export fn foo() void { \\ defer bar(); \\} \\fn bar() error!i32 { return 0; } - , ".tmp_source.zig:2:14: error: expression value is ignored"); + , + ".tmp_source.zig:2:14: error: expression value is ignored", + ); - cases.add("dereference an array", + cases.add( + "dereference an array", \\var s_buffer: [10]u8 = undefined; \\pub fn pass(in: []u8) []u8 { \\ var out = &s_buffer; - \\ *out[0] = in[0]; - \\ return (*out)[0..1]; + \\ out.*.* = in[0]; + \\ return out.*[0..1]; \\} \\ \\export fn entry() usize { return @sizeOf(@typeOf(pass)); } - , ".tmp_source.zig:4:5: error: attempt to dereference non pointer type '[10]u8'"); + , + ".tmp_source.zig:4:10: error: attempt to dereference non pointer type '[10]u8'", + ); - cases.add("pass const ptr to mutable ptr fn", + cases.add( + "pass const ptr to mutable ptr fn", \\fn foo() bool { - \\ const a = ([]const u8)("a"); + \\ const a = ([]const u8)("a",); \\ const b = &a; \\ return ptrEql(b, b); \\} - \\fn ptrEql(a: &[]const u8, b: &[]const u8) bool { + \\fn ptrEql(a: *[]const u8, b: *[]const u8) bool { \\ return true; \\} \\ \\export fn entry() usize { return @sizeOf(@typeOf(foo)); } - , ".tmp_source.zig:4:19: error: expected type '&[]const u8', found '&const []const u8'"); + , + ".tmp_source.zig:4:19: error: expected type '*[]const u8', found '*const []const u8'", + ); cases.addCase(x: { - const tc = cases.create("export collision", - \\const foo = @import("foo.zig"); + const tc = cases.create( + "export collision", + \\const foo = @import("foo.zig",); \\ \\export fn bar() usize { \\ return foo.baz; \\} , "foo.zig:1:8: error: exported symbol collision: 'bar'", - ".tmp_source.zig:3:8: note: other symbol here"); + ".tmp_source.zig:3:8: note: other symbol here", + ); tc.addSourceFile("foo.zig", \\export fn bar() void {} @@ -1902,35 +3327,28 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { break :x tc; }); - cases.add("pass non-copyable type by value to function", - \\const Point = struct { x: i32, y: i32, }; - \\fn foo(p: Point) void { } - \\export fn entry() usize { return @sizeOf(@typeOf(foo)); } - , ".tmp_source.zig:2:11: error: type 'Point' is not copyable; cannot pass by value"); - - cases.add("implicit cast from array to mutable slice", + cases.add( + "implicit cast from array to mutable slice", \\var global_array: [10]i32 = undefined; \\fn foo(param: []i32) void {} \\export fn entry() void { \\ foo(global_array); \\} - , ".tmp_source.zig:4:9: error: expected type '[]i32', found '[10]i32'"); + , + ".tmp_source.zig:4:9: error: expected type '[]i32', found '[10]i32'", + ); - cases.add("ptrcast to non-pointer", - \\export fn entry(a: &i32) usize { + cases.add( + "ptrcast to non-pointer", + \\export fn entry(a: *i32) usize { \\ return @ptrCast(usize, a); \\} - , ".tmp_source.zig:2:21: error: expected pointer, found 'usize'"); - - cases.add("too many error values to cast to small integer", - \\const Error = error { A, B, C, D, E, F, G, H }; - \\fn foo(e: Error) u2 { - \\ return u2(e); - \\} - \\export fn entry() usize { return @sizeOf(@typeOf(foo)); } - , ".tmp_source.zig:3:14: error: too many error values to fit in 'u2'"); + , + ".tmp_source.zig:2:21: error: expected pointer, found 'usize'", + ); - cases.add("asm at compile time", + cases.add( + "asm at compile time", \\comptime { \\ doSomeAsm(); \\} @@ -1942,48 +3360,66 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ \\.set aoeu, derp; \\ ); \\} - , ".tmp_source.zig:6:5: error: unable to evaluate constant expression"); + , + ".tmp_source.zig:6:5: error: unable to evaluate constant expression", + ); - cases.add("invalid member of builtin enum", - \\const builtin = @import("builtin"); + cases.add( + "invalid member of builtin enum", + \\const builtin = @import("builtin",); \\export fn entry() void { \\ const foo = builtin.Arch.x86; \\} - , ".tmp_source.zig:3:29: error: container 'Arch' has no member called 'x86'"); + , + ".tmp_source.zig:3:29: error: container 'Arch' has no member called 'x86'", + ); - cases.add("int to ptr of 0 bits", + cases.add( + "int to ptr of 0 bits", \\export fn foo() void { \\ var x: usize = 0x1000; - \\ var y: &void = @intToPtr(&void, x); + \\ var y: *void = @intToPtr(*void, x); \\} - , ".tmp_source.zig:3:31: error: type '&void' has 0 bits and cannot store information"); + , + ".tmp_source.zig:3:30: error: type '*void' has 0 bits and cannot store information", + ); - cases.add("@fieldParentPtr - non struct", + cases.add( + "@fieldParentPtr - non struct", \\const Foo = i32; - \\export fn foo(a: &i32) &Foo { + \\export fn foo(a: *i32) *Foo { \\ return @fieldParentPtr(Foo, "a", a); \\} - , ".tmp_source.zig:3:28: error: expected struct type, found 'i32'"); + , + ".tmp_source.zig:3:28: error: expected struct type, found 'i32'", + ); - cases.add("@fieldParentPtr - bad field name", + cases.add( + "@fieldParentPtr - bad field name", \\const Foo = extern struct { \\ derp: i32, \\}; - \\export fn foo(a: &i32) &Foo { + \\export fn foo(a: *i32) *Foo { \\ return @fieldParentPtr(Foo, "a", a); \\} - , ".tmp_source.zig:5:33: error: struct 'Foo' has no field 'a'"); + , + ".tmp_source.zig:5:33: error: struct 'Foo' has no field 'a'", + ); - cases.add("@fieldParentPtr - field pointer is not pointer", + cases.add( + "@fieldParentPtr - field pointer is not pointer", \\const Foo = extern struct { \\ a: i32, \\}; - \\export fn foo(a: i32) &Foo { + \\export fn foo(a: i32) *Foo { \\ return @fieldParentPtr(Foo, "a", a); \\} - , ".tmp_source.zig:5:38: error: expected pointer, found 'i32'"); + , + ".tmp_source.zig:5:38: error: expected pointer, found 'i32'", + ); - cases.add("@fieldParentPtr - comptime field ptr not based on struct", + cases.add( + "@fieldParentPtr - comptime field ptr not based on struct", \\const Foo = struct { \\ a: i32, \\ b: i32, @@ -1991,12 +3427,15 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\const foo = Foo { .a = 1, .b = 2, }; \\ \\comptime { - \\ const field_ptr = @intToPtr(&i32, 0x1234); + \\ const field_ptr = @intToPtr(*i32, 0x1234); \\ const another_foo_ptr = @fieldParentPtr(Foo, "b", field_ptr); \\} - , ".tmp_source.zig:9:55: error: pointer value not based on parent struct"); + , + ".tmp_source.zig:9:55: error: pointer value not based on parent struct", + ); - cases.add("@fieldParentPtr - comptime wrong field index", + cases.add( + "@fieldParentPtr - comptime wrong field index", \\const Foo = struct { \\ a: i32, \\ b: i32, @@ -2006,76 +3445,100 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\comptime { \\ const another_foo_ptr = @fieldParentPtr(Foo, "b", &foo.a); \\} - , ".tmp_source.zig:8:29: error: field 'b' has index 1 but pointer value is index 0 of struct 'Foo'"); + , + ".tmp_source.zig:8:29: error: field 'b' has index 1 but pointer value is index 0 of struct 'Foo'", + ); - cases.add("@offsetOf - non struct", + cases.add( + "@offsetOf - non struct", \\const Foo = i32; \\export fn foo() usize { - \\ return @offsetOf(Foo, "a"); + \\ return @offsetOf(Foo, "a",); \\} - , ".tmp_source.zig:3:22: error: expected struct type, found 'i32'"); + , + ".tmp_source.zig:3:22: error: expected struct type, found 'i32'", + ); - cases.add("@offsetOf - bad field name", + cases.add( + "@offsetOf - bad field name", \\const Foo = struct { \\ derp: i32, \\}; \\export fn foo() usize { - \\ return @offsetOf(Foo, "a"); + \\ return @offsetOf(Foo, "a",); \\} - , ".tmp_source.zig:5:27: error: struct 'Foo' has no field 'a'"); + , + ".tmp_source.zig:5:27: error: struct 'Foo' has no field 'a'", + ); - cases.addExe("missing main fn in executable", + cases.addExe( + "missing main fn in executable", \\ - , "error: no member named 'main' in '"); + , + "error: no member named 'main' in '", + ); - cases.addExe("private main fn", + cases.addExe( + "private main fn", \\fn main() void {} , "error: 'main' is private", - ".tmp_source.zig:1:1: note: declared here"); + ".tmp_source.zig:1:1: note: declared here", + ); - cases.add("setting a section on an extern variable", + cases.add( + "setting a section on an extern variable", \\extern var foo: i32 section(".text2"); \\export fn entry() i32 { \\ return foo; \\} , - ".tmp_source.zig:1:29: error: cannot set section of external variable 'foo'"); + ".tmp_source.zig:1:29: error: cannot set section of external variable 'foo'", + ); - cases.add("setting a section on a local variable", + cases.add( + "setting a section on a local variable", \\export fn entry() i32 { \\ var foo: i32 section(".text2") = 1234; \\ return foo; \\} , - ".tmp_source.zig:2:26: error: cannot set section of local variable 'foo'"); + ".tmp_source.zig:2:26: error: cannot set section of local variable 'foo'", + ); - cases.add("setting a section on an extern fn", + cases.add( + "setting a section on an extern fn", \\extern fn foo() section(".text2") void; \\export fn entry() void { \\ foo(); \\} , - ".tmp_source.zig:1:25: error: cannot set section of external function 'foo'"); + ".tmp_source.zig:1:25: error: cannot set section of external function 'foo'", + ); - cases.add("returning address of local variable - simple", - \\export fn foo() &i32 { + cases.add( + "returning address of local variable - simple", + \\export fn foo() *i32 { \\ var a: i32 = undefined; \\ return &a; \\} , - ".tmp_source.zig:3:13: error: function returns address of local variable"); + ".tmp_source.zig:3:13: error: function returns address of local variable", + ); - cases.add("returning address of local variable - phi", - \\export fn foo(c: bool) &i32 { + cases.add( + "returning address of local variable - phi", + \\export fn foo(c: bool) *i32 { \\ var a: i32 = undefined; \\ var b: i32 = undefined; \\ return if (c) &a else &b; \\} , - ".tmp_source.zig:4:12: error: function returns address of local variable"); + ".tmp_source.zig:4:12: error: function returns address of local variable", + ); - cases.add("inner struct member shadowing outer struct member", + cases.add( + "inner struct member shadowing outer struct member", \\fn A() type { \\ return struct { \\ b: B(), @@ -2097,57 +3560,71 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\} , ".tmp_source.zig:9:17: error: redefinition of 'Self'", - ".tmp_source.zig:5:9: note: previous definition is here"); + ".tmp_source.zig:5:9: note: previous definition is here", + ); - cases.add("while expected bool, got nullable", + cases.add( + "while expected bool, got optional", \\export fn foo() void { \\ while (bar()) {} \\} \\fn bar() ?i32 { return 1; } , - ".tmp_source.zig:2:15: error: expected type 'bool', found '?i32'"); + ".tmp_source.zig:2:15: error: expected type 'bool', found '?i32'", + ); - cases.add("while expected bool, got error union", + cases.add( + "while expected bool, got error union", \\export fn foo() void { \\ while (bar()) {} \\} \\fn bar() error!i32 { return 1; } , - ".tmp_source.zig:2:15: error: expected type 'bool', found 'error!i32'"); + ".tmp_source.zig:2:15: error: expected type 'bool', found 'error!i32'", + ); - cases.add("while expected nullable, got bool", + cases.add( + "while expected optional, got bool", \\export fn foo() void { \\ while (bar()) |x| {} \\} \\fn bar() bool { return true; } , - ".tmp_source.zig:2:15: error: expected nullable type, found 'bool'"); + ".tmp_source.zig:2:15: error: expected optional type, found 'bool'", + ); - cases.add("while expected nullable, got error union", + cases.add( + "while expected optional, got error union", \\export fn foo() void { \\ while (bar()) |x| {} \\} \\fn bar() error!i32 { return 1; } , - ".tmp_source.zig:2:15: error: expected nullable type, found 'error!i32'"); + ".tmp_source.zig:2:15: error: expected optional type, found 'error!i32'", + ); - cases.add("while expected error union, got bool", + cases.add( + "while expected error union, got bool", \\export fn foo() void { \\ while (bar()) |x| {} else |err| {} \\} \\fn bar() bool { return true; } , - ".tmp_source.zig:2:15: error: expected error union type, found 'bool'"); + ".tmp_source.zig:2:15: error: expected error union type, found 'bool'", + ); - cases.add("while expected error union, got nullable", + cases.add( + "while expected error union, got optional", \\export fn foo() void { \\ while (bar()) |x| {} else |err| {} \\} \\fn bar() ?i32 { return 1; } , - ".tmp_source.zig:2:15: error: expected error union type, found '?i32'"); + ".tmp_source.zig:2:15: error: expected error union type, found '?i32'", + ); - cases.add("inline fn calls itself indirectly", + cases.add( + "inline fn calls itself indirectly", \\export fn foo() void { \\ bar(); \\} @@ -2161,91 +3638,113 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\} \\extern fn quux() void; , - ".tmp_source.zig:4:8: error: unable to inline function"); + ".tmp_source.zig:4:8: error: unable to inline function", + ); - cases.add("save reference to inline function", + cases.add( + "save reference to inline function", \\export fn foo() void { \\ quux(@ptrToInt(bar)); \\} \\inline fn bar() void { } \\extern fn quux(usize) void; , - ".tmp_source.zig:4:8: error: unable to inline function"); + ".tmp_source.zig:4:8: error: unable to inline function", + ); - cases.add("signed integer division", + cases.add( + "signed integer division", \\export fn foo(a: i32, b: i32) i32 { \\ return a / b; \\} , - ".tmp_source.zig:2:14: error: division with 'i32' and 'i32': signed integers must use @divTrunc, @divFloor, or @divExact"); + ".tmp_source.zig:2:14: error: division with 'i32' and 'i32': signed integers must use @divTrunc, @divFloor, or @divExact", + ); - cases.add("signed integer remainder division", + cases.add( + "signed integer remainder division", \\export fn foo(a: i32, b: i32) i32 { \\ return a % b; \\} , - ".tmp_source.zig:2:14: error: remainder division with 'i32' and 'i32': signed integers and floats must use @rem or @mod"); + ".tmp_source.zig:2:14: error: remainder division with 'i32' and 'i32': signed integers and floats must use @rem or @mod", + ); - cases.add("cast negative value to unsigned integer", + cases.add( + "cast negative value to unsigned integer", \\comptime { \\ const value: i32 = -1; - \\ const unsigned = u32(value); + \\ const unsigned = @intCast(u32, value); \\} , - ".tmp_source.zig:3:25: error: attempt to cast negative value to unsigned integer"); + ".tmp_source.zig:3:22: error: attempt to cast negative value to unsigned integer", + ); - cases.add("compile-time division by zero", + cases.add( + "compile-time division by zero", \\comptime { \\ const a: i32 = 1; \\ const b: i32 = 0; \\ const c = a / b; \\} , - ".tmp_source.zig:4:17: error: division by zero"); + ".tmp_source.zig:4:17: error: division by zero", + ); - cases.add("compile-time remainder division by zero", + cases.add( + "compile-time remainder division by zero", \\comptime { \\ const a: i32 = 1; \\ const b: i32 = 0; \\ const c = a % b; \\} , - ".tmp_source.zig:4:17: error: division by zero"); + ".tmp_source.zig:4:17: error: division by zero", + ); - cases.add("compile-time integer cast truncates bits", + cases.add( + "compile-time integer cast truncates bits", \\comptime { \\ const spartan_count: u16 = 300; - \\ const byte = u8(spartan_count); + \\ const byte = @intCast(u8, spartan_count); \\} , - ".tmp_source.zig:3:20: error: cast from 'u16' to 'u8' truncates bits"); + ".tmp_source.zig:3:18: error: cast from 'u16' to 'u8' truncates bits", + ); - cases.add("@setRuntimeSafety twice for same scope", + cases.add( + "@setRuntimeSafety twice for same scope", \\export fn foo() void { \\ @setRuntimeSafety(false); \\ @setRuntimeSafety(false); \\} , ".tmp_source.zig:3:5: error: runtime safety set twice for same scope", - ".tmp_source.zig:2:5: note: first set here"); + ".tmp_source.zig:2:5: note: first set here", + ); - cases.add("@setFloatMode twice for same scope", + cases.add( + "@setFloatMode twice for same scope", \\export fn foo() void { \\ @setFloatMode(this, @import("builtin").FloatMode.Optimized); \\ @setFloatMode(this, @import("builtin").FloatMode.Optimized); \\} , ".tmp_source.zig:3:5: error: float mode set twice for same scope", - ".tmp_source.zig:2:5: note: first set here"); + ".tmp_source.zig:2:5: note: first set here", + ); - cases.add("array access of type", + cases.add( + "array access of type", \\export fn foo() void { \\ var b: u8[40] = undefined; \\} , - ".tmp_source.zig:2:14: error: array access of non-array type 'type'"); + ".tmp_source.zig:2:14: error: array access of non-array type 'type'", + ); - cases.add("cannot break out of defer expression", + cases.add( + "cannot break out of defer expression", \\export fn foo() void { \\ while (true) { \\ defer { @@ -2254,9 +3753,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ } \\} , - ".tmp_source.zig:4:13: error: cannot break out of defer expression"); + ".tmp_source.zig:4:13: error: cannot break out of defer expression", + ); - cases.add("cannot continue out of defer expression", + cases.add( + "cannot continue out of defer expression", \\export fn foo() void { \\ while (true) { \\ defer { @@ -2265,9 +3766,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ } \\} , - ".tmp_source.zig:4:13: error: cannot continue out of defer expression"); + ".tmp_source.zig:4:13: error: cannot continue out of defer expression", + ); - cases.add("calling a var args function only known at runtime", + cases.add( + "calling a var args function only known at runtime", \\var foos = []fn(...) void { foo1, foo2 }; \\ \\fn foo1(args: ...) void {} @@ -2277,9 +3780,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ foos[0](); \\} , - ".tmp_source.zig:7:9: error: calling a generic function requires compile-time known function value"); + ".tmp_source.zig:7:9: error: calling a generic function requires compile-time known function value", + ); - cases.add("calling a generic function only known at runtime", + cases.add( + "calling a generic function only known at runtime", \\var foos = []fn(var) void { foo1, foo2 }; \\ \\fn foo1(arg: var) void {} @@ -2289,10 +3794,12 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ foos[0](true); \\} , - ".tmp_source.zig:7:9: error: calling a generic function requires compile-time known function value"); + ".tmp_source.zig:7:9: error: calling a generic function requires compile-time known function value", + ); - cases.add("@compileError shows traceback of references that caused it", - \\const foo = @compileError("aoeu"); + cases.add( + "@compileError shows traceback of references that caused it", + \\const foo = @compileError("aoeu",); \\ \\const bar = baz + foo; \\const baz = 1; @@ -2303,9 +3810,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { , ".tmp_source.zig:1:13: error: aoeu", ".tmp_source.zig:3:19: note: referenced here", - ".tmp_source.zig:7:12: note: referenced here"); + ".tmp_source.zig:7:12: note: referenced here", + ); - cases.add("instantiating an undefined value for an invalid struct that contains itself", + cases.add( + "instantiating an undefined value for an invalid struct that contains itself", \\const Foo = struct { \\ x: Foo, \\}; @@ -2316,73 +3825,93 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ return @sizeOf(@typeOf(foo.x)); \\} , - ".tmp_source.zig:1:13: error: struct 'Foo' contains itself"); + ".tmp_source.zig:1:13: error: struct 'Foo' contains itself", + ); - cases.add("float literal too large error", + cases.add( + "float literal too large error", \\comptime { \\ const a = 0x1.0p16384; \\} , - ".tmp_source.zig:2:15: error: float literal out of range of any type"); + ".tmp_source.zig:2:15: error: float literal out of range of any type", + ); - cases.add("float literal too small error (denormal)", + cases.add( + "float literal too small error (denormal)", \\comptime { \\ const a = 0x1.0p-16384; \\} , - ".tmp_source.zig:2:15: error: float literal out of range of any type"); + ".tmp_source.zig:2:15: error: float literal out of range of any type", + ); - cases.add("explicit cast float literal to integer when there is a fraction component", + cases.add( + "explicit cast float literal to integer when there is a fraction component", \\export fn entry() i32 { \\ return i32(12.34); \\} , - ".tmp_source.zig:2:16: error: fractional component prevents float value 12.340000 from being casted to type 'i32'"); + ".tmp_source.zig:2:16: error: fractional component prevents float value 12.340000 from being casted to type 'i32'", + ); - cases.add("non pointer given to @ptrToInt", + cases.add( + "non pointer given to @ptrToInt", \\export fn entry(x: i32) usize { \\ return @ptrToInt(x); \\} , - ".tmp_source.zig:2:22: error: expected pointer, found 'i32'"); + ".tmp_source.zig:2:22: error: expected pointer, found 'i32'", + ); - cases.add("@shlExact shifts out 1 bits", + cases.add( + "@shlExact shifts out 1 bits", \\comptime { \\ const x = @shlExact(u8(0b01010101), 2); \\} , - ".tmp_source.zig:2:15: error: operation caused overflow"); + ".tmp_source.zig:2:15: error: operation caused overflow", + ); - cases.add("@shrExact shifts out 1 bits", + cases.add( + "@shrExact shifts out 1 bits", \\comptime { \\ const x = @shrExact(u8(0b10101010), 2); \\} , - ".tmp_source.zig:2:15: error: exact shift shifted out 1 bits"); + ".tmp_source.zig:2:15: error: exact shift shifted out 1 bits", + ); - cases.add("shifting without int type or comptime known", + cases.add( + "shifting without int type or comptime known", \\export fn entry(x: u8) u8 { \\ return 0x11 << x; \\} , - ".tmp_source.zig:2:17: error: LHS of shift must be an integer type, or RHS must be compile-time known"); + ".tmp_source.zig:2:17: error: LHS of shift must be an integer type, or RHS must be compile-time known", + ); - cases.add("shifting RHS is log2 of LHS int bit width", + cases.add( + "shifting RHS is log2 of LHS int bit width", \\export fn entry(x: u8, y: u8) u8 { \\ return x << y; \\} , - ".tmp_source.zig:2:17: error: expected type 'u3', found 'u8'"); + ".tmp_source.zig:2:17: error: expected type 'u3', found 'u8'", + ); - cases.add("globally shadowing a primitive type", + cases.add( + "globally shadowing a primitive type", \\const u16 = @intType(false, 8); \\export fn entry() void { \\ const a: u16 = 300; \\} , - ".tmp_source.zig:1:1: error: declaration shadows type 'u16'"); + ".tmp_source.zig:1:1: error: declaration shadows type 'u16'", + ); - cases.add("implicitly increasing pointer alignment", + cases.add( + "implicitly increasing pointer alignment", \\const Foo = packed struct { \\ a: u8, \\ b: u32, @@ -2393,13 +3922,15 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ bar(&foo.b); \\} \\ - \\fn bar(x: &u32) void { - \\ *x += 1; + \\fn bar(x: *u32) void { + \\ x.* += 1; \\} , - ".tmp_source.zig:8:13: error: expected type '&u32', found '&align(1) u32'"); + ".tmp_source.zig:8:13: error: expected type '*u32', found '*align(1) u32'", + ); - cases.add("implicitly increasing slice alignment", + cases.add( + "implicitly increasing slice alignment", \\const Foo = packed struct { \\ a: u8, \\ b: u32, @@ -2408,44 +3939,42 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\export fn entry() void { \\ var foo = Foo { .a = 1, .b = 10 }; \\ foo.b += 1; - \\ bar((&foo.b)[0..1]); + \\ bar((*[1]u32)(&foo.b)[0..]); \\} \\ \\fn bar(x: []u32) void { \\ x[0] += 1; \\} , - ".tmp_source.zig:9:17: error: expected type '[]u32', found '[]align(1) u32'"); + ".tmp_source.zig:9:18: error: cast increases pointer alignment", + ".tmp_source.zig:9:23: note: '*align(1) u32' has alignment 1", + ".tmp_source.zig:9:18: note: '*[1]u32' has alignment 4", + ); - cases.add("increase pointer alignment in @ptrCast", + cases.add( + "increase pointer alignment in @ptrCast", \\export fn entry() u32 { \\ var bytes: [4]u8 = []u8{0x01, 0x02, 0x03, 0x04}; - \\ const ptr = @ptrCast(&u32, &bytes[0]); - \\ return *ptr; + \\ const ptr = @ptrCast(*u32, &bytes[0]); + \\ return ptr.*; \\} , ".tmp_source.zig:3:17: error: cast increases pointer alignment", - ".tmp_source.zig:3:38: note: '&u8' has alignment 1", - ".tmp_source.zig:3:27: note: '&u32' has alignment 4"); - - cases.add("increase pointer alignment in slice resize", - \\export fn entry() u32 { - \\ var bytes = []u8{0x01, 0x02, 0x03, 0x04}; - \\ return ([]u32)(bytes[0..])[0]; - \\} - , - ".tmp_source.zig:3:19: error: cast increases pointer alignment", - ".tmp_source.zig:3:19: note: '[]u8' has alignment 1", - ".tmp_source.zig:3:19: note: '[]u32' has alignment 4"); + ".tmp_source.zig:3:38: note: '*u8' has alignment 1", + ".tmp_source.zig:3:26: note: '*u32' has alignment 4", + ); - cases.add("@alignCast expects pointer or slice", + cases.add( + "@alignCast expects pointer or slice", \\export fn entry() void { \\ @alignCast(4, u32(3)); \\} , - ".tmp_source.zig:2:22: error: expected pointer or slice, found 'u32'"); + ".tmp_source.zig:2:22: error: expected pointer or slice, found 'u32'", + ); - cases.add("passing an under-aligned function pointer", + cases.add( + "passing an under-aligned function pointer", \\export fn entry() void { \\ testImplicitlyDecreaseFnAlign(alignedSmall, 1234); \\} @@ -2454,26 +3983,32 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\} \\fn alignedSmall() align(4) i32 { return 1234; } , - ".tmp_source.zig:2:35: error: expected type 'fn() align(8) i32', found 'fn() align(4) i32'"); + ".tmp_source.zig:2:35: error: expected type 'fn() align(8) i32', found 'fn() align(4) i32'", + ); - cases.add("passing a not-aligned-enough pointer to cmpxchg", + cases.add( + "passing a not-aligned-enough pointer to cmpxchg", \\const AtomicOrder = @import("builtin").AtomicOrder; \\export fn entry() bool { \\ var x: i32 align(1) = 1234; - \\ while (!@cmpxchg(&x, 1234, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) {} + \\ while (!@cmpxchgWeak(i32, &x, 1234, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) {} \\ return x == 5678; \\} , - ".tmp_source.zig:4:23: error: expected pointer alignment of at least 4, found 1"); + ".tmp_source.zig:4:32: error: expected type '*i32', found '*align(1) i32'", + ); - cases.add("wrong size to an array literal", + cases.add( + "wrong size to an array literal", \\comptime { \\ const array = [2]u8{1, 2, 3}; \\} , - ".tmp_source.zig:2:24: error: expected [2]u8 literal, found [3]u8 literal"); + ".tmp_source.zig:2:24: error: expected [2]u8 literal, found [3]u8 literal", + ); - cases.add("@setEvalBranchQuota in non-root comptime execution context", + cases.add( + "@setEvalBranchQuota in non-root comptime execution context", \\comptime { \\ foo(); \\} @@ -2483,72 +4018,82 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { , ".tmp_source.zig:5:5: error: @setEvalBranchQuota must be called from the top of the comptime stack", ".tmp_source.zig:2:8: note: called from here", - ".tmp_source.zig:1:10: note: called from here"); + ".tmp_source.zig:1:10: note: called from here", + ); - cases.add("wrong pointer implicitly casted to pointer to @OpaqueType()", + cases.add( + "wrong pointer implicitly casted to pointer to @OpaqueType()", \\const Derp = @OpaqueType(); - \\extern fn bar(d: &Derp) void; + \\extern fn bar(d: *Derp) void; \\export fn foo() void { \\ var x = u8(1); - \\ bar(@ptrCast(&c_void, &x)); + \\ bar(@ptrCast(*c_void, &x)); \\} , - ".tmp_source.zig:5:9: error: expected type '&Derp', found '&c_void'"); + ".tmp_source.zig:5:9: error: expected type '*Derp', found '*c_void'", + ); - cases.add("non-const variables of things that require const variables", + cases.add( + "non-const variables of things that require const variables", \\const Opaque = @OpaqueType(); \\ - \\export fn entry(opaque: &Opaque) void { + \\export fn entry(opaque: *Opaque) void { \\ var m2 = &2; - \\ const y: u32 = *m2; + \\ const y: u32 = m2.*; \\ \\ var a = undefined; \\ var b = 1; \\ var c = 1.0; \\ var d = this; \\ var e = null; - \\ var f = *opaque; + \\ var f = opaque.*; \\ var g = i32; - \\ var h = @import("std"); + \\ var h = @import("std",); \\ var i = (Foo {}).bar; \\ \\ var z: noreturn = return; \\} \\ \\const Foo = struct { - \\ fn bar(self: &const Foo) void {} + \\ fn bar(self: *const Foo) void {} \\}; , - ".tmp_source.zig:4:4: error: variable of type '&const (integer literal)' must be const or comptime", + ".tmp_source.zig:4:4: error: variable of type '*comptime_int' must be const or comptime", ".tmp_source.zig:7:4: error: variable of type '(undefined)' must be const or comptime", - ".tmp_source.zig:8:4: error: variable of type '(integer literal)' must be const or comptime", - ".tmp_source.zig:9:4: error: variable of type '(float literal)' must be const or comptime", + ".tmp_source.zig:8:4: error: variable of type 'comptime_int' must be const or comptime", + ".tmp_source.zig:9:4: error: variable of type 'comptime_float' must be const or comptime", ".tmp_source.zig:10:4: error: variable of type '(block)' must be const or comptime", ".tmp_source.zig:11:4: error: variable of type '(null)' must be const or comptime", - ".tmp_source.zig:12:4: error: variable of type 'Opaque' must be const or comptime", + ".tmp_source.zig:12:4: error: variable of type 'Opaque' not allowed", ".tmp_source.zig:13:4: error: variable of type 'type' must be const or comptime", ".tmp_source.zig:14:4: error: variable of type '(namespace)' must be const or comptime", - ".tmp_source.zig:15:4: error: variable of type '(bound fn(&const Foo) void)' must be const or comptime", - ".tmp_source.zig:17:4: error: unreachable code"); + ".tmp_source.zig:15:4: error: variable of type '(bound fn(*const Foo) void)' must be const or comptime", + ".tmp_source.zig:17:4: error: unreachable code", + ); - cases.add("wrong types given to atomic order args in cmpxchg", + cases.add( + "wrong types given to atomic order args in cmpxchg", \\export fn entry() void { \\ var x: i32 = 1234; - \\ while (!@cmpxchg(&x, 1234, 5678, u32(1234), u32(1234))) {} + \\ while (!@cmpxchgWeak(i32, &x, 1234, 5678, u32(1234), u32(1234))) {} \\} , - ".tmp_source.zig:3:41: error: expected type 'AtomicOrder', found 'u32'"); + ".tmp_source.zig:3:50: error: expected type 'AtomicOrder', found 'u32'", + ); - cases.add("wrong types given to @export", + cases.add( + "wrong types given to @export", \\extern fn entry() void { } \\comptime { \\ @export("entry", entry, u32(1234)); \\} , - ".tmp_source.zig:3:32: error: expected type 'GlobalLinkage', found 'u32'"); + ".tmp_source.zig:3:32: error: expected type 'GlobalLinkage', found 'u32'", + ); - cases.add("struct with invalid field", - \\const std = @import("std"); + cases.add( + "struct with invalid field", + \\const std = @import("std",); \\const Allocator = std.mem.Allocator; \\const ArrayList = std.ArrayList; \\ @@ -2572,23 +4117,29 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ }; \\} , - ".tmp_source.zig:14:17: error: use of undeclared identifier 'HeaderValue'"); + ".tmp_source.zig:14:17: error: use of undeclared identifier 'HeaderValue'", + ); - cases.add("@setAlignStack outside function", + cases.add( + "@setAlignStack outside function", \\comptime { \\ @setAlignStack(16); \\} , - ".tmp_source.zig:2:5: error: @setAlignStack outside function"); + ".tmp_source.zig:2:5: error: @setAlignStack outside function", + ); - cases.add("@setAlignStack in naked function", + cases.add( + "@setAlignStack in naked function", \\export nakedcc fn entry() void { \\ @setAlignStack(16); \\} , - ".tmp_source.zig:2:5: error: @setAlignStack in naked function"); + ".tmp_source.zig:2:5: error: @setAlignStack in naked function", + ); - cases.add("@setAlignStack in inline function", + cases.add( + "@setAlignStack in inline function", \\export fn entry() void { \\ foo(); \\} @@ -2596,25 +4147,31 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ @setAlignStack(16); \\} , - ".tmp_source.zig:5:5: error: @setAlignStack in inline function"); + ".tmp_source.zig:5:5: error: @setAlignStack in inline function", + ); - cases.add("@setAlignStack set twice", + cases.add( + "@setAlignStack set twice", \\export fn entry() void { \\ @setAlignStack(16); \\ @setAlignStack(16); \\} , ".tmp_source.zig:3:5: error: alignstack set twice", - ".tmp_source.zig:2:5: note: first set here"); + ".tmp_source.zig:2:5: note: first set here", + ); - cases.add("@setAlignStack too big", + cases.add( + "@setAlignStack too big", \\export fn entry() void { \\ @setAlignStack(511 + 1); \\} , - ".tmp_source.zig:2:5: error: attempt to @setAlignStack(512); maximum is 256"); + ".tmp_source.zig:2:5: error: attempt to @setAlignStack(512); maximum is 256", + ); - cases.add("storing runtime value in compile time variable then using it", + cases.add( + "storing runtime value in compile time variable then using it", \\const Mode = @import("builtin").Mode; \\ \\fn Free(comptime filename: []const u8) TestCase { @@ -2657,134 +4214,164 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ } \\} , - ".tmp_source.zig:37:16: error: cannot store runtime value in compile time variable"); + ".tmp_source.zig:37:16: error: cannot store runtime value in compile time variable", + ); - cases.add("field access of opaque type", + cases.add( + "field access of opaque type", \\const MyType = @OpaqueType(); \\ \\export fn entry() bool { \\ var x: i32 = 1; - \\ return bar(@ptrCast(&MyType, &x)); + \\ return bar(@ptrCast(*MyType, &x)); \\} \\ - \\fn bar(x: &MyType) bool { + \\fn bar(x: *MyType) bool { \\ return x.blah; \\} , - ".tmp_source.zig:9:13: error: type '&MyType' does not support field access"); + ".tmp_source.zig:9:13: error: type '*MyType' does not support field access", + ); - cases.add("carriage return special case", + cases.add( + "carriage return special case", "fn test() bool {\r\n" ++ - " true\r\n" ++ - "}\r\n" - , - ".tmp_source.zig:1:17: error: invalid carriage return, only '\\n' line endings are supported"); - - cases.add("non-printable invalid character", - "\xff\xfe" ++ - \\fn test() bool {\r - \\ true\r - \\} - , - ".tmp_source.zig:1:1: error: invalid character: '\\xff'"); + " true\r\n" ++ + "}\r\n", + ".tmp_source.zig:1:17: error: invalid carriage return, only '\\n' line endings are supported", + ); + + cases.add( + "non-printable invalid character", + "\xff\xfe" ++ + \\fn test() bool {\r + \\ true\r + \\} + , + ".tmp_source.zig:1:1: error: invalid character: '\\xff'", + ); - cases.add("non-printable invalid character with escape alternative", + cases.add( + "non-printable invalid character with escape alternative", "fn test() bool {\n" ++ - "\ttrue\n" ++ - "}\n" - , - ".tmp_source.zig:2:1: error: invalid character: '\\t'"); + "\ttrue\n" ++ + "}\n", + ".tmp_source.zig:2:1: error: invalid character: '\\t'", + ); - cases.add("@ArgType given non function parameter", + cases.add( + "@ArgType given non function parameter", \\comptime { \\ _ = @ArgType(i32, 3); \\} , - ".tmp_source.zig:2:18: error: expected function, found 'i32'"); + ".tmp_source.zig:2:18: error: expected function, found 'i32'", + ); - cases.add("@ArgType arg index out of bounds", + cases.add( + "@ArgType arg index out of bounds", \\comptime { \\ _ = @ArgType(@typeOf(add), 2); \\} \\fn add(a: i32, b: i32) i32 { return a + b; } , - ".tmp_source.zig:2:32: error: arg index 2 out of bounds; 'fn(i32, i32) i32' has 2 arguments"); + ".tmp_source.zig:2:32: error: arg index 2 out of bounds; 'fn(i32, i32) i32' has 2 arguments", + ); - cases.add("@memberType on unsupported type", + cases.add( + "@memberType on unsupported type", \\comptime { \\ _ = @memberType(i32, 0); \\} , - ".tmp_source.zig:2:21: error: type 'i32' does not support @memberType"); + ".tmp_source.zig:2:21: error: type 'i32' does not support @memberType", + ); - cases.add("@memberType on enum", + cases.add( + "@memberType on enum", \\comptime { \\ _ = @memberType(Foo, 0); \\} \\const Foo = enum {A,}; , - ".tmp_source.zig:2:21: error: type 'Foo' does not support @memberType"); + ".tmp_source.zig:2:21: error: type 'Foo' does not support @memberType", + ); - cases.add("@memberType struct out of bounds", + cases.add( + "@memberType struct out of bounds", \\comptime { \\ _ = @memberType(Foo, 0); \\} \\const Foo = struct {}; , - ".tmp_source.zig:2:26: error: member index 0 out of bounds; 'Foo' has 0 members"); + ".tmp_source.zig:2:26: error: member index 0 out of bounds; 'Foo' has 0 members", + ); - cases.add("@memberType union out of bounds", + cases.add( + "@memberType union out of bounds", \\comptime { \\ _ = @memberType(Foo, 1); \\} \\const Foo = union {A: void,}; , - ".tmp_source.zig:2:26: error: member index 1 out of bounds; 'Foo' has 1 members"); + ".tmp_source.zig:2:26: error: member index 1 out of bounds; 'Foo' has 1 members", + ); - cases.add("@memberName on unsupported type", + cases.add( + "@memberName on unsupported type", \\comptime { \\ _ = @memberName(i32, 0); \\} , - ".tmp_source.zig:2:21: error: type 'i32' does not support @memberName"); + ".tmp_source.zig:2:21: error: type 'i32' does not support @memberName", + ); - cases.add("@memberName struct out of bounds", + cases.add( + "@memberName struct out of bounds", \\comptime { \\ _ = @memberName(Foo, 0); \\} \\const Foo = struct {}; , - ".tmp_source.zig:2:26: error: member index 0 out of bounds; 'Foo' has 0 members"); + ".tmp_source.zig:2:26: error: member index 0 out of bounds; 'Foo' has 0 members", + ); - cases.add("@memberName enum out of bounds", + cases.add( + "@memberName enum out of bounds", \\comptime { \\ _ = @memberName(Foo, 1); \\} \\const Foo = enum {A,}; , - ".tmp_source.zig:2:26: error: member index 1 out of bounds; 'Foo' has 1 members"); + ".tmp_source.zig:2:26: error: member index 1 out of bounds; 'Foo' has 1 members", + ); - cases.add("@memberName union out of bounds", + cases.add( + "@memberName union out of bounds", \\comptime { \\ _ = @memberName(Foo, 1); \\} \\const Foo = union {A:i32,}; , - ".tmp_source.zig:2:26: error: member index 1 out of bounds; 'Foo' has 1 members"); + ".tmp_source.zig:2:26: error: member index 1 out of bounds; 'Foo' has 1 members", + ); - cases.add("calling var args extern function, passing array instead of pointer", + cases.add( + "calling var args extern function, passing array instead of pointer", \\export fn entry() void { - \\ foo("hello"); + \\ foo("hello",); \\} - \\pub extern fn foo(format: &const u8, ...) void; + \\pub extern fn foo(format: *const u8, ...) void; , - ".tmp_source.zig:2:9: error: expected type '&const u8', found '[5]u8'"); + ".tmp_source.zig:2:9: error: expected type '*const u8', found '[5]u8'", + ); - cases.add("constant inside comptime function has compile error", + cases.add( + "constant inside comptime function has compile error", \\const ContextAllocator = MemoryPool(usize); \\ \\pub fn MemoryPool(comptime T: type) type { - \\ const free_list_t = @compileError("aoeu"); + \\ const free_list_t = @compileError("aoeu",); \\ \\ return struct { \\ free_list: free_list_t, @@ -2797,9 +4384,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { , ".tmp_source.zig:4:25: error: aoeu", ".tmp_source.zig:1:36: note: called from here", - ".tmp_source.zig:12:20: note: referenced here"); + ".tmp_source.zig:12:20: note: referenced here", + ); - cases.add("specify enum tag type that is too small", + cases.add( + "specify enum tag type that is too small", \\const Small = enum (u2) { \\ One, \\ Two, @@ -2812,9 +4401,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ var x = Small.One; \\} , - ".tmp_source.zig:1:20: error: 'u2' too small to hold all bits; must be at least 'u3'"); + ".tmp_source.zig:1:20: error: 'u2' too small to hold all bits; must be at least 'u3'", + ); - cases.add("specify non-integer enum tag type", + cases.add( + "specify non-integer enum tag type", \\const Small = enum (f32) { \\ One, \\ Two, @@ -2825,9 +4416,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ var x = Small.One; \\} , - ".tmp_source.zig:1:20: error: expected integer, found 'f32'"); + ".tmp_source.zig:1:20: error: expected integer, found 'f32'", + ); - cases.add("implicitly casting enum to tag type", + cases.add( + "implicitly casting enum to tag type", \\const Small = enum(u2) { \\ One, \\ Two, @@ -2839,23 +4432,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ var x: u2 = Small.Two; \\} , - ".tmp_source.zig:9:22: error: expected type 'u2', found 'Small'"); - - cases.add("explicitly casting enum to non tag type", - \\const Small = enum(u2) { - \\ One, - \\ Two, - \\ Three, - \\ Four, - \\}; - \\ - \\export fn entry() void { - \\ var x = u3(Small.Two); - \\} - , - ".tmp_source.zig:9:15: error: enum to integer cast to 'u3' instead of its tag type, 'u2'"); + ".tmp_source.zig:9:22: error: expected type 'u2', found 'Small'", + ); - cases.add("explicitly casting non tag type to enum", + cases.add( + "explicitly casting non tag type to enum", \\const Small = enum(u2) { \\ One, \\ Two, @@ -2865,12 +4446,14 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ \\export fn entry() void { \\ var y = u3(3); - \\ var x = Small(y); + \\ var x = @intToEnum(Small, y); \\} , - ".tmp_source.zig:10:18: error: integer to enum cast from 'u3' instead of its tag type, 'u2'"); + ".tmp_source.zig:10:31: error: expected type 'u2', found 'u3'", + ); - cases.add("non unsigned integer enum tag type", + cases.add( + "non unsigned integer enum tag type", \\const Small = enum(i2) { \\ One, \\ Two, @@ -2882,9 +4465,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ var y = Small.Two; \\} , - ".tmp_source.zig:1:19: error: expected unsigned integer, found 'i2'"); + ".tmp_source.zig:1:19: error: expected unsigned integer, found 'i2'", + ); - cases.add("struct fields with value assignments", + cases.add( + "struct fields with value assignments", \\const MultipleChoice = struct { \\ A: i32 = 20, \\}; @@ -2892,9 +4477,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ var x: MultipleChoice = undefined; \\} , - ".tmp_source.zig:2:14: error: enums, not structs, support field assignment"); + ".tmp_source.zig:2:14: error: enums, not structs, support field assignment", + ); - cases.add("union fields with value assignments", + cases.add( + "union fields with value assignments", \\const MultipleChoice = union { \\ A: i32 = 20, \\}; @@ -2903,25 +4490,31 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\} , ".tmp_source.zig:2:14: error: non-enum union field assignment", - ".tmp_source.zig:1:24: note: consider 'union(enum)' here"); + ".tmp_source.zig:1:24: note: consider 'union(enum)' here", + ); - cases.add("enum with 0 fields", + cases.add( + "enum with 0 fields", \\const Foo = enum {}; \\export fn entry() usize { \\ return @sizeOf(Foo); \\} , - ".tmp_source.zig:1:13: error: enums must have 1 or more fields"); + ".tmp_source.zig:1:13: error: enums must have 1 or more fields", + ); - cases.add("union with 0 fields", + cases.add( + "union with 0 fields", \\const Foo = union {}; \\export fn entry() usize { \\ return @sizeOf(Foo); \\} , - ".tmp_source.zig:1:13: error: unions must have 1 or more fields"); + ".tmp_source.zig:1:13: error: unions must have 1 or more fields", + ); - cases.add("enum value already taken", + cases.add( + "enum value already taken", \\const MultipleChoice = enum(u32) { \\ A = 20, \\ B = 40, @@ -2934,9 +4527,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\} , ".tmp_source.zig:6:9: error: enum tag value 60 already taken", - ".tmp_source.zig:4:9: note: other occurrence here"); + ".tmp_source.zig:4:9: note: other occurrence here", + ); - cases.add("union with specified enum omits field", + cases.add( + "union with specified enum omits field", \\const Letter = enum { \\ A, \\ B, @@ -2951,9 +4546,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\} , ".tmp_source.zig:6:17: error: enum field missing: 'C'", - ".tmp_source.zig:4:5: note: declared here"); + ".tmp_source.zig:4:5: note: declared here", + ); - cases.add("@TagType when union has no attached enum", + cases.add( + "@TagType when union has no attached enum", \\const Foo = union { \\ A: i32, \\}; @@ -2962,9 +4559,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\} , ".tmp_source.zig:5:24: error: union 'Foo' has no tag", - ".tmp_source.zig:1:13: note: consider 'union(enum)' here"); + ".tmp_source.zig:1:13: note: consider 'union(enum)' here", + ); - cases.add("non-integer tag type to automatic union enum", + cases.add( + "non-integer tag type to automatic union enum", \\const Foo = union(enum(f32)) { \\ A: i32, \\}; @@ -2972,9 +4571,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ const x = @TagType(Foo); \\} , - ".tmp_source.zig:1:23: error: expected integer tag type, found 'f32'"); + ".tmp_source.zig:1:23: error: expected integer tag type, found 'f32'", + ); - cases.add("non-enum tag type passed to union", + cases.add( + "non-enum tag type passed to union", \\const Foo = union(u32) { \\ A: i32, \\}; @@ -2982,9 +4583,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ const x = @TagType(Foo); \\} , - ".tmp_source.zig:1:18: error: expected enum tag type, found 'u32'"); + ".tmp_source.zig:1:18: error: expected enum tag type, found 'u32'", + ); - cases.add("union auto-enum value already taken", + cases.add( + "union auto-enum value already taken", \\const MultipleChoice = union(enum(u32)) { \\ A = 20, \\ B = 40, @@ -2997,9 +4600,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\} , ".tmp_source.zig:6:9: error: enum tag value 60 already taken", - ".tmp_source.zig:4:9: note: other occurrence here"); + ".tmp_source.zig:4:9: note: other occurrence here", + ); - cases.add("union enum field does not match enum", + cases.add( + "union enum field does not match enum", \\const Letter = enum { \\ A, \\ B, @@ -3016,9 +4621,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\} , ".tmp_source.zig:10:5: error: enum field not found: 'D'", - ".tmp_source.zig:1:16: note: enum declared here"); + ".tmp_source.zig:1:16: note: enum declared here", + ); - cases.add("field type supplied in an enum", + cases.add( + "field type supplied in an enum", \\const Letter = enum { \\ A: void, \\ B, @@ -3029,9 +4636,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\} , ".tmp_source.zig:2:8: error: structs and unions, not enums, support field types", - ".tmp_source.zig:1:16: note: consider 'union(enum)' here"); + ".tmp_source.zig:1:16: note: consider 'union(enum)' here", + ); - cases.add("struct field missing type", + cases.add( + "struct field missing type", \\const Letter = struct { \\ A, \\}; @@ -3039,9 +4648,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ var a = Letter { .A = {} }; \\} , - ".tmp_source.zig:2:5: error: struct field missing type"); + ".tmp_source.zig:2:5: error: struct field missing type", + ); - cases.add("extern union field missing type", + cases.add( + "extern union field missing type", \\const Letter = extern union { \\ A, \\}; @@ -3049,9 +4660,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ var a = Letter { .A = {} }; \\} , - ".tmp_source.zig:2:5: error: union field missing type"); + ".tmp_source.zig:2:5: error: union field missing type", + ); - cases.add("extern union given enum tag type", + cases.add( + "extern union given enum tag type", \\const Letter = enum { \\ A, \\ B, @@ -3066,9 +4679,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ var a = Payload { .A = 1234 }; \\} , - ".tmp_source.zig:6:29: error: extern union does not support enum tag type"); + ".tmp_source.zig:6:29: error: extern union does not support enum tag type", + ); - cases.add("packed union given enum tag type", + cases.add( + "packed union given enum tag type", \\const Letter = enum { \\ A, \\ B, @@ -3083,9 +4698,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ var a = Payload { .A = 1234 }; \\} , - ".tmp_source.zig:6:29: error: packed union does not support enum tag type"); + ".tmp_source.zig:6:29: error: packed union does not support enum tag type", + ); - cases.add("switch on union with no attached enum", + cases.add( + "switch on union with no attached enum", \\const Payload = union { \\ A: i32, \\ B: f64, @@ -3095,29 +4712,33 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\ const a = Payload { .A = 1234 }; \\ foo(a); \\} - \\fn foo(a: &const Payload) void { - \\ switch (*a) { + \\fn foo(a: *const Payload) void { + \\ switch (a.*) { \\ Payload.A => {}, \\ else => unreachable, \\ } \\} , - ".tmp_source.zig:11:13: error: switch on union which has no attached enum", - ".tmp_source.zig:1:17: note: consider 'union(enum)' here"); + ".tmp_source.zig:11:14: error: switch on union which has no attached enum", + ".tmp_source.zig:1:17: note: consider 'union(enum)' here", + ); - cases.add("enum in field count range but not matching tag", + cases.add( + "enum in field count range but not matching tag", \\const Foo = enum(u32) { \\ A = 10, \\ B = 11, \\}; \\export fn entry() void { - \\ var x = Foo(0); + \\ var x = @intToEnum(Foo, 0); \\} , - ".tmp_source.zig:6:16: error: enum 'Foo' has no tag matching integer value 0", - ".tmp_source.zig:1:13: note: 'Foo' declared here"); + ".tmp_source.zig:6:13: error: enum 'Foo' has no tag matching integer value 0", + ".tmp_source.zig:1:13: note: 'Foo' declared here", + ); - cases.add("comptime cast enum to union but field has payload", + cases.add( + "comptime cast enum to union but field has payload", \\const Letter = enum { A, B, C }; \\const Value = union(Letter) { \\ A: i32, @@ -3129,9 +4750,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\} , ".tmp_source.zig:8:26: error: cast to union 'Value' must initialize 'i32' field 'A'", - ".tmp_source.zig:3:5: note: field 'A' declared here"); + ".tmp_source.zig:3:5: note: field 'A' declared here", + ); - cases.add("runtime cast to union which has non-void fields", + cases.add( + "runtime cast to union which has non-void fields", \\const Letter = enum { A, B, C }; \\const Value = union(Letter) { \\ A: i32, @@ -3146,27 +4769,52 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\} , ".tmp_source.zig:11:20: error: runtime cast to union 'Value' which has non-void fields", - ".tmp_source.zig:3:5: note: field 'A' has type 'i32'"); + ".tmp_source.zig:3:5: note: field 'A' has type 'i32'", + ); - cases.add("self-referencing function pointer field", - \\const S = struct { - \\ f: fn(_: S) void, + cases.add( + "taking offset of void field in struct", + \\const Empty = struct { + \\ val: void, \\}; - \\fn f(_: S) void { - \\} - \\export fn entry() void { - \\ var _ = S { .f = f }; + \\export fn foo() void { + \\ const fieldOffset = @offsetOf(Empty, "val",); \\} , - ".tmp_source.zig:4:9: error: type 'S' is not copyable; cannot pass by value"); + ".tmp_source.zig:5:42: error: zero-bit field 'val' in struct 'Empty' has no offset", + ); - cases.add("taking offset of void field in struct", - \\const Empty = struct { - \\ val: void, + cases.add( + "invalid union field access in comptime", + \\const Foo = union { + \\ Bar: u8, + \\ Baz: void, \\}; - \\export fn foo() void { - \\ const fieldOffset = @offsetOf(Empty, "val"); + \\comptime { + \\ var foo = Foo {.Baz = {}}; + \\ const bar_val = foo.Bar; + \\} + , + ".tmp_source.zig:7:24: error: accessing union field 'Bar' while field 'Baz' is set", + ); + + cases.add( + "getting return type of generic function", + \\fn generic(a: var) void {} + \\comptime { + \\ _ = @typeOf(generic).ReturnType; + \\} + , + ".tmp_source.zig:3:25: error: ReturnType has not been resolved because 'fn(var)var' is generic", + ); + + cases.add( + "getting @ArgType of generic function", + \\fn generic(a: var) void {} + \\comptime { + \\ _ = @ArgType(@typeOf(generic), 0); \\} , - ".tmp_source.zig:5:42: error: zero-bit field 'val' in struct 'Empty' has no offset"); + ".tmp_source.zig:3:36: error: @ArgType could not resolve the type of arg 0 because 'fn(var)var' is generic", + ); } diff --git a/test/gen_h.zig b/test/gen_h.zig index 30d168cf2c..b3aaa263d6 100644 --- a/test/gen_h.zig +++ b/test/gen_h.zig @@ -1,6 +1,6 @@ const tests = @import("tests.zig"); -pub fn addCases(cases: &tests.GenHContext) void { +pub fn addCases(cases: *tests.GenHContext) void { cases.add("declare enum", \\const Foo = extern enum { A, B, C }; \\export fn entry(foo: Foo) void { } @@ -54,7 +54,7 @@ pub fn addCases(cases: &tests.GenHContext) void { cases.add("declare opaque type", \\export const Foo = @OpaqueType(); \\ - \\export fn entry(foo: ?&Foo) void { } + \\export fn entry(foo: ?*Foo) void { } , \\struct Foo; \\ @@ -64,7 +64,7 @@ pub fn addCases(cases: &tests.GenHContext) void { cases.add("array field-type", \\const Foo = extern struct { \\ A: [2]i32, - \\ B: [4]&u32, + \\ B: [4]*u32, \\}; \\export fn entry(foo: Foo, bar: [3]u8) void { } , @@ -77,4 +77,50 @@ pub fn addCases(cases: &tests.GenHContext) void { \\ ); + cases.add("ptr to zig struct", + \\const S = struct { + \\ a: u8, + \\}; + \\ + \\export fn a(s: *S) u8 { + \\ return s.a; + \\} + + , + \\struct S; + \\TEST_EXPORT uint8_t a(struct S * s); + \\ + ); + + cases.add("ptr to zig union", + \\const U = union(enum) { + \\ A: u8, + \\ B: u16, + \\}; + \\ + \\export fn a(s: *U) u8 { + \\ return s.A; + \\} + + , + \\union U; + \\TEST_EXPORT uint8_t a(union U * s); + \\ + ); + + cases.add("ptr to zig enum", + \\const E = enum(u8) { + \\ A, + \\ B, + \\}; + \\ + \\export fn a(s: *E) u8 { + \\ return @enumToInt(s.*); + \\} + + , + \\enum E; + \\TEST_EXPORT uint8_t a(enum E * s); + \\ + ); } diff --git a/test/runtime_safety.zig b/test/runtime_safety.zig index 1fea6347ab..3d58dfe748 100644 --- a/test/runtime_safety.zig +++ b/test/runtime_safety.zig @@ -1,8 +1,65 @@ const tests = @import("tests.zig"); -pub fn addCases(cases: &tests.CompareOutputContext) void { +pub fn addCases(cases: *tests.CompareOutputContext) void { + cases.addRuntimeSafety("@intToEnum - no matching tag value", + \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { + \\ @import("std").os.exit(126); + \\} + \\const Foo = enum { + \\ A, + \\ B, + \\ C, + \\}; + \\pub fn main() void { + \\ baz(bar(3)); + \\} + \\fn bar(a: u2) Foo { + \\ return @intToEnum(Foo, a); + \\} + \\fn baz(a: Foo) void {} + ); + + cases.addRuntimeSafety("@floatToInt cannot fit - negative to unsigned", + \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { + \\ @import("std").os.exit(126); + \\} + \\pub fn main() void { + \\ baz(bar(-1.1)); + \\} + \\fn bar(a: f32) u8 { + \\ return @floatToInt(u8, a); + \\} + \\fn baz(a: u8) void { } + ); + + cases.addRuntimeSafety("@floatToInt cannot fit - negative out of range", + \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { + \\ @import("std").os.exit(126); + \\} + \\pub fn main() void { + \\ baz(bar(-129.1)); + \\} + \\fn bar(a: f32) i8 { + \\ return @floatToInt(i8, a); + \\} + \\fn baz(a: i8) void { } + ); + + cases.addRuntimeSafety("@floatToInt cannot fit - positive out of range", + \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { + \\ @import("std").os.exit(126); + \\} + \\pub fn main() void { + \\ baz(bar(256.2)); + \\} + \\fn bar(a: f32) u8 { + \\ return @floatToInt(u8, a); + \\} + \\fn baz(a: u8) void { } + ); + cases.addRuntimeSafety("calling panic", - \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { + \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { \\ @import("std").os.exit(126); \\} \\pub fn main() void { @@ -11,7 +68,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void { ); cases.addRuntimeSafety("out of bounds slice access", - \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { + \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { \\ @import("std").os.exit(126); \\} \\pub fn main() void { @@ -25,7 +82,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void { ); cases.addRuntimeSafety("integer addition overflow", - \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { + \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { \\ @import("std").os.exit(126); \\} \\pub fn main() !void { @@ -38,7 +95,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void { ); cases.addRuntimeSafety("integer subtraction overflow", - \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { + \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { \\ @import("std").os.exit(126); \\} \\pub fn main() !void { @@ -51,7 +108,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void { ); cases.addRuntimeSafety("integer multiplication overflow", - \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { + \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { \\ @import("std").os.exit(126); \\} \\pub fn main() !void { @@ -64,7 +121,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void { ); cases.addRuntimeSafety("integer negation overflow", - \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { + \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { \\ @import("std").os.exit(126); \\} \\pub fn main() !void { @@ -77,7 +134,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void { ); cases.addRuntimeSafety("signed integer division overflow", - \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { + \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { \\ @import("std").os.exit(126); \\} \\pub fn main() !void { @@ -90,7 +147,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void { ); cases.addRuntimeSafety("signed shift left overflow", - \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { + \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { \\ @import("std").os.exit(126); \\} \\pub fn main() !void { @@ -103,7 +160,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void { ); cases.addRuntimeSafety("unsigned shift left overflow", - \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { + \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { \\ @import("std").os.exit(126); \\} \\pub fn main() !void { @@ -116,7 +173,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void { ); cases.addRuntimeSafety("signed shift right overflow", - \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { + \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { \\ @import("std").os.exit(126); \\} \\pub fn main() !void { @@ -129,7 +186,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void { ); cases.addRuntimeSafety("unsigned shift right overflow", - \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { + \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { \\ @import("std").os.exit(126); \\} \\pub fn main() !void { @@ -142,7 +199,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void { ); cases.addRuntimeSafety("integer division by zero", - \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { + \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { \\ @import("std").os.exit(126); \\} \\pub fn main() void { @@ -154,7 +211,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void { ); cases.addRuntimeSafety("exact division failure", - \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { + \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { \\ @import("std").os.exit(126); \\} \\pub fn main() !void { @@ -167,7 +224,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void { ); cases.addRuntimeSafety("cast []u8 to bigger slice of wrong size", - \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { + \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { \\ @import("std").os.exit(126); \\} \\pub fn main() !void { @@ -175,12 +232,12 @@ pub fn addCases(cases: &tests.CompareOutputContext) void { \\ if (x.len == 0) return error.Whatever; \\} \\fn widenSlice(slice: []align(1) const u8) []align(1) const i32 { - \\ return ([]align(1) const i32)(slice); + \\ return @bytesToSlice(i32, slice); \\} ); cases.addRuntimeSafety("value does not fit in shortening cast", - \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { + \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { \\ @import("std").os.exit(126); \\} \\pub fn main() !void { @@ -188,12 +245,12 @@ pub fn addCases(cases: &tests.CompareOutputContext) void { \\ if (x == 0) return error.Whatever; \\} \\fn shorten_cast(x: i32) i8 { - \\ return i8(x); + \\ return @intCast(i8, x); \\} ); cases.addRuntimeSafety("signed integer not fitting in cast to unsigned integer", - \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { + \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { \\ @import("std").os.exit(126); \\} \\pub fn main() !void { @@ -201,12 +258,12 @@ pub fn addCases(cases: &tests.CompareOutputContext) void { \\ if (x == 0) return error.Whatever; \\} \\fn unsigned_cast(x: i32) u32 { - \\ return u32(x); + \\ return @intCast(u32, x); \\} ); cases.addRuntimeSafety("unwrap error", - \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { + \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { \\ if (@import("std").mem.eql(u8, message, "attempt to unwrap error: Whatever")) { \\ @import("std").os.exit(126); // good \\ } @@ -221,19 +278,19 @@ pub fn addCases(cases: &tests.CompareOutputContext) void { ); cases.addRuntimeSafety("cast integer to global error and no code matches", - \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { + \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { \\ @import("std").os.exit(126); \\} \\pub fn main() void { \\ _ = bar(9999); \\} - \\fn bar(x: u32) error { - \\ return error(x); + \\fn bar(x: u16) error { + \\ return @intToError(x); \\} ); - cases.addRuntimeSafety("cast integer to non-global error set and no match", - \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { + cases.addRuntimeSafety("@errSetCast error not present in destination", + \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { \\ @import("std").os.exit(126); \\} \\const Set1 = error{A, B}; @@ -242,28 +299,28 @@ pub fn addCases(cases: &tests.CompareOutputContext) void { \\ _ = foo(Set1.B); \\} \\fn foo(set1: Set1) Set2 { - \\ return Set2(set1); + \\ return @errSetCast(Set2, set1); \\} ); cases.addRuntimeSafety("@alignCast misaligned", - \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { + \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { \\ @import("std").os.exit(126); \\} \\pub fn main() !void { \\ var array align(4) = []u32{0x11111111, 0x11111111}; - \\ const bytes = ([]u8)(array[0..]); + \\ const bytes = @sliceToBytes(array[0..]); \\ if (foo(bytes) != 0x11111111) return error.Wrong; \\} \\fn foo(bytes: []u8) u32 { \\ const slice4 = bytes[1..5]; - \\ const int_slice = ([]u32)(@alignCast(4, slice4)); + \\ const int_slice = @bytesToSlice(u32, @alignCast(4, slice4)); \\ return int_slice[0]; \\} ); cases.addRuntimeSafety("bad union field access", - \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { + \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { \\ @import("std").os.exit(126); \\} \\ @@ -277,7 +334,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void { \\ bar(&f); \\} \\ - \\fn bar(f: &Foo) void { + \\fn bar(f: *Foo) void { \\ f.float = 12.34; \\} ); @@ -287,7 +344,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void { cases.addRuntimeSafety("error return trace across suspend points", \\const std = @import("std"); \\ - \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { + \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { \\ std.os.exit(126); \\} \\ diff --git a/test/stage2/compare_output.zig b/test/stage2/compare_output.zig new file mode 100644 index 0000000000..fdc3d49145 --- /dev/null +++ b/test/stage2/compare_output.zig @@ -0,0 +1,25 @@ +const std = @import("std"); +const TestContext = @import("../../src-self-hosted/test.zig").TestContext; + +pub fn addCases(ctx: *TestContext) !void { + // hello world + try ctx.testCompareOutputLibC( + \\extern fn puts([*]const u8) void; + \\export fn main() c_int { + \\ puts(c"Hello, world!"); + \\ return 0; + \\} + , "Hello, world!" ++ std.cstr.line_sep); + + // function calling another function + try ctx.testCompareOutputLibC( + \\extern fn puts(s: [*]const u8) void; + \\export fn main() c_int { + \\ return foo(c"OK"); + \\} + \\fn foo(s: [*]const u8) c_int { + \\ puts(s); + \\ return 0; + \\} + , "OK" ++ std.cstr.line_sep); +} diff --git a/test/stage2/compile_errors.zig b/test/stage2/compile_errors.zig new file mode 100644 index 0000000000..2cecd78653 --- /dev/null +++ b/test/stage2/compile_errors.zig @@ -0,0 +1,30 @@ +const TestContext = @import("../../src-self-hosted/test.zig").TestContext; + +pub fn addCases(ctx: *TestContext) !void { + try ctx.testCompileError( + \\export fn entry() void {} + \\export fn entry() void {} + , "1.zig", 2, 8, "exported symbol collision: 'entry'"); + + try ctx.testCompileError( + \\fn() void {} + , "1.zig", 1, 1, "missing function name"); + + try ctx.testCompileError( + \\comptime { + \\ return; + \\} + , "1.zig", 2, 5, "return expression outside function definition"); + + try ctx.testCompileError( + \\export fn entry() void { + \\ defer return; + \\} + , "1.zig", 2, 11, "cannot return from defer expression"); + + try ctx.testCompileError( + \\export fn entry() c_int { + \\ return 36893488147419103232; + \\} + , "1.zig", 2, 12, "integer value '36893488147419103232' cannot be stored in type 'c_int'"); +} diff --git a/test/standalone/brace_expansion/build.zig b/test/standalone/brace_expansion/build.zig index 7752f599df..64f3c08583 100644 --- a/test/standalone/brace_expansion/build.zig +++ b/test/standalone/brace_expansion/build.zig @@ -1,6 +1,6 @@ const Builder = @import("std").build.Builder; -pub fn build(b: &Builder) void { +pub fn build(b: *Builder) void { const main = b.addTest("main.zig"); main.setBuildMode(b.standardReleaseOptions()); diff --git a/test/standalone/brace_expansion/main.zig b/test/standalone/brace_expansion/main.zig index d4d86ae12c..ccb4f6dd45 100644 --- a/test/standalone/brace_expansion/main.zig +++ b/test/standalone/brace_expansion/main.zig @@ -14,9 +14,9 @@ const Token = union(enum) { Eof, }; -var global_allocator: &mem.Allocator = undefined; +var global_allocator: *mem.Allocator = undefined; -fn tokenize(input:[] const u8) !ArrayList(Token) { +fn tokenize(input: []const u8) !ArrayList(Token) { const State = enum { Start, Word, @@ -41,7 +41,7 @@ fn tokenize(input:[] const u8) !ArrayList(Token) { State.Word => switch (b) { 'a'...'z', 'A'...'Z' => {}, '{', '}', ',' => { - try token_list.append(Token { .Word = input[tok_begin..i] }); + try token_list.append(Token{ .Word = input[tok_begin..i] }); switch (b) { '{' => try token_list.append(Token.OpenBrace), '}' => try token_list.append(Token.CloseBrace), @@ -56,7 +56,7 @@ fn tokenize(input:[] const u8) !ArrayList(Token) { } switch (state) { State.Start => {}, - State.Word => try token_list.append(Token {.Word = input[tok_begin..] }), + State.Word => try token_list.append(Token{ .Word = input[tok_begin..] }), } try token_list.append(Token.Eof); return token_list; @@ -68,24 +68,24 @@ const Node = union(enum) { Combine: []Node, }; -const ParseError = error { +const ParseError = error{ InvalidInput, OutOfMemory, }; -fn parse(tokens: &const ArrayList(Token), token_index: &usize) ParseError!Node { - const first_token = tokens.items[*token_index]; - *token_index += 1; +fn parse(tokens: *const ArrayList(Token), token_index: *usize) ParseError!Node { + const first_token = tokens.items[token_index.*]; + token_index.* += 1; const result_node = switch (first_token) { - Token.Word => |word| Node { .Scalar = word }, + Token.Word => |word| Node{ .Scalar = word }, Token.OpenBrace => blk: { var list = ArrayList(Node).init(global_allocator); while (true) { try list.append(try parse(tokens, token_index)); - const token = tokens.items[*token_index]; - *token_index += 1; + const token = tokens.items[token_index.*]; + token_index.* += 1; switch (token) { Token.CloseBrace => break, @@ -93,23 +93,23 @@ fn parse(tokens: &const ArrayList(Token), token_index: &usize) ParseError!Node { else => return error.InvalidInput, } } - break :blk Node { .List = list }; + break :blk Node{ .List = list }; }, else => return error.InvalidInput, }; - switch (tokens.items[*token_index]) { + switch (tokens.items[token_index.*]) { Token.Word, Token.OpenBrace => { const pair = try global_allocator.alloc(Node, 2); pair[0] = result_node; pair[1] = try parse(tokens, token_index); - return Node { .Combine = pair }; + return Node{ .Combine = pair }; }, else => return result_node, } } -fn expandString(input: []const u8, output: &Buffer) !void { +fn expandString(input: []const u8, output: *Buffer) !void { const tokens = try tokenize(input); if (tokens.len == 1) { return output.resize(0); @@ -137,13 +137,11 @@ fn expandString(input: []const u8, output: &Buffer) !void { } } -const ExpandNodeError = error { - OutOfMemory, -}; +const ExpandNodeError = error{OutOfMemory}; -fn expandNode(node: &const Node, output: &ArrayList(Buffer)) ExpandNodeError!void { +fn expandNode(node: *const Node, output: *ArrayList(Buffer)) ExpandNodeError!void { assert(output.len == 0); - switch (*node) { + switch (node.*) { Node.Scalar => |scalar| { try output.append(try Buffer.init(global_allocator, scalar)); }, diff --git a/test/standalone/issue_339/build.zig b/test/standalone/issue_339/build.zig index f3ab327006..733b3729c1 100644 --- a/test/standalone/issue_339/build.zig +++ b/test/standalone/issue_339/build.zig @@ -1,6 +1,6 @@ const Builder = @import("std").build.Builder; -pub fn build(b: &Builder) void { +pub fn build(b: *Builder) void { const obj = b.addObject("test", "test.zig"); const test_step = b.step("test", "Test the program"); diff --git a/test/standalone/issue_339/test.zig b/test/standalone/issue_339/test.zig index f65b9f734e..f4068dcfac 100644 --- a/test/standalone/issue_339/test.zig +++ b/test/standalone/issue_339/test.zig @@ -1,5 +1,8 @@ const StackTrace = @import("builtin").StackTrace; -pub fn panic(msg: []const u8, stack_trace: ?&StackTrace) noreturn { @breakpoint(); while (true) {} } +pub fn panic(msg: []const u8, stack_trace: ?*StackTrace) noreturn { + @breakpoint(); + while (true) {} +} fn bar() error!void {} diff --git a/test/standalone/issue_794/build.zig b/test/standalone/issue_794/build.zig index 4f5dcd7ff4..06c37a83a3 100644 --- a/test/standalone/issue_794/build.zig +++ b/test/standalone/issue_794/build.zig @@ -1,6 +1,6 @@ const Builder = @import("std").build.Builder; -pub fn build(b: &Builder) void { +pub fn build(b: *Builder) void { const test_artifact = b.addTest("main.zig"); test_artifact.addIncludeDir("a_directory"); diff --git a/test/standalone/load_dynamic_library/add.zig b/test/standalone/load_dynamic_library/add.zig new file mode 100644 index 0000000000..a04ec1544d --- /dev/null +++ b/test/standalone/load_dynamic_library/add.zig @@ -0,0 +1,3 @@ +export fn add(a: i32, b: i32) i32 { + return a + b; +} diff --git a/test/standalone/load_dynamic_library/build.zig b/test/standalone/load_dynamic_library/build.zig new file mode 100644 index 0000000000..2d47a893f2 --- /dev/null +++ b/test/standalone/load_dynamic_library/build.zig @@ -0,0 +1,21 @@ +const Builder = @import("std").build.Builder; + +pub fn build(b: *Builder) void { + const opts = b.standardReleaseOptions(); + + const lib = b.addSharedLibrary("add", "add.zig", b.version(1, 0, 0)); + lib.setBuildMode(opts); + + const main = b.addExecutable("main", "main.zig"); + main.setBuildMode(opts); + + const run = b.addCommand(".", b.env_map, [][]const u8{ + main.getOutputPath(), + lib.getOutputPath(), + }); + run.step.dependOn(&lib.step); + run.step.dependOn(&main.step); + + const test_step = b.step("test", "Test the program"); + test_step.dependOn(&run.step); +} diff --git a/test/standalone/load_dynamic_library/main.zig b/test/standalone/load_dynamic_library/main.zig new file mode 100644 index 0000000000..4c45ad6fde --- /dev/null +++ b/test/standalone/load_dynamic_library/main.zig @@ -0,0 +1,17 @@ +const std = @import("std"); + +pub fn main() !void { + const args = try std.os.argsAlloc(std.debug.global_allocator); + defer std.os.argsFree(std.debug.global_allocator, args); + + const dynlib_name = args[1]; + + var lib = try std.DynLib.open(std.debug.global_allocator, dynlib_name); + defer lib.close(); + + const addr = lib.lookup("add") orelse return error.SymbolNotFound; + const addFn = @intToPtr(extern fn (i32, i32) i32, addr); + + const result = addFn(12, 34); + std.debug.assert(result == 46); +} diff --git a/test/standalone/pkg_import/build.zig b/test/standalone/pkg_import/build.zig index bb9416d3c4..e0b3885dc3 100644 --- a/test/standalone/pkg_import/build.zig +++ b/test/standalone/pkg_import/build.zig @@ -1,6 +1,6 @@ const Builder = @import("std").build.Builder; -pub fn build(b: &Builder) void { +pub fn build(b: *Builder) void { const exe = b.addExecutable("test", "test.zig"); exe.addPackagePath("my_pkg", "pkg.zig"); diff --git a/test/standalone/pkg_import/pkg.zig b/test/standalone/pkg_import/pkg.zig index abb977a2ef..19ab525b81 100644 --- a/test/standalone/pkg_import/pkg.zig +++ b/test/standalone/pkg_import/pkg.zig @@ -1 +1,3 @@ -pub fn add(a: i32, b: i32) i32 { return a + b; } +pub fn add(a: i32, b: i32) i32 { + return a + b; +} diff --git a/test/standalone/use_alias/build.zig b/test/standalone/use_alias/build.zig index ecbba297d8..c700d43db9 100644 --- a/test/standalone/use_alias/build.zig +++ b/test/standalone/use_alias/build.zig @@ -1,6 +1,6 @@ const Builder = @import("std").build.Builder; -pub fn build(b: &Builder) void { +pub fn build(b: *Builder) void { b.addCIncludePath("."); const main = b.addTest("main.zig"); diff --git a/test/standalone/use_alias/main.zig b/test/standalone/use_alias/main.zig index 40cab9ad8a..873393cef7 100644 --- a/test/standalone/use_alias/main.zig +++ b/test/standalone/use_alias/main.zig @@ -2,7 +2,7 @@ const c = @import("c.zig"); const assert = @import("std").debug.assert; test "symbol exists" { - var foo = c.Foo { + var foo = c.Foo{ .a = 1, .b = 1, }; diff --git a/test/tests.zig b/test/tests.zig index 19a4f82b74..aa5eed17ee 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -27,18 +27,18 @@ const TestTarget = struct { environ: builtin.Environ, }; -const test_targets = []TestTarget { - TestTarget { +const test_targets = []TestTarget{ + TestTarget{ .os = builtin.Os.linux, .arch = builtin.Arch.x86_64, .environ = builtin.Environ.gnu, }, - TestTarget { + TestTarget{ .os = builtin.Os.macosx, .arch = builtin.Arch.x86_64, .environ = builtin.Environ.unknown, }, - TestTarget { + TestTarget{ .os = builtin.Os.windows, .arch = builtin.Arch.x86_64, .environ = builtin.Environ.msvc, @@ -47,120 +47,117 @@ const test_targets = []TestTarget { const max_stdout_size = 1 * 1024 * 1024; // 1 MB -pub fn addCompareOutputTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step { - const cases = b.allocator.create(CompareOutputContext) catch unreachable; - *cases = CompareOutputContext { +pub fn addCompareOutputTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step { + const cases = b.allocator.create(CompareOutputContext{ .b = b, .step = b.step("test-compare-output", "Run the compare output tests"), .test_index = 0, .test_filter = test_filter, - }; + .modes = modes, + }) catch unreachable; compare_output.addCases(cases); return cases.step; } -pub fn addRuntimeSafetyTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step { - const cases = b.allocator.create(CompareOutputContext) catch unreachable; - *cases = CompareOutputContext { +pub fn addRuntimeSafetyTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step { + const cases = b.allocator.create(CompareOutputContext{ .b = b, .step = b.step("test-runtime-safety", "Run the runtime safety tests"), .test_index = 0, .test_filter = test_filter, - }; + .modes = modes, + }) catch unreachable; runtime_safety.addCases(cases); return cases.step; } -pub fn addCompileErrorTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step { - const cases = b.allocator.create(CompileErrorContext) catch unreachable; - *cases = CompileErrorContext { +pub fn addCompileErrorTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step { + const cases = b.allocator.create(CompileErrorContext{ .b = b, .step = b.step("test-compile-errors", "Run the compile error tests"), .test_index = 0, .test_filter = test_filter, - }; + .modes = modes, + }) catch unreachable; compile_errors.addCases(cases); return cases.step; } -pub fn addBuildExampleTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step { - const cases = b.allocator.create(BuildExamplesContext) catch unreachable; - *cases = BuildExamplesContext { +pub fn addBuildExampleTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step { + const cases = b.allocator.create(BuildExamplesContext{ .b = b, .step = b.step("test-build-examples", "Build the examples"), .test_index = 0, .test_filter = test_filter, - }; + .modes = modes, + }) catch unreachable; build_examples.addCases(cases); return cases.step; } -pub fn addAssembleAndLinkTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step { - const cases = b.allocator.create(CompareOutputContext) catch unreachable; - *cases = CompareOutputContext { +pub fn addAssembleAndLinkTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step { + const cases = b.allocator.create(CompareOutputContext{ .b = b, .step = b.step("test-asm-link", "Run the assemble and link tests"), .test_index = 0, .test_filter = test_filter, - }; + .modes = modes, + }) catch unreachable; assemble_and_link.addCases(cases); return cases.step; } -pub fn addTranslateCTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step { - const cases = b.allocator.create(TranslateCContext) catch unreachable; - *cases = TranslateCContext { +pub fn addTranslateCTests(b: *build.Builder, test_filter: ?[]const u8) *build.Step { + const cases = b.allocator.create(TranslateCContext{ .b = b, .step = b.step("test-translate-c", "Run the C transation tests"), .test_index = 0, .test_filter = test_filter, - }; + }) catch unreachable; translate_c.addCases(cases); return cases.step; } -pub fn addGenHTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step { - const cases = b.allocator.create(GenHContext) catch unreachable; - *cases = GenHContext { +pub fn addGenHTests(b: *build.Builder, test_filter: ?[]const u8) *build.Step { + const cases = b.allocator.create(GenHContext{ .b = b, .step = b.step("test-gen-h", "Run the C header file generation tests"), .test_index = 0, .test_filter = test_filter, - }; + }) catch unreachable; gen_h.addCases(cases); return cases.step; } - -pub fn addPkgTests(b: &build.Builder, test_filter: ?[]const u8, root_src: []const u8, - name:[] const u8, desc: []const u8, with_lldb: bool) &build.Step -{ +pub fn addPkgTests(b: *build.Builder, test_filter: ?[]const u8, root_src: []const u8, name: []const u8, desc: []const u8, modes: []const Mode) *build.Step { const step = b.step(b.fmt("test-{}", name), desc); for (test_targets) |test_target| { const is_native = (test_target.os == builtin.os and test_target.arch == builtin.arch); - for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast}) |mode| { - for ([]bool{false, true}) |link_libc| { + for (modes) |mode| { + for ([]bool{ + false, + true, + }) |link_libc| { if (link_libc and !is_native) { // don't assume we have a cross-compiling libc set up continue; } const these_tests = b.addTest(root_src); - these_tests.setNamePrefix(b.fmt("{}-{}-{}-{}-{} ", name, @tagName(test_target.os), - @tagName(test_target.arch), @tagName(mode), if (link_libc) "c" else "bare")); + these_tests.setNamePrefix(b.fmt("{}-{}-{}-{}-{} ", name, @tagName(test_target.os), @tagName(test_target.arch), @tagName(mode), if (link_libc) "c" else "bare")); these_tests.setFilter(test_filter); these_tests.setBuildMode(mode); if (!is_native) { @@ -169,10 +166,6 @@ pub fn addPkgTests(b: &build.Builder, test_filter: ?[]const u8, root_src: []cons if (link_libc) { these_tests.linkSystemLibrary("c"); } - if (with_lldb) { - these_tests.setExecCmd([]?[]const u8{ - "lldb", null, "-o", "run", "-o", "bt", "-o", "exit"}); - } step.dependOn(&these_tests.step); } } @@ -181,10 +174,11 @@ pub fn addPkgTests(b: &build.Builder, test_filter: ?[]const u8, root_src: []cons } pub const CompareOutputContext = struct { - b: &build.Builder, - step: &build.Step, + b: *build.Builder, + step: *build.Step, test_index: usize, test_filter: ?[]const u8, + modes: []const Mode, const Special = enum { None, @@ -205,34 +199,30 @@ pub const CompareOutputContext = struct { source: []const u8, }; - pub fn addSourceFile(self: &TestCase, filename: []const u8, source: []const u8) void { - self.sources.append(SourceFile { + pub fn addSourceFile(self: *TestCase, filename: []const u8, source: []const u8) void { + self.sources.append(SourceFile{ .filename = filename, .source = source, }) catch unreachable; } - pub fn setCommandLineArgs(self: &TestCase, args: []const []const u8) void { + pub fn setCommandLineArgs(self: *TestCase, args: []const []const u8) void { self.cli_args = args; } }; const RunCompareOutputStep = struct { step: build.Step, - context: &CompareOutputContext, + context: *CompareOutputContext, exe_path: []const u8, name: []const u8, expected_output: []const u8, test_index: usize, cli_args: []const []const u8, - pub fn create(context: &CompareOutputContext, exe_path: []const u8, - name: []const u8, expected_output: []const u8, - cli_args: []const []const u8) &RunCompareOutputStep - { + pub fn create(context: *CompareOutputContext, exe_path: []const u8, name: []const u8, expected_output: []const u8, cli_args: []const []const u8) *RunCompareOutputStep { const allocator = context.b.allocator; - const ptr = allocator.create(RunCompareOutputStep) catch unreachable; - *ptr = RunCompareOutputStep { + const ptr = allocator.create(RunCompareOutputStep{ .context = context, .exe_path = exe_path, .name = name, @@ -240,12 +230,12 @@ pub const CompareOutputContext = struct { .test_index = context.test_index, .step = build.Step.init("RunCompareOutput", allocator, make), .cli_args = cli_args, - }; + }) catch unreachable; context.test_index += 1; return ptr; } - fn make(step: &build.Step) !void { + fn make(step: *build.Step) !void { const self = @fieldParentPtr(RunCompareOutputStep, "step", step); const b = self.context.b; @@ -258,7 +248,7 @@ pub const CompareOutputContext = struct { args.append(arg) catch unreachable; } - warn("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name); + warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name); const child = os.ChildProcess.init(args.toSliceConst(), b.allocator) catch unreachable; defer child.deinit(); @@ -273,8 +263,8 @@ pub const CompareOutputContext = struct { var stdout = Buffer.initNull(b.allocator); var stderr = Buffer.initNull(b.allocator); - var stdout_file_in_stream = io.FileInStream.init(&??child.stdout); - var stderr_file_in_stream = io.FileInStream.init(&??child.stderr); + var stdout_file_in_stream = io.FileInStream.init(&child.stdout.?); + var stderr_file_in_stream = io.FileInStream.init(&child.stderr.?); stdout_file_in_stream.stream.readAllBuffer(&stdout, max_stdout_size) catch unreachable; stderr_file_in_stream.stream.readAllBuffer(&stderr, max_stdout_size) catch unreachable; @@ -295,7 +285,6 @@ pub const CompareOutputContext = struct { }, } - if (!mem.eql(u8, self.expected_output, stdout.toSliceConst())) { warn( \\ @@ -313,34 +302,32 @@ pub const CompareOutputContext = struct { const RuntimeSafetyRunStep = struct { step: build.Step, - context: &CompareOutputContext, + context: *CompareOutputContext, exe_path: []const u8, name: []const u8, test_index: usize, - pub fn create(context: &CompareOutputContext, exe_path: []const u8, - name: []const u8) &RuntimeSafetyRunStep - { + pub fn create(context: *CompareOutputContext, exe_path: []const u8, name: []const u8) *RuntimeSafetyRunStep { const allocator = context.b.allocator; - const ptr = allocator.create(RuntimeSafetyRunStep) catch unreachable; - *ptr = RuntimeSafetyRunStep { + const ptr = allocator.create(RuntimeSafetyRunStep{ .context = context, .exe_path = exe_path, .name = name, .test_index = context.test_index, .step = build.Step.init("RuntimeSafetyRun", allocator, make), - }; + }) catch unreachable; + context.test_index += 1; return ptr; } - fn make(step: &build.Step) !void { + fn make(step: *build.Step) !void { const self = @fieldParentPtr(RuntimeSafetyRunStep, "step", step); const b = self.context.b; const full_exe_path = b.pathFromRoot(self.exe_path); - warn("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name); + warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name); const child = os.ChildProcess.init([][]u8{full_exe_path}, b.allocator) catch unreachable; defer child.deinit(); @@ -358,19 +345,16 @@ pub const CompareOutputContext = struct { switch (term) { Term.Exited => |code| { if (code != expected_exit_code) { - warn("\nProgram expected to exit with code {} " ++ - "but exited with code {}\n", expected_exit_code, code); + warn("\nProgram expected to exit with code {} " ++ "but exited with code {}\n", expected_exit_code, code); return error.TestFailed; } }, Term.Signal => |sig| { - warn("\nProgram expected to exit with code {} " ++ - "but instead signaled {}\n", expected_exit_code, sig); + warn("\nProgram expected to exit with code {} " ++ "but instead signaled {}\n", expected_exit_code, sig); return error.TestFailed; }, else => { - warn("\nProgram expected to exit with code {}" ++ - " but exited in an unexpected way\n", expected_exit_code); + warn("\nProgram expected to exit with code {}" ++ " but exited in an unexpected way\n", expected_exit_code); return error.TestFailed; }, } @@ -379,10 +363,8 @@ pub const CompareOutputContext = struct { } }; - pub fn createExtra(self: &CompareOutputContext, name: []const u8, source: []const u8, - expected_output: []const u8, special: Special) TestCase - { - var tc = TestCase { + pub fn createExtra(self: *CompareOutputContext, name: []const u8, source: []const u8, expected_output: []const u8, special: Special) TestCase { + var tc = TestCase{ .name = name, .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator), .expected_output = expected_output, @@ -395,34 +377,32 @@ pub const CompareOutputContext = struct { return tc; } - pub fn create(self: &CompareOutputContext, name: []const u8, source: []const u8, - expected_output: []const u8) TestCase - { + pub fn create(self: *CompareOutputContext, name: []const u8, source: []const u8, expected_output: []const u8) TestCase { return createExtra(self, name, source, expected_output, Special.None); } - pub fn addC(self: &CompareOutputContext, name: []const u8, source: []const u8, expected_output: []const u8) void { + pub fn addC(self: *CompareOutputContext, name: []const u8, source: []const u8, expected_output: []const u8) void { var tc = self.create(name, source, expected_output); tc.link_libc = true; self.addCase(tc); } - pub fn add(self: &CompareOutputContext, name: []const u8, source: []const u8, expected_output: []const u8) void { + pub fn add(self: *CompareOutputContext, name: []const u8, source: []const u8, expected_output: []const u8) void { const tc = self.create(name, source, expected_output); self.addCase(tc); } - pub fn addAsm(self: &CompareOutputContext, name: []const u8, source: []const u8, expected_output: []const u8) void { + pub fn addAsm(self: *CompareOutputContext, name: []const u8, source: []const u8, expected_output: []const u8) void { const tc = self.createExtra(name, source, expected_output, Special.Asm); self.addCase(tc); } - pub fn addRuntimeSafety(self: &CompareOutputContext, name: []const u8, source: []const u8) void { + pub fn addRuntimeSafety(self: *CompareOutputContext, name: []const u8, source: []const u8) void { const tc = self.createExtra(name, source, undefined, Special.RuntimeSafety); self.addCase(tc); } - pub fn addCase(self: &CompareOutputContext, case: &const TestCase) void { + pub fn addCase(self: *CompareOutputContext, case: *const TestCase) void { const b = self.b; const root_src = os.path.join(b.allocator, b.cache_root, case.sources.items[0].filename) catch unreachable; @@ -431,8 +411,7 @@ pub const CompareOutputContext = struct { Special.Asm => { const annotated_case_name = fmt.allocPrint(self.b.allocator, "assemble-and-link {}", case.name) catch unreachable; if (self.test_filter) |filter| { - if (mem.indexOf(u8, annotated_case_name, filter) == null) - return; + if (mem.indexOf(u8, annotated_case_name, filter) == null) return; } const exe = b.addExecutable("test", null); @@ -444,19 +423,16 @@ pub const CompareOutputContext = struct { exe.step.dependOn(&write_src.step); } - const run_and_cmp_output = RunCompareOutputStep.create(self, exe.getOutputPath(), annotated_case_name, - case.expected_output, case.cli_args); + const run_and_cmp_output = RunCompareOutputStep.create(self, exe.getOutputPath(), annotated_case_name, case.expected_output, case.cli_args); run_and_cmp_output.step.dependOn(&exe.step); self.step.dependOn(&run_and_cmp_output.step); }, Special.None => { - for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast}) |mode| { - const annotated_case_name = fmt.allocPrint(self.b.allocator, "{} {} ({})", - "compare-output", case.name, @tagName(mode)) catch unreachable; + for (self.modes) |mode| { + const annotated_case_name = fmt.allocPrint(self.b.allocator, "{} {} ({})", "compare-output", case.name, @tagName(mode)) catch unreachable; if (self.test_filter) |filter| { - if (mem.indexOf(u8, annotated_case_name, filter) == null) - continue; + if (mem.indexOf(u8, annotated_case_name, filter) == null) continue; } const exe = b.addExecutable("test", root_src); @@ -471,8 +447,7 @@ pub const CompareOutputContext = struct { exe.step.dependOn(&write_src.step); } - const run_and_cmp_output = RunCompareOutputStep.create(self, exe.getOutputPath(), - annotated_case_name, case.expected_output, case.cli_args); + const run_and_cmp_output = RunCompareOutputStep.create(self, exe.getOutputPath(), annotated_case_name, case.expected_output, case.cli_args); run_and_cmp_output.step.dependOn(&exe.step); self.step.dependOn(&run_and_cmp_output.step); @@ -481,8 +456,7 @@ pub const CompareOutputContext = struct { Special.RuntimeSafety => { const annotated_case_name = fmt.allocPrint(self.b.allocator, "safety {}", case.name) catch unreachable; if (self.test_filter) |filter| { - if (mem.indexOf(u8, annotated_case_name, filter) == null) - return; + if (mem.indexOf(u8, annotated_case_name, filter) == null) return; } const exe = b.addExecutable("test", root_src); @@ -506,10 +480,11 @@ pub const CompareOutputContext = struct { }; pub const CompileErrorContext = struct { - b: &build.Builder, - step: &build.Step, + b: *build.Builder, + step: *build.Step, test_index: usize, test_filter: ?[]const u8, + modes: []const Mode, const TestCase = struct { name: []const u8, @@ -523,44 +498,42 @@ pub const CompileErrorContext = struct { source: []const u8, }; - pub fn addSourceFile(self: &TestCase, filename: []const u8, source: []const u8) void { - self.sources.append(SourceFile { + pub fn addSourceFile(self: *TestCase, filename: []const u8, source: []const u8) void { + self.sources.append(SourceFile{ .filename = filename, .source = source, }) catch unreachable; } - pub fn addExpectedError(self: &TestCase, text: []const u8) void { + pub fn addExpectedError(self: *TestCase, text: []const u8) void { self.expected_errors.append(text) catch unreachable; } }; const CompileCmpOutputStep = struct { step: build.Step, - context: &CompileErrorContext, + context: *CompileErrorContext, name: []const u8, test_index: usize, - case: &const TestCase, + case: *const TestCase, build_mode: Mode, - pub fn create(context: &CompileErrorContext, name: []const u8, - case: &const TestCase, build_mode: Mode) &CompileCmpOutputStep - { + pub fn create(context: *CompileErrorContext, name: []const u8, case: *const TestCase, build_mode: Mode) *CompileCmpOutputStep { const allocator = context.b.allocator; - const ptr = allocator.create(CompileCmpOutputStep) catch unreachable; - *ptr = CompileCmpOutputStep { + const ptr = allocator.create(CompileCmpOutputStep{ .step = build.Step.init("CompileCmpOutput", allocator, make), .context = context, .name = name, .test_index = context.test_index, .case = case, .build_mode = build_mode, - }; + }) catch unreachable; + context.test_index += 1; return ptr; } - fn make(step: &build.Step) !void { + fn make(step: *build.Step) !void { const self = @fieldParentPtr(CompileCmpOutputStep, "step", step); const b = self.context.b; @@ -583,9 +556,10 @@ pub const CompileErrorContext = struct { Mode.Debug => {}, Mode.ReleaseSafe => zig_args.append("--release-safe") catch unreachable, Mode.ReleaseFast => zig_args.append("--release-fast") catch unreachable, + Mode.ReleaseSmall => zig_args.append("--release-small") catch unreachable, } - warn("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name); + warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name); if (b.verbose) { printInvocation(zig_args.toSliceConst()); @@ -604,8 +578,8 @@ pub const CompileErrorContext = struct { var stdout_buf = Buffer.initNull(b.allocator); var stderr_buf = Buffer.initNull(b.allocator); - var stdout_file_in_stream = io.FileInStream.init(&??child.stdout); - var stderr_file_in_stream = io.FileInStream.init(&??child.stderr); + var stdout_file_in_stream = io.FileInStream.init(&child.stdout.?); + var stderr_file_in_stream = io.FileInStream.init(&child.stderr.?); stdout_file_in_stream.stream.readAllBuffer(&stdout_buf, max_stdout_size) catch unreachable; stderr_file_in_stream.stream.readAllBuffer(&stderr_buf, max_stdout_size) catch unreachable; @@ -625,7 +599,6 @@ pub const CompileErrorContext = struct { }, } - const stdout = stdout_buf.toSliceConst(); const stderr = stderr_buf.toSliceConst(); @@ -665,17 +638,15 @@ pub const CompileErrorContext = struct { warn("\n"); } - pub fn create(self: &CompileErrorContext, name: []const u8, source: []const u8, - expected_lines: ...) &TestCase - { - const tc = self.b.allocator.create(TestCase) catch unreachable; - *tc = TestCase { + pub fn create(self: *CompileErrorContext, name: []const u8, source: []const u8, expected_lines: ...) *TestCase { + const tc = self.b.allocator.create(TestCase{ .name = name, .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator), .expected_errors = ArrayList([]const u8).init(self.b.allocator), .link_libc = false, .is_exe = false, - }; + }) catch unreachable; + tc.addSourceFile(".tmp_source.zig", source); comptime var arg_i = 0; inline while (arg_i < expected_lines.len) : (arg_i += 1) { @@ -684,32 +655,30 @@ pub const CompileErrorContext = struct { return tc; } - pub fn addC(self: &CompileErrorContext, name: []const u8, source: []const u8, expected_lines: ...) void { + pub fn addC(self: *CompileErrorContext, name: []const u8, source: []const u8, expected_lines: ...) void { var tc = self.create(name, source, expected_lines); tc.link_libc = true; self.addCase(tc); } - pub fn addExe(self: &CompileErrorContext, name: []const u8, source: []const u8, expected_lines: ...) void { + pub fn addExe(self: *CompileErrorContext, name: []const u8, source: []const u8, expected_lines: ...) void { var tc = self.create(name, source, expected_lines); tc.is_exe = true; self.addCase(tc); } - pub fn add(self: &CompileErrorContext, name: []const u8, source: []const u8, expected_lines: ...) void { + pub fn add(self: *CompileErrorContext, name: []const u8, source: []const u8, expected_lines: ...) void { const tc = self.create(name, source, expected_lines); self.addCase(tc); } - pub fn addCase(self: &CompileErrorContext, case: &const TestCase) void { + pub fn addCase(self: *CompileErrorContext, case: *const TestCase) void { const b = self.b; - for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast}) |mode| { - const annotated_case_name = fmt.allocPrint(self.b.allocator, "compile-error {} ({})", - case.name, @tagName(mode)) catch unreachable; + for (self.modes) |mode| { + const annotated_case_name = fmt.allocPrint(self.b.allocator, "compile-error {} ({})", case.name, @tagName(mode)) catch unreachable; if (self.test_filter) |filter| { - if (mem.indexOf(u8, annotated_case_name, filter) == null) - continue; + if (mem.indexOf(u8, annotated_case_name, filter) == null) continue; } const compile_and_cmp_errors = CompileCmpOutputStep.create(self, annotated_case_name, case, mode); @@ -725,26 +694,26 @@ pub const CompileErrorContext = struct { }; pub const BuildExamplesContext = struct { - b: &build.Builder, - step: &build.Step, + b: *build.Builder, + step: *build.Step, test_index: usize, test_filter: ?[]const u8, + modes: []const Mode, - pub fn addC(self: &BuildExamplesContext, root_src: []const u8) void { + pub fn addC(self: *BuildExamplesContext, root_src: []const u8) void { self.addAllArgs(root_src, true); } - pub fn add(self: &BuildExamplesContext, root_src: []const u8) void { + pub fn add(self: *BuildExamplesContext, root_src: []const u8) void { self.addAllArgs(root_src, false); } - pub fn addBuildFile(self: &BuildExamplesContext, build_file: []const u8) void { + pub fn addBuildFile(self: *BuildExamplesContext, build_file: []const u8) void { const b = self.b; const annotated_case_name = b.fmt("build {} (Debug)", build_file); if (self.test_filter) |filter| { - if (mem.indexOf(u8, annotated_case_name, filter) == null) - return; + if (mem.indexOf(u8, annotated_case_name, filter) == null) return; } var zig_args = ArrayList([]const u8).init(b.allocator); @@ -769,15 +738,13 @@ pub const BuildExamplesContext = struct { self.step.dependOn(&log_step.step); } - pub fn addAllArgs(self: &BuildExamplesContext, root_src: []const u8, link_libc: bool) void { + pub fn addAllArgs(self: *BuildExamplesContext, root_src: []const u8, link_libc: bool) void { const b = self.b; - for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast}) |mode| { - const annotated_case_name = fmt.allocPrint(self.b.allocator, "build {} ({})", - root_src, @tagName(mode)) catch unreachable; + for (self.modes) |mode| { + const annotated_case_name = fmt.allocPrint(self.b.allocator, "build {} ({})", root_src, @tagName(mode)) catch unreachable; if (self.test_filter) |filter| { - if (mem.indexOf(u8, annotated_case_name, filter) == null) - continue; + if (mem.indexOf(u8, annotated_case_name, filter) == null) continue; } const exe = b.addExecutable("test", root_src); @@ -795,8 +762,8 @@ pub const BuildExamplesContext = struct { }; pub const TranslateCContext = struct { - b: &build.Builder, - step: &build.Step, + b: *build.Builder, + step: *build.Step, test_index: usize, test_filter: ?[]const u8, @@ -811,40 +778,40 @@ pub const TranslateCContext = struct { source: []const u8, }; - pub fn addSourceFile(self: &TestCase, filename: []const u8, source: []const u8) void { - self.sources.append(SourceFile { + pub fn addSourceFile(self: *TestCase, filename: []const u8, source: []const u8) void { + self.sources.append(SourceFile{ .filename = filename, .source = source, }) catch unreachable; } - pub fn addExpectedLine(self: &TestCase, text: []const u8) void { + pub fn addExpectedLine(self: *TestCase, text: []const u8) void { self.expected_lines.append(text) catch unreachable; } }; const TranslateCCmpOutputStep = struct { step: build.Step, - context: &TranslateCContext, + context: *TranslateCContext, name: []const u8, test_index: usize, - case: &const TestCase, + case: *const TestCase, - pub fn create(context: &TranslateCContext, name: []const u8, case: &const TestCase) &TranslateCCmpOutputStep { + pub fn create(context: *TranslateCContext, name: []const u8, case: *const TestCase) *TranslateCCmpOutputStep { const allocator = context.b.allocator; - const ptr = allocator.create(TranslateCCmpOutputStep) catch unreachable; - *ptr = TranslateCCmpOutputStep { + const ptr = allocator.create(TranslateCCmpOutputStep{ .step = build.Step.init("ParseCCmpOutput", allocator, make), .context = context, .name = name, .test_index = context.test_index, .case = case, - }; + }) catch unreachable; + context.test_index += 1; return ptr; } - fn make(step: &build.Step) !void { + fn make(step: *build.Step) !void { const self = @fieldParentPtr(TranslateCCmpOutputStep, "step", step); const b = self.context.b; @@ -856,7 +823,7 @@ pub const TranslateCContext = struct { zig_args.append("translate-c") catch unreachable; zig_args.append(b.pathFromRoot(root_src)) catch unreachable; - warn("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name); + warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name); if (b.verbose) { printInvocation(zig_args.toSliceConst()); @@ -875,8 +842,8 @@ pub const TranslateCContext = struct { var stdout_buf = Buffer.initNull(b.allocator); var stderr_buf = Buffer.initNull(b.allocator); - var stdout_file_in_stream = io.FileInStream.init(&??child.stdout); - var stderr_file_in_stream = io.FileInStream.init(&??child.stderr); + var stdout_file_in_stream = io.FileInStream.init(&child.stdout.?); + var stderr_file_in_stream = io.FileInStream.init(&child.stderr.?); stdout_file_in_stream.stream.readAllBuffer(&stdout_buf, max_stdout_size) catch unreachable; stderr_file_in_stream.stream.readAllBuffer(&stderr_buf, max_stdout_size) catch unreachable; @@ -938,16 +905,14 @@ pub const TranslateCContext = struct { warn("\n"); } - pub fn create(self: &TranslateCContext, allow_warnings: bool, filename: []const u8, name: []const u8, - source: []const u8, expected_lines: ...) &TestCase - { - const tc = self.b.allocator.create(TestCase) catch unreachable; - *tc = TestCase { + pub fn create(self: *TranslateCContext, allow_warnings: bool, filename: []const u8, name: []const u8, source: []const u8, expected_lines: ...) *TestCase { + const tc = self.b.allocator.create(TestCase{ .name = name, .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator), .expected_lines = ArrayList([]const u8).init(self.b.allocator), .allow_warnings = allow_warnings, - }; + }) catch unreachable; + tc.addSourceFile(filename, source); comptime var arg_i = 0; inline while (arg_i < expected_lines.len) : (arg_i += 1) { @@ -956,28 +921,27 @@ pub const TranslateCContext = struct { return tc; } - pub fn add(self: &TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void { + pub fn add(self: *TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void { const tc = self.create(false, "source.h", name, source, expected_lines); self.addCase(tc); } - pub fn addC(self: &TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void { + pub fn addC(self: *TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void { const tc = self.create(false, "source.c", name, source, expected_lines); self.addCase(tc); } - pub fn addAllowWarnings(self: &TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void { + pub fn addAllowWarnings(self: *TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void { const tc = self.create(true, "source.h", name, source, expected_lines); self.addCase(tc); } - pub fn addCase(self: &TranslateCContext, case: &const TestCase) void { + pub fn addCase(self: *TranslateCContext, case: *const TestCase) void { const b = self.b; const annotated_case_name = fmt.allocPrint(self.b.allocator, "translate-c {}", case.name) catch unreachable; if (self.test_filter) |filter| { - if (mem.indexOf(u8, annotated_case_name, filter) == null) - return; + if (mem.indexOf(u8, annotated_case_name, filter) == null) return; } const translate_c_and_cmp = TranslateCCmpOutputStep.create(self, annotated_case_name, case); @@ -992,8 +956,8 @@ pub const TranslateCContext = struct { }; pub const GenHContext = struct { - b: &build.Builder, - step: &build.Step, + b: *build.Builder, + step: *build.Step, test_index: usize, test_filter: ?[]const u8, @@ -1007,46 +971,46 @@ pub const GenHContext = struct { source: []const u8, }; - pub fn addSourceFile(self: &TestCase, filename: []const u8, source: []const u8) void { - self.sources.append(SourceFile { + pub fn addSourceFile(self: *TestCase, filename: []const u8, source: []const u8) void { + self.sources.append(SourceFile{ .filename = filename, .source = source, }) catch unreachable; } - pub fn addExpectedLine(self: &TestCase, text: []const u8) void { + pub fn addExpectedLine(self: *TestCase, text: []const u8) void { self.expected_lines.append(text) catch unreachable; } }; const GenHCmpOutputStep = struct { step: build.Step, - context: &GenHContext, + context: *GenHContext, h_path: []const u8, name: []const u8, test_index: usize, - case: &const TestCase, + case: *const TestCase, - pub fn create(context: &GenHContext, h_path: []const u8, name: []const u8, case: &const TestCase) &GenHCmpOutputStep { + pub fn create(context: *GenHContext, h_path: []const u8, name: []const u8, case: *const TestCase) *GenHCmpOutputStep { const allocator = context.b.allocator; - const ptr = allocator.create(GenHCmpOutputStep) catch unreachable; - *ptr = GenHCmpOutputStep { + const ptr = allocator.create(GenHCmpOutputStep{ .step = build.Step.init("ParseCCmpOutput", allocator, make), .context = context, .h_path = h_path, .name = name, .test_index = context.test_index, .case = case, - }; + }) catch unreachable; + context.test_index += 1; return ptr; } - fn make(step: &build.Step) !void { + fn make(step: *build.Step) !void { const self = @fieldParentPtr(GenHCmpOutputStep, "step", step); const b = self.context.b; - warn("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name); + warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name); const full_h_path = b.pathFromRoot(self.h_path); const actual_h = try io.readFileAlloc(b.allocator, full_h_path); @@ -1075,15 +1039,13 @@ pub const GenHContext = struct { warn("\n"); } - pub fn create(self: &GenHContext, filename: []const u8, name: []const u8, - source: []const u8, expected_lines: ...) &TestCase - { - const tc = self.b.allocator.create(TestCase) catch unreachable; - *tc = TestCase { + pub fn create(self: *GenHContext, filename: []const u8, name: []const u8, source: []const u8, expected_lines: ...) *TestCase { + const tc = self.b.allocator.create(TestCase{ .name = name, .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator), .expected_lines = ArrayList([]const u8).init(self.b.allocator), - }; + }) catch unreachable; + tc.addSourceFile(filename, source); comptime var arg_i = 0; inline while (arg_i < expected_lines.len) : (arg_i += 1) { @@ -1092,20 +1054,19 @@ pub const GenHContext = struct { return tc; } - pub fn add(self: &GenHContext, name: []const u8, source: []const u8, expected_lines: ...) void { + pub fn add(self: *GenHContext, name: []const u8, source: []const u8, expected_lines: ...) void { const tc = self.create("test.zig", name, source, expected_lines); self.addCase(tc); } - pub fn addCase(self: &GenHContext, case: &const TestCase) void { + pub fn addCase(self: *GenHContext, case: *const TestCase) void { const b = self.b; const root_src = os.path.join(b.allocator, b.cache_root, case.sources.items[0].filename) catch unreachable; const mode = builtin.Mode.Debug; const annotated_case_name = fmt.allocPrint(self.b.allocator, "gen-h {} ({})", case.name, @tagName(mode)) catch unreachable; if (self.test_filter) |filter| { - if (mem.indexOf(u8, annotated_case_name, filter) == null) - return; + if (mem.indexOf(u8, annotated_case_name, filter) == null) return; } const obj = b.addObject("test", root_src); diff --git a/test/translate_c.zig b/test/translate_c.zig index 9a69c2b03e..b31e515aa2 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -1,6 +1,72 @@ const tests = @import("tests.zig"); -pub fn addCases(cases: &tests.TranslateCContext) void { +pub fn addCases(cases: *tests.TranslateCContext) void { + cases.add("for loop with var init but empty body", + \\void foo(void) { + \\ for (int x = 0; x < 10; x++); + \\} + , + \\pub fn foo() void { + \\ { + \\ var x: c_int = 0; + \\ while (x < 10) : (x += 1) {} + \\ } + \\} + ); + + cases.add("do while with empty body", + \\void foo(void) { + \\ do ; while (1); + \\} + , // TODO this should be if (1 != 0) break + \\pub fn foo() void { + \\ while (true) { + \\ if (!1) break; + \\ } + \\} + ); + + cases.add("for with empty body", + \\void foo(void) { + \\ for (;;); + \\} + , + \\pub fn foo() void { + \\ while (true) {} + \\} + ); + + cases.add("while with empty body", + \\void foo(void) { + \\ while (1); + \\} + , + \\pub fn foo() void { + \\ while (1 != 0) {} + \\} + ); + + cases.add("double define struct", + \\typedef struct Bar Bar; + \\typedef struct Foo Foo; + \\ + \\struct Foo { + \\ Foo *a; + \\}; + \\ + \\struct Bar { + \\ Foo *a; + \\}; + , + \\pub const struct_Foo = extern struct { + \\ a: ?[*]Foo, + \\}; + \\pub const Foo = struct_Foo; + \\pub const struct_Bar = extern struct { + \\ a: ?[*]Foo, + \\}; + ); + cases.addAllowWarnings("simple data types", \\#include <stdint.h> \\int foo(char a, unsigned char b, signed char c); @@ -53,10 +119,32 @@ pub fn addCases(cases: &tests.TranslateCContext) void { \\pub const Foo = enum_Foo; ); + cases.add("enums", + \\enum Foo { + \\ FooA = 2, + \\ FooB = 5, + \\ Foo1, + \\}; + , + \\pub const enum_Foo = extern enum { + \\ A = 2, + \\ B = 5, + \\ @"1" = 6, + \\}; + , + \\pub const FooA = enum_Foo.A; + , + \\pub const FooB = enum_Foo.B; + , + \\pub const Foo1 = enum_Foo.@"1"; + , + \\pub const Foo = enum_Foo; + ); + cases.add("restrict -> noalias", \\void foo(void *restrict bar, void *restrict); , - \\pub extern fn foo(noalias bar: ?&c_void, noalias arg1: ?&c_void) void; + \\pub extern fn foo(noalias bar: ?*c_void, noalias arg1: ?*c_void) void; ); cases.add("simple struct", @@ -67,7 +155,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void { , \\const struct_Foo = extern struct { \\ x: c_int, - \\ y: ?&u8, + \\ y: ?[*]u8, \\}; , \\pub const Foo = struct_Foo; @@ -98,7 +186,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void { , \\pub const BarB = enum_Bar.B; , - \\pub extern fn func(a: ?&struct_Foo, b: ?&(?&enum_Bar)) void; + \\pub extern fn func(a: ?[*]struct_Foo, b: ?[*](?[*]enum_Bar)) void; , \\pub const Foo = struct_Foo; , @@ -108,7 +196,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void { cases.add("constant size array", \\void func(int array[20]); , - \\pub extern fn func(array: ?&c_int) void; + \\pub extern fn func(array: ?[*]c_int) void; ); cases.add("self referential struct with function pointer", @@ -117,7 +205,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void { \\}; , \\pub const struct_Foo = extern struct { - \\ derp: ?extern fn(?&struct_Foo) void, + \\ derp: ?extern fn(?[*]struct_Foo) void, \\}; , \\pub const Foo = struct_Foo; @@ -129,7 +217,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void { , \\pub const struct_Foo = @OpaqueType(); , - \\pub extern fn some_func(foo: ?&struct_Foo, x: c_int) ?&struct_Foo; + \\pub extern fn some_func(foo: ?*struct_Foo, x: c_int) ?*struct_Foo; , \\pub const Foo = struct_Foo; ); @@ -176,11 +264,11 @@ pub fn addCases(cases: &tests.TranslateCContext) void { \\}; , \\pub const struct_Bar = extern struct { - \\ next: ?&struct_Foo, + \\ next: ?[*]struct_Foo, \\}; , \\pub const struct_Foo = extern struct { - \\ next: ?&struct_Bar, + \\ next: ?[*]struct_Bar, \\}; ); @@ -190,7 +278,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void { , \\pub const Foo = c_void; , - \\pub extern fn fun(a: ?&Foo) Foo; + \\pub extern fn fun(a: ?*Foo) Foo; ); cases.add("generate inline func for #define global extern fn", @@ -203,13 +291,13 @@ pub fn addCases(cases: &tests.TranslateCContext) void { \\pub extern var fn_ptr: ?extern fn() void; , \\pub inline fn foo() void { - \\ return (??fn_ptr)(); + \\ return fn_ptr.?(); \\} , \\pub extern var fn_ptr2: ?extern fn(c_int, f32) u8; , \\pub inline fn bar(arg0: c_int, arg1: f32) u8 { - \\ return (??fn_ptr2)(arg0, arg1); + \\ return fn_ptr2.?(arg0, arg1); \\} ); @@ -462,7 +550,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void { \\ return 6; \\} , - \\pub export fn and_or_none_bool(a: c_int, b: f32, c: ?&c_void) c_int { + \\pub export fn and_or_none_bool(a: c_int, b: f32, c: ?*c_void) c_int { \\ if ((a != 0) and (b != 0)) return 0; \\ if ((b != 0) and (c != null)) return 1; \\ if ((a != 0) and (c != null)) return 2; @@ -564,8 +652,8 @@ pub fn addCases(cases: &tests.TranslateCContext) void { \\pub const struct_Foo = extern struct { \\ field: c_int, \\}; - \\pub export fn read_field(foo: ?&struct_Foo) c_int { - \\ return (??foo).field; + \\pub export fn read_field(foo: ?[*]struct_Foo) c_int { + \\ return foo.?.field; \\} ); @@ -595,7 +683,6 @@ pub fn addCases(cases: &tests.TranslateCContext) void { \\} ); - cases.addC("c style cast", \\int float_to_int(float a) { \\ return (int)a; @@ -611,8 +698,8 @@ pub fn addCases(cases: &tests.TranslateCContext) void { \\ return x; \\} , - \\pub export fn foo(x: ?&c_ushort) ?&c_void { - \\ return @ptrCast(?&c_void, x); + \\pub export fn foo(x: ?[*]c_ushort) ?*c_void { + \\ return @ptrCast(?*c_void, x); \\} ); @@ -632,7 +719,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void { \\ return 0; \\} , - \\pub export fn foo() ?&c_int { + \\pub export fn foo() ?[*]c_int { \\ return null; \\} ); @@ -677,43 +764,43 @@ pub fn addCases(cases: &tests.TranslateCContext) void { \\ var a: c_int = 0; \\ a += x: { \\ const _ref = &a; - \\ (*_ref) = ((*_ref) + 1); - \\ break :x *_ref; + \\ _ref.* = (_ref.* + 1); + \\ break :x _ref.*; \\ }; \\ a -= x: { \\ const _ref = &a; - \\ (*_ref) = ((*_ref) - 1); - \\ break :x *_ref; + \\ _ref.* = (_ref.* - 1); + \\ break :x _ref.*; \\ }; \\ a *= x: { \\ const _ref = &a; - \\ (*_ref) = ((*_ref) * 1); - \\ break :x *_ref; + \\ _ref.* = (_ref.* * 1); + \\ break :x _ref.*; \\ }; \\ a &= x: { \\ const _ref = &a; - \\ (*_ref) = ((*_ref) & 1); - \\ break :x *_ref; + \\ _ref.* = (_ref.* & 1); + \\ break :x _ref.*; \\ }; \\ a |= x: { \\ const _ref = &a; - \\ (*_ref) = ((*_ref) | 1); - \\ break :x *_ref; + \\ _ref.* = (_ref.* | 1); + \\ break :x _ref.*; \\ }; \\ a ^= x: { \\ const _ref = &a; - \\ (*_ref) = ((*_ref) ^ 1); - \\ break :x *_ref; + \\ _ref.* = (_ref.* ^ 1); + \\ break :x _ref.*; \\ }; \\ a >>= @import("std").math.Log2Int(c_int)(x: { \\ const _ref = &a; - \\ (*_ref) = ((*_ref) >> @import("std").math.Log2Int(c_int)(1)); - \\ break :x *_ref; + \\ _ref.* = (_ref.* >> @import("std").math.Log2Int(c_int)(1)); + \\ break :x _ref.*; \\ }); \\ a <<= @import("std").math.Log2Int(c_int)(x: { \\ const _ref = &a; - \\ (*_ref) = ((*_ref) << @import("std").math.Log2Int(c_int)(1)); - \\ break :x *_ref; + \\ _ref.* = (_ref.* << @import("std").math.Log2Int(c_int)(1)); + \\ break :x _ref.*; \\ }); \\} ); @@ -735,43 +822,43 @@ pub fn addCases(cases: &tests.TranslateCContext) void { \\ var a: c_uint = c_uint(0); \\ a +%= x: { \\ const _ref = &a; - \\ (*_ref) = ((*_ref) +% c_uint(1)); - \\ break :x *_ref; + \\ _ref.* = (_ref.* +% c_uint(1)); + \\ break :x _ref.*; \\ }; \\ a -%= x: { \\ const _ref = &a; - \\ (*_ref) = ((*_ref) -% c_uint(1)); - \\ break :x *_ref; + \\ _ref.* = (_ref.* -% c_uint(1)); + \\ break :x _ref.*; \\ }; \\ a *%= x: { \\ const _ref = &a; - \\ (*_ref) = ((*_ref) *% c_uint(1)); - \\ break :x *_ref; + \\ _ref.* = (_ref.* *% c_uint(1)); + \\ break :x _ref.*; \\ }; \\ a &= x: { \\ const _ref = &a; - \\ (*_ref) = ((*_ref) & c_uint(1)); - \\ break :x *_ref; + \\ _ref.* = (_ref.* & c_uint(1)); + \\ break :x _ref.*; \\ }; \\ a |= x: { \\ const _ref = &a; - \\ (*_ref) = ((*_ref) | c_uint(1)); - \\ break :x *_ref; + \\ _ref.* = (_ref.* | c_uint(1)); + \\ break :x _ref.*; \\ }; \\ a ^= x: { \\ const _ref = &a; - \\ (*_ref) = ((*_ref) ^ c_uint(1)); - \\ break :x *_ref; + \\ _ref.* = (_ref.* ^ c_uint(1)); + \\ break :x _ref.*; \\ }; \\ a >>= @import("std").math.Log2Int(c_uint)(x: { \\ const _ref = &a; - \\ (*_ref) = ((*_ref) >> @import("std").math.Log2Int(c_uint)(1)); - \\ break :x *_ref; + \\ _ref.* = (_ref.* >> @import("std").math.Log2Int(c_uint)(1)); + \\ break :x _ref.*; \\ }); \\ a <<= @import("std").math.Log2Int(c_uint)(x: { \\ const _ref = &a; - \\ (*_ref) = ((*_ref) << @import("std").math.Log2Int(c_uint)(1)); - \\ break :x *_ref; + \\ _ref.* = (_ref.* << @import("std").math.Log2Int(c_uint)(1)); + \\ break :x _ref.*; \\ }); \\} ); @@ -810,26 +897,26 @@ pub fn addCases(cases: &tests.TranslateCContext) void { \\ u -%= 1; \\ i = x: { \\ const _ref = &i; - \\ const _tmp = *_ref; - \\ (*_ref) += 1; + \\ const _tmp = _ref.*; + \\ _ref.* += 1; \\ break :x _tmp; \\ }; \\ i = x: { \\ const _ref = &i; - \\ const _tmp = *_ref; - \\ (*_ref) -= 1; + \\ const _tmp = _ref.*; + \\ _ref.* -= 1; \\ break :x _tmp; \\ }; \\ u = x: { \\ const _ref = &u; - \\ const _tmp = *_ref; - \\ (*_ref) +%= 1; + \\ const _tmp = _ref.*; + \\ _ref.* +%= 1; \\ break :x _tmp; \\ }; \\ u = x: { \\ const _ref = &u; - \\ const _tmp = *_ref; - \\ (*_ref) -%= 1; + \\ const _tmp = _ref.*; + \\ _ref.* -%= 1; \\ break :x _tmp; \\ }; \\} @@ -858,23 +945,23 @@ pub fn addCases(cases: &tests.TranslateCContext) void { \\ u -%= 1; \\ i = x: { \\ const _ref = &i; - \\ (*_ref) += 1; - \\ break :x *_ref; + \\ _ref.* += 1; + \\ break :x _ref.*; \\ }; \\ i = x: { \\ const _ref = &i; - \\ (*_ref) -= 1; - \\ break :x *_ref; + \\ _ref.* -= 1; + \\ break :x _ref.*; \\ }; \\ u = x: { \\ const _ref = &u; - \\ (*_ref) +%= 1; - \\ break :x *_ref; + \\ _ref.* +%= 1; + \\ break :x _ref.*; \\ }; \\ u = x: { \\ const _ref = &u; - \\ (*_ref) -%= 1; - \\ break :x *_ref; + \\ _ref.* -%= 1; + \\ break :x _ref.*; \\ }; \\} ); @@ -927,11 +1014,11 @@ pub fn addCases(cases: &tests.TranslateCContext) void { \\pub export fn bar() void { \\ var f: ?extern fn() void = foo; \\ var b: ?extern fn() c_int = baz; - \\ (??f)(); - \\ (??f)(); + \\ f.?(); + \\ f.?(); \\ foo(); - \\ _ = (??b)(); - \\ _ = (??b)(); + \\ _ = b.?(); + \\ _ = b.?(); \\ _ = baz(); \\} ); @@ -941,8 +1028,8 @@ pub fn addCases(cases: &tests.TranslateCContext) void { \\ *x = 1; \\} , - \\pub export fn foo(x: ?&c_int) void { - \\ (*??x) = 1; + \\pub export fn foo(x: ?[*]c_int) void { + \\ x.?.* = 1; \\} ); @@ -969,8 +1056,8 @@ pub fn addCases(cases: &tests.TranslateCContext) void { , \\pub fn foo() c_int { \\ var x: c_int = 1234; - \\ var ptr: ?&c_int = &x; - \\ return *??ptr; + \\ var ptr: ?[*]c_int = &x; + \\ return ptr.?.*; \\} ); @@ -979,7 +1066,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void { \\ return "bar"; \\} , - \\pub fn foo() ?&const u8 { + \\pub fn foo() ?[*]const u8 { \\ return c"bar"; \\} ); @@ -1077,7 +1164,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void { \\pub const glClearPFN = PFNGLCLEARPROC; , \\pub inline fn glClearUnion(arg0: GLbitfield) void { - \\ return (??glProcs.gl.Clear)(arg0); + \\ return glProcs.gl.Clear.?(arg0); \\} , \\pub const OpenGLProcs = union_OpenGLProcs; @@ -1108,8 +1195,8 @@ pub fn addCases(cases: &tests.TranslateCContext) void { \\ return (float *)a; \\} , - \\fn ptrcast(a: ?&c_int) ?&f32 { - \\ return @ptrCast(?&f32, a); + \\fn ptrcast(a: ?[*]c_int) ?[*]f32 { + \\ return @ptrCast(?[*]f32, a); \\} ); @@ -1131,7 +1218,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void { \\ return !c; \\} , - \\pub fn foo(a: c_int, b: f32, c: ?&c_void) c_int { + \\pub fn foo(a: c_int, b: f32, c: ?*c_void) c_int { \\ return !(a == 0); \\ return !(a != 0); \\ return !(b != 0); @@ -1152,7 +1239,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void { cases.add("const ptr initializer", \\static const char *v0 = "0.0.0"; , - \\pub var v0: ?&const u8 = c"0.0.0"; + \\pub var v0: ?[*]const u8 = c"0.0.0"; ); cases.add("static incomplete array inside function", @@ -1161,14 +1248,14 @@ pub fn addCases(cases: &tests.TranslateCContext) void { \\} , \\pub fn foo() void { - \\ const v2: &const u8 = c"2.2.2"; + \\ const v2: [*]const u8 = c"2.2.2"; \\} ); cases.add("macro pointer cast", \\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE) , - \\pub const NRF_GPIO = if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Pointer) @ptrCast(&NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Int) @intToPtr(&NRF_GPIO_Type, NRF_GPIO_BASE) else (&NRF_GPIO_Type)(NRF_GPIO_BASE); + \\pub const NRF_GPIO = if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Pointer) @ptrCast([*]NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Int) @intToPtr([*]NRF_GPIO_Type, NRF_GPIO_BASE) else ([*]NRF_GPIO_Type)(NRF_GPIO_BASE); ); cases.add("if on none bool", @@ -1189,7 +1276,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void { \\ B, \\ C, \\}; - \\pub fn if_none_bool(a: c_int, b: f32, c: ?&c_void, d: enum_SomeEnum) c_int { + \\pub fn if_none_bool(a: c_int, b: f32, c: ?*c_void, d: enum_SomeEnum) c_int { \\ if (a != 0) return 0; \\ if (b != 0) return 1; \\ if (c != null) return 2; @@ -1206,7 +1293,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void { \\ return 3; \\} , - \\pub fn while_none_bool(a: c_int, b: f32, c: ?&c_void) c_int { + \\pub fn while_none_bool(a: c_int, b: f32, c: ?*c_void) c_int { \\ while (a != 0) return 0; \\ while (b != 0) return 1; \\ while (c != null) return 2; @@ -1222,7 +1309,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void { \\ return 3; \\} , - \\pub fn for_none_bool(a: c_int, b: f32, c: ?&c_void) c_int { + \\pub fn for_none_bool(a: c_int, b: f32, c: ?*c_void) c_int { \\ while (a != 0) return 0; \\ while (b != 0) return 1; \\ while (c != null) return 2; @@ -1246,29 +1333,29 @@ pub fn addCases(cases: &tests.TranslateCContext) void { \\ } \\} , - \\pub fn switch_fn(i: c_int) c_int { - \\ var res: c_int = 0; - \\ __switch: { - \\ __case_2: { - \\ __default: { - \\ __case_1: { - \\ __case_0: { - \\ switch (i) { - \\ 0 => break :__case_0, - \\ 1 => break :__case_1, - \\ else => break :__default, - \\ 2 => break :__case_2, - \\ } - \\ } - \\ res = 1; - \\ } - \\ res = 2; - \\ } - \\ res = (3 * i); - \\ break :__switch; - \\ } - \\ res = 5; - \\ } - \\} + \\pub fn switch_fn(i: c_int) c_int { + \\ var res: c_int = 0; + \\ __switch: { + \\ __case_2: { + \\ __default: { + \\ __case_1: { + \\ __case_0: { + \\ switch (i) { + \\ 0 => break :__case_0, + \\ 1 => break :__case_1, + \\ else => break :__default, + \\ 2 => break :__case_2, + \\ } + \\ } + \\ res = 1; + \\ } + \\ res = 2; + \\ } + \\ res = (3 * i); + \\ break :__switch; + \\ } + \\ res = 5; + \\ } + \\} ); } |
