mirror of
https://github.com/ziglang/zig.git
synced 2024-11-27 15:42:49 +00:00
cba7e8a4e9
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
2523 lines
90 KiB
Zig
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);
|
|
}
|