mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
Some tests are now failing due to debug info changes, some tests now pass due to improved compiler functionality.
2432 lines
82 KiB
Zig
2432 lines
82 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" {
|
|
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
|
|
|
|
{
|
|
const result = @as(f16, @floatFromInt(1234));
|
|
try expect(@TypeOf(result) == f16);
|
|
try expect(result == 1234.0);
|
|
}
|
|
{
|
|
const result = @as(f32, @floatFromInt(1234));
|
|
try expect(@TypeOf(result) == f32);
|
|
try expect(result == 1234.0);
|
|
}
|
|
{
|
|
const result = @as(f64, @floatFromInt(1234));
|
|
try expect(@TypeOf(result) == f64);
|
|
try expect(result == 1234.0);
|
|
}
|
|
|
|
{
|
|
const result = @as(f128, @floatFromInt(1234));
|
|
try expect(@TypeOf(result) == f128);
|
|
try expect(result == 1234.0);
|
|
}
|
|
// big comptime_int (> 64 bits) to f128 conversion
|
|
{
|
|
const result = @as(f128, @floatFromInt(0x1_0000_0000_0000_0000));
|
|
try expect(@TypeOf(result) == f128);
|
|
try expect(result == 0x1_0000_0000_0000_0000.0);
|
|
}
|
|
}
|
|
|
|
test "@floatFromInt" {
|
|
if (builtin.zig_backend == .stage2_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_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;
|
|
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) 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
|
|
|
|
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
|
|
|
|
try expect(MakeType(void).getNull() == null);
|
|
try expect(MakeType(void).getNonNull() != null);
|
|
}
|
|
|
|
fn MakeType(comptime T: type) type {
|
|
return struct {
|
|
fn getNull() ?T {
|
|
return null;
|
|
}
|
|
|
|
fn getNonNull() ?T {
|
|
return @as(T, undefined);
|
|
}
|
|
};
|
|
}
|
|
|
|
test "implicit cast from *[N]T to [*c]T" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
var x: [4]u16 = [4]u16{ 0, 1, 2, 3 };
|
|
var y: [*c]u16 = &x;
|
|
|
|
try expect(std.mem.eql(u16, x[0..4], y[0..4]));
|
|
x[0] = 8;
|
|
y[3] = 6;
|
|
try expect(std.mem.eql(u16, x[0..4], y[0..4]));
|
|
}
|
|
|
|
test "*usize to *void" {
|
|
var i = @as(usize, 0);
|
|
var v = @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 coercion 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;
|
|
if (builtin.zig_backend == .stage2_x86_64) 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
|
|
|
|
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
|
|
|
|
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
|
|
|
|
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
|
|
|
|
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
|
|
|
|
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
|
|
|
|
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
|
|
|
|
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
|
|
|
|
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
|
|
|
|
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
|
|
|
|
{
|
|
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
|
|
|
|
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
|
|
|
|
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
|
|
|
|
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
|
|
|
|
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
|
|
|
|
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
|
|
|
|
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
|
|
|
|
var buffer: [5]u8 = "abcde".*;
|
|
var buf: []const u8 = buffer[0..];
|
|
var b = false;
|
|
var y = if (b) &[0]u8{} else buf;
|
|
try expect(mem.eql(u8, "abcde", y));
|
|
}
|
|
|
|
test "peer cast *[N]T to [*]T" {
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
var array = [4:99]i32{ 1, 2, 3, 4 };
|
|
var dest: [*]i32 = undefined;
|
|
try expect(@TypeOf(&array, dest) == [*]i32);
|
|
try expect(@TypeOf(dest, &array) == [*]i32);
|
|
}
|
|
|
|
test "peer resolution of string literals" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
const S = struct {
|
|
const E = enum { a, b, c, d };
|
|
|
|
fn doTheTest(e: E) !void {
|
|
const cmd = switch (e) {
|
|
.a => "one",
|
|
.b => "two",
|
|
.c => "three",
|
|
.d => "four",
|
|
};
|
|
try expect(mem.eql(u8, cmd, "two"));
|
|
}
|
|
};
|
|
try S.doTheTest(.b);
|
|
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
|
|
|
|
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
|
|
|
|
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
|
|
|
|
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
|
|
|
|
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
|
|
|
|
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
|
|
|
|
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
|
|
|
|
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
|
|
|
|
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
|
|
|
|
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" {
|
|
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" {
|
|
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" {
|
|
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
|
|
|
|
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" {
|
|
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;
|
|
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
|
|
|
|
if (builtin.zig_backend == .stage2_c) {
|
|
// https://github.com/ziglang/zig/issues/16845
|
|
return error.SkipZigTest;
|
|
}
|
|
|
|
const Container = struct {
|
|
const Ctx = opaque {};
|
|
ctx: *Ctx,
|
|
func: *const fn (*Ctx) void,
|
|
};
|
|
const Foo = struct {
|
|
x: i32,
|
|
y: i32,
|
|
fn funcImpl(self: *@This()) void {
|
|
self.x += 1;
|
|
self.y += 1;
|
|
}
|
|
};
|
|
var foo = Foo{ .x = 100, .y = 200 };
|
|
var c = Container{
|
|
.ctx = @ptrCast(&foo),
|
|
.func = @ptrCast(&Foo.funcImpl),
|
|
};
|
|
c.func(c.ctx);
|
|
try std.testing.expectEqual(foo, .{ .x = 101, .y = 201 });
|
|
}
|
|
|
|
test "implicit ptr to *anyopaque" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
var a: u32 = 1;
|
|
var ptr: *align(@alignOf(u32)) anyopaque = &a;
|
|
var b: *u32 = @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
|
|
|
|
const a = returnNullFromOptionalTypeErrorRef();
|
|
const b = returnNullLitFromOptionalTypeErrorRef();
|
|
try expect((try a) == null and (try b) == null);
|
|
}
|
|
fn returnNullFromOptionalTypeErrorRef() anyerror!?*A {
|
|
const a: ?*A = null;
|
|
return a;
|
|
}
|
|
fn returnNullLitFromOptionalTypeErrorRef() anyerror!?*A {
|
|
return null;
|
|
}
|
|
|
|
test "peer type resolution: [0]u8 and []const u8" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
try expect(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
|
|
try expect(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
|
|
comptime {
|
|
try expect(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
|
|
try expect(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
|
|
}
|
|
}
|
|
fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 {
|
|
if (a) {
|
|
return &[_]u8{};
|
|
}
|
|
|
|
return slice[0..1];
|
|
}
|
|
|
|
test "implicitly cast from [N]T to ?[]const T" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
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
|
|
|
|
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
|
|
|
|
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
|
|
|
|
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" {
|
|
const S = struct {
|
|
const Handler = ?fn ([*c]const u8) callconv(.C) void;
|
|
fn addCallback(comptime handler: Handler) void {
|
|
_ = handler;
|
|
}
|
|
|
|
fn myCallback(cstr: ?[*:0]const u8) callconv(.C) void {
|
|
_ = cstr;
|
|
}
|
|
|
|
fn doTheTest() void {
|
|
addCallback(myCallback);
|
|
}
|
|
};
|
|
S.doTheTest();
|
|
}
|
|
|
|
var global_struct: struct { f0: usize } = undefined;
|
|
test "assignment to optional pointer result loc" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
var foo: struct { ptr: ?*anyopaque } = .{ .ptr = &global_struct };
|
|
try expect(foo.ptr.? == @as(*anyopaque, @ptrCast(&global_struct)));
|
|
}
|
|
|
|
test "cast between *[N]void and []void" {
|
|
var a: [4]void = undefined;
|
|
var b: []void = &a;
|
|
try expect(b.len == 4);
|
|
}
|
|
|
|
test "peer resolve arrays of different size to const slice" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
try expect(mem.eql(u8, boolToStr(true), "true"));
|
|
try expect(mem.eql(u8, boolToStr(false), "false"));
|
|
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_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;
|
|
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) 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_sparc64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) 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
|
|
|
|
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
|
|
|
|
var a: ?[:0]const u8 = null;
|
|
var b: ?[]const u8 = a;
|
|
try expect(b == null);
|
|
}
|
|
|
|
test "coerce undefined single-item pointer of array to error union of slice" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
const a = @as([*]u8, undefined)[0..0];
|
|
var b: error{a}![]const u8 = a;
|
|
const s = try b;
|
|
try expect(s.len == 0);
|
|
}
|
|
|
|
test "pointer to empty struct literal to mutable slice" {
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
var x: []i32 = &.{};
|
|
try expect(x.len == 0);
|
|
}
|
|
|
|
test "coerce between pointers of compatible differently-named floats" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) 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
|
|
|
|
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_spirv64) return error.SkipZigTest;
|
|
|
|
const S = packed struct(u2) { a: u0, b: u2 };
|
|
const s = @as(S, @bitCast(@as(u2, 2)));
|
|
try expect(s.a == 0);
|
|
try expect(s.b == 2);
|
|
const i = @as(u2, @bitCast(s));
|
|
try expect(i == 2);
|
|
}
|
|
|
|
test "optional pointer coerced to optional allowzero pointer" {
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
|
|
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" {
|
|
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" {
|
|
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" {
|
|
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_sparc64) 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_sparc64) 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_sparc64) 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_sparc64) 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_sparc64) 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_sparc64) 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_sparc64) 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_sparc64) 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_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_sparc64) 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_sparc64) 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_wasm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) 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_wasm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) 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_sparc64) 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_sparc64) 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_sparc64) 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_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_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_sparc64) 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_sparc64) 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_sparc64) 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_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
const S = struct {
|
|
const MyEnum = enum(u32) { _ };
|
|
const E = error{ImpossibleError};
|
|
fn a() E!MyEnum {
|
|
return @enumFromInt(123);
|
|
}
|
|
fn b() E!u32 {
|
|
return @intFromFloat(42.50);
|
|
}
|
|
fn c() E!*const f32 {
|
|
const x: u32 = 1;
|
|
return @ptrCast(&x);
|
|
}
|
|
|
|
fn doTheTest() !void {
|
|
const ra = try a();
|
|
const rb = try b();
|
|
const rc = try c();
|
|
|
|
comptime assert(@TypeOf(ra) == MyEnum);
|
|
comptime assert(@TypeOf(rb) == u32);
|
|
comptime assert(@TypeOf(rc) == *const f32);
|
|
|
|
try expect(@intFromEnum(ra) == 123);
|
|
try expect(rb == 42);
|
|
try expect(@as(*const u32, @ptrCast(rc)).* == 1);
|
|
}
|
|
};
|
|
|
|
try S.doTheTest();
|
|
try comptime S.doTheTest();
|
|
}
|
|
|
|
test "cast builtins can wrap result in error union and optional" {
|
|
if (builtin.zig_backend == .stage2_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 {
|
|
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_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 "15-bit int to float" {
|
|
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
|
|
|
var a: u15 = 42;
|
|
var b: f32 = @floatFromInt(a);
|
|
try expect(b == 42.0);
|
|
}
|
|
|
|
test "@as does not corrupt values with incompatible representations" {
|
|
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);
|
|
}
|
|
|
|
test "result information is preserved through many nested structures" {
|
|
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 {
|
|
const E = error{Foo};
|
|
const T = *const ?E!struct { x: ?*const E!?u8 };
|
|
|
|
var val: T = &.{ .x = &@truncate(0x1234) };
|
|
|
|
const struct_val = val.*.? catch unreachable;
|
|
const int_val = (struct_val.x.?.* catch unreachable).?;
|
|
|
|
try expect(int_val == 0x34);
|
|
}
|
|
};
|
|
|
|
try S.doTheTest();
|
|
try comptime S.doTheTest();
|
|
}
|