zig/test/behavior/cast.zig
mlugg cba7e8a4e9 AstGen: do not forward result pointers through @as
The `coerce_result_ptr` instruction is highly problematic and leads to
unintentional memory reinterpretation in some cases. It is more correct
to simply not forward result pointers through this builtin.

`coerce_result_ptr` is still used for struct and array initializations,
where it can still cause issues. Eliminating this usage will be a future
change.

Resolves: #16991
2023-09-15 01:05:02 -07:00

2523 lines
90 KiB
Zig

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" {
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" {
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_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);
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;
try expect(b == 255);
}
test "implicit cast comptime_int to comptime_float" {
try comptime expect(@as(comptime_float, 10) == @as(f32, 10));
try expect(2 == 2.0);
}
test "comptime_int @floatFromInt" {
{
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_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 {
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_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
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) 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 "@intFromFloat" {
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
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_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) 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_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
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
if (builtin.zig_backend == .stage2_spirv64) 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_spirv64) return error.SkipZigTest;
var i = @as(usize, 0);
var v = @as(*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_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);
try comptime expect(S.blah(0) == null);
try expect(S.blah(10).? == 1);
try comptime expect(S.blah(10).? == 1);
try expect(S.blah(-10).? == -1);
try comptime 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_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
if (builtin.zig_backend == .stage2_spirv64) 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_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();
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_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
var w: u31 = 5;
var x: u8 = 7;
var y: i32 = -5;
var a = w + y + x;
try comptime 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
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
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_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_spirv64) 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_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 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_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
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_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
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_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_spirv64) 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_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) 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_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
try expect(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
try comptime expect(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
try expect(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
try comptime 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
if (builtin.zig_backend == .stage2_spirv64) 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_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) 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_wasm) 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
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
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 = @as(@Vector(2, u32), @intCast(down0));
var down2 = @as(@Vector(2, u16), @intCast(down0));
var down3 = @as(@Vector(2, u8), @intCast(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: @Vector(2, f32) = @splat(1234.0);
var wider: @Vector(2, f64) = vec;
try expect(wider[0] == 1234.0);
try expect(wider[1] == 1234.0);
}
};
try S.doTheTest();
try comptime S.doTheTest();
try S.doTheTestFloat();
try comptime S.doTheTestFloat();
}
test "@floatCast cast down" {
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
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
{
var double: f64 = 0.001534;
var 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_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
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_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
if (builtin.zig_backend == .stage2_spirv64) 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 == .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_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
if (builtin.zig_backend == .stage2_spirv64) 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 == .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, "Two"));
try expect(mem.eql(u8, error_set_info.ErrorSet.?[2].name, "Three"));
}
{
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, "Two"));
try expect(mem.eql(u8, error_set_info.ErrorSet.?[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_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) 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 == .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, "Two"));
try expect(mem.eql(u8, error_set_info.ErrorSet.?[2].name, "Three"));
}
{
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, "Two"));
try expect(mem.eql(u8, error_set_info.ErrorSet.?[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_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) 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 == .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_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
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_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
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
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
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_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) 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_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
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();
try comptime 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
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
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();
try comptime 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
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
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();
try comptime S.doTheTest();
}
test "peer cast [*:x]T to [*]T" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
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();
try comptime 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_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
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();
try comptime 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
if (builtin.zig_backend == .stage2_spirv64) 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_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) 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;
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
if (builtin.zig_backend == .stage2_spirv64) 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_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
var array: [4:0]u8 = undefined;
array[4] = 0; // TODO remove this when #4372 is solved
var slice: [:0]u8 = array[0..4 :0];
try comptime expect(@TypeOf(slice, "hi") == [:0]const u8);
try comptime expect(@TypeOf("hi", slice) == [:0]const u8);
}
test "peer type resolve array pointers, one of them const" {
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
var array1: [4]u8 = undefined;
const array2: [5]u8 = undefined;
try comptime expect(@TypeOf(&array1, &array2) == []const u8);
try comptime expect(@TypeOf(&array2, &array1) == []const u8);
}
test "peer type resolve array pointer and unknown pointer" {
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
const const_array: [4]u8 = undefined;
var array: [4]u8 = undefined;
var const_ptr: [*]const u8 = undefined;
var ptr: [*]u8 = undefined;
try comptime expect(@TypeOf(&array, ptr) == [*]u8);
try comptime expect(@TypeOf(ptr, &array) == [*]u8);
try comptime expect(@TypeOf(&const_array, ptr) == [*]const u8);
try comptime expect(@TypeOf(ptr, &const_array) == [*]const u8);
try comptime expect(@TypeOf(&array, const_ptr) == [*]const u8);
try comptime expect(@TypeOf(const_ptr, &array) == [*]const u8);
try comptime expect(@TypeOf(&const_array, const_ptr) == [*]const u8);
try comptime expect(@TypeOf(const_ptr, &const_array) == [*]const u8);
}
test "comptime float casts" {
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
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_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 = @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_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_spirv64) return error.SkipZigTest;
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) {
@as([*]u8, @ptrCast(array.?))[n] += 1;
}
}
test "compile time int to ptr of function" {
if (builtin.zig_backend == .stage2_spirv64) 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_c) 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 });
}
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
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
var a: u32 = 1;
var ptr: *align(@alignOf(u32)) anyopaque = &a;
var b: *u32 = @as(*u32, @ptrCast(ptr));
try expect(b.* == 1);
var ptr2: ?*align(@alignOf(u32)) anyopaque = &a;
var c: *u32 = @as(*u32, @ptrCast(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
if (builtin.zig_backend == .stage2_spirv64) 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_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) 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_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_spirv64) return error.SkipZigTest;
try expect(mem.eql(u8, castToOptionalSlice().?, "hi"));
try comptime 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_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) 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_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_spirv64) 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_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_spirv64) 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_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
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 = @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" {
var f = @as(*align(1) const fn () callconv(.C) void, @ptrCast(&global_array));
try expect(@intFromPtr(f) == @intFromPtr(&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_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
const S = struct {
fn doTheTest() !void {
var a = "Hello";
var 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" {
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
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
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
var foo: struct { ptr: ?*anyopaque } = .{ .ptr = &global_struct };
try expect(foo.ptr.? == @as(*anyopaque, @ptrCast(&global_struct)));
}
test "cast between *[N]void and []void" {
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
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
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
try expect(mem.eql(u8, boolToStr(true), "true"));
try expect(mem.eql(u8, boolToStr(false), "false"));
try comptime expect(mem.eql(u8, boolToStr(true), "true"));
try comptime 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_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
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();
try comptime 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_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
const S = struct {
fn doTheTest() !void {
var x: f128 = 1234.0;
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_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_spirv64) 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_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();
try comptime 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_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
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
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
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
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
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_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
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 = @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_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: 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" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
var a: [:0]const u8 = "foo";
var b: [*c]const u8 = a;
var 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_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
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_spirv64) 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 "single item pointer to pointer to array to slice" {
if (builtin.zig_backend == .stage2_spirv64) 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_wasm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
var foo: i32 = 123;
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 "@volatileCast without a result location" {
var x: i32 = 1234;
var 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_spirv64) 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_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.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
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));
comptime assert(@TypeOf(a, b) == []const T);
comptime assert(@TypeOf(b, a) == []const T);
var t = true;
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_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.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
const i: u8 = 100;
var f: f32 = 1.234;
comptime assert(@TypeOf(i, f) == f32);
comptime assert(@TypeOf(f, i) == f32);
var t = true;
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; // 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.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
var a: [2:0]u32 = .{ 0, 1 };
var b: [2:0]u32 = .{ 2, 3 };
comptime assert(@TypeOf(a, b) == [2:0]u32);
comptime assert(@TypeOf(b, a) == [2:0]u32);
var t = true;
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_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.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
var a: [2:0]u32 = .{ 0, 1 };
var b: [2]u32 = .{ 2, 3 };
comptime assert(@TypeOf(a, b) == [2]u32);
comptime assert(@TypeOf(b, a) == [2]u32);
var t = true;
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; // 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.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
var arr: [2]u32 = .{ 0, 1 };
var vec: @Vector(2, u32) = .{ 2, 3 };
comptime assert(@TypeOf(arr, vec) == @Vector(2, u32));
comptime assert(@TypeOf(vec, arr) == @Vector(2, u32));
var t = true;
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; // 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.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
var arr: [2]u8 = .{ 0, 1 };
var vec: @Vector(2, u64) = .{ 2, 3 };
comptime assert(@TypeOf(arr, vec) == @Vector(2, u64));
comptime assert(@TypeOf(vec, arr) == @Vector(2, u64));
var t = true;
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; // 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.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
const E = error{Foo};
var a: E!*u8 = error.Foo;
var b: ?*u8 = null;
comptime assert(@TypeOf(a, b) == E!?*u8);
comptime assert(@TypeOf(b, a) == E!?*u8);
var t = true;
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_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.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
var a: [*c]c_int = 0x1000;
const b = null;
comptime assert(@TypeOf(a, b) == [*c]c_int);
comptime assert(@TypeOf(b, a) == [*c]c_int);
var t = true;
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_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.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
const E = error{Foo};
var a: E = error.Foo;
var b: *const [5:0]u8 = @as(*const [5:0]u8, @ptrFromInt(0x1000));
var c: ?[*:0]u8 = null;
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;
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; // 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.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
var a: ?@Vector(3, u32) = .{ 0, 1, 2 };
var b: @Vector(3, u32) = .{ 3, 4, 5 };
comptime assert(@TypeOf(a, b) == ?@Vector(3, u32));
comptime assert(@TypeOf(b, a) == ?@Vector(3, u32));
var t = true;
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_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.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
var a: ?i32 = 42;
const b: comptime_int = 50;
comptime assert(@TypeOf(a, b) == ?i32);
comptime assert(@TypeOf(b, a) == ?i32);
var t = true;
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; // 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.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
var arr: [3]i32 = .{ 1, 2, 3 };
const tup = .{ 4, 5, 6 };
comptime assert(@TypeOf(arr, tup) == [3]i32);
comptime assert(@TypeOf(tup, arr) == [3]i32);
var t = true;
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; // 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.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
var vec: @Vector(3, i32) = .{ 1, 2, 3 };
const tup = .{ 4, 5, 6 };
comptime assert(@TypeOf(vec, tup) == @Vector(3, i32));
comptime assert(@TypeOf(tup, vec) == @Vector(3, i32));
var t = true;
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; // 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.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
var vec: @Vector(2, i8) = .{ 10, 20 };
var arr: [2]i8 = .{ 30, 40 };
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;
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_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.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
var a: [:0]const u8 = "Hello";
var b = &.{};
comptime assert(@TypeOf(a, b) == []const u8);
comptime assert(@TypeOf(b, a) == []const u8);
var t = true;
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_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.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
var a: [:0]const u8 = "Hello";
var b = &.{ @as(u8, 'x'), @as(u8, 'y'), @as(u8, 'z') };
comptime assert(@TypeOf(a, b) == []const u8);
comptime assert(@TypeOf(b, a) == []const u8);
var t = true;
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_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.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
var a: ?[:0]const u8 = null;
var b = &.{ @as(u8, 'x'), @as(u8, 'y'), @as(u8, 'z') };
comptime assert(@TypeOf(a, b) == ?[]const u8);
comptime assert(@TypeOf(b, a) == ?[]const u8);
var t = true;
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_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.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
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"),
};
// 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;
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_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.zig_backend == .stage2_spirv64) 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;
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_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.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
var buf = "hello".*;
var a: [*c]u8 = &buf;
var b: [*:0]const u8 = "world";
comptime assert(@TypeOf(a, b) == [*c]const u8);
comptime assert(@TypeOf(b, a) == [*c]const u8);
var t = true;
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_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.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
var buf_a align(4) = "foo".*;
var buf_b align(4) = "bar".*;
var buf_c align(4) = "baz".*;
var a: [*:0]align(4) const u8 = &buf_a;
var b: *align(2) volatile [3:0]u8 = &buf_b;
var c: [*:0]align(4) u8 = &buf_c;
comptime assert(@TypeOf(a, b, c) == [*:0]align(2) const volatile u8);
comptime assert(@TypeOf(a, c, b) == [*:0]align(2) const volatile u8);
comptime assert(@TypeOf(b, a, c) == [*:0]align(2) const volatile u8);
comptime assert(@TypeOf(b, c, a) == [*:0]align(2) const volatile u8);
comptime assert(@TypeOf(c, a, b) == [*:0]align(2) const volatile u8);
comptime assert(@TypeOf(c, b, a) == [*:0]align(2) const volatile u8);
var x: u8 = 0;
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,
};
try expectEqualSlices(u8, std.mem.span(@volatileCast(r1)), "foo");
try expectEqualSlices(u8, std.mem.span(@volatileCast(r2)), "bar");
try expectEqualSlices(u8, std.mem.span(@volatileCast(r3)), "baz");
}
test "cast builtins can wrap result in optional" {
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.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
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_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.zig_backend == .stage2_spirv64) 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_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.zig_backend == .stage2_spirv64) 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() 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_wasm) 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
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
const S = struct {
fn doTheTest() !void {
var a: @Vector(3, f64) = .{ 1.5, 2.5, 3.5 };
const b: @Vector(3, f32) = @floatCast(a);
try expectEqual(@Vector(3, f32){ 1.5, 2.5, 3.5 }, b);
}
};
try S.doTheTest();
try comptime S.doTheTest();
}
test "@ptrFromInt on vector" {
if (builtin.zig_backend == .stage2_wasm) 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
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
const S = struct {
fn doTheTest() !void {
var a: @Vector(3, usize) = .{ 0x1000, 0x2000, 0x3000 };
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_wasm) 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
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
const S = struct {
fn doTheTest() !void {
var a: @Vector(3, *anyopaque) = .{
@ptrFromInt(0x1000),
@ptrFromInt(0x2000),
@ptrFromInt(0x3000),
};
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_wasm) 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
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
const S = struct {
fn doTheTest() !void {
var a: @Vector(3, u32) = .{ 10, 20, 30 };
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_wasm) 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
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
const S = struct {
fn doTheTest() !void {
var a: @Vector(3, f32) = .{ 10.3, 20.5, 30.7 };
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_wasm) 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
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
const S = struct {
fn doTheTest() !void {
var a: @Vector(3, bool) = .{ false, true, false };
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" {
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
const from: i32 = undefined;
var to: f32 = from;
to = @floatFromInt(from);
to = 42.0;
try expectEqual(@as(f32, 42.0), to);
}
test "@as does not corrupt values with incompatible representations" {
if (builtin.zig_backend == .stage2_wasm) 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
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
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);
}