Commit 2c9a5e791b
Changed files (22)
test/behavior/align.zig
@@ -204,3 +204,229 @@ test "function alignment" {
noop1();
noop4();
}
+
+test "implicitly decreasing fn alignment" {
+ if (builtin.zig_backend == .stage1) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
+
+ // function alignment is a compile error on wasm32/wasm64
+ if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;
+
+ try testImplicitlyDecreaseFnAlign(alignedSmall, 1234);
+ try testImplicitlyDecreaseFnAlign(alignedBig, 5678);
+}
+
+// TODO make it a compile error to put align on the fn proto instead of on the ptr
+fn testImplicitlyDecreaseFnAlign(ptr: *align(1) const fn () i32, answer: i32) !void {
+ try expect(ptr() == answer);
+}
+
+fn alignedSmall() align(8) i32 {
+ return 1234;
+}
+fn alignedBig() align(16) i32 {
+ return 5678;
+}
+
+test "@alignCast functions" {
+ if (builtin.zig_backend == .stage1) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
+
+ // function alignment is a compile error on wasm32/wasm64
+ if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;
+ if (native_arch == .thumb) return error.SkipZigTest;
+
+ try expect(fnExpectsOnly1(simple4) == 0x19);
+}
+fn fnExpectsOnly1(ptr: *const fn () align(1) i32) i32 {
+ return fnExpects4(@alignCast(4, ptr));
+}
+fn fnExpects4(ptr: *align(4) const fn () i32) i32 {
+ return ptr();
+}
+fn simple4() align(4) i32 {
+ return 0x19;
+}
+
+test "generic function with align param" {
+ if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
+
+ // function alignment is a compile error on wasm32/wasm64
+ if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;
+ if (native_arch == .thumb) return error.SkipZigTest;
+
+ try expect(whyWouldYouEverDoThis(1) == 0x1);
+ try expect(whyWouldYouEverDoThis(4) == 0x1);
+ try expect(whyWouldYouEverDoThis(8) == 0x1);
+}
+
+fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 {
+ _ = align_bytes;
+ return 0x1;
+}
+
+test "runtime known array index has best alignment possible" {
+ if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
+
+ // take full advantage of over-alignment
+ var array align(4) = [_]u8{ 1, 2, 3, 4 };
+ try expect(@TypeOf(&array[0]) == *align(4) u8);
+ try expect(@TypeOf(&array[1]) == *u8);
+ try expect(@TypeOf(&array[2]) == *align(2) u8);
+ try expect(@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 };
+ try expect(@TypeOf(&bigger[0]) == *align(2) u64);
+ try expect(@TypeOf(&bigger[1]) == *align(2) u64);
+ try expect(@TypeOf(&bigger[2]) == *align(2) u64);
+ try expect(@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 };
+ var runtime_zero: usize = 0;
+ comptime try expect(@TypeOf(smaller[runtime_zero..]) == []align(2) u32);
+ comptime try expect(@TypeOf(smaller[runtime_zero..].ptr) == [*]align(2) u32);
+ try testIndex(smaller[runtime_zero..].ptr, 0, *align(2) u32);
+ try testIndex(smaller[runtime_zero..].ptr, 1, *align(2) u32);
+ try testIndex(smaller[runtime_zero..].ptr, 2, *align(2) u32);
+ try testIndex(smaller[runtime_zero..].ptr, 3, *align(2) u32);
+
+ // has to use ABI alignment because index known at runtime only
+ try testIndex2(array[runtime_zero..].ptr, 0, *u8);
+ try testIndex2(array[runtime_zero..].ptr, 1, *u8);
+ try testIndex2(array[runtime_zero..].ptr, 2, *u8);
+ try testIndex2(array[runtime_zero..].ptr, 3, *u8);
+}
+fn testIndex(smaller: [*]align(2) u32, index: usize, comptime T: type) !void {
+ comptime try expect(@TypeOf(&smaller[index]) == T);
+}
+fn testIndex2(ptr: [*]align(4) u8, index: usize, comptime T: type) !void {
+ comptime try expect(@TypeOf(&ptr[index]) == T);
+}
+
+test "alignment of function with c calling convention" {
+ if (builtin.zig_backend == .stage1) return error.SkipZigTest;
+
+ var runtime_nothing = ¬hing;
+ const casted1 = @ptrCast(*const u8, runtime_nothing);
+ const casted2 = @ptrCast(*const fn () callconv(.C) void, casted1);
+ casted2();
+}
+
+fn nothing() callconv(.C) void {}
+
+const DefaultAligned = struct {
+ nevermind: u32,
+ badguy: i128,
+};
+
+test "read 128-bit field from default aligned struct in stack memory" {
+ if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
+
+ var default_aligned = DefaultAligned{
+ .nevermind = 1,
+ .badguy = 12,
+ };
+ try expect((@ptrToInt(&default_aligned.badguy) % 16) == 0);
+ try expect(12 == default_aligned.badguy);
+}
+
+var default_aligned_global = DefaultAligned{
+ .nevermind = 1,
+ .badguy = 12,
+};
+
+test "read 128-bit field from default aligned struct in global memory" {
+ if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
+
+ try expect((@ptrToInt(&default_aligned_global.badguy) % 16) == 0);
+ try expect(12 == default_aligned_global.badguy);
+}
+
+test "struct field explicit alignment" {
+ if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
+
+ const S = struct {
+ const Node = struct {
+ next: *Node,
+ massive_byte: u8 align(64),
+ };
+ };
+
+ var node: S.Node = undefined;
+ node.massive_byte = 100;
+ try expect(node.massive_byte == 100);
+ comptime try expect(@TypeOf(&node.massive_byte) == *align(64) u8);
+ try expect(@ptrToInt(&node.massive_byte) % 64 == 0);
+}
+
+test "align(@alignOf(T)) T does not force resolution of T" {
+ if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
+
+ const S = struct {
+ const A = struct {
+ a: *align(@alignOf(A)) A,
+ };
+ fn doTheTest() void {
+ suspend {
+ resume @frame();
+ }
+ _ = bar(@Frame(doTheTest));
+ }
+ fn bar(comptime T: type) *align(@alignOf(T)) T {
+ ok = true;
+ return undefined;
+ }
+
+ var ok = false;
+ };
+ _ = async S.doTheTest();
+ try expect(S.ok);
+}
+
+test "align(N) on functions" {
+ if (builtin.zig_backend == .stage1) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
+
+ // function alignment is a compile error on wasm32/wasm64
+ if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;
+ if (native_arch == .thumb) return error.SkipZigTest;
+
+ try expect((@ptrToInt(&overaligned_fn) & (0x1000 - 1)) == 0);
+}
+fn overaligned_fn() align(0x1000) i32 {
+ return 42;
+}
test/behavior/align_stage1.zig
@@ -1,174 +0,0 @@
-const std = @import("std");
-const expect = std.testing.expect;
-const builtin = @import("builtin");
-const native_arch = builtin.target.cpu.arch;
-
-test "implicitly decreasing fn alignment" {
- // function alignment is a compile error on wasm32/wasm64
- if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;
-
- try testImplicitlyDecreaseFnAlign(alignedSmall, 1234);
- try testImplicitlyDecreaseFnAlign(alignedBig, 5678);
-}
-
-fn testImplicitlyDecreaseFnAlign(ptr: fn () align(1) i32, answer: i32) !void {
- try expect(ptr() == answer);
-}
-
-fn alignedSmall() align(8) i32 {
- return 1234;
-}
-fn alignedBig() align(16) i32 {
- return 5678;
-}
-
-test "@alignCast functions" {
- // function alignment is a compile error on wasm32/wasm64
- if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;
- if (native_arch == .thumb) return error.SkipZigTest;
-
- try expect(fnExpectsOnly1(simple4) == 0x19);
-}
-fn fnExpectsOnly1(ptr: fn () align(1) i32) i32 {
- return fnExpects4(@alignCast(4, ptr));
-}
-fn fnExpects4(ptr: fn () align(4) i32) i32 {
- return ptr();
-}
-fn simple4() align(4) i32 {
- return 0x19;
-}
-
-test "generic function with align param" {
- // function alignment is a compile error on wasm32/wasm64
- if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;
- if (native_arch == .thumb) return error.SkipZigTest;
-
- try expect(whyWouldYouEverDoThis(1) == 0x1);
- try expect(whyWouldYouEverDoThis(4) == 0x1);
- try expect(whyWouldYouEverDoThis(8) == 0x1);
-}
-
-fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 {
- _ = align_bytes;
- return 0x1;
-}
-
-test "runtime known array index has best alignment possible" {
- // take full advantage of over-alignment
- var array align(4) = [_]u8{ 1, 2, 3, 4 };
- try expect(@TypeOf(&array[0]) == *align(4) u8);
- try expect(@TypeOf(&array[1]) == *u8);
- try expect(@TypeOf(&array[2]) == *align(2) u8);
- try expect(@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 };
- try expect(@TypeOf(&bigger[0]) == *align(2) u64);
- try expect(@TypeOf(&bigger[1]) == *align(2) u64);
- try expect(@TypeOf(&bigger[2]) == *align(2) u64);
- try expect(@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 };
- var runtime_zero: usize = 0;
- comptime try expect(@TypeOf(smaller[runtime_zero..]) == []align(2) u32);
- comptime try expect(@TypeOf(smaller[runtime_zero..].ptr) == [*]align(2) u32);
- try testIndex(smaller[runtime_zero..].ptr, 0, *align(2) u32);
- try testIndex(smaller[runtime_zero..].ptr, 1, *align(2) u32);
- try testIndex(smaller[runtime_zero..].ptr, 2, *align(2) u32);
- try testIndex(smaller[runtime_zero..].ptr, 3, *align(2) u32);
-
- // has to use ABI alignment because index known at runtime only
- try testIndex2(array[runtime_zero..].ptr, 0, *u8);
- try testIndex2(array[runtime_zero..].ptr, 1, *u8);
- try testIndex2(array[runtime_zero..].ptr, 2, *u8);
- try testIndex2(array[runtime_zero..].ptr, 3, *u8);
-}
-fn testIndex(smaller: [*]align(2) u32, index: usize, comptime T: type) !void {
- comptime try expect(@TypeOf(&smaller[index]) == T);
-}
-fn testIndex2(ptr: [*]align(4) u8, index: usize, comptime T: type) !void {
- comptime try expect(@TypeOf(&ptr[index]) == T);
-}
-
-test "alignment of function with c calling convention" {
- var runtime_nothing = nothing;
- const casted1 = @ptrCast(*const u8, runtime_nothing);
- const casted2 = @ptrCast(fn () callconv(.C) void, casted1);
- casted2();
-}
-
-fn nothing() callconv(.C) void {}
-
-const DefaultAligned = struct {
- nevermind: u32,
- badguy: i128,
-};
-
-test "read 128-bit field from default aligned struct in stack memory" {
- var default_aligned = DefaultAligned{
- .nevermind = 1,
- .badguy = 12,
- };
- try expect((@ptrToInt(&default_aligned.badguy) % 16) == 0);
- try expect(12 == default_aligned.badguy);
-}
-
-var default_aligned_global = DefaultAligned{
- .nevermind = 1,
- .badguy = 12,
-};
-
-test "read 128-bit field from default aligned struct in global memory" {
- try expect((@ptrToInt(&default_aligned_global.badguy) % 16) == 0);
- try expect(12 == default_aligned_global.badguy);
-}
-
-test "struct field explicit alignment" {
- const S = struct {
- const Node = struct {
- next: *Node,
- massive_byte: u8 align(64),
- };
- };
-
- var node: S.Node = undefined;
- node.massive_byte = 100;
- try expect(node.massive_byte == 100);
- comptime try expect(@TypeOf(&node.massive_byte) == *align(64) u8);
- try expect(@ptrToInt(&node.massive_byte) % 64 == 0);
-}
-
-test "align(@alignOf(T)) T does not force resolution of T" {
- const S = struct {
- const A = struct {
- a: *align(@alignOf(A)) A,
- };
- fn doTheTest() void {
- suspend {
- resume @frame();
- }
- _ = bar(@Frame(doTheTest));
- }
- fn bar(comptime T: type) *align(@alignOf(T)) T {
- ok = true;
- return undefined;
- }
-
- var ok = false;
- };
- _ = async S.doTheTest();
- try expect(S.ok);
-}
-
-test "align(N) on functions" {
- // function alignment is a compile error on wasm32/wasm64
- if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;
- if (native_arch == .thumb) return error.SkipZigTest;
-
- try expect((@ptrToInt(overaligned_fn) & (0x1000 - 1)) == 0);
-}
-fn overaligned_fn() align(0x1000) i32 {
- return 42;
-}
test/behavior/basic.zig
@@ -294,3 +294,402 @@ test "const ptr from var variable" {
fn copy(src: *const u64, dst: *u64) void {
dst.* = src.*;
}
+
+test "call result of if else expression" {
+ if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
+
+ try expect(mem.eql(u8, f2(true), "a"));
+ try expect(mem.eql(u8, f2(false), "b"));
+}
+fn f2(x: bool) []const u8 {
+ return (if (x) fA else fB)();
+}
+
+test "memcpy and memset intrinsics" {
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
+
+ try testMemcpyMemset();
+ // TODO add comptime test coverage
+ //comptime try testMemcpyMemset();
+}
+
+fn testMemcpyMemset() !void {
+ var foo: [20]u8 = undefined;
+ var bar: [20]u8 = undefined;
+
+ @memset(&foo, 'A', foo.len);
+ @memcpy(&bar, &foo, bar.len);
+
+ try expect(bar[0] == 'A');
+ try expect(bar[11] == 'A');
+ try expect(bar[19] == 'A');
+}
+
+test "variable is allowed to be a pointer to an opaque type" {
+ if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
+
+ var x: i32 = 1234;
+ _ = hereIsAnOpaqueType(@ptrCast(*OpaqueA, &x));
+}
+fn hereIsAnOpaqueType(ptr: *OpaqueA) *OpaqueA {
+ var a = ptr;
+ return a;
+}
+
+test "take address of parameter" {
+ try testTakeAddressOfParameter(12.34);
+}
+fn testTakeAddressOfParameter(f: f32) !void {
+ const f_ptr = &f;
+ try expect(f_ptr.* == 12.34);
+}
+
+test "pointer to void return type" {
+ if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
+
+ try testPointerToVoidReturnType();
+}
+fn testPointerToVoidReturnType() anyerror!void {
+ const a = testPointerToVoidReturnType2();
+ return a.*;
+}
+const test_pointer_to_void_return_type_x = void{};
+fn testPointerToVoidReturnType2() *const void {
+ return &test_pointer_to_void_return_type_x;
+}
+
+test "array 2D const double ptr" {
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
+
+ const rect_2d_vertexes = [_][1]f32{
+ [_]f32{1.0},
+ [_]f32{2.0},
+ };
+ try testArray2DConstDoublePtr(&rect_2d_vertexes[0][0]);
+}
+
+fn testArray2DConstDoublePtr(ptr: *const f32) !void {
+ const ptr2 = @ptrCast([*]const f32, ptr);
+ try expect(ptr2[0] == 1.0);
+ try expect(ptr2[1] == 2.0);
+}
+
+test "double implicit cast in same expression" {
+ var x = @as(i32, @as(u16, nine()));
+ try expect(x == 9);
+}
+fn nine() u8 {
+ return 9;
+}
+
+test "struct inside function" {
+ try testStructInFn();
+ comptime try testStructInFn();
+}
+
+fn testStructInFn() !void {
+ const BlockKind = u32;
+
+ const Block = struct {
+ kind: BlockKind,
+ };
+
+ var block = Block{ .kind = 1234 };
+
+ block.kind += 1;
+
+ try expect(block.kind == 1235);
+}
+
+test "fn call returning scalar optional in equality expression" {
+ try expect(getNull() == null);
+}
+
+fn getNull() ?*i32 {
+ return null;
+}
+
+test "global variable assignment with optional unwrapping with var initialized to undefined" {
+ const S = struct {
+ var data: i32 = 1234;
+ fn foo() ?*i32 {
+ return &data;
+ }
+ };
+ global_foo = S.foo() orelse {
+ @panic("bad");
+ };
+ try expect(global_foo.* == 1234);
+}
+
+var global_foo: *i32 = undefined;
+
+test "peer result location with typed parent, runtime condition, comptime prongs" {
+ const S = struct {
+ fn doTheTest(arg: i32) i32 {
+ const st = Structy{
+ .bleh = if (arg == 1) 1 else 1,
+ };
+
+ if (st.bleh == 1)
+ return 1234;
+ return 0;
+ }
+
+ const Structy = struct {
+ bleh: i32,
+ };
+ };
+ try expect(S.doTheTest(0) == 1234);
+ try expect(S.doTheTest(1) == 1234);
+}
+
+test "non-ambiguous reference of shadowed decls" {
+ try expect(ZA().B().Self != ZA().Self);
+}
+
+fn ZA() type {
+ return struct {
+ b: B(),
+
+ const Self = @This();
+
+ fn B() type {
+ return struct {
+ const Self = @This();
+ };
+ }
+ };
+}
+
+test "use of declaration with same name as primitive" {
+ const S = struct {
+ const @"u8" = u16;
+ const alias = @"u8";
+ };
+ const a: S.u8 = 300;
+ try expect(a == 300);
+
+ const b: S.alias = 300;
+ try expect(b == 300);
+
+ const @"u8" = u16;
+ const c: @"u8" = 300;
+ try expect(c == 300);
+}
+
+test "constant equal function pointers" {
+ const alias = emptyFn;
+ try expect(comptime x: {
+ break :x emptyFn == alias;
+ });
+}
+
+fn emptyFn() void {}
+
+const addr1 = @ptrCast(*const u8, &emptyFn);
+test "comptime cast fn to ptr" {
+ if (builtin.zig_backend == .stage1) return error.SkipZigTest;
+
+ const addr2 = @ptrCast(*const u8, &emptyFn);
+ comptime try expect(addr1 == addr2);
+}
+
+test "equality compare fn ptrs" {
+ if (builtin.zig_backend == .stage1) return error.SkipZigTest;
+
+ var a = &emptyFn;
+ try expect(a == a);
+}
+
+test "self reference through fn ptr field" {
+ if (builtin.zig_backend == .stage1) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+
+ const S = struct {
+ const A = struct {
+ f: *const fn (A) u8,
+ };
+
+ fn foo(a: A) u8 {
+ _ = a;
+ return 12;
+ }
+ };
+ var a: S.A = undefined;
+ a.f = S.foo;
+ try expect(a.f(a) == 12);
+}
+
+test "global variable initialized to global variable array element" {
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
+
+ try expect(global_ptr == &gdt[0]);
+}
+const GDTEntry = struct {
+ field: i32,
+};
+var gdt = [_]GDTEntry{
+ GDTEntry{ .field = 1 },
+ GDTEntry{ .field = 2 },
+};
+var global_ptr = &gdt[0];
+
+test "global constant is loaded with a runtime-known index" {
+ const S = struct {
+ fn doTheTest() !void {
+ var index: usize = 1;
+ const ptr = &pieces[index].field;
+ try expect(ptr.* == 2);
+ }
+ const Piece = struct {
+ field: i32,
+ };
+ const pieces = [_]Piece{ Piece{ .field = 1 }, Piece{ .field = 2 }, Piece{ .field = 3 } };
+ };
+ try S.doTheTest();
+}
+
+test "multiline string literal is null terminated" {
+ const s1 =
+ \\one
+ \\two)
+ \\three
+ ;
+ const s2 = "one\ntwo)\nthree";
+ try expect(std.cstr.cmp(s1, s2) == 0);
+}
+
+test "string escapes" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ try expectEqualStrings("\"", "\x22");
+ try expectEqualStrings("\'", "\x27");
+ try expectEqualStrings("\n", "\x0a");
+ try expectEqualStrings("\r", "\x0d");
+ try expectEqualStrings("\t", "\x09");
+ try expectEqualStrings("\\", "\x5c");
+ try expectEqualStrings("\u{1234}\u{069}\u{1}", "\xe1\x88\xb4\x69\x01");
+}
+
+test "explicit cast optional pointers" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ const a: ?*i32 = undefined;
+ const b: ?*f32 = @ptrCast(?*f32, a);
+ _ = b;
+}
+
+test "pointer comparison" {
+ const a = @as([]const u8, "a");
+ const b = &a;
+ try expect(ptrEql(b, b));
+}
+fn ptrEql(a: *const []const u8, b: *const []const u8) bool {
+ return a == b;
+}
+
+test "string concatenation" {
+ const a = "OK" ++ " IT " ++ "WORKED";
+ const b = "OK IT WORKED";
+
+ comptime try expect(@TypeOf(a) == *const [12:0]u8);
+ comptime try expect(@TypeOf(b) == *const [12:0]u8);
+
+ const len = mem.len(b);
+ const len_with_null = len + 1;
+ {
+ var i: u32 = 0;
+ while (i < len_with_null) : (i += 1) {
+ try expect(a[i] == b[i]);
+ }
+ }
+ try expect(a[len] == 0);
+ try expect(b[len] == 0);
+}
+
+test "thread local variable" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ const S = struct {
+ threadlocal var t: i32 = 1234;
+ };
+ S.t += 1;
+ try expect(S.t == 1235);
+}
+
+test "result location is optional inside error union" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ const x = maybe(true) catch unreachable;
+ try expect(x.? == 42);
+}
+
+fn maybe(x: bool) anyerror!?u32 {
+ return switch (x) {
+ true => @as(u32, 42),
+ else => null,
+ };
+}
+
+test "pointer to thread local array" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ const s = "Hello world";
+ std.mem.copy(u8, buffer[0..], s);
+ try std.testing.expectEqualSlices(u8, buffer[0..], s);
+}
+
+threadlocal var buffer: [11]u8 = undefined;
+
+test "auto created variables have correct alignment" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ const S = struct {
+ fn foo(str: [*]const u8) u32 {
+ for (@ptrCast([*]align(1) const u32, str)[0..1]) |v| {
+ return v;
+ }
+ return 0;
+ }
+ };
+ try expect(S.foo("\x7a\x7a\x7a\x7a") == 0x7a7a7a7a);
+ comptime try expect(S.foo("\x7a\x7a\x7a\x7a") == 0x7a7a7a7a);
+}
+
+test "extern variable with non-pointer opaque type" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ @export(var_to_export, .{ .name = "opaque_extern_var" });
+ try expect(@ptrCast(*align(1) u32, &opaque_extern_var).* == 42);
+}
+extern var opaque_extern_var: opaque {};
+var var_to_export: u32 = 42;
+
+test "lazy typeInfo value as generic parameter" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ const S = struct {
+ fn foo(args: anytype) void {
+ _ = args;
+ }
+ };
+ S.foo(@typeInfo(@TypeOf(.{})));
+}
+
+test "variable name containing underscores does not shadow int primitive" {
+ const _u0 = 0;
+ const i_8 = 0;
+ const u16_ = 0;
+ const i3_2 = 0;
+ const u6__4 = 0;
+ const i2_04_8 = 0;
+
+ _ = _u0;
+ _ = i_8;
+ _ = u16_;
+ _ = i3_2;
+ _ = u6__4;
+ _ = i2_04_8;
+}
test/behavior/basic_llvm.zig
@@ -1,250 +0,0 @@
-const std = @import("std");
-const builtin = @import("builtin");
-const mem = std.mem;
-const expect = std.testing.expect;
-const expectEqualStrings = std.testing.expectEqualStrings;
-
-test "call result of if else expression" {
- try expect(mem.eql(u8, f2(true), "a"));
- try expect(mem.eql(u8, f2(false), "b"));
-}
-fn f2(x: bool) []const u8 {
- return (if (x) fA else fB)();
-}
-fn fA() []const u8 {
- return "a";
-}
-fn fB() []const u8 {
- return "b";
-}
-
-test "memcpy and memset intrinsics" {
- try testMemcpyMemset();
- // TODO add comptime test coverage
- //comptime try testMemcpyMemset();
-}
-
-fn testMemcpyMemset() !void {
- var foo: [20]u8 = undefined;
- var bar: [20]u8 = undefined;
-
- @memset(&foo, 'A', foo.len);
- @memcpy(&bar, &foo, bar.len);
-
- try expect(bar[0] == 'A');
- try expect(bar[11] == 'A');
- try expect(bar[19] == 'A');
-}
-
-const OpaqueA = opaque {};
-const OpaqueB = opaque {};
-
-test "variable is allowed to be a pointer to an opaque type" {
- var x: i32 = 1234;
- _ = hereIsAnOpaqueType(@ptrCast(*OpaqueA, &x));
-}
-fn hereIsAnOpaqueType(ptr: *OpaqueA) *OpaqueA {
- var a = ptr;
- return a;
-}
-
-test "take address of parameter" {
- try testTakeAddressOfParameter(12.34);
-}
-fn testTakeAddressOfParameter(f: f32) !void {
- const f_ptr = &f;
- try expect(f_ptr.* == 12.34);
-}
-
-test "pointer to void return type" {
- try testPointerToVoidReturnType();
-}
-fn testPointerToVoidReturnType() anyerror!void {
- const a = testPointerToVoidReturnType2();
- return a.*;
-}
-const test_pointer_to_void_return_type_x = void{};
-fn testPointerToVoidReturnType2() *const void {
- return &test_pointer_to_void_return_type_x;
-}
-
-test "array 2D const double ptr" {
- const rect_2d_vertexes = [_][1]f32{
- [_]f32{1.0},
- [_]f32{2.0},
- };
- try testArray2DConstDoublePtr(&rect_2d_vertexes[0][0]);
-}
-
-fn testArray2DConstDoublePtr(ptr: *const f32) !void {
- const ptr2 = @ptrCast([*]const f32, ptr);
- try expect(ptr2[0] == 1.0);
- try expect(ptr2[1] == 2.0);
-}
-
-test "double implicit cast in same expression" {
- var x = @as(i32, @as(u16, nine()));
- try expect(x == 9);
-}
-fn nine() u8 {
- return 9;
-}
-
-test "struct inside function" {
- try testStructInFn();
- comptime try testStructInFn();
-}
-
-fn testStructInFn() !void {
- const BlockKind = u32;
-
- const Block = struct {
- kind: BlockKind,
- };
-
- var block = Block{ .kind = 1234 };
-
- block.kind += 1;
-
- try expect(block.kind == 1235);
-}
-
-test "fn call returning scalar optional in equality expression" {
- try expect(getNull() == null);
-}
-
-fn getNull() ?*i32 {
- return null;
-}
-
-var global_foo: *i32 = undefined;
-
-test "global variable assignment with optional unwrapping with var initialized to undefined" {
- const S = struct {
- var data: i32 = 1234;
- fn foo() ?*i32 {
- return &data;
- }
- };
- global_foo = S.foo() orelse {
- @panic("bad");
- };
- try expect(global_foo.* == 1234);
-}
-
-test "peer result location with typed parent, runtime condition, comptime prongs" {
- const S = struct {
- fn doTheTest(arg: i32) i32 {
- const st = Structy{
- .bleh = if (arg == 1) 1 else 1,
- };
-
- if (st.bleh == 1)
- return 1234;
- return 0;
- }
-
- const Structy = struct {
- bleh: i32,
- };
- };
- try expect(S.doTheTest(0) == 1234);
- try expect(S.doTheTest(1) == 1234);
-}
-
-fn ZA() type {
- return struct {
- b: B(),
-
- const Self = @This();
-
- fn B() type {
- return struct {
- const Self = @This();
- };
- }
- };
-}
-test "non-ambiguous reference of shadowed decls" {
- try expect(ZA().B().Self != ZA().Self);
-}
-
-test "use of declaration with same name as primitive" {
- const S = struct {
- const @"u8" = u16;
- const alias = @"u8";
- };
- const a: S.u8 = 300;
- try expect(a == 300);
-
- const b: S.alias = 300;
- try expect(b == 300);
-
- const @"u8" = u16;
- const c: @"u8" = 300;
- try expect(c == 300);
-}
-
-fn emptyFn() void {}
-
-test "constant equal function pointers" {
- const alias = emptyFn;
- try expect(comptime x: {
- break :x emptyFn == alias;
- });
-}
-
-test "multiline string literal is null terminated" {
- const s1 =
- \\one
- \\two)
- \\three
- ;
- const s2 = "one\ntwo)\nthree";
- try expect(std.cstr.cmp(s1, s2) == 0);
-}
-
-test "self reference through fn ptr field" {
- if (builtin.zig_backend == .stage1) return error.SkipZigTest;
-
- const S = struct {
- const A = struct {
- f: *const fn (A) u8,
- };
-
- fn foo(a: A) u8 {
- _ = a;
- return 12;
- }
- };
- var a: S.A = undefined;
- a.f = S.foo;
- try expect(a.f(a) == 12);
-}
-
-test "global variable initialized to global variable array element" {
- try expect(global_ptr == &gdt[0]);
-}
-const GDTEntry = struct {
- field: i32,
-};
-var gdt = [_]GDTEntry{
- GDTEntry{ .field = 1 },
- GDTEntry{ .field = 2 },
-};
-var global_ptr = &gdt[0];
-
-test "global constant is loaded with a runtime-known index" {
- const S = struct {
- fn doTheTest() !void {
- var index: usize = 1;
- const ptr = &pieces[index].field;
- try expect(ptr.* == 2);
- }
- const Piece = struct {
- field: i32,
- };
- const pieces = [_]Piece{ Piece{ .field = 1 }, Piece{ .field = 2 }, Piece{ .field = 3 } };
- };
- try S.doTheTest();
-}
test/behavior/bitcast.zig
@@ -70,3 +70,166 @@ test "bitcast generates a temporary value" {
const x = @bitCast(u16, @bitCast([2]u8, y));
try expect(y == x);
}
+
+test "@bitCast packed structs at runtime and comptime" {
+ if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
+
+ const Full = packed struct {
+ number: u16,
+ };
+ const Divided = packed struct {
+ half1: u8,
+ quarter3: u4,
+ quarter4: u4,
+ };
+ const S = struct {
+ fn doTheTest() !void {
+ var full = Full{ .number = 0x1234 };
+ var two_halves = @bitCast(Divided, full);
+ switch (native_endian) {
+ .Big => {
+ try expect(two_halves.half1 == 0x12);
+ try expect(two_halves.quarter3 == 0x3);
+ try expect(two_halves.quarter4 == 0x4);
+ },
+ .Little => {
+ try expect(two_halves.half1 == 0x34);
+ try expect(two_halves.quarter3 == 0x2);
+ try expect(two_halves.quarter4 == 0x1);
+ },
+ }
+ }
+ };
+ try S.doTheTest();
+ comptime try S.doTheTest();
+}
+
+test "@bitCast extern structs at runtime and comptime" {
+ if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
+
+ const Full = extern struct {
+ number: u16,
+ };
+ const TwoHalves = extern struct {
+ half1: u8,
+ half2: u8,
+ };
+ const S = struct {
+ fn doTheTest() !void {
+ var full = Full{ .number = 0x1234 };
+ var two_halves = @bitCast(TwoHalves, full);
+ switch (native_endian) {
+ .Big => {
+ try expect(two_halves.half1 == 0x12);
+ try expect(two_halves.half2 == 0x34);
+ },
+ .Little => {
+ try expect(two_halves.half1 == 0x34);
+ try expect(two_halves.half2 == 0x12);
+ },
+ }
+ }
+ };
+ try S.doTheTest();
+ comptime try S.doTheTest();
+}
+
+test "bitcast packed struct to integer and back" {
+ if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
+
+ const LevelUpMove = packed struct {
+ move_id: u9,
+ level: u7,
+ };
+ const S = struct {
+ fn doTheTest() !void {
+ var move = LevelUpMove{ .move_id = 1, .level = 2 };
+ var v = @bitCast(u16, move);
+ var back_to_a_move = @bitCast(LevelUpMove, v);
+ try expect(back_to_a_move.move_id == 1);
+ try expect(back_to_a_move.level == 2);
+ }
+ };
+ try S.doTheTest();
+ comptime try S.doTheTest();
+}
+
+test "implicit cast to error union by returning" {
+ const S = struct {
+ fn entry() !void {
+ try expect((func(-1) catch unreachable) == maxInt(u64));
+ }
+ pub fn func(sz: i64) anyerror!u64 {
+ return @bitCast(u64, sz);
+ }
+ };
+ try S.entry();
+ comptime try S.entry();
+}
+
+test "bitcast packed struct literal to byte" {
+ if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
+
+ const Foo = packed struct {
+ value: u8,
+ };
+ const casted = @bitCast(u8, Foo{ .value = 0xF });
+ try expect(casted == 0xf);
+}
+
+test "comptime bitcast used in expression has the correct type" {
+ if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
+
+ const Foo = packed struct {
+ value: u8,
+ };
+ try expect(@bitCast(u8, Foo{ .value = 0xF }) == 0xf);
+}
+
+test "bitcast passed as tuple element" {
+ if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
+
+ const S = struct {
+ fn foo(args: anytype) !void {
+ comptime try expect(@TypeOf(args[0]) == f32);
+ try expect(args[0] == 12.34);
+ }
+ };
+ try S.foo(.{@bitCast(f32, @as(u32, 0x414570A4))});
+}
+
+test "triple level result location with bitcast sandwich passed as tuple element" {
+ if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+
+ const S = struct {
+ fn foo(args: anytype) !void {
+ comptime try expect(@TypeOf(args[0]) == f64);
+ try expect(args[0] > 12.33 and args[0] < 12.35);
+ }
+ };
+ try S.foo(.{@as(f64, @bitCast(f32, @as(u32, 0x414570A4)))});
+}
test/behavior/bitcast_stage1.zig
@@ -1,131 +0,0 @@
-const std = @import("std");
-const builtin = @import("builtin");
-const expect = std.testing.expect;
-const expectEqual = std.testing.expectEqual;
-const maxInt = std.math.maxInt;
-const native_endian = builtin.target.cpu.arch.endian();
-
-test "@bitCast packed structs at runtime and comptime" {
- const Full = packed struct {
- number: u16,
- };
- const Divided = packed struct {
- half1: u8,
- quarter3: u4,
- quarter4: u4,
- };
- const S = struct {
- fn doTheTest() !void {
- var full = Full{ .number = 0x1234 };
- var two_halves = @bitCast(Divided, full);
- switch (native_endian) {
- .Big => {
- try expect(two_halves.half1 == 0x12);
- try expect(two_halves.quarter3 == 0x3);
- try expect(two_halves.quarter4 == 0x4);
- },
- .Little => {
- try expect(two_halves.half1 == 0x34);
- try expect(two_halves.quarter3 == 0x2);
- try expect(two_halves.quarter4 == 0x1);
- },
- }
- }
- };
- try S.doTheTest();
- comptime try S.doTheTest();
-}
-
-test "@bitCast extern structs at runtime and comptime" {
- const Full = extern struct {
- number: u16,
- };
- const TwoHalves = extern struct {
- half1: u8,
- half2: u8,
- };
- const S = struct {
- fn doTheTest() !void {
- var full = Full{ .number = 0x1234 };
- var two_halves = @bitCast(TwoHalves, full);
- switch (native_endian) {
- .Big => {
- try expect(two_halves.half1 == 0x12);
- try expect(two_halves.half2 == 0x34);
- },
- .Little => {
- try expect(two_halves.half1 == 0x34);
- try expect(two_halves.half2 == 0x12);
- },
- }
- }
- };
- try S.doTheTest();
- comptime try S.doTheTest();
-}
-
-test "bitcast packed struct to integer and back" {
- const LevelUpMove = packed struct {
- move_id: u9,
- level: u7,
- };
- const S = struct {
- fn doTheTest() !void {
- var move = LevelUpMove{ .move_id = 1, .level = 2 };
- var v = @bitCast(u16, move);
- var back_to_a_move = @bitCast(LevelUpMove, v);
- try expect(back_to_a_move.move_id == 1);
- try expect(back_to_a_move.level == 2);
- }
- };
- try S.doTheTest();
- comptime try S.doTheTest();
-}
-
-test "implicit cast to error union by returning" {
- const S = struct {
- fn entry() !void {
- try expect((func(-1) catch unreachable) == maxInt(u64));
- }
- pub fn func(sz: i64) anyerror!u64 {
- return @bitCast(u64, sz);
- }
- };
- try S.entry();
- comptime try S.entry();
-}
-
-test "bitcast packed struct literal to byte" {
- const Foo = packed struct {
- value: u8,
- };
- const casted = @bitCast(u8, Foo{ .value = 0xF });
- try expect(casted == 0xf);
-}
-
-test "comptime bitcast used in expression has the correct type" {
- const Foo = packed struct {
- value: u8,
- };
- try expect(@bitCast(u8, Foo{ .value = 0xF }) == 0xf);
-}
-
-test "bitcast passed as tuple element" {
- const S = struct {
- fn foo(args: anytype) !void {
- comptime try expect(@TypeOf(args[0]) == f32);
- try expect(args[0] == 12.34);
- }
- };
- try S.foo(.{@bitCast(f32, @as(u32, 0x414570A4))});
-}
-
-test "triple level result location with bitcast sandwich passed as tuple element" {
- const S = struct {
- fn foo(args: anytype) !void {
- comptime try expect(@TypeOf(args[0]) == f64);
- try expect(args[0] > 12.33 and args[0] < 12.35);
- }
- };
- try S.foo(.{@as(f64, @bitCast(f32, @as(u32, 0x414570A4)))});
-}
test/behavior/cast.zig
@@ -336,3 +336,474 @@ test "expected [*c]const u8, found [*:0]const u8" {
var c: [*:0]const u8 = b;
try expect(std.mem.eql(u8, c[0..5], "hello"));
}
+
+test "explicit cast from integer to error type" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ try testCastIntToErr(error.ItBroke);
+ comptime try testCastIntToErr(error.ItBroke);
+}
+fn testCastIntToErr(err: anyerror) !void {
+ const x = @errorToInt(err);
+ const y = @intToError(x);
+ try expect(error.ItBroke == y);
+}
+
+test "peer resolve array and const slice" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ try testPeerResolveArrayConstSlice(true);
+ comptime try testPeerResolveArrayConstSlice(true);
+}
+fn testPeerResolveArrayConstSlice(b: bool) !void {
+ const value1 = if (b) "aoeu" else @as([]const u8, "zz");
+ const value2 = if (b) @as([]const u8, "zz") else "aoeu";
+ try expect(mem.eql(u8, value1, "aoeu"));
+ try expect(mem.eql(u8, value2, "zz"));
+}
+
+test "implicitly cast from T to anyerror!?T" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ try castToOptionalTypeError(1);
+ comptime try castToOptionalTypeError(1);
+}
+
+const A = struct {
+ a: i32,
+};
+fn castToOptionalTypeError(z: i32) !void {
+ const x = @as(i32, 1);
+ const y: anyerror!?i32 = x;
+ try expect((try y).? == 1);
+
+ const f = z;
+ const g: anyerror!?i32 = f;
+ _ = g catch {};
+
+ const a = A{ .a = z };
+ const b: anyerror!?A = a;
+ try expect((b catch unreachable).?.a == 1);
+}
+
+test "implicitly cast from [0]T to anyerror![]T" {
+ if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
+
+ try testCastZeroArrayToErrSliceMut();
+ comptime try testCastZeroArrayToErrSliceMut();
+}
+
+fn testCastZeroArrayToErrSliceMut() !void {
+ try expect((gimmeErrOrSlice() catch unreachable).len == 0);
+}
+
+fn gimmeErrOrSlice() anyerror![]u8 {
+ return &[_]u8{};
+}
+
+test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ const S = struct {
+ fn doTheTest() anyerror!void {
+ {
+ var data = "hi".*;
+ const slice = data[0..];
+ try expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
+ try expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
+ }
+ {
+ var data: [2]u8 = "hi".*;
+ const slice = data[0..];
+ try expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
+ try expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
+ }
+ }
+ };
+ try S.doTheTest();
+ comptime try S.doTheTest();
+}
+fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 {
+ if (a) {
+ return &[_]u8{};
+ }
+
+ return slice[0..1];
+}
+
+test "implicit cast from *const [N]T to []const T" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ try testCastConstArrayRefToConstSlice();
+ comptime try testCastConstArrayRefToConstSlice();
+}
+
+fn testCastConstArrayRefToConstSlice() !void {
+ {
+ const blah = "aoeu".*;
+ const const_array_ref = &blah;
+ try expect(@TypeOf(const_array_ref) == *const [4:0]u8);
+ const slice: []const u8 = const_array_ref;
+ try expect(mem.eql(u8, slice, "aoeu"));
+ }
+ {
+ const blah: [4]u8 = "aoeu".*;
+ const const_array_ref = &blah;
+ try expect(@TypeOf(const_array_ref) == *const [4]u8);
+ const slice: []const u8 = const_array_ref;
+ try expect(mem.eql(u8, slice, "aoeu"));
+ }
+}
+
+test "peer type resolution: error and [N]T" {
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
+
+ try expect(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
+ comptime try expect(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
+ try expect(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
+ comptime try expect(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
+}
+
+fn testPeerErrorAndArray(x: u8) anyerror![]const u8 {
+ return switch (x) {
+ 0x00 => "OK",
+ else => error.BadValue,
+ };
+}
+fn testPeerErrorAndArray2(x: u8) anyerror![]const u8 {
+ return switch (x) {
+ 0x00 => "OK",
+ 0x01 => "OKK",
+ else => error.BadValue,
+ };
+}
+
+test "single-item pointer of array to slice to unknown length pointer" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ try testCastPtrOfArrayToSliceAndPtr();
+ comptime try testCastPtrOfArrayToSliceAndPtr();
+}
+
+fn testCastPtrOfArrayToSliceAndPtr() !void {
+ {
+ var array = "aoeu".*;
+ const x: [*]u8 = &array;
+ x[0] += 1;
+ try expect(mem.eql(u8, array[0..], "boeu"));
+ const y: []u8 = &array;
+ y[0] += 1;
+ try expect(mem.eql(u8, array[0..], "coeu"));
+ }
+ {
+ var array: [4]u8 = "aoeu".*;
+ const x: [*]u8 = &array;
+ x[0] += 1;
+ try expect(mem.eql(u8, array[0..], "boeu"));
+ const y: []u8 = &array;
+ y[0] += 1;
+ try expect(mem.eql(u8, array[0..], "coeu"));
+ }
+}
+
+test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ const window_name = [1][*]const u8{"window name"};
+ const x: [*]const ?[*]const u8 = &window_name;
+ try expect(mem.eql(u8, std.mem.sliceTo(@ptrCast([*:0]const u8, x[0].?), 0), "window name"));
+}
+
+test "vector casts" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ const S = struct {
+ fn doTheTest() !void {
+ // Upcast (implicit, equivalent to @intCast)
+ var up0: @Vector(2, u8) = [_]u8{ 0x55, 0xaa };
+ var up1 = @as(@Vector(2, u16), up0);
+ var up2 = @as(@Vector(2, u32), up0);
+ var up3 = @as(@Vector(2, u64), up0);
+ // Downcast (safety-checked)
+ var down0 = up3;
+ var down1 = @intCast(@Vector(2, u32), down0);
+ var down2 = @intCast(@Vector(2, u16), down0);
+ var down3 = @intCast(@Vector(2, u8), down0);
+
+ try expect(mem.eql(u16, &@as([2]u16, up1), &[2]u16{ 0x55, 0xaa }));
+ try expect(mem.eql(u32, &@as([2]u32, up2), &[2]u32{ 0x55, 0xaa }));
+ try expect(mem.eql(u64, &@as([2]u64, up3), &[2]u64{ 0x55, 0xaa }));
+
+ try expect(mem.eql(u32, &@as([2]u32, down1), &[2]u32{ 0x55, 0xaa }));
+ try expect(mem.eql(u16, &@as([2]u16, down2), &[2]u16{ 0x55, 0xaa }));
+ try expect(mem.eql(u8, &@as([2]u8, down3), &[2]u8{ 0x55, 0xaa }));
+ }
+
+ fn doTheTestFloat() !void {
+ var vec = @splat(2, @as(f32, 1234.0));
+ var wider: @Vector(2, f64) = vec;
+ try expect(wider[0] == 1234.0);
+ try expect(wider[1] == 1234.0);
+ }
+ };
+
+ try S.doTheTest();
+ comptime try S.doTheTest();
+ try S.doTheTestFloat();
+ comptime try S.doTheTestFloat();
+}
+
+test "@floatCast cast down" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ {
+ var double: f64 = 0.001534;
+ var single = @floatCast(f32, double);
+ try expect(single == 0.001534);
+ }
+ {
+ const double: f64 = 0.001534;
+ const single = @floatCast(f32, double);
+ try expect(single == 0.001534);
+ }
+}
+
+test "peer type resolution: unreachable, error set, unreachable" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ const Error = error{
+ FileDescriptorAlreadyPresentInSet,
+ OperationCausesCircularLoop,
+ FileDescriptorNotRegistered,
+ SystemResources,
+ UserResourceLimitReached,
+ FileDescriptorIncompatibleWithEpoll,
+ Unexpected,
+ };
+ var err = Error.SystemResources;
+ const transformed_err = switch (err) {
+ error.FileDescriptorAlreadyPresentInSet => unreachable,
+ error.OperationCausesCircularLoop => unreachable,
+ error.FileDescriptorNotRegistered => unreachable,
+ error.SystemResources => error.SystemResources,
+ error.UserResourceLimitReached => error.UserResourceLimitReached,
+ error.FileDescriptorIncompatibleWithEpoll => unreachable,
+ error.Unexpected => unreachable,
+ };
+ try expect(transformed_err == error.SystemResources);
+}
+
+test "peer cast *[0]T to E![]const T" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ var buffer: [5]u8 = "abcde".*;
+ var buf: anyerror![]const u8 = buffer[0..];
+ var b = false;
+ var y = if (b) &[0]u8{} else buf;
+ try expect(mem.eql(u8, "abcde", y catch unreachable));
+}
+
+test "peer cast *[0]T to []const T" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ var buffer: [5]u8 = "abcde".*;
+ var buf: []const u8 = buffer[0..];
+ var b = false;
+ var y = if (b) &[0]u8{} else buf;
+ try expect(mem.eql(u8, "abcde", y));
+}
+
+test "peer resolution of string literals" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ const S = struct {
+ const E = enum { a, b, c, d };
+
+ fn doTheTest(e: E) !void {
+ const cmd = switch (e) {
+ .a => "one",
+ .b => "two",
+ .c => "three",
+ .d => "four",
+ };
+ try expect(mem.eql(u8, cmd, "two"));
+ }
+ };
+ try S.doTheTest(.b);
+ comptime try S.doTheTest(.b);
+}
+
+test "type coercion related to sentinel-termination" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ const S = struct {
+ fn doTheTest() !void {
+ // [:x]T to []T
+ {
+ var array = [4:0]i32{ 1, 2, 3, 4 };
+ var slice: [:0]i32 = &array;
+ var dest: []i32 = slice;
+ try expect(mem.eql(i32, dest, &[_]i32{ 1, 2, 3, 4 }));
+ }
+
+ // [*:x]T to [*]T
+ {
+ var array = [4:99]i32{ 1, 2, 3, 4 };
+ var dest: [*]i32 = &array;
+ try expect(dest[0] == 1);
+ try expect(dest[1] == 2);
+ try expect(dest[2] == 3);
+ try expect(dest[3] == 4);
+ try expect(dest[4] == 99);
+ }
+
+ // [N:x]T to [N]T
+ {
+ var array = [4:0]i32{ 1, 2, 3, 4 };
+ var dest: [4]i32 = array;
+ try expect(mem.eql(i32, &dest, &[_]i32{ 1, 2, 3, 4 }));
+ }
+
+ // *[N:x]T to *[N]T
+ {
+ var array = [4:0]i32{ 1, 2, 3, 4 };
+ var dest: *[4]i32 = &array;
+ try expect(mem.eql(i32, dest, &[_]i32{ 1, 2, 3, 4 }));
+ }
+
+ // [:x]T to [*:x]T
+ {
+ var array = [4:0]i32{ 1, 2, 3, 4 };
+ var slice: [:0]i32 = &array;
+ var dest: [*:0]i32 = slice;
+ try expect(dest[0] == 1);
+ try expect(dest[1] == 2);
+ try expect(dest[2] == 3);
+ try expect(dest[3] == 4);
+ try expect(dest[4] == 0);
+ }
+ }
+ };
+ try S.doTheTest();
+ comptime try S.doTheTest();
+}
+
+test "peer type resolution implicit cast to return type" {
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
+
+ const S = struct {
+ fn doTheTest() !void {
+ for ("hello") |c| _ = f(c);
+ }
+ fn f(c: u8) []const u8 {
+ return switch (c) {
+ 'h', 'e' => &[_]u8{c}, // should cast to slice
+ 'l', ' ' => &[_]u8{ c, '.' }, // should cast to slice
+ else => ([_]u8{c})[0..], // is a slice
+ };
+ }
+ };
+ try S.doTheTest();
+ comptime try S.doTheTest();
+}
+
+test "peer type resolution implicit cast to variable type" {
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
+
+ const S = struct {
+ fn doTheTest() !void {
+ var x: []const u8 = undefined;
+ for ("hello") |c| x = switch (c) {
+ 'h', 'e' => &[_]u8{c}, // should cast to slice
+ 'l', ' ' => &[_]u8{ c, '.' }, // should cast to slice
+ else => ([_]u8{c})[0..], // is a slice
+ };
+ }
+ };
+ try S.doTheTest();
+ comptime try S.doTheTest();
+}
+
+test "variable initialization uses result locations properly with regards to the type" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ var b = true;
+ const x: i32 = if (b) 1 else 2;
+ try expect(x == 1);
+}
+
+test "cast between C pointer with different but compatible types" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ const S = struct {
+ fn foo(arg: [*]c_ushort) u16 {
+ return arg[0];
+ }
+ fn doTheTest() !void {
+ var x = [_]u16{ 4, 2, 1, 3 };
+ try expect(foo(@ptrCast([*]u16, &x)) == 4);
+ }
+ };
+ try S.doTheTest();
+}
+
+test "peer type resolve string lit with sentinel-terminated mutable slice" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ var array: [4:0]u8 = undefined;
+ array[4] = 0; // TODO remove this when #4372 is solved
+ var slice: [:0]u8 = array[0..4 :0];
+ comptime try expect(@TypeOf(slice, "hi") == [:0]const u8);
+ comptime try expect(@TypeOf("hi", slice) == [:0]const u8);
+}
+
+test "peer type resolve array pointers, one of them const" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ var array1: [4]u8 = undefined;
+ const array2: [5]u8 = undefined;
+ comptime try expect(@TypeOf(&array1, &array2) == []const u8);
+ comptime try expect(@TypeOf(&array2, &array1) == []const u8);
+}
+
+test "peer type resolve array pointer and unknown pointer" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ const const_array: [4]u8 = undefined;
+ var array: [4]u8 = undefined;
+ var const_ptr: [*]const u8 = undefined;
+ var ptr: [*]u8 = undefined;
+
+ comptime try expect(@TypeOf(&array, ptr) == [*]u8);
+ comptime try expect(@TypeOf(ptr, &array) == [*]u8);
+
+ comptime try expect(@TypeOf(&const_array, ptr) == [*]const u8);
+ comptime try expect(@TypeOf(ptr, &const_array) == [*]const u8);
+
+ comptime try expect(@TypeOf(&array, const_ptr) == [*]const u8);
+ comptime try expect(@TypeOf(const_ptr, &array) == [*]const u8);
+
+ comptime try expect(@TypeOf(&const_array, const_ptr) == [*]const u8);
+ comptime try expect(@TypeOf(const_ptr, &const_array) == [*]const u8);
+}
+
+test "comptime float casts" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ const a = @intToFloat(comptime_float, 1);
+ try expect(a == 1);
+ try expect(@TypeOf(a) == comptime_float);
+ const b = @floatToInt(comptime_int, 2);
+ try expect(b == 2);
+ try expect(@TypeOf(b) == comptime_int);
+
+ try expectFloatToInt(comptime_int, 1234, i16, 1234);
+ try expectFloatToInt(comptime_float, 12.3, comptime_int, 12);
+}
test/behavior/cast_stage1.zig
@@ -1,426 +0,0 @@
-const std = @import("std");
-const expect = std.testing.expect;
-const mem = std.mem;
-const maxInt = std.math.maxInt;
-const Vector = std.meta.Vector;
-const native_endian = @import("builtin").target.cpu.arch.endian();
-
-test "explicit cast from integer to error type" {
- try testCastIntToErr(error.ItBroke);
- comptime try testCastIntToErr(error.ItBroke);
-}
-fn testCastIntToErr(err: anyerror) !void {
- const x = @errorToInt(err);
- const y = @intToError(x);
- try expect(error.ItBroke == y);
-}
-
-test "peer resolve array and const slice" {
- try testPeerResolveArrayConstSlice(true);
- comptime try testPeerResolveArrayConstSlice(true);
-}
-fn testPeerResolveArrayConstSlice(b: bool) !void {
- const value1 = if (b) "aoeu" else @as([]const u8, "zz");
- const value2 = if (b) @as([]const u8, "zz") else "aoeu";
- try expect(mem.eql(u8, value1, "aoeu"));
- try expect(mem.eql(u8, value2, "zz"));
-}
-
-test "implicitly cast from T to anyerror!?T" {
- try castToOptionalTypeError(1);
- comptime try castToOptionalTypeError(1);
-}
-
-const A = struct {
- a: i32,
-};
-fn castToOptionalTypeError(z: i32) !void {
- const x = @as(i32, 1);
- const y: anyerror!?i32 = x;
- try expect((try y).? == 1);
-
- const f = z;
- const g: anyerror!?i32 = f;
- _ = g catch {};
-
- const a = A{ .a = z };
- const b: anyerror!?A = a;
- try expect((b catch unreachable).?.a == 1);
-}
-
-test "implicitly cast from [0]T to anyerror![]T" {
- try testCastZeroArrayToErrSliceMut();
- comptime try testCastZeroArrayToErrSliceMut();
-}
-
-fn testCastZeroArrayToErrSliceMut() !void {
- try expect((gimmeErrOrSlice() catch unreachable).len == 0);
-}
-
-fn gimmeErrOrSlice() anyerror![]u8 {
- return &[_]u8{};
-}
-
-test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {
- const S = struct {
- fn doTheTest() anyerror!void {
- {
- var data = "hi".*;
- const slice = data[0..];
- try expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
- try expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
- }
- {
- var data: [2]u8 = "hi".*;
- const slice = data[0..];
- try expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
- try expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
- }
- }
- };
- try S.doTheTest();
- comptime try S.doTheTest();
-}
-fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 {
- if (a) {
- return &[_]u8{};
- }
-
- return slice[0..1];
-}
-
-test "implicit cast from *const [N]T to []const T" {
- try testCastConstArrayRefToConstSlice();
- comptime try testCastConstArrayRefToConstSlice();
-}
-
-fn testCastConstArrayRefToConstSlice() !void {
- {
- const blah = "aoeu".*;
- const const_array_ref = &blah;
- try expect(@TypeOf(const_array_ref) == *const [4:0]u8);
- const slice: []const u8 = const_array_ref;
- try expect(mem.eql(u8, slice, "aoeu"));
- }
- {
- const blah: [4]u8 = "aoeu".*;
- const const_array_ref = &blah;
- try expect(@TypeOf(const_array_ref) == *const [4]u8);
- const slice: []const u8 = const_array_ref;
- try expect(mem.eql(u8, slice, "aoeu"));
- }
-}
-
-test "peer type resolution: error and [N]T" {
- try expect(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
- comptime try expect(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
- try expect(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
- comptime try expect(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
-}
-
-fn testPeerErrorAndArray(x: u8) anyerror![]const u8 {
- return switch (x) {
- 0x00 => "OK",
- else => error.BadValue,
- };
-}
-fn testPeerErrorAndArray2(x: u8) anyerror![]const u8 {
- return switch (x) {
- 0x00 => "OK",
- 0x01 => "OKK",
- else => error.BadValue,
- };
-}
-
-test "single-item pointer of array to slice to unknown length pointer" {
- try testCastPtrOfArrayToSliceAndPtr();
- comptime try testCastPtrOfArrayToSliceAndPtr();
-}
-
-fn testCastPtrOfArrayToSliceAndPtr() !void {
- {
- var array = "aoeu".*;
- const x: [*]u8 = &array;
- x[0] += 1;
- try expect(mem.eql(u8, array[0..], "boeu"));
- const y: []u8 = &array;
- y[0] += 1;
- try expect(mem.eql(u8, array[0..], "coeu"));
- }
- {
- var array: [4]u8 = "aoeu".*;
- const x: [*]u8 = &array;
- x[0] += 1;
- try expect(mem.eql(u8, array[0..], "boeu"));
- const y: []u8 = &array;
- y[0] += 1;
- try expect(mem.eql(u8, array[0..], "coeu"));
- }
-}
-
-test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
- const window_name = [1][*]const u8{"window name"};
- const x: [*]const ?[*]const u8 = &window_name;
- try expect(mem.eql(u8, std.mem.sliceTo(@ptrCast([*:0]const u8, x[0].?), 0), "window name"));
-}
-
-test "vector casts" {
- const S = struct {
- fn doTheTest() !void {
- // Upcast (implicit, equivalent to @intCast)
- var up0: Vector(2, u8) = [_]u8{ 0x55, 0xaa };
- var up1 = @as(Vector(2, u16), up0);
- var up2 = @as(Vector(2, u32), up0);
- var up3 = @as(Vector(2, u64), up0);
- // Downcast (safety-checked)
- var down0 = up3;
- var down1 = @intCast(Vector(2, u32), down0);
- var down2 = @intCast(Vector(2, u16), down0);
- var down3 = @intCast(Vector(2, u8), down0);
-
- try expect(mem.eql(u16, &@as([2]u16, up1), &[2]u16{ 0x55, 0xaa }));
- try expect(mem.eql(u32, &@as([2]u32, up2), &[2]u32{ 0x55, 0xaa }));
- try expect(mem.eql(u64, &@as([2]u64, up3), &[2]u64{ 0x55, 0xaa }));
-
- try expect(mem.eql(u32, &@as([2]u32, down1), &[2]u32{ 0x55, 0xaa }));
- try expect(mem.eql(u16, &@as([2]u16, down2), &[2]u16{ 0x55, 0xaa }));
- try expect(mem.eql(u8, &@as([2]u8, down3), &[2]u8{ 0x55, 0xaa }));
- }
-
- fn doTheTestFloat() !void {
- var vec = @splat(2, @as(f32, 1234.0));
- var wider: Vector(2, f64) = vec;
- try expect(wider[0] == 1234.0);
- try expect(wider[1] == 1234.0);
- }
- };
-
- try S.doTheTest();
- comptime try S.doTheTest();
- try S.doTheTestFloat();
- comptime try S.doTheTestFloat();
-}
-
-test "@floatCast cast down" {
- {
- var double: f64 = 0.001534;
- var single = @floatCast(f32, double);
- try expect(single == 0.001534);
- }
- {
- const double: f64 = 0.001534;
- const single = @floatCast(f32, double);
- try expect(single == 0.001534);
- }
-}
-
-test "peer type resolution: unreachable, error set, unreachable" {
- const Error = error{
- FileDescriptorAlreadyPresentInSet,
- OperationCausesCircularLoop,
- FileDescriptorNotRegistered,
- SystemResources,
- UserResourceLimitReached,
- FileDescriptorIncompatibleWithEpoll,
- Unexpected,
- };
- var err = Error.SystemResources;
- const transformed_err = switch (err) {
- error.FileDescriptorAlreadyPresentInSet => unreachable,
- error.OperationCausesCircularLoop => unreachable,
- error.FileDescriptorNotRegistered => unreachable,
- error.SystemResources => error.SystemResources,
- error.UserResourceLimitReached => error.UserResourceLimitReached,
- error.FileDescriptorIncompatibleWithEpoll => unreachable,
- error.Unexpected => unreachable,
- };
- try expect(transformed_err == error.SystemResources);
-}
-
-test "peer cast *[0]T to E![]const T" {
- var buffer: [5]u8 = "abcde".*;
- var buf: anyerror![]const u8 = buffer[0..];
- var b = false;
- var y = if (b) &[0]u8{} else buf;
- try expect(mem.eql(u8, "abcde", y catch unreachable));
-}
-
-test "peer cast *[0]T to []const T" {
- var buffer: [5]u8 = "abcde".*;
- var buf: []const u8 = buffer[0..];
- var b = false;
- var y = if (b) &[0]u8{} else buf;
- try expect(mem.eql(u8, "abcde", y));
-}
-
-test "peer resolution of string literals" {
- const S = struct {
- const E = enum { a, b, c, d };
-
- fn doTheTest(e: E) !void {
- const cmd = switch (e) {
- .a => "one",
- .b => "two",
- .c => "three",
- .d => "four",
- };
- try expect(mem.eql(u8, cmd, "two"));
- }
- };
- try S.doTheTest(.b);
- comptime try S.doTheTest(.b);
-}
-
-test "type coercion related to sentinel-termination" {
- const S = struct {
- fn doTheTest() !void {
- // [:x]T to []T
- {
- var array = [4:0]i32{ 1, 2, 3, 4 };
- var slice: [:0]i32 = &array;
- var dest: []i32 = slice;
- try expect(mem.eql(i32, dest, &[_]i32{ 1, 2, 3, 4 }));
- }
-
- // [*:x]T to [*]T
- {
- var array = [4:99]i32{ 1, 2, 3, 4 };
- var dest: [*]i32 = &array;
- try expect(dest[0] == 1);
- try expect(dest[1] == 2);
- try expect(dest[2] == 3);
- try expect(dest[3] == 4);
- try expect(dest[4] == 99);
- }
-
- // [N:x]T to [N]T
- {
- var array = [4:0]i32{ 1, 2, 3, 4 };
- var dest: [4]i32 = array;
- try expect(mem.eql(i32, &dest, &[_]i32{ 1, 2, 3, 4 }));
- }
-
- // *[N:x]T to *[N]T
- {
- var array = [4:0]i32{ 1, 2, 3, 4 };
- var dest: *[4]i32 = &array;
- try expect(mem.eql(i32, dest, &[_]i32{ 1, 2, 3, 4 }));
- }
-
- // [:x]T to [*:x]T
- {
- var array = [4:0]i32{ 1, 2, 3, 4 };
- var slice: [:0]i32 = &array;
- var dest: [*:0]i32 = slice;
- try expect(dest[0] == 1);
- try expect(dest[1] == 2);
- try expect(dest[2] == 3);
- try expect(dest[3] == 4);
- try expect(dest[4] == 0);
- }
- }
- };
- try S.doTheTest();
- comptime try S.doTheTest();
-}
-
-test "peer type resolution implicit cast to return type" {
- const S = struct {
- fn doTheTest() !void {
- for ("hello") |c| _ = f(c);
- }
- fn f(c: u8) []const u8 {
- return switch (c) {
- 'h', 'e' => &[_]u8{c}, // should cast to slice
- 'l', ' ' => &[_]u8{ c, '.' }, // should cast to slice
- else => ([_]u8{c})[0..], // is a slice
- };
- }
- };
- try S.doTheTest();
- comptime try S.doTheTest();
-}
-
-test "peer type resolution implicit cast to variable type" {
- const S = struct {
- fn doTheTest() !void {
- var x: []const u8 = undefined;
- for ("hello") |c| x = switch (c) {
- 'h', 'e' => &[_]u8{c}, // should cast to slice
- 'l', ' ' => &[_]u8{ c, '.' }, // should cast to slice
- else => ([_]u8{c})[0..], // is a slice
- };
- }
- };
- try S.doTheTest();
- comptime try S.doTheTest();
-}
-
-test "variable initialization uses result locations properly with regards to the type" {
- var b = true;
- const x: i32 = if (b) 1 else 2;
- try expect(x == 1);
-}
-
-test "cast between C pointer with different but compatible types" {
- const S = struct {
- fn foo(arg: [*]c_ushort) u16 {
- return arg[0];
- }
- fn doTheTest() !void {
- var x = [_]u16{ 4, 2, 1, 3 };
- try expect(foo(@ptrCast([*]u16, &x)) == 4);
- }
- };
- try S.doTheTest();
-}
-
-test "peer type resolve string lit with sentinel-terminated mutable slice" {
- var array: [4:0]u8 = undefined;
- array[4] = 0; // TODO remove this when #4372 is solved
- var slice: [:0]u8 = array[0..4 :0];
- comptime try expect(@TypeOf(slice, "hi") == [:0]const u8);
- comptime try expect(@TypeOf("hi", slice) == [:0]const u8);
-}
-
-test "peer type resolve array pointers, one of them const" {
- var array1: [4]u8 = undefined;
- const array2: [5]u8 = undefined;
- comptime try expect(@TypeOf(&array1, &array2) == []const u8);
- comptime try expect(@TypeOf(&array2, &array1) == []const u8);
-}
-
-test "peer type resolve array pointer and unknown pointer" {
- const const_array: [4]u8 = undefined;
- var array: [4]u8 = undefined;
- var const_ptr: [*]const u8 = undefined;
- var ptr: [*]u8 = undefined;
-
- comptime try expect(@TypeOf(&array, ptr) == [*]u8);
- comptime try expect(@TypeOf(ptr, &array) == [*]u8);
-
- comptime try expect(@TypeOf(&const_array, ptr) == [*]const u8);
- comptime try expect(@TypeOf(ptr, &const_array) == [*]const u8);
-
- comptime try expect(@TypeOf(&array, const_ptr) == [*]const u8);
- comptime try expect(@TypeOf(const_ptr, &array) == [*]const u8);
-
- comptime try expect(@TypeOf(&const_array, const_ptr) == [*]const u8);
- comptime try expect(@TypeOf(const_ptr, &const_array) == [*]const u8);
-}
-
-test "comptime float casts" {
- const a = @intToFloat(comptime_float, 1);
- try expect(a == 1);
- try expect(@TypeOf(a) == comptime_float);
- const b = @floatToInt(comptime_int, 2);
- try expect(b == 2);
- try expect(@TypeOf(b) == comptime_int);
-
- try expectFloatToInt(comptime_int, 1234, i16, 1234);
- try expectFloatToInt(comptime_float, 12.3, comptime_int, 12);
-}
-
-fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) !void {
- try expect(@floatToInt(I, f) == i);
-}
test/behavior/defer.zig
@@ -1,3 +1,4 @@
+const builtin = @import("builtin");
const std = @import("std");
const expect = std.testing.expect;
const expectEqual = std.testing.expectEqual;
@@ -61,3 +62,58 @@ test "return variable while defer expression in scope to modify it" {
try S.doTheTest();
comptime try S.doTheTest();
}
+
+var result: [3]u8 = undefined;
+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;
+ }
+ return if (x) x else error.FalseNotAllowed;
+}
+
+test "mixing normal and error defers" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ try expect(runSomeErrorDefers(true) catch unreachable);
+ try expect(result[0] == 'c');
+ try expect(result[1] == 'a');
+
+ const ok = runSomeErrorDefers(false) catch |err| x: {
+ try expect(err == error.FalseNotAllowed);
+ break :x true;
+ };
+ try expect(ok);
+ try expect(result[0] == 'c');
+ try expect(result[1] == 'b');
+ try expect(result[2] == 'a');
+}
+
+test "errdefer with payload" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ const S = struct {
+ fn foo() !i32 {
+ errdefer |a| {
+ expectEqual(error.One, a) catch @panic("test failure");
+ }
+ return error.One;
+ }
+ fn doTheTest() !void {
+ try expectError(error.One, foo());
+ }
+ };
+ try S.doTheTest();
+ comptime try S.doTheTest();
+}
test/behavior/defer_stage1.zig
@@ -1,55 +0,0 @@
-const std = @import("std");
-const expect = std.testing.expect;
-const expectEqual = std.testing.expectEqual;
-const expectError = std.testing.expectError;
-
-var result: [3]u8 = undefined;
-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;
- }
- return if (x) x else error.FalseNotAllowed;
-}
-
-test "mixing normal and error defers" {
- try expect(runSomeErrorDefers(true) catch unreachable);
- try expect(result[0] == 'c');
- try expect(result[1] == 'a');
-
- const ok = runSomeErrorDefers(false) catch |err| x: {
- try expect(err == error.FalseNotAllowed);
- break :x true;
- };
- try expect(ok);
- try expect(result[0] == 'c');
- try expect(result[1] == 'b');
- try expect(result[2] == 'a');
-}
-
-test "errdefer with payload" {
- const S = struct {
- fn foo() !i32 {
- errdefer |a| {
- expectEqual(error.One, a) catch @panic("test failure");
- }
- return error.One;
- }
- fn doTheTest() !void {
- try expectError(error.One, foo());
- }
- };
- try S.doTheTest();
- comptime try S.doTheTest();
-}
test/behavior/enum.zig
@@ -1,3 +1,4 @@
+const builtin = @import("builtin");
const std = @import("std");
const expect = std.testing.expect;
const mem = std.mem;
@@ -870,3 +871,104 @@ test "method call on an enum" {
try S.doTheTest();
comptime try S.doTheTest();
}
+
+test "enum value allocation" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ const LargeEnum = enum(u32) {
+ A0 = 0x80000000,
+ A1,
+ A2,
+ };
+
+ try expect(@enumToInt(LargeEnum.A0) == 0x80000000);
+ try expect(@enumToInt(LargeEnum.A1) == 0x80000001);
+ try expect(@enumToInt(LargeEnum.A2) == 0x80000002);
+}
+
+test "enum literal casting to tagged union" {
+ const Arch = union(enum) {
+ x86_64,
+ arm: Arm32,
+
+ const Arm32 = enum {
+ v8_5a,
+ v8_4a,
+ };
+ };
+
+ var t = true;
+ var x: Arch = .x86_64;
+ var y = if (t) x else .x86_64;
+ switch (y) {
+ .x86_64 => {},
+ else => @panic("fail"),
+ }
+}
+
+const Bar = enum { A, B, C, D };
+
+test "enum literal casting to error union with payload enum" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ var bar: error{B}!Bar = undefined;
+ bar = .B; // should never cast to the error set
+
+ try expect((try bar) == Bar.B);
+}
+
+test "exporting enum type and value" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ const S = struct {
+ const E = enum(c_int) { one, two };
+ comptime {
+ @export(E, .{ .name = "E" });
+ }
+ const e: E = .two;
+ comptime {
+ @export(e, .{ .name = "e" });
+ }
+ };
+ try expect(S.e == .two);
+}
+
+test "constant enum initialization with differing sizes" {
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
+
+ try test3_1(test3_foo);
+ try test3_2(test3_bar);
+}
+const Test3Foo = union(enum) {
+ One: void,
+ Two: f32,
+ Three: Test3Point,
+};
+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: Test3Foo) !void {
+ switch (f) {
+ Test3Foo.Three => |pt| {
+ try expect(pt.x == 3);
+ try expect(pt.y == 4);
+ },
+ else => unreachable,
+ }
+}
+fn test3_2(f: Test3Foo) !void {
+ switch (f) {
+ Test3Foo.Two => |x| {
+ try expect(x == 13);
+ },
+ else => unreachable,
+ }
+}
test/behavior/enum_stage1.zig
@@ -1,97 +0,0 @@
-const std = @import("std");
-const expect = std.testing.expect;
-const mem = std.mem;
-const Tag = std.meta.Tag;
-
-test "enum value allocation" {
- const LargeEnum = enum(u32) {
- A0 = 0x80000000,
- A1,
- A2,
- };
-
- try expect(@enumToInt(LargeEnum.A0) == 0x80000000);
- try expect(@enumToInt(LargeEnum.A1) == 0x80000001);
- try expect(@enumToInt(LargeEnum.A2) == 0x80000002);
-}
-
-test "enum literal casting to tagged union" {
- const Arch = union(enum) {
- x86_64,
- arm: Arm32,
-
- const Arm32 = enum {
- v8_5a,
- v8_4a,
- };
- };
-
- var t = true;
- var x: Arch = .x86_64;
- var y = if (t) x else .x86_64;
- switch (y) {
- .x86_64 => {},
- else => @panic("fail"),
- }
-}
-
-const Bar = enum { A, B, C, D };
-
-test "enum literal casting to error union with payload enum" {
- var bar: error{B}!Bar = undefined;
- bar = .B; // should never cast to the error set
-
- try expect((try bar) == Bar.B);
-}
-
-test "exporting enum type and value" {
- const S = struct {
- const E = enum(c_int) { one, two };
- comptime {
- @export(E, .{ .name = "E" });
- }
- const e: E = .two;
- comptime {
- @export(e, .{ .name = "e" });
- }
- };
- try expect(S.e == .two);
-}
-
-test "constant enum initialization with differing sizes" {
- try test3_1(test3_foo);
- try test3_2(test3_bar);
-}
-const Test3Foo = union(enum) {
- One: void,
- Two: f32,
- Three: Test3Point,
-};
-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: Test3Foo) !void {
- switch (f) {
- Test3Foo.Three => |pt| {
- try expect(pt.x == 3);
- try expect(pt.y == 4);
- },
- else => unreachable,
- }
-}
-fn test3_2(f: Test3Foo) !void {
- switch (f) {
- Test3Foo.Two => |x| {
- try expect(x == 13);
- },
- else => unreachable,
- }
-}
test/behavior/eval.zig
@@ -1,3 +1,4 @@
+const builtin = @import("builtin");
const std = @import("std");
const expect = std.testing.expect;
const expectEqual = std.testing.expectEqual;
@@ -492,3 +493,308 @@ test "@tagName of @typeInfo" {
const str = @tagName(@typeInfo(u8));
try expect(std.mem.eql(u8, str, "Int"));
}
+
+test "static eval list init" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ try expect(static_vec3.data[2] == 1.0);
+ try expect(vec3(0.0, 0.0, 3.0).data[2] == 3.0);
+}
+const static_vec3 = vec3(0.0, 0.0, 1.0);
+pub const Vec3 = struct {
+ data: [3]f32,
+};
+pub fn vec3(x: f32, y: f32, z: f32) Vec3 {
+ return Vec3{
+ .data = [_]f32{ x, y, z },
+ };
+}
+
+test "inlined loop has array literal with elided runtime scope on first iteration but not second iteration" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ var runtime = [1]i32{3};
+ comptime var i: usize = 0;
+ inline while (i < 2) : (i += 1) {
+ const result = if (i == 0) [1]i32{2} else runtime;
+ _ = result;
+ }
+ comptime {
+ try expect(i == 2);
+ }
+}
+
+test "eval @setFloatMode at compile-time" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ const result = comptime fnWithFloatMode();
+ try expect(result == 1234.0);
+}
+
+fn fnWithFloatMode() f32 {
+ @setFloatMode(std.builtin.FloatMode.Strict);
+ return 1234.0;
+}
+
+test "call method on bound fn referring to var instance" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ try expect(bound_fn() == 1237);
+}
+
+const SimpleStruct = struct {
+ field: i32,
+
+ fn method(self: *const SimpleStruct) i32 {
+ return self.field + 3;
+ }
+};
+
+var simple_struct = SimpleStruct{ .field = 1234 };
+
+const bound_fn = simple_struct.method;
+
+test "ptr to local array argument at comptime" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ comptime {
+ var bytes: [10]u8 = undefined;
+ modifySomeBytes(bytes[0..]);
+ try expect(bytes[0] == 'a');
+ try expect(bytes[9] == 'b');
+ }
+}
+
+fn modifySomeBytes(bytes: []u8) void {
+ bytes[0] = 'a';
+ bytes[9] = 'b';
+}
+
+test "comparisons 0 <= uint and 0 > uint should be comptime" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ testCompTimeUIntComparisons(1234);
+}
+fn testCompTimeUIntComparisons(x: u32) void {
+ if (!(0 <= x)) {
+ @compileError("this condition should be comptime known");
+ }
+ if (0 > x) {
+ @compileError("this condition should be comptime known");
+ }
+ if (!(x >= 0)) {
+ @compileError("this condition should be comptime known");
+ }
+ if (x < 0) {
+ @compileError("this condition should be comptime known");
+ }
+}
+
+const hi1 = "hi";
+const hi2 = hi1;
+test "const global shares pointer with other same one" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ try assertEqualPtrs(&hi1[0], &hi2[0]);
+ comptime try expect(&hi1[0] == &hi2[0]);
+}
+fn assertEqualPtrs(ptr1: *const u8, ptr2: *const u8) !void {
+ try expect(ptr1 == ptr2);
+}
+
+test "float literal at compile time not lossy" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ try expect(16777216.0 + 1.0 == 16777217.0);
+ try expect(9007199254740992.0 + 1.0 == 9007199254740993.0);
+}
+
+test "f128 at compile time is lossy" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ try expect(@as(f128, 10384593717069655257060992658440192.0) + 1 == 10384593717069655257060992658440192.0);
+}
+
+test "string literal used as comptime slice is memoized" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ const a = "link";
+ const b = "link";
+ comptime try expect(TypeWithCompTimeSlice(a).Node == TypeWithCompTimeSlice(b).Node);
+ comptime try expect(TypeWithCompTimeSlice("link").Node == TypeWithCompTimeSlice("link").Node);
+}
+
+pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) type {
+ _ = field_name;
+ return struct {
+ pub const Node = struct {};
+ };
+}
+
+test "comptime function with mutable pointer is not memoized" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ comptime {
+ var x: i32 = 1;
+ const ptr = &x;
+ increment(ptr);
+ increment(ptr);
+ try expect(x == 3);
+ }
+}
+
+fn increment(value: *i32) void {
+ value.* += 1;
+}
+
+test "const ptr to comptime mutable data is not memoized" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ comptime {
+ var foo = SingleFieldStruct{ .x = 1 };
+ try expect(foo.read_x() == 1);
+ foo.x = 2;
+ try expect(foo.read_x() == 2);
+ }
+}
+
+const SingleFieldStruct = struct {
+ x: i32,
+
+ fn read_x(self: *const SingleFieldStruct) i32 {
+ return self.x;
+ }
+};
+
+test "function which returns struct with type field causes implicit comptime" {
+ const ty = wrap(i32).T;
+ try expect(ty == i32);
+}
+
+const Wrapper = struct {
+ T: type,
+};
+
+fn wrap(comptime T: type) Wrapper {
+ return Wrapper{ .T = T };
+}
+
+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();
+ try expect(b == 2);
+}
+
+test "setting backward branch quota just before a generic fn call" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ @setEvalBranchQuota(1001);
+ loopNTimes(1001);
+}
+
+fn loopNTimes(comptime n: usize) void {
+ comptime var i = 0;
+ inline while (i < n) : (i += 1) {}
+}
+
+test "variable inside inline loop that has different types on different iterations" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ try testVarInsideInlineLoop(.{ true, @as(u32, 42) });
+}
+
+fn testVarInsideInlineLoop(args: anytype) !void {
+ comptime var i = 0;
+ inline while (i < args.len) : (i += 1) {
+ const x = args[i];
+ if (i == 0) try expect(x);
+ if (i == 1) try expect(x == 42);
+ }
+}
+
+test "bit shift a u1" {
+ // note: when debugging this test case for stage2, be sure to run it
+ // in valgrind. I noticed the rhs value is undefined in the lowering
+ // of the const value.
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ var x: u1 = 1;
+ var y = x << 0;
+ try expect(y == 1);
+}
+
+test "*align(1) u16 is the same as *align(1:0:2) u16" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ comptime {
+ try expect(*align(1:0:2) u16 == *align(1) u16);
+ try expect(*align(2:0:2) u16 == *u16);
+ }
+}
+
+test "array concatenation forces comptime" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ var a = oneItem(3) ++ oneItem(4);
+ try expect(std.mem.eql(i32, &a, &[_]i32{ 3, 4 }));
+}
+
+test "array multiplication forces comptime" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ var a = oneItem(3) ** scalar(2);
+ try expect(std.mem.eql(i32, &a, &[_]i32{ 3, 3 }));
+}
+
+fn oneItem(x: i32) [1]i32 {
+ return [_]i32{x};
+}
+
+fn scalar(x: u32) u32 {
+ return x;
+}
+
+test "comptime assign int to optional int" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ comptime {
+ var x: ?i32 = null;
+ x = 2;
+ x.? *= 10;
+ try expectEqual(20, x.?);
+ }
+}
+
+test "two comptime calls with array default initialized to undefined" {
+ const S = struct {
+ const CrossTarget = struct {
+ dynamic_linker: DynamicLinker = DynamicLinker{},
+
+ pub fn parse() void {
+ var result: CrossTarget = .{};
+ result.getCpuArch();
+ }
+
+ pub fn getCpuArch(self: CrossTarget) void {
+ _ = self;
+ }
+ };
+
+ const DynamicLinker = struct {
+ buffer: [255]u8 = undefined,
+ };
+ };
+
+ comptime {
+ S.CrossTarget.parse();
+ S.CrossTarget.parse();
+ }
+}
test/behavior/eval_stage1.zig
@@ -1,266 +0,0 @@
-const std = @import("std");
-const expect = std.testing.expect;
-const expectEqual = std.testing.expectEqual;
-
-test "static eval list init" {
- try expect(static_vec3.data[2] == 1.0);
- try expect(vec3(0.0, 0.0, 3.0).data[2] == 3.0);
-}
-const static_vec3 = vec3(0.0, 0.0, 1.0);
-pub const Vec3 = struct {
- data: [3]f32,
-};
-pub fn vec3(x: f32, y: f32, z: f32) Vec3 {
- return Vec3{
- .data = [_]f32{ x, y, z },
- };
-}
-
-test "inlined loop has array literal with elided runtime scope on first iteration but not second iteration" {
- var runtime = [1]i32{3};
- comptime var i: usize = 0;
- inline while (i < 2) : (i += 1) {
- const result = if (i == 0) [1]i32{2} else runtime;
- _ = result;
- }
- comptime {
- try expect(i == 2);
- }
-}
-
-test "eval @setFloatMode at compile-time" {
- const result = comptime fnWithFloatMode();
- try expect(result == 1234.0);
-}
-
-fn fnWithFloatMode() f32 {
- @setFloatMode(std.builtin.FloatMode.Strict);
- return 1234.0;
-}
-
-const SimpleStruct = struct {
- field: i32,
-
- fn method(self: *const SimpleStruct) i32 {
- return self.field + 3;
- }
-};
-
-var simple_struct = SimpleStruct{ .field = 1234 };
-
-const bound_fn = simple_struct.method;
-
-test "call method on bound fn referring to var instance" {
- try expect(bound_fn() == 1237);
-}
-
-test "ptr to local array argument at comptime" {
- comptime {
- var bytes: [10]u8 = undefined;
- modifySomeBytes(bytes[0..]);
- try expect(bytes[0] == 'a');
- try expect(bytes[9] == 'b');
- }
-}
-
-fn modifySomeBytes(bytes: []u8) void {
- bytes[0] = 'a';
- bytes[9] = 'b';
-}
-
-test "comparisons 0 <= uint and 0 > uint should be comptime" {
- testCompTimeUIntComparisons(1234);
-}
-fn testCompTimeUIntComparisons(x: u32) void {
- if (!(0 <= x)) {
- @compileError("this condition should be comptime known");
- }
- if (0 > x) {
- @compileError("this condition should be comptime known");
- }
- if (!(x >= 0)) {
- @compileError("this condition should be comptime known");
- }
- if (x < 0) {
- @compileError("this condition should be comptime known");
- }
-}
-
-const hi1 = "hi";
-const hi2 = hi1;
-test "const global shares pointer with other same one" {
- try assertEqualPtrs(&hi1[0], &hi2[0]);
- comptime try expect(&hi1[0] == &hi2[0]);
-}
-fn assertEqualPtrs(ptr1: *const u8, ptr2: *const u8) !void {
- try expect(ptr1 == ptr2);
-}
-
-test "float literal at compile time not lossy" {
- try expect(16777216.0 + 1.0 == 16777217.0);
- try expect(9007199254740992.0 + 1.0 == 9007199254740993.0);
-}
-
-test "f128 at compile time is lossy" {
- try expect(@as(f128, 10384593717069655257060992658440192.0) + 1 == 10384593717069655257060992658440192.0);
-}
-
-pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) type {
- _ = field_name;
- return struct {
- pub const Node = struct {};
- };
-}
-
-test "string literal used as comptime slice is memoized" {
- const a = "link";
- const b = "link";
- comptime try expect(TypeWithCompTimeSlice(a).Node == TypeWithCompTimeSlice(b).Node);
- comptime try expect(TypeWithCompTimeSlice("link").Node == TypeWithCompTimeSlice("link").Node);
-}
-
-test "comptime function with mutable pointer is not memoized" {
- comptime {
- var x: i32 = 1;
- const ptr = &x;
- increment(ptr);
- increment(ptr);
- try expect(x == 3);
- }
-}
-
-fn increment(value: *i32) void {
- value.* += 1;
-}
-
-const SingleFieldStruct = struct {
- x: 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 };
- try expect(foo.read_x() == 1);
- foo.x = 2;
- try expect(foo.read_x() == 2);
- }
-}
-
-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;
- try expect(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();
- try expect(b == 2);
-}
-
-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) {}
-}
-
-test "variable inside inline loop that has different types on different iterations" {
- try testVarInsideInlineLoop(.{ true, @as(u32, 42) });
-}
-
-fn testVarInsideInlineLoop(args: anytype) !void {
- comptime var i = 0;
- inline while (i < args.len) : (i += 1) {
- const x = args[i];
- if (i == 0) try expect(x);
- if (i == 1) try expect(x == 42);
- }
-}
-
-test "bit shift a u1" {
- var x: u1 = 1;
- var y = x << 0;
- try expect(y == 1);
-}
-
-test "*align(1) u16 is the same as *align(1:0:2) u16" {
- comptime {
- try expect(*align(1:0:2) u16 == *align(1) u16);
- try expect(*align(2:0:2) u16 == *u16);
- }
-}
-
-test "array concatenation forces comptime" {
- var a = oneItem(3) ++ oneItem(4);
- try expect(std.mem.eql(i32, &a, &[_]i32{ 3, 4 }));
-}
-
-test "array multiplication forces comptime" {
- var a = oneItem(3) ** scalar(2);
- try expect(std.mem.eql(i32, &a, &[_]i32{ 3, 3 }));
-}
-
-fn oneItem(x: i32) [1]i32 {
- return [_]i32{x};
-}
-
-fn scalar(x: u32) u32 {
- return x;
-}
-
-test "comptime assign int to optional int" {
- comptime {
- var x: ?i32 = null;
- x = 2;
- x.? *= 10;
- try expectEqual(20, x.?);
- }
-}
-
-test "two comptime calls with array default initialized to undefined" {
- const S = struct {
- const CrossTarget = struct {
- dynamic_linker: DynamicLinker = DynamicLinker{},
-
- pub fn parse() void {
- var result: CrossTarget = .{};
- result.getCpuArch();
- }
-
- pub fn getCpuArch(self: CrossTarget) void {
- _ = self;
- }
- };
-
- const DynamicLinker = struct {
- buffer: [255]u8 = undefined,
- };
- };
-
- comptime {
- S.CrossTarget.parse();
- S.CrossTarget.parse();
- }
-}
test/behavior/fn.zig
@@ -250,3 +250,101 @@ test "implicit cast fn call result to optional in field result" {
try S.entry();
comptime try S.entry();
}
+
+test "void parameters" {
+ try voidFun(1, void{}, 2, {});
+}
+fn voidFun(a: i32, b: void, c: i32, d: void) !void {
+ _ = d;
+ const v = b;
+ const vv: void = if (a == 1) v else {};
+ try expect(a + c == 3);
+ return vv;
+}
+
+test "call function with empty string" {
+ acceptsString("");
+}
+
+fn acceptsString(foo: []u8) void {
+ _ = foo;
+}
+
+test "function pointers" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ const fns = [_]@TypeOf(fn1){
+ fn1,
+ fn2,
+ fn3,
+ fn4,
+ };
+ for (fns) |f, i| {
+ try expect(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;
+}
+
+test "number literal as an argument" {
+ try numberLiteralArg(3);
+ comptime try numberLiteralArg(3);
+}
+
+fn numberLiteralArg(a: anytype) !void {
+ try expect(a == 3);
+}
+
+test "function call with anon list literal" {
+ const S = struct {
+ fn doTheTest() !void {
+ try consumeVec(.{ 9, 8, 7 });
+ }
+
+ fn consumeVec(vec: [3]f32) !void {
+ try expect(vec[0] == 9);
+ try expect(vec[1] == 8);
+ try expect(vec[2] == 7);
+ }
+ };
+ try S.doTheTest();
+ comptime try S.doTheTest();
+}
+
+test "ability to give comptime types and non comptime types to same parameter" {
+ const S = struct {
+ fn doTheTest() !void {
+ var x: i32 = 1;
+ try expect(foo(x) == 10);
+ try expect(foo(i32) == 20);
+ }
+
+ fn foo(arg: anytype) i32 {
+ if (@typeInfo(@TypeOf(arg)) == .Type and arg == i32) return 20;
+ return 9 + arg;
+ }
+ };
+ try S.doTheTest();
+ comptime try S.doTheTest();
+}
+
+test "function with inferred error set but returning no error" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ const S = struct {
+ fn foo() !void {}
+ };
+
+ const return_ty = @typeInfo(@TypeOf(S.foo)).Fn.return_type.?;
+ try expectEqual(0, @typeInfo(@typeInfo(return_ty).ErrorUnion.error_set).ErrorSet.?.len);
+}
test/behavior/fn_stage1.zig
@@ -1,99 +0,0 @@
-const std = @import("std");
-const builtin = @import("builtin");
-const testing = std.testing;
-const expect = testing.expect;
-const expectEqual = testing.expectEqual;
-
-test "void parameters" {
- try voidFun(1, void{}, 2, {});
-}
-fn voidFun(a: i32, b: void, c: i32, d: void) !void {
- _ = d;
- const v = b;
- const vv: void = if (a == 1) v else {};
- try expect(a + c == 3);
- return vv;
-}
-
-test "call function with empty string" {
- acceptsString("");
-}
-
-fn acceptsString(foo: []u8) void {
- _ = foo;
-}
-
-test "function pointers" {
- const fns = [_]@TypeOf(fn1){
- fn1,
- fn2,
- fn3,
- fn4,
- };
- for (fns) |f, i| {
- try expect(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;
-}
-
-test "number literal as an argument" {
- try numberLiteralArg(3);
- comptime try numberLiteralArg(3);
-}
-
-fn numberLiteralArg(a: anytype) !void {
- try expect(a == 3);
-}
-
-test "function call with anon list literal" {
- const S = struct {
- fn doTheTest() !void {
- try consumeVec(.{ 9, 8, 7 });
- }
-
- fn consumeVec(vec: [3]f32) !void {
- try expect(vec[0] == 9);
- try expect(vec[1] == 8);
- try expect(vec[2] == 7);
- }
- };
- try S.doTheTest();
- comptime try S.doTheTest();
-}
-
-test "ability to give comptime types and non comptime types to same parameter" {
- const S = struct {
- fn doTheTest() !void {
- var x: i32 = 1;
- try expect(foo(x) == 10);
- try expect(foo(i32) == 20);
- }
-
- fn foo(arg: anytype) i32 {
- if (@typeInfo(@TypeOf(arg)) == .Type and arg == i32) return 20;
- return 9 + arg;
- }
- };
- try S.doTheTest();
- comptime try S.doTheTest();
-}
-
-test "function with inferred error set but returning no error" {
- const S = struct {
- fn foo() !void {}
- };
-
- const return_ty = @typeInfo(@TypeOf(S.foo)).Fn.return_type.?;
- try expectEqual(0, @typeInfo(@typeInfo(return_ty).ErrorUnion.error_set).ErrorSet.?.len);
-}
test/behavior/for.zig
@@ -1,3 +1,4 @@
+const builtin = @import("builtin");
const std = @import("std");
const expect = std.testing.expect;
const expectEqual = std.testing.expectEqual;
@@ -133,3 +134,59 @@ test "2 break statements and an else" {
try S.entry(true, false);
comptime try S.entry(true, false);
}
+
+test "for loop with pointer elem var" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ const source = "abcdefg";
+ var target: [source.len]u8 = undefined;
+ mem.copy(u8, target[0..], source);
+ mangleString(target[0..]);
+ try expect(mem.eql(u8, &target, "bcdefgh"));
+
+ for (source) |*c, i| {
+ _ = i;
+ try expect(@TypeOf(c) == *const u8);
+ }
+ for (target) |*c, i| {
+ _ = i;
+ try expect(@TypeOf(c) == *u8);
+ }
+}
+
+fn mangleString(s: []u8) void {
+ for (s) |*c| {
+ c.* += 1;
+ }
+}
+
+test "for copies its payload" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ const S = struct {
+ fn doTheTest() !void {
+ var x = [_]usize{ 1, 2, 3 };
+ for (x) |value, i| {
+ // Modify the original array
+ x[i] += 99;
+ try expectEqual(value, i + 1);
+ }
+ }
+ };
+ try S.doTheTest();
+ comptime try S.doTheTest();
+}
+
+test "for on slice with allowzero ptr" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ const S = struct {
+ fn doTheTest(slice: []const u8) !void {
+ var ptr = @ptrCast([*]allowzero const u8, slice.ptr)[0..slice.len];
+ for (ptr) |x, i| try expect(x == i + 1);
+ for (ptr) |*x, i| try expect(x.* == i + 1);
+ }
+ };
+ try S.doTheTest(&[_]u8{ 1, 2, 3, 4 });
+ comptime try S.doTheTest(&[_]u8{ 1, 2, 3, 4 });
+}
test/behavior/for_stage1.zig
@@ -1,54 +0,0 @@
-const std = @import("std");
-const expect = std.testing.expect;
-const expectEqual = std.testing.expectEqual;
-const mem = std.mem;
-
-test "for loop with pointer elem var" {
- const source = "abcdefg";
- var target: [source.len]u8 = undefined;
- mem.copy(u8, target[0..], source);
- mangleString(target[0..]);
- try expect(mem.eql(u8, &target, "bcdefgh"));
-
- for (source) |*c, i| {
- _ = i;
- try expect(@TypeOf(c) == *const u8);
- }
- for (target) |*c, i| {
- _ = i;
- try expect(@TypeOf(c) == *u8);
- }
-}
-
-fn mangleString(s: []u8) void {
- for (s) |*c| {
- c.* += 1;
- }
-}
-
-test "for copies its payload" {
- const S = struct {
- fn doTheTest() !void {
- var x = [_]usize{ 1, 2, 3 };
- for (x) |value, i| {
- // Modify the original array
- x[i] += 99;
- try expectEqual(value, i + 1);
- }
- }
- };
- try S.doTheTest();
- comptime try S.doTheTest();
-}
-
-test "for on slice with allowzero ptr" {
- const S = struct {
- fn doTheTest(slice: []const u8) !void {
- var ptr = @ptrCast([*]allowzero const u8, slice.ptr)[0..slice.len];
- for (ptr) |x, i| try expect(x == i + 1);
- for (ptr) |*x, i| try expect(x.* == i + 1);
- }
- };
- try S.doTheTest(&[_]u8{ 1, 2, 3, 4 });
- comptime try S.doTheTest(&[_]u8{ 1, 2, 3, 4 });
-}
test/behavior/if.zig
@@ -1,3 +1,4 @@
+const builtin = @import("builtin");
const std = @import("std");
const expect = std.testing.expect;
const expectEqual = std.testing.expectEqual;
@@ -88,3 +89,21 @@ test "if copies its payload" {
try S.doTheTest();
comptime try S.doTheTest();
}
+
+test "if prongs cast to expected type instead of peer type resolution" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ const S = struct {
+ fn doTheTest(f: bool) !void {
+ var x: i32 = 0;
+ x = if (f) 1 else 2;
+ try expect(x == 2);
+
+ var b = true;
+ const y: i32 = if (b) 1 else 2;
+ try expect(y == 1);
+ }
+ };
+ try S.doTheTest(false);
+ comptime try S.doTheTest(false);
+}
test/behavior/if_stage1.zig
@@ -1,19 +0,0 @@
-const std = @import("std");
-const expect = std.testing.expect;
-const expectEqual = std.testing.expectEqual;
-
-test "if prongs cast to expected type instead of peer type resolution" {
- const S = struct {
- fn doTheTest(f: bool) !void {
- var x: i32 = 0;
- x = if (f) 1 else 2;
- try expect(x == 2);
-
- var b = true;
- const y: i32 = if (b) 1 else 2;
- try expect(y == 1);
- }
- };
- try S.doTheTest(false);
- comptime try S.doTheTest(false);
-}
test/behavior/misc.zig
@@ -5,63 +5,6 @@ const expectEqualStrings = std.testing.expectEqualStrings;
const mem = std.mem;
const builtin = @import("builtin");
-fn emptyFn() void {}
-
-const addr1 = @ptrCast(*const u8, emptyFn);
-test "comptime cast fn to ptr" {
- const addr2 = @ptrCast(*const u8, emptyFn);
- comptime try expect(addr1 == addr2);
-}
-
-test "equality compare fn ptrs" {
- var a = emptyFn;
- try expect(a == a);
-}
-
-test "string escapes" {
- try expectEqualStrings("\"", "\x22");
- try expectEqualStrings("\'", "\x27");
- try expectEqualStrings("\n", "\x0a");
- try expectEqualStrings("\r", "\x0d");
- try expectEqualStrings("\t", "\x09");
- try expectEqualStrings("\\", "\x5c");
- try expectEqualStrings("\u{1234}\u{069}\u{1}", "\xe1\x88\xb4\x69\x01");
-}
-
-test "explicit cast optional pointers" {
- const a: ?*i32 = undefined;
- const b: ?*f32 = @ptrCast(?*f32, a);
- _ = b;
-}
-
-test "pointer comparison" {
- const a = @as([]const u8, "a");
- const b = &a;
- try expect(ptrEql(b, b));
-}
-fn ptrEql(a: *const []const u8, b: *const []const u8) bool {
- return a == b;
-}
-
-test "string concatenation" {
- const a = "OK" ++ " IT " ++ "WORKED";
- const b = "OK IT WORKED";
-
- comptime try expect(@TypeOf(a) == *const [12:0]u8);
- comptime try expect(@TypeOf(b) == *const [12:0]u8);
-
- const len = mem.len(b);
- const len_with_null = len + 1;
- {
- var i: u32 = 0;
- while (i < len_with_null) : (i += 1) {
- try expect(a[i] == b[i]);
- }
- }
- try expect(a[len] == 0);
- try expect(b[len] == 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];
@@ -91,76 +34,3 @@ export fn testPackedStuff(a: *const PackedStruct, b: *const PackedUnion) void {
b;
}
}
-
-test "thread local variable" {
- const S = struct {
- threadlocal var t: i32 = 1234;
- };
- S.t += 1;
- try expect(S.t == 1235);
-}
-
-fn maybe(x: bool) anyerror!?u32 {
- return switch (x) {
- true => @as(u32, 42),
- else => null,
- };
-}
-
-test "result location is optional inside error union" {
- const x = maybe(true) catch unreachable;
- try expect(x.? == 42);
-}
-
-threadlocal var buffer: [11]u8 = undefined;
-
-test "pointer to thread local array" {
- const s = "Hello world";
- std.mem.copy(u8, buffer[0..], s);
- try std.testing.expectEqualSlices(u8, buffer[0..], s);
-}
-
-test "auto created variables have correct alignment" {
- const S = struct {
- fn foo(str: [*]const u8) u32 {
- for (@ptrCast([*]align(1) const u32, str)[0..1]) |v| {
- return v;
- }
- return 0;
- }
- };
- try expect(S.foo("\x7a\x7a\x7a\x7a") == 0x7a7a7a7a);
- comptime try expect(S.foo("\x7a\x7a\x7a\x7a") == 0x7a7a7a7a);
-}
-
-extern var opaque_extern_var: opaque {};
-var var_to_export: u32 = 42;
-test "extern variable with non-pointer opaque type" {
- @export(var_to_export, .{ .name = "opaque_extern_var" });
- try expect(@ptrCast(*align(1) u32, &opaque_extern_var).* == 42);
-}
-
-test "lazy typeInfo value as generic parameter" {
- const S = struct {
- fn foo(args: anytype) void {
- _ = args;
- }
- };
- S.foo(@typeInfo(@TypeOf(.{})));
-}
-
-test "variable name containing underscores does not shadow int primitive" {
- const _u0 = 0;
- const i_8 = 0;
- const u16_ = 0;
- const i3_2 = 0;
- const u6__4 = 0;
- const i2_04_8 = 0;
-
- _ = _u0;
- _ = i_8;
- _ = u16_;
- _ = i3_2;
- _ = u6__4;
- _ = i2_04_8;
-}
test/behavior.zig
@@ -91,8 +91,9 @@ test {
// Tests that pass for stage1 and the llvm backend.
_ = @import("behavior/array_llvm.zig");
_ = @import("behavior/atomics.zig");
- _ = @import("behavior/basic_llvm.zig");
+ _ = @import("behavior/bugs/1025.zig");
_ = @import("behavior/bugs/1741.zig");
+ _ = @import("behavior/bugs/1914.zig");
_ = @import("behavior/bugs/2578.zig");
_ = @import("behavior/bugs/3007.zig");
_ = @import("behavior/bugs/9584.zig");
@@ -116,13 +117,11 @@ test {
if (builtin.zig_backend == .stage1) {
// Tests that only pass for the stage1 backend.
- _ = @import("behavior/align_stage1.zig");
if (builtin.os.tag != .wasi) {
_ = @import("behavior/asm.zig");
_ = @import("behavior/async_fn.zig");
}
_ = @import("behavior/await_struct.zig");
- _ = @import("behavior/bitcast_stage1.zig");
_ = @import("behavior/bitreverse.zig");
_ = @import("behavior/bugs/421.zig");
_ = @import("behavior/bugs/529.zig");
@@ -130,14 +129,12 @@ test {
_ = @import("behavior/bugs/726.zig");
_ = @import("behavior/bugs/828.zig");
_ = @import("behavior/bugs/920.zig");
- _ = @import("behavior/bugs/1025.zig");
_ = @import("behavior/bugs/1076.zig");
_ = @import("behavior/bugs/1120.zig");
_ = @import("behavior/bugs/1421.zig");
_ = @import("behavior/bugs/1442.zig");
_ = @import("behavior/bugs/1607.zig");
_ = @import("behavior/bugs/1851.zig");
- _ = @import("behavior/bugs/1914.zig");
_ = @import("behavior/bugs/2114.zig");
_ = @import("behavior/bugs/3384.zig");
_ = @import("behavior/bugs/3742.zig");
@@ -155,18 +152,11 @@ test {
_ = @import("behavior/bugs/10147.zig");
_ = @import("behavior/byteswap.zig");
_ = @import("behavior/call_stage1.zig");
- _ = @import("behavior/cast_stage1.zig");
_ = @import("behavior/const_slice_child.zig");
- _ = @import("behavior/defer_stage1.zig");
- _ = @import("behavior/enum_stage1.zig");
_ = @import("behavior/error_stage1.zig");
- _ = @import("behavior/eval_stage1.zig");
_ = @import("behavior/field_parent_ptr.zig");
_ = @import("behavior/floatop_stage1.zig");
- _ = @import("behavior/fn_stage1.zig");
_ = @import("behavior/fn_delegation.zig");
- _ = @import("behavior/for_stage1.zig");
- _ = @import("behavior/if_stage1.zig");
_ = @import("behavior/ir_block_deps.zig");
_ = @import("behavior/math_stage1.zig");
_ = @import("behavior/misc.zig");