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/cases | |
| parent | 06614b3fa09954464c2e2f32756cacedc178a282 (diff) | |
| parent | 63a23e848a62d5f167f8d5478de9766cb24aa6eb (diff) | |
| download | zig-d2f5e57b68da0b16e5789ca19045ccbcb4ecfa8d.tar.gz zig-d2f5e57b68da0b16e5789ca19045ccbcb4ecfa8d.zip | |
Merge branch 'master' into zen_stdlib
Diffstat (limited to 'test/cases')
62 files changed, 2979 insertions, 896 deletions
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); +} |
