const builtin = @import("builtin"); const std = @import("std"); const expect = std.testing.expect; const mem = std.mem; const maxInt = std.math.maxInt; const native_endian = builtin.target.cpu.arch.endian(); test "int to ptr cast" { const x = @as(usize, 13); const y = @intToPtr(*u8, x); const z = @ptrToInt(y); try expect(z == 13); } test "integer literal to pointer cast" { const vga_mem = @intToPtr(*u16, 0xB8000); try expect(@ptrToInt(vga_mem) == 0xB8000); } test "peer type resolution: ?T and T" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO try expect(peerTypeTAndOptionalT(true, false).? == 0); try expect(peerTypeTAndOptionalT(false, false).? == 3); comptime { try expect(peerTypeTAndOptionalT(true, false).? == 0); try expect(peerTypeTAndOptionalT(false, false).? == 3); } } fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize { if (c) { return if (b) null else @as(usize, 0); } return @as(usize, 3); } test "resolve undefined with integer" { try testResolveUndefWithInt(true, 1234); comptime try testResolveUndefWithInt(true, 1234); } fn testResolveUndefWithInt(b: bool, x: i32) !void { const value = if (b) x else undefined; if (b) { try expect(value == x); } } test "@intCast to comptime_int" { try expect(@intCast(comptime_int, 0) == 0); } test "implicit cast comptime numbers to any type when the value fits" { const a: u64 = 255; var b: u8 = a; try expect(b == 255); } test "implicit cast comptime_int to comptime_float" { comptime try expect(@as(comptime_float, 10) == @as(f32, 10)); try expect(2 == 2.0); } test "comptime_int @intToFloat" { { const result = @intToFloat(f16, 1234); try expect(@TypeOf(result) == f16); try expect(result == 1234.0); } { const result = @intToFloat(f32, 1234); try expect(@TypeOf(result) == f32); try expect(result == 1234.0); } { const result = @intToFloat(f64, 1234); try expect(@TypeOf(result) == f64); try expect(result == 1234.0); } { const result = @intToFloat(f128, 1234); try expect(@TypeOf(result) == f128); try expect(result == 1234.0); } // big comptime_int (> 64 bits) to f128 conversion { const result = @intToFloat(f128, 0x1_0000_0000_0000_0000); try expect(@TypeOf(result) == f128); try expect(result == 0x1_0000_0000_0000_0000.0); } } test "@intToFloat" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO const S = struct { fn doTheTest() !void { try testIntToFloat(-2); } fn testIntToFloat(k: i32) !void { const f = @intToFloat(f32, k); const i = @floatToInt(i32, f); try expect(i == k); } }; try S.doTheTest(); comptime try S.doTheTest(); } test "@intToFloat(f80)" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO const S = struct { fn doTheTest(comptime Int: type) !void { try testIntToFloat(Int, -2); } fn testIntToFloat(comptime Int: type, k: Int) !void { @setRuntimeSafety(false); // TODO const f = @intToFloat(f80, k); const i = @floatToInt(Int, f); try expect(i == k); } }; try S.doTheTest(i31); try S.doTheTest(i32); try S.doTheTest(i45); try S.doTheTest(i64); try S.doTheTest(i80); try S.doTheTest(i128); // try S.doTheTest(i256); // TODO missing compiler_rt symbols comptime try S.doTheTest(i31); comptime try S.doTheTest(i32); comptime try S.doTheTest(i45); comptime try S.doTheTest(i64); comptime try S.doTheTest(i80); comptime try S.doTheTest(i128); comptime try S.doTheTest(i256); } test "@floatToInt" { if (builtin.zig_backend == .stage2_aarch64) 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 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO try testFloatToInts(); comptime try testFloatToInts(); } fn testFloatToInts() !void { const x = @as(i32, 1e4); try expect(x == 10000); const y = @floatToInt(i32, @as(f32, 1e4)); try expect(y == 10000); try expectFloatToInt(f32, 255.1, u8, 255); try expectFloatToInt(f32, 127.2, i8, 127); try expectFloatToInt(f32, -128.2, i8, -128); } fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) !void { try expect(@floatToInt(I, f) == i); } test "implicitly cast indirect pointer to maybe-indirect pointer" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO const S = struct { const Self = @This(); x: u8, fn constConst(p: *const *const Self) u8 { return p.*.x; } fn maybeConstConst(p: ?*const *const Self) u8 { return p.?.*.x; } fn constConstConst(p: *const *const *const Self) u8 { return p.*.*.x; } fn maybeConstConstConst(p: ?*const *const *const Self) u8 { return p.?.*.*.x; } }; const s = S{ .x = 42 }; const p = &s; const q = &p; const r = &q; try expect(42 == S.constConst(q)); try expect(42 == S.maybeConstConst(q)); try expect(42 == S.constConstConst(r)); try expect(42 == S.maybeConstConstConst(r)); } test "@intCast comptime_int" { const result = @intCast(i32, 1234); try expect(@TypeOf(result) == i32); try expect(result == 1234); } test "@floatCast comptime_int and comptime_float" { { const result = @floatCast(f16, 1234); try expect(@TypeOf(result) == f16); try expect(result == 1234.0); } { const result = @floatCast(f16, 1234.0); try expect(@TypeOf(result) == f16); try expect(result == 1234.0); } { const result = @floatCast(f32, 1234); try expect(@TypeOf(result) == f32); try expect(result == 1234.0); } { const result = @floatCast(f32, 1234.0); try expect(@TypeOf(result) == f32); try expect(result == 1234.0); } } test "coerce undefined to optional" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO try expect(MakeType(void).getNull() == null); try expect(MakeType(void).getNonNull() != null); } fn MakeType(comptime T: type) type { return struct { fn getNull() ?T { return null; } fn getNonNull() ?T { return @as(T, undefined); } }; } test "implicit cast from *[N]T to [*c]T" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO var x: [4]u16 = [4]u16{ 0, 1, 2, 3 }; var y: [*c]u16 = &x; try expect(std.mem.eql(u16, x[0..4], y[0..4])); x[0] = 8; y[3] = 6; try expect(std.mem.eql(u16, x[0..4], y[0..4])); } test "*usize to *void" { var i = @as(usize, 0); var v = @ptrCast(*void, &i); v.* = {}; } test "@intToEnum passed a comptime_int to an enum with one item" { const E = enum { A }; const x = @intToEnum(E, 0); try expect(x == E.A); } test "@intCast to u0 and use the result" { const S = struct { fn doTheTest(zero: u1, one: u1, bigzero: i32) !void { try expect((one << @intCast(u0, bigzero)) == 1); try expect((zero << @intCast(u0, bigzero)) == 0); } }; try S.doTheTest(0, 1, 0); comptime try S.doTheTest(0, 1, 0); } test "peer result null and comptime_int" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO const S = struct { fn blah(n: i32) ?i32 { if (n == 0) { return null; } else if (n < 0) { return -1; } else { return 1; } } }; try expect(S.blah(0) == null); comptime try expect(S.blah(0) == null); try expect(S.blah(10).? == 1); comptime try expect(S.blah(10).? == 1); try expect(S.blah(-10).? == -1); comptime try expect(S.blah(-10).? == -1); } test "*const ?[*]const T to [*c]const [*c]const T" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO var array = [_]u8{ 'o', 'k' }; const opt_array_ptr: ?[*]const u8 = &array; const a: *const ?[*]const u8 = &opt_array_ptr; const b: [*c]const [*c]const u8 = a; try expect(b.*[0] == 'o'); try expect(b[0][1] == 'k'); } test "array coersion to undefined at runtime" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO @setRuntimeSafety(true); if (builtin.mode != .Debug and builtin.mode != .ReleaseSafe) { return error.SkipZigTest; } var array = [4]u8{ 3, 4, 5, 6 }; var undefined_val = [4]u8{ 0xAA, 0xAA, 0xAA, 0xAA }; try expect(std.mem.eql(u8, &array, &array)); array = undefined; try expect(std.mem.eql(u8, &array, &undefined_val)); } test "implicitly cast from int to anyerror!?T" { implicitIntLitToOptional(); comptime implicitIntLitToOptional(); } fn implicitIntLitToOptional() void { const f: ?i32 = 1; _ = f; const g: anyerror!?i32 = 1; _ = g catch {}; } test "return u8 coercing into ?u32 return type" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO const S = struct { fn doTheTest() !void { try expect(foo(123).? == 123); } fn foo(arg: u8) ?u32 { return arg; } }; try S.doTheTest(); comptime try S.doTheTest(); } test "cast from ?[*]T to ??[*]T" { const a: ??[*]u8 = @as(?[*]u8, null); try expect(a != null and a.? == null); } test "peer type unsigned int to signed" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO var w: u31 = 5; var x: u8 = 7; var y: i32 = -5; var a = w + y + x; comptime try expect(@TypeOf(a) == i32); try expect(a == 7); } test "expected [*c]const u8, found [*:0]const u8" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO var a: [*:0]const u8 = "hello"; var b: [*c]const u8 = a; 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 == .stage2_wasm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) 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 == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) 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 == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) 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; _ = try g; 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_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) 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 == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) 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 == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) 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_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) 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 == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) 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 == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) 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 == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) 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 == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) 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 == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) 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: error set any anyerror" { const a: error{ One, Two } = undefined; const b: anyerror = undefined; try expect(@TypeOf(a, b) == anyerror); try expect(@TypeOf(b, a) == anyerror); } test "peer type resolution: error set supersets" { if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO const a: error{ One, Two } = undefined; const b: error{One} = undefined; // A superset of B { const ty = @TypeOf(a, b); const error_set_info = @typeInfo(ty); try expect(error_set_info == .ErrorSet); try expect(error_set_info.ErrorSet.?.len == 2); try expect(mem.eql(u8, error_set_info.ErrorSet.?[0].name, "One")); try expect(mem.eql(u8, error_set_info.ErrorSet.?[1].name, "Two")); } // B superset of A { const ty = @TypeOf(b, a); const error_set_info = @typeInfo(ty); try expect(error_set_info == .ErrorSet); try expect(error_set_info.ErrorSet.?.len == 2); try expect(mem.eql(u8, error_set_info.ErrorSet.?[0].name, "One")); try expect(mem.eql(u8, error_set_info.ErrorSet.?[1].name, "Two")); } } test "peer type resolution: disjoint error sets" { if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO const a: error{ One, Two } = undefined; const b: error{Three} = undefined; { const ty = @TypeOf(a, b); const error_set_info = @typeInfo(ty); try expect(error_set_info == .ErrorSet); try expect(error_set_info.ErrorSet.?.len == 3); try expect(mem.eql(u8, error_set_info.ErrorSet.?[0].name, "One")); try expect(mem.eql(u8, error_set_info.ErrorSet.?[1].name, "Three")); try expect(mem.eql(u8, error_set_info.ErrorSet.?[2].name, "Two")); } { const ty = @TypeOf(b, a); const error_set_info = @typeInfo(ty); try expect(error_set_info == .ErrorSet); try expect(error_set_info.ErrorSet.?.len == 3); try expect(mem.eql(u8, error_set_info.ErrorSet.?[0].name, "One")); try expect(mem.eql(u8, error_set_info.ErrorSet.?[1].name, "Three")); try expect(mem.eql(u8, error_set_info.ErrorSet.?[2].name, "Two")); } } test "peer type resolution: error union and error set" { if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO const a: error{Three} = undefined; const b: error{ One, Two }!u32 = undefined; { const ty = @TypeOf(a, b); const info = @typeInfo(ty); try expect(info == .ErrorUnion); const error_set_info = @typeInfo(info.ErrorUnion.error_set); try expect(error_set_info.ErrorSet.?.len == 3); try expect(mem.eql(u8, error_set_info.ErrorSet.?[0].name, "One")); try expect(mem.eql(u8, error_set_info.ErrorSet.?[1].name, "Three")); try expect(mem.eql(u8, error_set_info.ErrorSet.?[2].name, "Two")); } { const ty = @TypeOf(b, a); const info = @typeInfo(ty); try expect(info == .ErrorUnion); const error_set_info = @typeInfo(info.ErrorUnion.error_set); try expect(error_set_info.ErrorSet.?.len == 3); try expect(mem.eql(u8, error_set_info.ErrorSet.?[0].name, "One")); try expect(mem.eql(u8, error_set_info.ErrorSet.?[1].name, "Three")); try expect(mem.eql(u8, error_set_info.ErrorSet.?[2].name, "Two")); } } test "peer type resolution: error union after non-error" { if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO const a: u32 = undefined; const b: error{ One, Two }!u32 = undefined; { const ty = @TypeOf(a, b); const info = @typeInfo(ty); try expect(info == .ErrorUnion); try expect(info.ErrorUnion.payload == u32); const error_set_info = @typeInfo(info.ErrorUnion.error_set); try expect(error_set_info.ErrorSet.?.len == 2); try expect(mem.eql(u8, error_set_info.ErrorSet.?[0].name, "One")); try expect(mem.eql(u8, error_set_info.ErrorSet.?[1].name, "Two")); } { const ty = @TypeOf(b, a); const info = @typeInfo(ty); try expect(info == .ErrorUnion); try expect(info.ErrorUnion.payload == u32); const error_set_info = @typeInfo(info.ErrorUnion.error_set); try expect(error_set_info.ErrorSet.?.len == 2); try expect(mem.eql(u8, error_set_info.ErrorSet.?[0].name, "One")); try expect(mem.eql(u8, error_set_info.ErrorSet.?[1].name, "Two")); } } test "peer cast *[0]T to E![]const T" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) 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; var z = if (!b) buf else &[0]u8{}; try expect(mem.eql(u8, "abcde", y catch unreachable)); try expect(mem.eql(u8, "abcde", z catch unreachable)); } test "peer cast *[0]T to []const T" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) 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 cast *[N]T to [*]T" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO var array = [4:99]i32{ 1, 2, 3, 4 }; var dest: [*]i32 = undefined; try expect(@TypeOf(&array, dest) == [*]i32); try expect(@TypeOf(dest, &array) == [*]i32); } test "peer resolution of string literals" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) 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 "peer cast [:x]T to []T" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO const S = struct { fn doTheTest() !void { 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 })); } }; try S.doTheTest(); comptime try S.doTheTest(); } test "peer cast [N:x]T to [N]T" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO const S = struct { fn doTheTest() !void { 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 })); } }; try S.doTheTest(); comptime try S.doTheTest(); } test "peer cast *[N:x]T to *[N]T" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO const S = struct { fn doTheTest() !void { 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 })); } }; try S.doTheTest(); comptime try S.doTheTest(); } test "peer cast [*:x]T to [*]T" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO const S = struct { fn doTheTest() !void { 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); } }; try S.doTheTest(); comptime try S.doTheTest(); } test "peer cast [:x]T to [*:x]T" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO const S = struct { fn doTheTest() !void { 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_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) 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_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) 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" { 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 == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) 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(); comptime try S.doTheTest(); } test "peer type resolve string lit with sentinel-terminated mutable slice" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) 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" { 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); } test "pointer reinterpret const float to int" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO // The hex representation is 0x3fe3333333333303. const float: f64 = 5.99999999999994648725e-01; const float_ptr = &float; const int_ptr = @ptrCast(*const i32, float_ptr); const int_val = int_ptr.*; if (native_endian == .Little) try expect(int_val == 0x33333303) else try expect(int_val == 0x3fe33333); } test "implicit cast from [*]T to ?*anyopaque" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO var a = [_]u8{ 3, 2, 1 }; var runtime_zero: usize = 0; incrementVoidPtrArray(a[runtime_zero..].ptr, 3); try expect(std.mem.eql(u8, &a, &[_]u8{ 4, 3, 2 })); } fn incrementVoidPtrArray(array: ?*anyopaque, len: usize) void { var n: usize = 0; while (n < len) : (n += 1) { @ptrCast([*]u8, array.?)[n] += 1; } } test "compile time int to ptr of function" { if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO try foobar(FUNCTION_CONSTANT); } // On some architectures function pointers must be aligned. const hardcoded_fn_addr = maxInt(usize) & ~@as(usize, 0xf); pub const FUNCTION_CONSTANT = @intToPtr(PFN_void, hardcoded_fn_addr); pub const PFN_void = *const fn (*anyopaque) callconv(.C) void; fn foobar(func: PFN_void) !void { try std.testing.expect(@ptrToInt(func) == hardcoded_fn_addr); } test "implicit ptr to *anyopaque" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO var a: u32 = 1; var ptr: *align(@alignOf(u32)) anyopaque = &a; var b: *u32 = @ptrCast(*u32, ptr); try expect(b.* == 1); var ptr2: ?*align(@alignOf(u32)) anyopaque = &a; var c: *u32 = @ptrCast(*u32, ptr2.?); try expect(c.* == 1); } test "return null from fn() anyerror!?&T" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO const a = returnNullFromOptionalTypeErrorRef(); const b = returnNullLitFromOptionalTypeErrorRef(); try expect((try a) == null and (try b) == null); } fn returnNullFromOptionalTypeErrorRef() anyerror!?*A { const a: ?*A = null; return a; } fn returnNullLitFromOptionalTypeErrorRef() anyerror!?*A { return null; } test "peer type resolution: [0]u8 and []const u8" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO try expect(peerTypeEmptyArrayAndSlice(true, "hi").len == 0); try expect(peerTypeEmptyArrayAndSlice(false, "hi").len == 1); comptime { try expect(peerTypeEmptyArrayAndSlice(true, "hi").len == 0); try expect(peerTypeEmptyArrayAndSlice(false, "hi").len == 1); } } fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 { if (a) { return &[_]u8{}; } return slice[0..1]; } test "implicitly cast from [N]T to ?[]const T" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO try expect(mem.eql(u8, castToOptionalSlice().?, "hi")); comptime try expect(mem.eql(u8, castToOptionalSlice().?, "hi")); } fn castToOptionalSlice() ?[]const u8 { return "hi"; } test "cast u128 to f128 and back" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO comptime try testCast128(); try testCast128(); } fn testCast128() !void { try expect(cast128Int(cast128Float(0x7fff0000000000000000000000000000)) == 0x7fff0000000000000000000000000000); } fn cast128Int(x: f128) u128 { return @bitCast(u128, x); } fn cast128Float(x: u128) f128 { return @bitCast(f128, x); } test "implicit cast from *[N]T to ?[*]T" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO var x: ?[*]u16 = null; var y: [4]u16 = [4]u16{ 0, 1, 2, 3 }; x = &y; try expect(std.mem.eql(u16, x.?[0..4], y[0..4])); x.?[0] = 8; y[3] = 6; try expect(std.mem.eql(u16, x.?[0..4], y[0..4])); } test "implicit cast from *T to ?*anyopaque" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO var a: u8 = 1; incrementVoidPtrValue(&a); try std.testing.expect(a == 2); } fn incrementVoidPtrValue(value: ?*anyopaque) void { @ptrCast(*u8, value.?).* += 1; } test "implicit cast *[0]T to E![]const u8" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO var x = @as(anyerror![]const u8, &[0]u8{}); try expect((x catch unreachable).len == 0); } var global_array: [4]u8 = undefined; test "cast from array reference to fn: comptime fn ptr" { const f = @ptrCast(*align(1) const fn () callconv(.C) void, &global_array); try expect(@ptrToInt(f) == @ptrToInt(&global_array)); } test "cast from array reference to fn: runtime fn ptr" { var f = @ptrCast(*align(1) const fn () callconv(.C) void, &global_array); try expect(@ptrToInt(f) == @ptrToInt(&global_array)); } test "*const [N]null u8 to ?[]const u8" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO const S = struct { fn doTheTest() !void { var a = "Hello"; var b: ?[]const u8 = a; try expect(mem.eql(u8, b.?, "Hello")); } }; try S.doTheTest(); comptime try S.doTheTest(); } test "cast between [*c]T and ?[*:0]T on fn parameter" { const S = struct { const Handler = ?fn ([*c]const u8) callconv(.C) void; fn addCallback(comptime handler: Handler) void { _ = handler; } fn myCallback(cstr: ?[*:0]const u8) callconv(.C) void { _ = cstr; } fn doTheTest() void { addCallback(myCallback); } }; S.doTheTest(); } var global_struct: struct { f0: usize } = undefined; test "assignment to optional pointer result loc" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO var foo: struct { ptr: ?*anyopaque } = .{ .ptr = &global_struct }; try expect(foo.ptr.? == @ptrCast(*anyopaque, &global_struct)); } test "cast between *[N]void and []void" { var a: [4]void = undefined; var b: []void = &a; try expect(b.len == 4); } test "peer resolve arrays of different size to const slice" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO try expect(mem.eql(u8, boolToStr(true), "true")); try expect(mem.eql(u8, boolToStr(false), "false")); comptime try expect(mem.eql(u8, boolToStr(true), "true")); comptime try expect(mem.eql(u8, boolToStr(false), "false")); } fn boolToStr(b: bool) []const u8 { return if (b) "true" else "false"; } test "cast f16 to wider types" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO const S = struct { fn doTheTest() !void { var x: f16 = 1234.0; try expect(@as(f32, 1234.0) == x); try expect(@as(f64, 1234.0) == x); try expect(@as(f128, 1234.0) == x); } }; try S.doTheTest(); comptime try S.doTheTest(); } test "cast f128 to narrower types" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.os.tag == .windows and builtin.cpu.arch == .aarch64 and builtin.zig_backend == .stage2_c) { // https://github.com/ziglang/zig/issues/13876 return error.SkipZigTest; } const S = struct { fn doTheTest() !void { var x: f128 = 1234.0; try expect(@as(f16, 1234.0) == @floatCast(f16, x)); try expect(@as(f32, 1234.0) == @floatCast(f32, x)); try expect(@as(f64, 1234.0) == @floatCast(f64, x)); } }; try S.doTheTest(); comptime try S.doTheTest(); } test "peer type resolution: unreachable, null, slice" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO const S = struct { fn doTheTest(num: usize, word: []const u8) !void { const result = switch (num) { 0 => null, 1 => word, else => unreachable, }; try expect(mem.eql(u8, result.?, "hi")); } }; try S.doTheTest(1, "hi"); } test "cast i8 fn call peers to i32 result" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO const S = struct { fn doTheTest() !void { var cond = true; const value: i32 = if (cond) smallBoi() else bigBoi(); try expect(value == 123); } fn smallBoi() i8 { return 123; } fn bigBoi() i16 { return 1234; } }; try S.doTheTest(); comptime try S.doTheTest(); } test "cast compatible optional types" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO var a: ?[:0]const u8 = null; var b: ?[]const u8 = a; try expect(b == null); } test "coerce undefined single-item pointer of array to error union of slice" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO const a = @as([*]u8, undefined)[0..0]; var b: error{a}![]const u8 = a; const s = try b; try expect(s.len == 0); } test "pointer to empty struct literal to mutable slice" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO var x: []i32 = &.{}; try expect(x.len == 0); } test "coerce between pointers of compatible differently-named floats" { if (builtin.zig_backend == .stage2_aarch64) 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 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.os.tag == .windows) { // https://github.com/ziglang/zig/issues/12396 return error.SkipZigTest; } const F = switch (@typeInfo(c_longdouble).Float.bits) { 16 => f16, 32 => f32, 64 => f64, 80 => f80, 128 => f128, else => @compileError("unreachable"), }; var f1: F = 12.34; var f2: *c_longdouble = &f1; f2.* += 1; try expect(f1 == @as(F, 12.34) + 1); } test "peer type resolution of const and non-const pointer to array" { const a = @intToPtr(*[1024]u8, 42); const b = @intToPtr(*const [1024]u8, 42); try std.testing.expect(@TypeOf(a, b) == *const [1024]u8); try std.testing.expect(a == b); } test "floatToInt to zero-bit int" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO var a: f32 = 0.0; comptime try std.testing.expect(@floatToInt(u0, a) == 0); } test "peer type resolution of function pointer and function body" { const T = fn () u32; const a: T = undefined; const b: *const T = undefined; try expect(@TypeOf(a, b) == *const fn () u32); try expect(@TypeOf(b, a) == *const fn () u32); } test "cast typed undefined to int" { comptime { const a: u16 = undefined; const b: u8 = a; _ = b; } }