const builtin = @import("builtin"); const std = @import("std"); const assert = std.debug.assert; const expect = std.testing.expect; const expectEqual = std.testing.expectEqual; const expectEqualSlices = std.testing.expectEqualSlices; const mem = std.mem; const maxInt = std.math.maxInt; const native_endian = builtin.target.cpu.arch.endian(); test "int to ptr cast" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const x = @as(usize, 13); const y = @as(*u8, @ptrFromInt(x)); const z = @intFromPtr(y); try expect(z == 13); } test "integer literal to pointer cast" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const vga_mem = @as(*u16, @ptrFromInt(0xB8000)); try expect(@intFromPtr(vga_mem) == 0xB8000); } test "peer type resolution: ?T and T" { 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); try comptime 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(@as(comptime_int, @intCast(0)) == 0); } test "implicit cast comptime numbers to any type when the value fits" { const a: u64 = 255; var b: u8 = a; _ = &b; try expect(b == 255); } test "implicit cast comptime_int to comptime_float" { comptime assert(@as(comptime_float, 10) == @as(f32, 10)); try expect(2 == 2.0); } test "comptime_int @floatFromInt" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; { const result = @as(f16, @floatFromInt(1234)); try expect(@TypeOf(result) == f16); try expect(result == 1234.0); } { const result = @as(f32, @floatFromInt(1234)); try expect(@TypeOf(result) == f32); try expect(result == 1234.0); } { const result = @as(f64, @floatFromInt(1234)); try expect(@TypeOf(result) == f64); try expect(result == 1234.0); } { const result = @as(f128, @floatFromInt(1234)); try expect(@TypeOf(result) == f128); try expect(result == 1234.0); } // big comptime_int (> 64 bits) to f128 conversion { const result = @as(f128, @floatFromInt(0x1_0000_0000_0000_0000)); try expect(@TypeOf(result) == f128); try expect(result == 0x1_0000_0000_0000_0000.0); } } test "@floatFromInt" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 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 = @as(f32, @floatFromInt(k)); const i = @as(i32, @intFromFloat(f)); try expect(i == k); } }; try S.doTheTest(); try comptime S.doTheTest(); } test "@floatFromInt(f80)" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 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 = @as(f80, @floatFromInt(k)); const i = @as(Int, @intFromFloat(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 try comptime S.doTheTest(i31); try comptime S.doTheTest(i32); try comptime S.doTheTest(i45); try comptime S.doTheTest(i64); try comptime S.doTheTest(i80); try comptime S.doTheTest(i128); try comptime S.doTheTest(i256); } test "type coercion from int to float" { const check = struct { // Check that an integer value can be coerced to a float type and // then converted back to the original value without rounding issues. fn value(Float: type, int: anytype) !void { const float: Float = int; const Int = @TypeOf(int); try std.testing.expectEqual(int, @as(Int, @intFromFloat(float))); if (Float != f80) { // https://codeberg.org/ziglang/zig/issues/30035 try std.testing.expectEqual(int, @as(Int, @intFromFloat(@ceil(float)))); try std.testing.expectEqual(int, @as(Int, @intFromFloat(@floor(float)))); } } // Exhaustively check that all possible values of the integer type can // safely be coerced to the float type. fn allValues(Float: type, Int: type) !void { var int: Int = std.math.minInt(Int); while (int < std.math.maxInt(Int)) : (int += 1) try value(Float, int); } // Check that the min and max values of the integer type can safely be // coerced to the float type. fn edgeValues(Float: type, Int: type) !void { var int: Int = std.math.minInt(Int); try value(Float, int); int = std.math.maxInt(Int); try value(Float, int); } }; try check.allValues(f16, u11); try check.allValues(f16, i12); try check.edgeValues(f32, u24); try check.edgeValues(f32, i25); try check.edgeValues(f64, u53); try check.edgeValues(f64, i54); try check.edgeValues(f80, u64); try check.edgeValues(f80, i65); try check.edgeValues(f128, u113); try check.edgeValues(f128, i114); if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // Basic sanity check that the coercions work for vectors too. const int_vec: @Vector(2, u24) = @splat(123); try check.value(@Vector(2, f32), int_vec); } test "@intFromFloat" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testIntFromFloats(); try comptime testIntFromFloats(); } fn testIntFromFloats() !void { const x = @as(i32, 1e4); try expect(x == 10000); const y = @as(i32, @intFromFloat(@as(f32, 1e4))); try expect(y == 10000); try expectIntFromFloat(f32, 255.1, u8, 255); try expectIntFromFloat(f32, 127.2, i8, 127); try expectIntFromFloat(f32, -128.2, i8, -128); } fn expectIntFromFloat(comptime F: type, f: F, comptime I: type, i: I) !void { try expect(@as(I, @intFromFloat(f)) == i); } test "implicitly cast indirect pointer to maybe-indirect pointer" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; 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 = @as(i32, @intCast(1234)); try expect(@TypeOf(result) == i32); try expect(result == 1234); } test "@floatCast comptime_int and comptime_float" { { const result = @as(f16, @floatCast(1234)); try expect(@TypeOf(result) == f16); try expect(result == 1234.0); } { const result = @as(f16, @floatCast(1234.0)); try expect(@TypeOf(result) == f16); try expect(result == 1234.0); } { const result = @as(f32, @floatCast(1234)); try expect(@TypeOf(result) == f32); try expect(result == 1234.0); } { const result = @as(f32, @floatCast(1234.0)); try expect(@TypeOf(result) == f32); try expect(result == 1234.0); } } test "coerce undefined to optional" { 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_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; 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" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; var i = @as(usize, 0); const v: *void = @ptrCast(&i); v.* = {}; } test "@enumFromInt passed a comptime_int to an enum with one item" { const E = enum { A }; const x = @as(E, @enumFromInt(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 << @as(u0, @intCast(bigzero))) == 1); try expect((zero << @as(u0, @intCast(bigzero))) == 0); } }; try S.doTheTest(0, 1, 0); try comptime S.doTheTest(0, 1, 0); } test "peer result null and comptime_int" { 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 assert(S.blah(0) == null); try expect(S.blah(10).? == 1); comptime assert(S.blah(10).? == 1); try expect(S.blah(-10).? == -1); comptime assert(S.blah(-10).? == -1); } test "*const ?[*]const T to [*c]const [*c]const T" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; 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 coercion to undefined at runtime" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; @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_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(); try comptime 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_sparc64) return error.SkipZigTest; // TODO var w: u31 = 5; var x: u8 = 7; var y: i32 = -5; _ = .{ &w, &x, &y }; const a = w + y + x; comptime assert(@TypeOf(a) == i32); try expect(a == 7); } test "expected [*c]const u8, found [*:0]const u8" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; var a: [*:0]const u8 = "hello"; _ = &a; const b: [*c]const u8 = a; const 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_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; try testCastIntToErr(error.ItBroke); try comptime testCastIntToErr(error.ItBroke); } fn testCastIntToErr(err: anyerror) !void { const x = @intFromError(err); const y = @errorFromInt(x); try expect(error.ItBroke == y); } test "peer resolve array and const slice" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testPeerResolveArrayConstSlice(true); try comptime 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_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO try castToOptionalTypeError(1); try comptime 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_sparc64) return error.SkipZigTest; // TODO try testCastZeroArrayToErrSliceMut(); try comptime 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_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; 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(); try comptime 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_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testCastConstArrayRefToConstSlice(); try comptime 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_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try expect(mem.eql(u8, try testPeerErrorAndArray(0), "OK")); comptime assert(mem.eql(u8, try testPeerErrorAndArray(0), "OK")); try expect(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK")); comptime assert(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_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testCastPtrOfArrayToSliceAndPtr(); try comptime 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_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const window_name = [1][*]const u8{"window name"}; const x: [*]const ?[*]const u8 = &window_name; try expect(mem.eql(u8, std.mem.sliceTo(@as([*:0]const u8, @ptrCast(x[0].?)), 0), "window name")); } test "@intCast on vector" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 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_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest; const S = struct { fn doTheTest() !void { { // Upcast (implicit, equivalent to @intCast) var up0: @Vector(2, u8) = .{ 0x55, 0xaa }; _ = &up0; const up1: @Vector(2, u16) = up0; const up2: @Vector(2, u32) = up0; const up3: @Vector(2, u64) = up0; 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 })); { // Downcast (safety-checked) const down2: @Vector(2, u32) = @intCast(up3); const down1: @Vector(2, u16) = @intCast(up3); const down0: @Vector(2, u8) = @intCast(up3); try expect(mem.eql(u32, &@as([2]u32, down2), &[2]u32{ 0x55, 0xaa })); try expect(mem.eql(u16, &@as([2]u16, down1), &[2]u16{ 0x55, 0xaa })); try expect(mem.eql(u8, &@as([2]u8, down0), &[2]u8{ 0x55, 0xaa })); } { // Downcast (safety-checked) const down1: @Vector(2, u16) = @intCast(up2); const down0: @Vector(2, u8) = @intCast(up2); try expect(mem.eql(u16, &@as([2]u16, down1), &[2]u16{ 0x55, 0xaa })); try expect(mem.eql(u8, &@as([2]u8, down0), &[2]u8{ 0x55, 0xaa })); } { // Downcast (safety-checked) const down0: @Vector(2, u8) = @intCast(up1); try expect(mem.eql(u8, &@as([2]u8, down0), &[2]u8{ 0x55, 0xaa })); } } { // Upcast (implicit, equivalent to @intCast) var up0: @Vector(4, u8) = .{ 0x00, 0x55, 0xaa, 0xff }; _ = &up0; const up1: @Vector(4, u16) = up0; const up2: @Vector(4, u32) = up0; const up3: @Vector(4, u64) = up0; try expect(mem.eql(u16, &@as([4]u16, up1), &[4]u16{ 0x00, 0x55, 0xaa, 0xff })); try expect(mem.eql(u32, &@as([4]u32, up2), &[4]u32{ 0x00, 0x55, 0xaa, 0xff })); try expect(mem.eql(u64, &@as([4]u64, up3), &[4]u64{ 0x00, 0x55, 0xaa, 0xff })); { // Downcast (safety-checked) const down2: @Vector(4, u32) = @intCast(up3); const down1: @Vector(4, u16) = @intCast(up3); const down0: @Vector(4, u8) = @intCast(up3); try expect(mem.eql(u32, &@as([4]u32, down2), &[4]u32{ 0x00, 0x55, 0xaa, 0xff })); try expect(mem.eql(u16, &@as([4]u16, down1), &[4]u16{ 0x00, 0x55, 0xaa, 0xff })); try expect(mem.eql(u8, &@as([4]u8, down0), &[4]u8{ 0x00, 0x55, 0xaa, 0xff })); } { // Downcast (safety-checked) const down1: @Vector(4, u16) = @intCast(up2); const down0: @Vector(4, u8) = @intCast(up2); try expect(mem.eql(u16, &@as([4]u16, down1), &[4]u16{ 0x00, 0x55, 0xaa, 0xff })); try expect(mem.eql(u8, &@as([4]u8, down0), &[4]u8{ 0x00, 0x55, 0xaa, 0xff })); } { // Downcast (safety-checked) const down0: @Vector(4, u8) = @intCast(up1); try expect(mem.eql(u8, &@as([4]u8, down0), &[4]u8{ 0x00, 0x55, 0xaa, 0xff })); } } { // Upcast (implicit, equivalent to @intCast) var up0: @Vector(8, u8) = .{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, }; _ = &up0; const up1: @Vector(8, u16) = up0; const up2: @Vector(8, u32) = up0; const up3: @Vector(8, u64) = up0; try expect(mem.eql(u16, &@as([8]u16, up1), &[8]u16{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, })); try expect(mem.eql(u32, &@as([8]u32, up2), &[8]u32{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, })); try expect(mem.eql(u64, &@as([8]u64, up3), &[8]u64{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, })); { // Downcast (safety-checked) const down2: @Vector(8, u32) = @intCast(up3); const down1: @Vector(8, u16) = @intCast(up3); const down0: @Vector(8, u8) = @intCast(up3); try expect(mem.eql(u32, &@as([8]u32, down2), &[8]u32{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, })); try expect(mem.eql(u16, &@as([8]u16, down1), &[8]u16{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, })); try expect(mem.eql(u8, &@as([8]u8, down0), &[8]u8{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, })); } { // Downcast (safety-checked) const down1: @Vector(8, u16) = @intCast(up2); const down0: @Vector(8, u8) = @intCast(up2); try expect(mem.eql(u16, &@as([8]u16, down1), &[8]u16{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, })); try expect(mem.eql(u8, &@as([8]u8, down0), &[8]u8{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, })); } { // Downcast (safety-checked) const down0: @Vector(8, u8) = @intCast(up1); try expect(mem.eql(u8, &@as([8]u8, down0), &[8]u8{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, })); } } { // Upcast (implicit, equivalent to @intCast) var up0: @Vector(16, u8) = .{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, }; _ = &up0; const up1: @Vector(16, u16) = up0; const up2: @Vector(16, u32) = up0; const up3: @Vector(16, u64) = up0; try expect(mem.eql(u16, &@as([16]u16, up1), &[16]u16{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, })); try expect(mem.eql(u32, &@as([16]u32, up2), &[16]u32{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, })); try expect(mem.eql(u64, &@as([16]u64, up3), &[16]u64{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, })); { // Downcast (safety-checked) const down2: @Vector(16, u32) = @intCast(up3); const down1: @Vector(16, u16) = @intCast(up3); const down0: @Vector(16, u8) = @intCast(up3); try expect(mem.eql(u32, &@as([16]u32, down2), &[16]u32{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, })); try expect(mem.eql(u16, &@as([16]u16, down1), &[16]u16{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, })); try expect(mem.eql(u8, &@as([16]u8, down0), &[16]u8{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, })); } { // Downcast (safety-checked) const down1: @Vector(16, u16) = @intCast(up2); const down0: @Vector(16, u8) = @intCast(up2); try expect(mem.eql(u16, &@as([16]u16, down1), &[16]u16{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, })); try expect(mem.eql(u8, &@as([16]u8, down0), &[16]u8{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, })); } { // Downcast (safety-checked) const down0: @Vector(16, u8) = @intCast(up1); try expect(mem.eql(u8, &@as([16]u8, down0), &[16]u8{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, })); } } } }; try S.doTheTest(); try comptime S.doTheTest(); } test "@floatCast cast down" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; { var double: f64 = 0.001534; _ = &double; const single = @as(f32, @floatCast(double)); try expect(single == 0.001534); } { const double: f64 = 0.001534; const single = @as(f32, @floatCast(double)); try expect(single == 0.001534); } } test "peer type resolution: unreachable, error set, unreachable" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO const Error = error{ FileDescriptorAlreadyPresentInSet, OperationCausesCircularLoop, FileDescriptorNotRegistered, SystemResources, UserResourceLimitReached, FileDescriptorIncompatibleWithEpoll, Unexpected, }; var err = Error.SystemResources; _ = &err; 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_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; 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 == .error_set); try expect(error_set_info.error_set.?.len == 2); try expect(mem.eql(u8, error_set_info.error_set.?[0].name, "One")); try expect(mem.eql(u8, error_set_info.error_set.?[1].name, "Two")); } // B superset of A { const ty = @TypeOf(b, a); const error_set_info = @typeInfo(ty); try expect(error_set_info == .error_set); try expect(error_set_info.error_set.?.len == 2); try expect(mem.eql(u8, error_set_info.error_set.?[0].name, "One")); try expect(mem.eql(u8, error_set_info.error_set.?[1].name, "Two")); } } test "peer type resolution: disjoint error sets" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; 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 == .error_set); try expect(error_set_info.error_set.?.len == 3); try expect(mem.eql(u8, error_set_info.error_set.?[0].name, "One")); try expect(mem.eql(u8, error_set_info.error_set.?[1].name, "Two")); try expect(mem.eql(u8, error_set_info.error_set.?[2].name, "Three")); } { const ty = @TypeOf(b, a); const error_set_info = @typeInfo(ty); try expect(error_set_info == .error_set); try expect(error_set_info.error_set.?.len == 3); try expect(mem.eql(u8, error_set_info.error_set.?[0].name, "One")); try expect(mem.eql(u8, error_set_info.error_set.?[1].name, "Two")); try expect(mem.eql(u8, error_set_info.error_set.?[2].name, "Three")); } } test "peer type resolution: error union and error set" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const a: error{Three} = undefined; const b: error{ One, Two }!u32 = undefined; { const ty = @TypeOf(a, b); const info = @typeInfo(ty); try expect(info == .error_union); const error_set_info = @typeInfo(info.error_union.error_set); try expect(error_set_info.error_set.?.len == 3); try expect(mem.eql(u8, error_set_info.error_set.?[0].name, "One")); try expect(mem.eql(u8, error_set_info.error_set.?[1].name, "Two")); try expect(mem.eql(u8, error_set_info.error_set.?[2].name, "Three")); } { const ty = @TypeOf(b, a); const info = @typeInfo(ty); try expect(info == .error_union); const error_set_info = @typeInfo(info.error_union.error_set); try expect(error_set_info.error_set.?.len == 3); try expect(mem.eql(u8, error_set_info.error_set.?[0].name, "One")); try expect(mem.eql(u8, error_set_info.error_set.?[1].name, "Two")); try expect(mem.eql(u8, error_set_info.error_set.?[2].name, "Three")); } } test "peer type resolution: error union after non-error" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const a: u32 = undefined; const b: error{ One, Two }!u32 = undefined; { const ty = @TypeOf(a, b); const info = @typeInfo(ty); try expect(info == .error_union); try expect(info.error_union.payload == u32); const error_set_info = @typeInfo(info.error_union.error_set); try expect(error_set_info.error_set.?.len == 2); try expect(mem.eql(u8, error_set_info.error_set.?[0].name, "One")); try expect(mem.eql(u8, error_set_info.error_set.?[1].name, "Two")); } { const ty = @TypeOf(b, a); const info = @typeInfo(ty); try expect(info == .error_union); try expect(info.error_union.payload == u32); const error_set_info = @typeInfo(info.error_union.error_set); try expect(error_set_info.error_set.?.len == 2); try expect(mem.eql(u8, error_set_info.error_set.?[0].name, "One")); try expect(mem.eql(u8, error_set_info.error_set.?[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_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; var buffer: [5]u8 = "abcde".*; const buf: anyerror![]const u8 = buffer[0..]; var b = false; _ = &b; const y = if (b) &[0]u8{} else buf; const 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_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; var buffer: [5]u8 = "abcde".*; const buf: []const u8 = buffer[0..]; var b = false; _ = &b; const 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; _ = &dest; try expect(@TypeOf(&array, dest) == [*]i32); try expect(@TypeOf(dest, &array) == [*]i32); } test "peer resolution of string literals" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; 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); try comptime S.doTheTest(.b); } test "peer cast [:x]T to []T" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const S = struct { fn doTheTest() !void { var array = [4:0]i32{ 1, 2, 3, 4 }; const slice: [:0]i32 = &array; const dest: []i32 = slice; try expect(mem.eql(i32, dest, &[_]i32{ 1, 2, 3, 4 })); } }; try S.doTheTest(); try comptime S.doTheTest(); } test "peer cast [N:x]T to [N]T" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const S = struct { fn doTheTest() !void { var array = [4:0]i32{ 1, 2, 3, 4 }; _ = &array; const dest: [4]i32 = array; try expect(mem.eql(i32, &dest, &[_]i32{ 1, 2, 3, 4 })); } }; try S.doTheTest(); try comptime S.doTheTest(); } test "peer cast *[N:x]T to *[N]T" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const S = struct { fn doTheTest() !void { var array = [4:0]i32{ 1, 2, 3, 4 }; const dest: *[4]i32 = &array; try expect(mem.eql(i32, dest, &[_]i32{ 1, 2, 3, 4 })); } }; try S.doTheTest(); try comptime S.doTheTest(); } test "peer cast [*:x]T to [*]T" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const S = struct { fn doTheTest() !void { var array = [4:99]i32{ 1, 2, 3, 4 }; const 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(); try comptime S.doTheTest(); } test "peer cast [:x]T to [*:x]T" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const S = struct { fn doTheTest() !void { var array = [4:0]i32{ 1, 2, 3, 4 }; const slice: [:0]i32 = &array; const 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(); try comptime S.doTheTest(); } test "peer type resolution implicit cast to return type" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; 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(); try comptime S.doTheTest(); } test "peer type resolution implicit cast to variable type" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; 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(); try comptime S.doTheTest(); } test "variable initialization uses result locations properly with regards to the type" { var b = true; _ = &b; 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_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; 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(@as([*]u16, @ptrCast(&x))) == 4); } }; try S.doTheTest(); try comptime S.doTheTest(); } test "peer type resolve string lit with sentinel-terminated mutable slice" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; var array: [4:0]u8 = undefined; array[4] = 0; // TODO remove this when #4372 is solved const slice: [:0]u8 = array[0..4 :0]; comptime assert(@TypeOf(slice, "hi") == [:0]const u8); comptime assert(@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 assert(@TypeOf(&array1, &array2) == []const u8); comptime assert(@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; _ = .{ &const_ptr, &ptr }; comptime assert(@TypeOf(&array, ptr) == [*]u8); comptime assert(@TypeOf(ptr, &array) == [*]u8); comptime assert(@TypeOf(&const_array, ptr) == [*]const u8); comptime assert(@TypeOf(ptr, &const_array) == [*]const u8); comptime assert(@TypeOf(&array, const_ptr) == [*]const u8); comptime assert(@TypeOf(const_ptr, &array) == [*]const u8); comptime assert(@TypeOf(&const_array, const_ptr) == [*]const u8); comptime assert(@TypeOf(const_ptr, &const_array) == [*]const u8); } test "comptime float casts" { const a = @as(comptime_float, @floatFromInt(1)); try expect(a == 1); try expect(@TypeOf(a) == comptime_float); const b = @as(comptime_int, @intFromFloat(2)); try expect(b == 2); try expect(@TypeOf(b) == comptime_int); try expectIntFromFloat(comptime_int, 1234, i16, 1234); try expectIntFromFloat(comptime_float, 12.3, comptime_int, 12); } test "pointer reinterpret const float to int" { 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 = @as(*const i32, @ptrCast(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_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; var a = [_]u8{ 3, 2, 1 }; var runtime_zero: usize = 0; _ = &runtime_zero; 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) { @as([*]u8, @ptrCast(array.?))[n] += 1; } } test "compile time int to ptr of function" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; 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 = @as(PFN_void, @ptrFromInt(hardcoded_fn_addr)); pub const PFN_void = *const fn (*anyopaque) callconv(.c) void; fn foobar(func: PFN_void) !void { try std.testing.expect(@intFromPtr(func) == hardcoded_fn_addr); } test "cast function with an opaque parameter" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_c) { // https://github.com/ziglang/zig/issues/16845 return error.SkipZigTest; } const Container = struct { const Ctx = opaque {}; ctx: *Ctx, func: *const fn (*Ctx) void, }; const Foo = struct { x: i32, y: i32, fn funcImpl(self: *@This()) void { self.x += 1; self.y += 1; } }; var foo = Foo{ .x = 100, .y = 200 }; var c = Container{ .ctx = @ptrCast(&foo), .func = @ptrCast(&Foo.funcImpl), }; c.func(c.ctx); try std.testing.expectEqual(Foo{ .x = 101, .y = 201 }, foo); } test "implicit ptr to *anyopaque" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; var a: u32 = 1; const ptr: *align(@alignOf(u32)) anyopaque = &a; const b: *u32 = @as(*u32, @ptrCast(ptr)); try expect(b.* == 1); const ptr2: ?*align(@alignOf(u32)) anyopaque = &a; const c: *u32 = @as(*u32, @ptrCast(ptr2.?)); try expect(c.* == 1); } test "return null from fn () anyerror!?&T" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; 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_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; 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_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try expect(mem.eql(u8, castToOptionalSlice().?, "hi")); comptime assert(mem.eql(u8, castToOptionalSlice().?, "hi")); } fn castToOptionalSlice() ?[]const u8 { return "hi"; } test "cast u128 to f128 and back" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; try comptime testCast128(); try testCast128(); } fn testCast128() !void { try expect(cast128Int(cast128Float(0x7fff0000000000000000000000000000)) == 0x7fff0000000000000000000000000000); } fn cast128Int(x: f128) u128 { return @as(u128, @bitCast(x)); } fn cast128Float(x: u128) f128 { return @as(f128, @bitCast(x)); } test "implicit cast from *[N]T to ?[*]T" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; 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_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; var a: u8 = 1; incrementVoidPtrValue(&a); try std.testing.expect(a == 2); } fn incrementVoidPtrValue(value: ?*anyopaque) void { @as(*u8, @ptrCast(value.?)).* += 1; } test "implicit cast *[0]T to E![]const u8" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO var x = @as(anyerror![]const u8, &[0]u8{}); _ = &x; try expect((x catch unreachable).len == 0); } var global_array: [4]u8 = undefined; test "cast from array reference to fn: comptime fn ptr" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const f = @as(*align(1) const fn () callconv(.c) void, @ptrCast(&global_array)); try expect(@intFromPtr(f) == @intFromPtr(&global_array)); } test "cast from array reference to fn: runtime fn ptr" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; var f = @as(*align(1) const fn () callconv(.c) void, @ptrCast(&global_array)); _ = &f; try expect(@intFromPtr(f) == @intFromPtr(&global_array)); } test "*const [N]null u8 to ?[]const u8" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const S = struct { fn doTheTest() !void { var a = "Hello"; _ = &a; const b: ?[]const u8 = a; try expect(mem.eql(u8, b.?, "Hello")); } }; try S.doTheTest(); try comptime 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_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; var foo: struct { ptr: ?*anyopaque } = .{ .ptr = &global_struct }; _ = &foo; try expect(foo.ptr.? == @as(*anyopaque, @ptrCast(&global_struct))); } test "cast between *[N]void and []void" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; var a: [4]void = undefined; const b: []void = &a; try expect(b.len == 4); } test "peer resolve arrays of different size to const slice" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try expect(mem.eql(u8, boolToStr(true), "true")); try expect(mem.eql(u8, boolToStr(false), "false")); comptime assert(mem.eql(u8, boolToStr(true), "true")); comptime assert(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_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; const S = struct { fn doTheTest() !void { var x: f16 = 1234.0; _ = &x; try expect(@as(f32, 1234.0) == x); try expect(@as(f64, 1234.0) == x); try expect(@as(f128, 1234.0) == x); } }; try S.doTheTest(); try comptime S.doTheTest(); } test "cast f128 to narrower types" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; const S = struct { fn doTheTest() !void { var x: f128 = 1234.0; _ = &x; try expect(@as(f16, 1234.0) == @as(f16, @floatCast(x))); try expect(@as(f32, 1234.0) == @as(f32, @floatCast(x))); try expect(@as(f64, 1234.0) == @as(f64, @floatCast(x))); } }; try S.doTheTest(); try comptime S.doTheTest(); } test "peer type resolution: unreachable, null, slice" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; 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_sparc64) return error.SkipZigTest; // TODO const S = struct { fn doTheTest() !void { var cond = true; _ = &cond; 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(); try comptime S.doTheTest(); } test "cast compatible optional types" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; var a: ?[:0]const u8 = null; _ = &a; const 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_sparc64) return error.SkipZigTest; // TODO const a = @as([*]u8, undefined)[0..0]; var b: error{a}![]const u8 = a; _ = &b; 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 = &.{}; _ = &x; try expect(x.len == 0); } test "coerce between pointers of compatible differently-named floats" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows and !builtin.link_libc) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm and 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; const 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" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const a = @as(*[1024]u8, @ptrFromInt(42)); const b = @as(*const [1024]u8, @ptrFromInt(42)); try std.testing.expect(@TypeOf(a, b) == *const [1024]u8); try std.testing.expect(a == b); } test "intFromFloat to zero-bit int" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO const a: f32 = 0.0; try comptime std.testing.expect(@as(u0, @intFromFloat(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; } } // test "implicit cast from [:0]T to [*c]T" { // var a: [:0]const u8 = "foo"; // _ = &a; // const b: [*c]const u8 = a; // const c = std.mem.span(b); // try expect(c.len == a.len); // try expect(c.ptr == a.ptr); // } test "bitcast packed struct with u0" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const S = packed struct(u2) { a: u0, b: u2 }; const s = @as(S, @bitCast(@as(u2, 2))); try expect(s.a == 0); try expect(s.b == 2); const i = @as(u2, @bitCast(s)); try expect(i == 2); } test "optional pointer coerced to optional allowzero pointer" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; var p: ?*u32 = undefined; var q: ?*allowzero u32 = undefined; p = @as(*u32, @ptrFromInt(4)); q = p; try expect(@intFromPtr(q.?) == 4); } test "optional slice coerced to allowzero many pointer" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const a: ?[]const u32 = null; const b: [*]allowzero const u8 = @ptrCast(a); const c = @intFromPtr(b); try std.testing.expect(c == 0); } test "optional slice passed as parameter coerced to allowzero many pointer" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const ns = struct { const Color = struct { r: u8, g: u8, b: u8, a: u8, }; fn foo(pixels: ?[]const Color) !void { const data: [*]allowzero const u8 = @ptrCast(pixels); const int = @intFromPtr(data); try std.testing.expect(int == 0); } }; try ns.foo(null); } test "single item pointer to pointer to array to slice" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; var x: i32 = 1234; try expect(@as([]const i32, @as(*[1]i32, &x))[0] == 1234); const z1 = @as([]const i32, @as(*[1]i32, &x)); try expect(z1[0] == 1234); } test "peer type resolution forms error union" { if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; var foo: i32 = 123; _ = &foo; const result = if (foo < 0) switch (-foo) { 0 => unreachable, 42 => error.AccessDenied, else => unreachable, } else @as(u32, @intCast(foo)); try expect(try result == 123); } test "@constCast without a result location" { const x: i32 = 1234; const y = @constCast(&x); try expect(@TypeOf(y) == *i32); try expect(y.* == 1234); } test "@constCast optional" { const x: u8 = 10; const m: ?*const u8 = &x; const p = @constCast(m); try expect(@TypeOf(p) == ?*u8); } test "@volatileCast without a result location" { var x: i32 = 1234; const y: *volatile i32 = &x; const z = @volatileCast(y); try expect(@TypeOf(z) == *i32); try expect(z.* == 1234); } test "coercion from single-item pointer to @as to slice" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; var x: u32 = 1; // Why the following line gets a compile error? const t: []u32 = @as(*[1]u32, &x); try expect(t[0] == 1); } test "peer type resolution: const sentinel slice and mutable non-sentinel slice" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const S = struct { fn doTheTest(comptime T: type, comptime s: T) !void { var a: [:s]const T = @as(*const [2:s]T, @ptrFromInt(0x1000)); var b: []T = @as(*[3]T, @ptrFromInt(0x2000)); _ = .{ &a, &b }; comptime assert(@TypeOf(a, b) == []const T); comptime assert(@TypeOf(b, a) == []const T); var t = true; _ = &t; const r1 = if (t) a else b; const r2 = if (t) b else a; const R = @TypeOf(r1); try expectEqual(@as(R, @as(*const [2:s]T, @ptrFromInt(0x1000))), r1); try expectEqual(@as(R, @as(*const [3]T, @ptrFromInt(0x2000))), r2); } }; try S.doTheTest(u8, 0); try S.doTheTest(?*anyopaque, null); } test "peer type resolution: float and comptime-known fixed-width integer" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO const i: u8 = 100; var f: f32 = 1.234; _ = &f; comptime assert(@TypeOf(i, f) == f32); comptime assert(@TypeOf(f, i) == f32); var t = true; _ = &t; const r1 = if (t) i else f; const r2 = if (t) f else i; const T = @TypeOf(r1); try expectEqual(@as(T, 100.0), r1); try expectEqual(@as(T, 1.234), r2); } test "peer type resolution: same array type with sentinel" { 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 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; var a: [2:0]u32 = .{ 0, 1 }; var b: [2:0]u32 = .{ 2, 3 }; _ = .{ &a, &b }; comptime assert(@TypeOf(a, b) == [2:0]u32); comptime assert(@TypeOf(b, a) == [2:0]u32); var t = true; _ = &t; const r1 = if (t) a else b; const r2 = if (t) b else a; const T = @TypeOf(r1); try expectEqual(T{ 0, 1 }, r1); try expectEqual(T{ 2, 3 }, r2); } test "peer type resolution: array with sentinel and array without sentinel" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; var a: [2:0]u32 = .{ 0, 1 }; var b: [2]u32 = .{ 2, 3 }; _ = .{ &a, &b }; comptime assert(@TypeOf(a, b) == [2]u32); comptime assert(@TypeOf(b, a) == [2]u32); var t = true; _ = &t; const r1 = if (t) a else b; const r2 = if (t) b else a; const T = @TypeOf(r1); try expectEqual(T{ 0, 1 }, r1); try expectEqual(T{ 2, 3 }, r2); } test "peer type resolution: array and vector with same child type" { 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 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; var arr: [2]u32 = .{ 0, 1 }; var vec: @Vector(2, u32) = .{ 2, 3 }; _ = .{ &arr, &vec }; comptime assert(@TypeOf(arr, vec) == @Vector(2, u32)); comptime assert(@TypeOf(vec, arr) == @Vector(2, u32)); var t = true; _ = &t; const r1 = if (t) arr else vec; const r2 = if (t) vec else arr; const T = @TypeOf(r1); try expectEqual(T{ 0, 1 }, r1); try expectEqual(T{ 2, 3 }, r2); } test "peer type resolution: array with smaller child type and vector with larger child type" { 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 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; var arr: [2]u8 = .{ 0, 1 }; var vec: @Vector(2, u64) = .{ 2, 3 }; _ = .{ &arr, &vec }; comptime assert(@TypeOf(arr, vec) == @Vector(2, u64)); comptime assert(@TypeOf(vec, arr) == @Vector(2, u64)); var t = true; _ = &t; const r1 = if (t) arr else vec; const r2 = if (t) vec else arr; const T = @TypeOf(r1); try expectEqual(T{ 0, 1 }, r1); try expectEqual(T{ 2, 3 }, r2); } test "peer type resolution: error union and optional of same type" { 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 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const E = error{Foo}; var a: E!*u8 = error.Foo; var b: ?*u8 = null; _ = .{ &a, &b }; comptime assert(@TypeOf(a, b) == E!?*u8); comptime assert(@TypeOf(b, a) == E!?*u8); var t = true; _ = &t; const r1 = if (t) a else b; const r2 = if (t) b else a; const T = @TypeOf(r1); try expectEqual(@as(T, error.Foo), r1); try expectEqual(@as(T, null), r2); } test "peer type resolution: C pointer and @TypeOf(null)" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; var a: [*c]c_int = 0x1000; _ = &a; const b = null; comptime assert(@TypeOf(a, b) == [*c]c_int); comptime assert(@TypeOf(b, a) == [*c]c_int); var t = true; _ = &t; const r1 = if (t) a else b; const r2 = if (t) b else a; const T = @TypeOf(r1); try expectEqual(@as(T, 0x1000), r1); try expectEqual(@as(T, null), r2); } test "peer type resolution: three-way resolution combines error set and optional" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const E = error{Foo}; var a: E = error.Foo; var b: *const [5:0]u8 = @ptrFromInt(0x1000); var c: ?[*:0]u8 = null; _ = .{ &a, &b, &c }; comptime assert(@TypeOf(a, b, c) == E!?[*:0]const u8); comptime assert(@TypeOf(a, c, b) == E!?[*:0]const u8); comptime assert(@TypeOf(b, a, c) == E!?[*:0]const u8); comptime assert(@TypeOf(b, c, a) == E!?[*:0]const u8); comptime assert(@TypeOf(c, a, b) == E!?[*:0]const u8); comptime assert(@TypeOf(c, b, a) == E!?[*:0]const u8); var x: u8 = 0; _ = &x; const r1 = switch (x) { 0 => a, 1 => b, else => c, }; const r2 = switch (x) { 0 => b, 1 => a, else => c, }; const r3 = switch (x) { 0 => c, 1 => a, else => b, }; const T = @TypeOf(r1); try expectEqual(@as(T, error.Foo), r1); try expectEqual(@as(T, @as([*:0]u8, @ptrFromInt(0x1000))), r2); try expectEqual(@as(T, null), r3); } test "peer type resolution: vector and optional vector" { 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 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO var a: ?@Vector(3, u32) = .{ 0, 1, 2 }; var b: @Vector(3, u32) = .{ 3, 4, 5 }; _ = .{ &a, &b }; comptime assert(@TypeOf(a, b) == ?@Vector(3, u32)); comptime assert(@TypeOf(b, a) == ?@Vector(3, u32)); var t = true; _ = &t; const r1 = if (t) a else b; const r2 = if (t) b else a; const T = @TypeOf(r1); try expectEqual(@as(T, .{ 0, 1, 2 }), r1); try expectEqual(@as(T, .{ 3, 4, 5 }), r2); } test "peer type resolution: optional fixed-width int and comptime_int" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO var a: ?i32 = 42; _ = &a; const b: comptime_int = 50; comptime assert(@TypeOf(a, b) == ?i32); comptime assert(@TypeOf(b, a) == ?i32); var t = true; _ = &t; const r1 = if (t) a else b; const r2 = if (t) b else a; const T = @TypeOf(r1); try expectEqual(@as(T, 42), r1); try expectEqual(@as(T, 50), r2); } test "peer type resolution: array and tuple" { 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 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; var arr: [3]i32 = .{ 1, 2, 3 }; _ = &arr; const tup = .{ 4, 5, 6 }; comptime assert(@TypeOf(arr, tup) == [3]i32); comptime assert(@TypeOf(tup, arr) == [3]i32); var t = true; _ = &t; const r1 = if (t) arr else tup; const r2 = if (t) tup else arr; const T = @TypeOf(r1); try expectEqual(T{ 1, 2, 3 }, r1); try expectEqual(T{ 4, 5, 6 }, r2); } test "peer type resolution: vector and tuple" { 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 var vec: @Vector(3, i32) = .{ 1, 2, 3 }; _ = &vec; const tup = .{ 4, 5, 6 }; comptime assert(@TypeOf(vec, tup) == @Vector(3, i32)); comptime assert(@TypeOf(tup, vec) == @Vector(3, i32)); var t = true; _ = &t; const r1 = if (t) vec else tup; const r2 = if (t) tup else vec; const T = @TypeOf(r1); try expectEqual(T{ 1, 2, 3 }, r1); try expectEqual(T{ 4, 5, 6 }, r2); } test "peer type resolution: vector and array and tuple" { 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 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; var vec: @Vector(2, i8) = .{ 10, 20 }; var arr: [2]i8 = .{ 30, 40 }; _ = .{ &vec, &arr }; const tup = .{ 50, 60 }; comptime assert(@TypeOf(vec, arr, tup) == @Vector(2, i8)); comptime assert(@TypeOf(vec, tup, arr) == @Vector(2, i8)); comptime assert(@TypeOf(arr, vec, tup) == @Vector(2, i8)); comptime assert(@TypeOf(arr, tup, vec) == @Vector(2, i8)); comptime assert(@TypeOf(tup, vec, arr) == @Vector(2, i8)); comptime assert(@TypeOf(tup, arr, vec) == @Vector(2, i8)); var x: u8 = 0; _ = &x; const r1 = switch (x) { 0 => vec, 1 => arr, else => tup, }; const r2 = switch (x) { 0 => arr, 1 => vec, else => tup, }; const r3 = switch (x) { 0 => tup, 1 => vec, else => arr, }; const T = @TypeOf(r1); try expectEqual(T{ 10, 20 }, r1); try expectEqual(T{ 30, 40 }, r2); try expectEqual(T{ 50, 60 }, r3); } test "peer type resolution: empty tuple pointer and slice" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; var a: [:0]const u8 = "Hello"; var b = &.{}; _ = .{ &a, &b }; comptime assert(@TypeOf(a, b) == []const u8); comptime assert(@TypeOf(b, a) == []const u8); var t = true; _ = &t; const r1 = if (t) a else b; const r2 = if (t) b else a; try expectEqualSlices(u8, "Hello", r1); try expectEqualSlices(u8, "", r2); } test "peer type resolution: tuple pointer and slice" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; var a: [:0]const u8 = "Hello"; var b = &.{ @as(u8, 'x'), @as(u8, 'y'), @as(u8, 'z') }; _ = .{ &a, &b }; comptime assert(@TypeOf(a, b) == []const u8); comptime assert(@TypeOf(b, a) == []const u8); var t = true; _ = &t; const r1 = if (t) a else b; const r2 = if (t) b else a; try expectEqualSlices(u8, "Hello", r1); try expectEqualSlices(u8, "xyz", r2); } test "peer type resolution: tuple pointer and optional slice" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO // Miscompilation on Intel's OpenCL CPU runtime. if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // flaky var a: ?[:0]const u8 = null; var b = &.{ @as(u8, 'x'), @as(u8, 'y'), @as(u8, 'z') }; _ = .{ &a, &b }; comptime assert(@TypeOf(a, b) == ?[]const u8); comptime assert(@TypeOf(b, a) == ?[]const u8); var t = true; _ = &t; const r1 = if (t) a else b; const r2 = if (t) b else a; try expectEqual(@as(?[]const u8, null), r1); try expectEqualSlices(u8, "xyz", r2 orelse ""); } test "peer type resolution: many compatible pointers" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; var buf = "foo-3".*; var vals = .{ @as([*]const u8, "foo-0"), @as([*:0]const u8, "foo-1"), @as([*:0]const u8, "foo-2"), @as([*]u8, &buf), @as(*const [5]u8, "foo-4"), }; _ = &vals; // Check every possible permutation of types in @TypeOf @setEvalBranchQuota(5000); comptime var perms = 0; // check the loop is hitting every permutation inline for (0..5) |i_0| { inline for (0..5) |i_1| { if (i_1 == i_0) continue; inline for (0..5) |i_2| { if (i_2 == i_0 or i_2 == i_1) continue; inline for (0..5) |i_3| { if (i_3 == i_0 or i_3 == i_1 or i_3 == i_2) continue; inline for (0..5) |i_4| { if (i_4 == i_0 or i_4 == i_1 or i_4 == i_2 or i_4 == i_3) continue; perms += 1; comptime assert(@TypeOf( vals[i_0], vals[i_1], vals[i_2], vals[i_3], vals[i_4], ) == [*]const u8); } } } } } comptime assert(perms == 5 * 4 * 3 * 2 * 1); var x: u8 = 0; _ = &x; inline for (0..5) |i| { const r = switch (x) { 0 => vals[i], 1 => vals[0], 2 => vals[1], 3 => vals[2], 4 => vals[3], else => vals[4], }; const expected = switch (i) { 0 => "foo-0", 1 => "foo-1", 2 => "foo-2", 3 => "foo-3", 4 => "foo-4", else => unreachable, }; try expectEqualSlices(u8, expected, std.mem.span(@as([*:0]const u8, @ptrCast(r)))); } } test "peer type resolution: tuples with comptime fields" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO const a = .{ 1, 2 }; const b = .{ @as(u32, 3), @as(i16, 4) }; // TODO: tuple type equality doesn't work properly yet const ti1 = @typeInfo(@TypeOf(a, b)); const ti2 = @typeInfo(@TypeOf(b, a)); inline for (.{ ti1, ti2 }) |ti| { const s = ti.@"struct"; comptime assert(s.is_tuple); comptime assert(s.fields.len == 2); comptime assert(s.fields[0].type == u32); comptime assert(s.fields[1].type == i16); } var t = true; _ = &t; const r1 = if (t) a else b; const r2 = if (t) b else a; try expectEqual(@as(u32, 1), r1[0]); try expectEqual(@as(i16, 2), r1[1]); try expectEqual(@as(u32, 3), r2[0]); try expectEqual(@as(i16, 4), r2[1]); } test "peer type resolution: C pointer and many pointer" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; var buf = "hello".*; const a: [*c]u8 = &buf; var b: [*:0]const u8 = "world"; _ = &b; comptime assert(@TypeOf(a, b) == [*c]const u8); comptime assert(@TypeOf(b, a) == [*c]const u8); var t = true; _ = &t; const r1 = if (t) a else b; const r2 = if (t) b else a; try expectEqual(r1, a); try expectEqual(r2, b); } test "peer type resolution: pointer attributes are combined correctly" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; var buf_a align(4) = "foo".*; var buf_b align(4) = "bar".*; var buf_c align(4) = "baz".*; var buf_d align(4) = "qux".*; const a: [*:0]align(4) const u8 = &buf_a; const b: *align(2) volatile [3:0]u8 = &buf_b; const c: [*:0]align(4) u8 = &buf_c; const d: [*:0]allowzero align(4) u8 = &buf_d; comptime assert(@TypeOf(a, b, c, d) == [*:0]allowzero align(2) const volatile u8); comptime assert(@TypeOf(a, b, d, c) == [*:0]allowzero align(2) const volatile u8); comptime assert(@TypeOf(a, c, b, d) == [*:0]allowzero align(2) const volatile u8); comptime assert(@TypeOf(a, c, d, b) == [*:0]allowzero align(2) const volatile u8); comptime assert(@TypeOf(a, d, b, c) == [*:0]allowzero align(2) const volatile u8); comptime assert(@TypeOf(a, d, c, b) == [*:0]allowzero align(2) const volatile u8); comptime assert(@TypeOf(b, a, c, d) == [*:0]allowzero align(2) const volatile u8); comptime assert(@TypeOf(b, a, d, c) == [*:0]allowzero align(2) const volatile u8); comptime assert(@TypeOf(b, c, a, d) == [*:0]allowzero align(2) const volatile u8); comptime assert(@TypeOf(b, c, d, a) == [*:0]allowzero align(2) const volatile u8); comptime assert(@TypeOf(b, d, c, a) == [*:0]allowzero align(2) const volatile u8); comptime assert(@TypeOf(b, d, a, c) == [*:0]allowzero align(2) const volatile u8); comptime assert(@TypeOf(c, a, b, d) == [*:0]allowzero align(2) const volatile u8); comptime assert(@TypeOf(c, a, d, b) == [*:0]allowzero align(2) const volatile u8); comptime assert(@TypeOf(c, b, a, d) == [*:0]allowzero align(2) const volatile u8); comptime assert(@TypeOf(c, b, d, a) == [*:0]allowzero align(2) const volatile u8); comptime assert(@TypeOf(c, d, b, a) == [*:0]allowzero align(2) const volatile u8); comptime assert(@TypeOf(c, d, a, b) == [*:0]allowzero align(2) const volatile u8); comptime assert(@TypeOf(d, a, b, c) == [*:0]allowzero align(2) const volatile u8); comptime assert(@TypeOf(d, a, c, b) == [*:0]allowzero align(2) const volatile u8); comptime assert(@TypeOf(d, b, a, c) == [*:0]allowzero align(2) const volatile u8); comptime assert(@TypeOf(d, b, c, a) == [*:0]allowzero align(2) const volatile u8); comptime assert(@TypeOf(d, c, b, a) == [*:0]allowzero align(2) const volatile u8); comptime assert(@TypeOf(d, c, a, b) == [*:0]allowzero align(2) const volatile u8); var x: u8 = 0; _ = &x; const r1 = switch (x) { 0 => a, 1 => b, 2 => c, else => d, }; const r2 = switch (x) { 0 => b, 1 => a, 2 => c, else => d, }; const r3 = switch (x) { 0 => c, 1 => a, 2 => b, else => d, }; const r4 = switch (x) { 0 => d, 1 => a, 2 => b, else => c, }; const NonAllowZero = comptime blk: { const ptr = @typeInfo(@TypeOf(r1, r2, r3, r4)).pointer; break :blk @Pointer(ptr.size, .{ .@"const" = ptr.is_const, .@"volatile" = ptr.is_volatile, .@"allowzero" = false, .@"align" = ptr.alignment, .@"addrspace" = ptr.address_space, }, ptr.child, ptr.sentinel()); }; try expectEqualSlices(u8, std.mem.span(@volatileCast(@as(NonAllowZero, @ptrCast(r1)))), "foo"); try expectEqualSlices(u8, std.mem.span(@volatileCast(@as(NonAllowZero, @ptrCast(r2)))), "bar"); try expectEqualSlices(u8, std.mem.span(@volatileCast(@as(NonAllowZero, @ptrCast(r3)))), "baz"); try expectEqualSlices(u8, std.mem.span(@volatileCast(@as(NonAllowZero, @ptrCast(r4)))), "qux"); } test "peer type resolution: arrays of compatible 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_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; var e0: u8 = 3; var e1: u8 = 2; var e2: u8 = 1; const a = [3]*u8{ &e0, &e1, &e2 }; const b = [3]*const u8{ &e0, &e1, &e2 }; comptime assert(@TypeOf(a, b) == [3]*const u8); comptime assert(@TypeOf(b, a) == [3]*const u8); try expectEqual(@as(@TypeOf(a, b), a), b); } test "cast builtins can wrap result in optional" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const S = struct { const MyEnum = enum(u32) { _ }; fn a() ?MyEnum { return @enumFromInt(123); } fn b() ?u32 { return @intFromFloat(42.50); } fn c() ?*const f32 { const x: u32 = 1; return @ptrCast(&x); } fn doTheTest() !void { const ra = a() orelse return error.ImpossibleError; const rb = b() orelse return error.ImpossibleError; const rc = c() orelse return error.ImpossibleError; comptime assert(@TypeOf(ra) == MyEnum); comptime assert(@TypeOf(rb) == u32); comptime assert(@TypeOf(rc) == *const f32); try expect(@intFromEnum(ra) == 123); try expect(rb == 42); try expect(@as(*const u32, @ptrCast(rc)).* == 1); } }; try S.doTheTest(); try comptime S.doTheTest(); } test "cast builtins can wrap result in error union" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO const S = struct { const MyEnum = enum(u32) { _ }; const E = error{ImpossibleError}; fn a() E!MyEnum { return @enumFromInt(123); } fn b() E!u32 { return @intFromFloat(42.50); } fn c() E!*const f32 { const x: u32 = 1; return @ptrCast(&x); } fn doTheTest() !void { const ra = try a(); const rb = try b(); const rc = try c(); comptime assert(@TypeOf(ra) == MyEnum); comptime assert(@TypeOf(rb) == u32); comptime assert(@TypeOf(rc) == *const f32); try expect(@intFromEnum(ra) == 123); try expect(rb == 42); try expect(@as(*const u32, @ptrCast(rc)).* == 1); } }; try S.doTheTest(); try comptime S.doTheTest(); } test "cast builtins can wrap result in error union and optional" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const S = struct { const MyEnum = enum(u32) { _ }; const E = error{ImpossibleError}; fn a() E!?MyEnum { return @enumFromInt(123); } fn b() E!?u32 { return @intFromFloat(42.50); } fn c() E!?*const f32 { const x: u32 = 1; return @ptrCast(&x); } fn doTheTest() !void { const ra = try a() orelse return error.ImpossibleError; const rb = try b() orelse return error.ImpossibleError; const rc = try c() orelse return error.ImpossibleError; comptime assert(@TypeOf(ra) == MyEnum); comptime assert(@TypeOf(rb) == u32); comptime assert(@TypeOf(rc) == *const f32); try expect(@intFromEnum(ra) == 123); try expect(rb == 42); try expect(@as(*const u32, @ptrCast(rc)).* == 1); } }; try S.doTheTest(); try comptime S.doTheTest(); } test "@floatCast on vector" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 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_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; const S = struct { fn doTheTest() !void { { var a: @Vector(2, f64) = .{ 1.5, 2.5 }; _ = &a; const b: @Vector(2, f32) = @floatCast(a); try expectEqual(@Vector(2, f32){ 1.5, 2.5 }, b); } { var a: @Vector(2, f32) = .{ 3.25, 4.25 }; _ = &a; const b: @Vector(2, f64) = @floatCast(a); try expectEqual(@Vector(2, f64){ 3.25, 4.25 }, b); } { var a: @Vector(2, f32) = .{ 5.75, 6.75 }; _ = &a; const b: @Vector(2, f64) = a; try expectEqual(@Vector(2, f64){ 5.75, 6.75 }, b); } { var vec: @Vector(2, f32) = @splat(1234.0); _ = &vec; const wider: @Vector(2, f64) = vec; try expect(wider[0] == 1234.0); try expect(wider[1] == 1234.0); } } }; try S.doTheTest(); try comptime S.doTheTest(); } test "@ptrFromInt on vector" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 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_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const S = struct { fn doTheTest() !void { var a: @Vector(3, usize) = .{ 0x1000, 0x2000, 0x3000 }; _ = &a; const b: @Vector(3, *anyopaque) = @ptrFromInt(a); try expectEqual(@Vector(3, *anyopaque){ @ptrFromInt(0x1000), @ptrFromInt(0x2000), @ptrFromInt(0x3000), }, b); } }; try S.doTheTest(); try comptime S.doTheTest(); } test "@intFromPtr on vector" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 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_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const S = struct { fn doTheTest() !void { var a: @Vector(3, *anyopaque) = .{ @ptrFromInt(0x1000), @ptrFromInt(0x2000), @ptrFromInt(0x3000), }; _ = &a; const b: @Vector(3, usize) = @intFromPtr(a); try expectEqual(@Vector(3, usize){ 0x1000, 0x2000, 0x3000 }, b); } }; try S.doTheTest(); try comptime S.doTheTest(); } test "@floatFromInt on vector" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 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_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; const S = struct { fn doTheTest() !void { var a: @Vector(3, u32) = .{ 10, 20, 30 }; _ = &a; const b: @Vector(3, f32) = @floatFromInt(a); try expectEqual(@Vector(3, f32){ 10.0, 20.0, 30.0 }, b); } }; try S.doTheTest(); try comptime S.doTheTest(); } test "@intFromFloat on vector" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 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_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; const S = struct { fn doTheTest() !void { var a: @Vector(3, f32) = .{ 10.3, 20.5, 30.7 }; _ = &a; const b: @Vector(3, u32) = @intFromFloat(a); try expectEqual(@Vector(3, u32){ 10, 20, 30 }, b); } }; try S.doTheTest(); try comptime S.doTheTest(); } test "@intFromBool on vector" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 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_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; const S = struct { fn doTheTest() !void { var a: @Vector(3, bool) = .{ false, true, false }; _ = &a; const b: @Vector(3, u1) = @intFromBool(a); try expectEqual(@Vector(3, u1){ 0, 1, 0 }, b); } }; try S.doTheTest(); try comptime S.doTheTest(); } test "numeric coercions with undefined" { const from: i32 = undefined; var to: f32 = from; to = @floatFromInt(from); to = 42.0; try expectEqual(@as(f32, 42.0), to); } test "15-bit int to float" { if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; var a: u15 = 42; _ = &a; const b: f32 = @floatFromInt(a); try expect(b == 42.0); } test "@as does not corrupt values with incompatible representations" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO const x: f32 = @as(f16, blk: { if (false) { // Trick the compiler into trying to use a result pointer if it can! break :blk .{undefined}; } break :blk 1.23; }); try std.testing.expectApproxEqAbs(@as(f32, 1.23), x, 0.001); } test "result information is preserved through many nested structures" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const S = struct { fn doTheTest() !void { const E = error{Foo}; const T = *const ?E!struct { x: ?*const E!?u8 }; var val: T = &.{ .x = &@truncate(0x1234) }; _ = &val; const struct_val = val.*.? catch unreachable; const int_val = (struct_val.x.?.* catch unreachable).?; try expect(int_val == 0x34); } }; try S.doTheTest(); try comptime S.doTheTest(); } test "@intCast vector of signed integer" { 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 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest; var x: @Vector(4, i32) = .{ 1, 2, 3, 4 }; _ = &x; const y: @Vector(4, i8) = @intCast(x); try expect(y[0] == 1); try expect(y[1] == 2); try expect(y[2] == 3); try expect(y[3] == 4); } test "result type is preserved into comptime block" { const x: u32 = comptime @intCast(123); try expect(x == 123); } test "bitcast vector" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO const u8x32 = @Vector(32, u8); const u32x8 = @Vector(8, u32); const zerox32: u8x32 = [_]u8{0} ** 32; const bigsum: u32x8 = @bitCast(zerox32); try std.testing.expectEqual(0, @reduce(.Add, bigsum)); } test "peer type resolution: slice of sentinel-terminated array" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; var f: bool = undefined; f = false; const a: [][2:0]u8 = &.{}; const b: []const [2:0]u8 = &.{.{ 10, 20 }}; const result = if (f) a else b; comptime assert(@TypeOf(result) == []const [2:0]u8); try expect(result.len == 1); try expect(result[0].len == 2); try expect(result[0][0] == 10); try expect(result[0][1] == 20); } test "@intFromFloat boundary cases" { if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; const S = struct { fn case(comptime I: type, x: f32, bump: enum { up, down }, expected: I) !void { const input: f32 = switch (bump) { .up => std.math.nextAfter(f32, x, std.math.inf(f32)), .down => std.math.nextAfter(f32, x, -std.math.inf(f32)), }; const output: I = @intFromFloat(input); try expect(output == expected); } fn doTheTest() !void { try case(u8, 256.0, .down, 255); try case(u8, -1.0, .up, 0); try case(i8, 128.0, .down, 127); try case(i8, -129.0, .up, -128); try case(u0, 1.0, .down, 0); try case(u0, -1.0, .up, 0); try case(i0, 1.0, .down, 0); try case(i0, -1.0, .up, 0); try case(u10, 1024.0, .down, 1023); try case(u10, -1.0, .up, 0); try case(i10, 512.0, .down, 511); try case(i10, -513.0, .up, -512); } }; try S.doTheTest(); try comptime S.doTheTest(); } test "@intFromFloat vector boundary cases" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; const S = struct { fn case(comptime I: type, unshifted_inputs: [2]f32, expected: [2]I) !void { const inputs: @Vector(2, f32) = .{ std.math.nextAfter(f32, unshifted_inputs[0], std.math.inf(f32)), std.math.nextAfter(f32, unshifted_inputs[1], -std.math.inf(f32)), }; const outputs: @Vector(2, I) = @intFromFloat(inputs); try expect(outputs[0] == expected[0]); try expect(outputs[1] == expected[1]); } fn doTheTest() !void { try case(u8, .{ -1.0, 256.0 }, .{ 0, 255 }); try case(i8, .{ -129.0, 128.0 }, .{ -128, 127 }); try case(u0, .{ -1.0, 1.0 }, .{ 0, 0 }); try case(i0, .{ -1.0, 1.0 }, .{ 0, 0 }); try case(u10, .{ -1.0, 1024.0 }, .{ 0, 1023 }); try case(i10, .{ -513.0, 512.0 }, .{ -512, 511 }); } }; try S.doTheTest(); try comptime S.doTheTest(); } test "coerce enum to union with zero-bit fields through local variables" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; const E = enum(u1) { foo, bar }; const U = union(E) { foo, bar }; var runtime: E = undefined; runtime = .foo; var result: U = undefined; result = runtime; try expect(result == .foo); }