mirror of
https://github.com/ziglang/zig.git
synced 2026-02-03 13:13:40 +00:00
The existing logic for peer type resolution was quite convoluted and buggy. This rewrite makes it much more resilient, readable, and extensible. The algorithm works by first iterating over the types to select a "strategy", then applying that strategy, possibly applying peer resolution recursively. Several new tests have been added to cover cases which the old logic did not correctly handle. Resolves: #15138 Resolves: #15644 Resolves: #15693 Resolves: #15709 Resolves: #15752
2222 lines
78 KiB
Zig
2222 lines
78 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 = @intToPtr(*u8, x);
|
|
const z = @ptrToInt(y);
|
|
try expect(z == 13);
|
|
}
|
|
|
|
test "integer literal to pointer cast" {
|
|
const vga_mem = @intToPtr(*u16, 0xB8000);
|
|
try expect(@ptrToInt(vga_mem) == 0xB8000);
|
|
}
|
|
|
|
test "peer type resolution: ?T and T" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
try expect(peerTypeTAndOptionalT(true, false).? == 0);
|
|
try expect(peerTypeTAndOptionalT(false, false).? == 3);
|
|
comptime {
|
|
try expect(peerTypeTAndOptionalT(true, false).? == 0);
|
|
try expect(peerTypeTAndOptionalT(false, false).? == 3);
|
|
}
|
|
}
|
|
fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize {
|
|
if (c) {
|
|
return if (b) null else @as(usize, 0);
|
|
}
|
|
|
|
return @as(usize, 3);
|
|
}
|
|
|
|
test "resolve undefined with integer" {
|
|
try testResolveUndefWithInt(true, 1234);
|
|
comptime try testResolveUndefWithInt(true, 1234);
|
|
}
|
|
fn testResolveUndefWithInt(b: bool, x: i32) !void {
|
|
const value = if (b) x else undefined;
|
|
if (b) {
|
|
try expect(value == x);
|
|
}
|
|
}
|
|
|
|
test "@intCast to comptime_int" {
|
|
try expect(@intCast(comptime_int, 0) == 0);
|
|
}
|
|
|
|
test "implicit cast comptime numbers to any type when the value fits" {
|
|
const a: u64 = 255;
|
|
var b: u8 = a;
|
|
try expect(b == 255);
|
|
}
|
|
|
|
test "implicit cast comptime_int to comptime_float" {
|
|
comptime try expect(@as(comptime_float, 10) == @as(f32, 10));
|
|
try expect(2 == 2.0);
|
|
}
|
|
|
|
test "comptime_int @intToFloat" {
|
|
{
|
|
const result = @intToFloat(f16, 1234);
|
|
try expect(@TypeOf(result) == f16);
|
|
try expect(result == 1234.0);
|
|
}
|
|
{
|
|
const result = @intToFloat(f32, 1234);
|
|
try expect(@TypeOf(result) == f32);
|
|
try expect(result == 1234.0);
|
|
}
|
|
{
|
|
const result = @intToFloat(f64, 1234);
|
|
try expect(@TypeOf(result) == f64);
|
|
try expect(result == 1234.0);
|
|
}
|
|
|
|
{
|
|
const result = @intToFloat(f128, 1234);
|
|
try expect(@TypeOf(result) == f128);
|
|
try expect(result == 1234.0);
|
|
}
|
|
// big comptime_int (> 64 bits) to f128 conversion
|
|
{
|
|
const result = @intToFloat(f128, 0x1_0000_0000_0000_0000);
|
|
try expect(@TypeOf(result) == f128);
|
|
try expect(result == 0x1_0000_0000_0000_0000.0);
|
|
}
|
|
}
|
|
|
|
test "@intToFloat" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
const S = struct {
|
|
fn doTheTest() !void {
|
|
try testIntToFloat(-2);
|
|
}
|
|
|
|
fn testIntToFloat(k: i32) !void {
|
|
const f = @intToFloat(f32, k);
|
|
const i = @floatToInt(i32, f);
|
|
try expect(i == k);
|
|
}
|
|
};
|
|
try S.doTheTest();
|
|
comptime try S.doTheTest();
|
|
}
|
|
|
|
test "@intToFloat(f80)" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_spirv64) 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 = @intToFloat(f80, k);
|
|
const i = @floatToInt(Int, f);
|
|
try expect(i == k);
|
|
}
|
|
};
|
|
try S.doTheTest(i31);
|
|
try S.doTheTest(i32);
|
|
try S.doTheTest(i45);
|
|
try S.doTheTest(i64);
|
|
try S.doTheTest(i80);
|
|
try S.doTheTest(i128);
|
|
// try S.doTheTest(i256); // TODO missing compiler_rt symbols
|
|
comptime try S.doTheTest(i31);
|
|
comptime try S.doTheTest(i32);
|
|
comptime try S.doTheTest(i45);
|
|
comptime try S.doTheTest(i64);
|
|
comptime try S.doTheTest(i80);
|
|
comptime try S.doTheTest(i128);
|
|
comptime try S.doTheTest(i256);
|
|
}
|
|
|
|
test "@floatToInt" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
try testFloatToInts();
|
|
comptime try testFloatToInts();
|
|
}
|
|
|
|
fn testFloatToInts() !void {
|
|
const x = @as(i32, 1e4);
|
|
try expect(x == 10000);
|
|
const y = @floatToInt(i32, @as(f32, 1e4));
|
|
try expect(y == 10000);
|
|
try expectFloatToInt(f32, 255.1, u8, 255);
|
|
try expectFloatToInt(f32, 127.2, i8, 127);
|
|
try expectFloatToInt(f32, -128.2, i8, -128);
|
|
}
|
|
|
|
fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) !void {
|
|
try expect(@floatToInt(I, f) == i);
|
|
}
|
|
|
|
test "implicitly cast indirect pointer to maybe-indirect pointer" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_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 = @intCast(i32, 1234);
|
|
try expect(@TypeOf(result) == i32);
|
|
try expect(result == 1234);
|
|
}
|
|
|
|
test "@floatCast comptime_int and comptime_float" {
|
|
{
|
|
const result = @floatCast(f16, 1234);
|
|
try expect(@TypeOf(result) == f16);
|
|
try expect(result == 1234.0);
|
|
}
|
|
{
|
|
const result = @floatCast(f16, 1234.0);
|
|
try expect(@TypeOf(result) == f16);
|
|
try expect(result == 1234.0);
|
|
}
|
|
{
|
|
const result = @floatCast(f32, 1234);
|
|
try expect(@TypeOf(result) == f32);
|
|
try expect(result == 1234.0);
|
|
}
|
|
{
|
|
const result = @floatCast(f32, 1234.0);
|
|
try expect(@TypeOf(result) == f32);
|
|
try expect(result == 1234.0);
|
|
}
|
|
}
|
|
|
|
test "coerce undefined to optional" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
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 = @ptrCast(*void, &i);
|
|
v.* = {};
|
|
}
|
|
|
|
test "@intToEnum passed a comptime_int to an enum with one item" {
|
|
const E = enum { A };
|
|
const x = @intToEnum(E, 0);
|
|
try expect(x == E.A);
|
|
}
|
|
|
|
test "@intCast to u0 and use the result" {
|
|
const S = struct {
|
|
fn doTheTest(zero: u1, one: u1, bigzero: i32) !void {
|
|
try expect((one << @intCast(u0, bigzero)) == 1);
|
|
try expect((zero << @intCast(u0, bigzero)) == 0);
|
|
}
|
|
};
|
|
try S.doTheTest(0, 1, 0);
|
|
comptime try S.doTheTest(0, 1, 0);
|
|
}
|
|
|
|
test "peer result null and comptime_int" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
const S = struct {
|
|
fn blah(n: i32) ?i32 {
|
|
if (n == 0) {
|
|
return null;
|
|
} else if (n < 0) {
|
|
return -1;
|
|
} else {
|
|
return 1;
|
|
}
|
|
}
|
|
};
|
|
|
|
try expect(S.blah(0) == null);
|
|
comptime try expect(S.blah(0) == null);
|
|
try expect(S.blah(10).? == 1);
|
|
comptime try expect(S.blah(10).? == 1);
|
|
try expect(S.blah(-10).? == -1);
|
|
comptime try expect(S.blah(-10).? == -1);
|
|
}
|
|
|
|
test "*const ?[*]const T to [*c]const [*c]const T" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_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();
|
|
comptime try S.doTheTest();
|
|
}
|
|
|
|
test "cast from ?[*]T to ??[*]T" {
|
|
const a: ??[*]u8 = @as(?[*]u8, null);
|
|
try expect(a != null and a.? == null);
|
|
}
|
|
|
|
test "peer type unsigned int to signed" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
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;
|
|
comptime try expect(@TypeOf(a) == i32);
|
|
try expect(a == 7);
|
|
}
|
|
|
|
test "expected [*c]const u8, found [*:0]const u8" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
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);
|
|
comptime try testCastIntToErr(error.ItBroke);
|
|
}
|
|
fn testCastIntToErr(err: anyerror) !void {
|
|
const x = @errorToInt(err);
|
|
const y = @intToError(x);
|
|
try expect(error.ItBroke == y);
|
|
}
|
|
|
|
test "peer resolve array and const slice" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
try testPeerResolveArrayConstSlice(true);
|
|
comptime try testPeerResolveArrayConstSlice(true);
|
|
}
|
|
fn testPeerResolveArrayConstSlice(b: bool) !void {
|
|
const value1 = if (b) "aoeu" else @as([]const u8, "zz");
|
|
const value2 = if (b) @as([]const u8, "zz") else "aoeu";
|
|
try expect(mem.eql(u8, value1, "aoeu"));
|
|
try expect(mem.eql(u8, value2, "zz"));
|
|
}
|
|
|
|
test "implicitly cast from T to anyerror!?T" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
|
|
|
|
try castToOptionalTypeError(1);
|
|
comptime try castToOptionalTypeError(1);
|
|
}
|
|
|
|
const A = struct {
|
|
a: i32,
|
|
};
|
|
fn castToOptionalTypeError(z: i32) !void {
|
|
const x = @as(i32, 1);
|
|
const y: anyerror!?i32 = x;
|
|
try expect((try y).? == 1);
|
|
|
|
const f = z;
|
|
const g: anyerror!?i32 = f;
|
|
_ = try g;
|
|
|
|
const a = A{ .a = z };
|
|
const b: anyerror!?A = a;
|
|
try expect((b catch unreachable).?.a == 1);
|
|
}
|
|
|
|
test "implicitly cast from [0]T to anyerror![]T" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
|
|
|
|
try testCastZeroArrayToErrSliceMut();
|
|
comptime try testCastZeroArrayToErrSliceMut();
|
|
}
|
|
|
|
fn testCastZeroArrayToErrSliceMut() !void {
|
|
try expect((gimmeErrOrSlice() catch unreachable).len == 0);
|
|
}
|
|
|
|
fn gimmeErrOrSlice() anyerror![]u8 {
|
|
return &[_]u8{};
|
|
}
|
|
|
|
test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
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();
|
|
comptime try S.doTheTest();
|
|
}
|
|
fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 {
|
|
if (a) {
|
|
return &[_]u8{};
|
|
}
|
|
|
|
return slice[0..1];
|
|
}
|
|
|
|
test "implicit cast from *const [N]T to []const T" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
|
|
|
|
try testCastConstArrayRefToConstSlice();
|
|
comptime try testCastConstArrayRefToConstSlice();
|
|
}
|
|
|
|
fn testCastConstArrayRefToConstSlice() !void {
|
|
{
|
|
const blah = "aoeu".*;
|
|
const const_array_ref = &blah;
|
|
try expect(@TypeOf(const_array_ref) == *const [4:0]u8);
|
|
const slice: []const u8 = const_array_ref;
|
|
try expect(mem.eql(u8, slice, "aoeu"));
|
|
}
|
|
{
|
|
const blah: [4]u8 = "aoeu".*;
|
|
const const_array_ref = &blah;
|
|
try expect(@TypeOf(const_array_ref) == *const [4]u8);
|
|
const slice: []const u8 = const_array_ref;
|
|
try expect(mem.eql(u8, slice, "aoeu"));
|
|
}
|
|
}
|
|
|
|
test "peer type resolution: error and [N]T" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
|
|
|
|
try expect(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
|
|
comptime try expect(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
|
|
try expect(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
|
|
comptime try expect(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
|
|
}
|
|
|
|
fn testPeerErrorAndArray(x: u8) anyerror![]const u8 {
|
|
return switch (x) {
|
|
0x00 => "OK",
|
|
else => error.BadValue,
|
|
};
|
|
}
|
|
fn testPeerErrorAndArray2(x: u8) anyerror![]const u8 {
|
|
return switch (x) {
|
|
0x00 => "OK",
|
|
0x01 => "OKK",
|
|
else => error.BadValue,
|
|
};
|
|
}
|
|
|
|
test "single-item pointer of array to slice to unknown length pointer" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
|
|
|
|
try testCastPtrOfArrayToSliceAndPtr();
|
|
comptime try testCastPtrOfArrayToSliceAndPtr();
|
|
}
|
|
|
|
fn testCastPtrOfArrayToSliceAndPtr() !void {
|
|
{
|
|
var array = "aoeu".*;
|
|
const x: [*]u8 = &array;
|
|
x[0] += 1;
|
|
try expect(mem.eql(u8, array[0..], "boeu"));
|
|
const y: []u8 = &array;
|
|
y[0] += 1;
|
|
try expect(mem.eql(u8, array[0..], "coeu"));
|
|
}
|
|
{
|
|
var array: [4]u8 = "aoeu".*;
|
|
const x: [*]u8 = &array;
|
|
x[0] += 1;
|
|
try expect(mem.eql(u8, array[0..], "boeu"));
|
|
const y: []u8 = &array;
|
|
y[0] += 1;
|
|
try expect(mem.eql(u8, array[0..], "coeu"));
|
|
}
|
|
}
|
|
|
|
test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_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(@ptrCast([*:0]const u8, x[0].?), 0), "window name"));
|
|
}
|
|
|
|
test "vector casts" {
|
|
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_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 = @intCast(@Vector(2, u32), down0);
|
|
var down2 = @intCast(@Vector(2, u16), down0);
|
|
var down3 = @intCast(@Vector(2, u8), down0);
|
|
|
|
try expect(mem.eql(u16, &@as([2]u16, up1), &[2]u16{ 0x55, 0xaa }));
|
|
try expect(mem.eql(u32, &@as([2]u32, up2), &[2]u32{ 0x55, 0xaa }));
|
|
try expect(mem.eql(u64, &@as([2]u64, up3), &[2]u64{ 0x55, 0xaa }));
|
|
|
|
try expect(mem.eql(u32, &@as([2]u32, down1), &[2]u32{ 0x55, 0xaa }));
|
|
try expect(mem.eql(u16, &@as([2]u16, down2), &[2]u16{ 0x55, 0xaa }));
|
|
try expect(mem.eql(u8, &@as([2]u8, down3), &[2]u8{ 0x55, 0xaa }));
|
|
}
|
|
|
|
fn doTheTestFloat() !void {
|
|
var vec = @splat(2, @as(f32, 1234.0));
|
|
var wider: @Vector(2, f64) = vec;
|
|
try expect(wider[0] == 1234.0);
|
|
try expect(wider[1] == 1234.0);
|
|
}
|
|
};
|
|
|
|
try S.doTheTest();
|
|
comptime try S.doTheTest();
|
|
try S.doTheTestFloat();
|
|
comptime try S.doTheTestFloat();
|
|
}
|
|
|
|
test "@floatCast cast down" {
|
|
if (builtin.zig_backend == .stage2_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 = @floatCast(f32, double);
|
|
try expect(single == 0.001534);
|
|
}
|
|
{
|
|
const double: f64 = 0.001534;
|
|
const single = @floatCast(f32, double);
|
|
try expect(single == 0.001534);
|
|
}
|
|
}
|
|
|
|
test "peer type resolution: unreachable, error set, unreachable" {
|
|
if (builtin.zig_backend == .stage2_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);
|
|
comptime try S.doTheTest(.b);
|
|
}
|
|
|
|
test "peer cast [:x]T to []T" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
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();
|
|
comptime try S.doTheTest();
|
|
}
|
|
|
|
test "peer cast [N:x]T to [N]T" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
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();
|
|
comptime try S.doTheTest();
|
|
}
|
|
|
|
test "peer cast *[N:x]T to *[N]T" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
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();
|
|
comptime try S.doTheTest();
|
|
}
|
|
|
|
test "peer cast [*:x]T to [*]T" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_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();
|
|
comptime try S.doTheTest();
|
|
}
|
|
|
|
test "peer cast [:x]T to [*:x]T" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_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();
|
|
comptime try S.doTheTest();
|
|
}
|
|
|
|
test "peer type resolution implicit cast to return type" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
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();
|
|
comptime try S.doTheTest();
|
|
}
|
|
|
|
test "peer type resolution implicit cast to variable type" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_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();
|
|
comptime try S.doTheTest();
|
|
}
|
|
|
|
test "variable initialization uses result locations properly with regards to the type" {
|
|
var b = true;
|
|
const x: i32 = if (b) 1 else 2;
|
|
try expect(x == 1);
|
|
}
|
|
|
|
test "cast between C pointer with different but compatible types" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
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(@ptrCast([*]u16, &x)) == 4);
|
|
}
|
|
};
|
|
try S.doTheTest();
|
|
comptime try S.doTheTest();
|
|
}
|
|
|
|
test "peer type resolve string lit with sentinel-terminated mutable slice" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
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];
|
|
comptime try expect(@TypeOf(slice, "hi") == [:0]const u8);
|
|
comptime try expect(@TypeOf("hi", slice) == [:0]const u8);
|
|
}
|
|
|
|
test "peer type resolve array pointers, one of them const" {
|
|
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
|
|
|
|
var array1: [4]u8 = undefined;
|
|
const array2: [5]u8 = undefined;
|
|
comptime try expect(@TypeOf(&array1, &array2) == []const u8);
|
|
comptime try expect(@TypeOf(&array2, &array1) == []const u8);
|
|
}
|
|
|
|
test "peer type resolve array pointer and unknown pointer" {
|
|
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;
|
|
|
|
comptime try expect(@TypeOf(&array, ptr) == [*]u8);
|
|
comptime try expect(@TypeOf(ptr, &array) == [*]u8);
|
|
|
|
comptime try expect(@TypeOf(&const_array, ptr) == [*]const u8);
|
|
comptime try expect(@TypeOf(ptr, &const_array) == [*]const u8);
|
|
|
|
comptime try expect(@TypeOf(&array, const_ptr) == [*]const u8);
|
|
comptime try expect(@TypeOf(const_ptr, &array) == [*]const u8);
|
|
|
|
comptime try expect(@TypeOf(&const_array, const_ptr) == [*]const u8);
|
|
comptime try expect(@TypeOf(const_ptr, &const_array) == [*]const u8);
|
|
}
|
|
|
|
test "comptime float casts" {
|
|
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
|
|
|
|
const a = @intToFloat(comptime_float, 1);
|
|
try expect(a == 1);
|
|
try expect(@TypeOf(a) == comptime_float);
|
|
const b = @floatToInt(comptime_int, 2);
|
|
try expect(b == 2);
|
|
try expect(@TypeOf(b) == comptime_int);
|
|
|
|
try expectFloatToInt(comptime_int, 1234, i16, 1234);
|
|
try expectFloatToInt(comptime_float, 12.3, comptime_int, 12);
|
|
}
|
|
|
|
test "pointer reinterpret const float to int" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
// The hex representation is 0x3fe3333333333303.
|
|
const float: f64 = 5.99999999999994648725e-01;
|
|
const float_ptr = &float;
|
|
const int_ptr = @ptrCast(*const i32, float_ptr);
|
|
const int_val = int_ptr.*;
|
|
if (native_endian == .Little)
|
|
try expect(int_val == 0x33333303)
|
|
else
|
|
try expect(int_val == 0x3fe33333);
|
|
}
|
|
|
|
test "implicit cast from [*]T to ?*anyopaque" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
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) {
|
|
@ptrCast([*]u8, 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 = @intToPtr(PFN_void, hardcoded_fn_addr);
|
|
pub const PFN_void = *const fn (*anyopaque) callconv(.C) void;
|
|
|
|
fn foobar(func: PFN_void) !void {
|
|
try std.testing.expect(@ptrToInt(func) == hardcoded_fn_addr);
|
|
}
|
|
|
|
test "implicit ptr to *anyopaque" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
|
|
|
|
var a: u32 = 1;
|
|
var ptr: *align(@alignOf(u32)) anyopaque = &a;
|
|
var b: *u32 = @ptrCast(*u32, ptr);
|
|
try expect(b.* == 1);
|
|
var ptr2: ?*align(@alignOf(u32)) anyopaque = &a;
|
|
var c: *u32 = @ptrCast(*u32, ptr2.?);
|
|
try expect(c.* == 1);
|
|
}
|
|
|
|
test "return null from fn() anyerror!?&T" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
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"));
|
|
comptime try expect(mem.eql(u8, castToOptionalSlice().?, "hi"));
|
|
}
|
|
|
|
fn castToOptionalSlice() ?[]const u8 {
|
|
return "hi";
|
|
}
|
|
|
|
test "cast u128 to f128 and back" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
|
|
|
|
comptime try testCast128();
|
|
try testCast128();
|
|
}
|
|
|
|
fn testCast128() !void {
|
|
try expect(cast128Int(cast128Float(0x7fff0000000000000000000000000000)) == 0x7fff0000000000000000000000000000);
|
|
}
|
|
|
|
fn cast128Int(x: f128) u128 {
|
|
return @bitCast(u128, x);
|
|
}
|
|
|
|
fn cast128Float(x: u128) f128 {
|
|
return @bitCast(f128, x);
|
|
}
|
|
|
|
test "implicit cast from *[N]T to ?[*]T" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_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 {
|
|
@ptrCast(*u8, value.?).* += 1;
|
|
}
|
|
|
|
test "implicit cast *[0]T to E![]const u8" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
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 = @ptrCast(*align(1) const fn () callconv(.C) void, &global_array);
|
|
try expect(@ptrToInt(f) == @ptrToInt(&global_array));
|
|
}
|
|
test "cast from array reference to fn: runtime fn ptr" {
|
|
var f = @ptrCast(*align(1) const fn () callconv(.C) void, &global_array);
|
|
try expect(@ptrToInt(f) == @ptrToInt(&global_array));
|
|
}
|
|
|
|
test "*const [N]null u8 to ?[]const u8" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_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();
|
|
comptime try 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.? == @ptrCast(*anyopaque, &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"));
|
|
comptime try expect(mem.eql(u8, boolToStr(true), "true"));
|
|
comptime try expect(mem.eql(u8, boolToStr(false), "false"));
|
|
}
|
|
fn boolToStr(b: bool) []const u8 {
|
|
return if (b) "true" else "false";
|
|
}
|
|
|
|
test "cast f16 to wider types" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_spirv64) 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();
|
|
comptime try S.doTheTest();
|
|
}
|
|
|
|
test "cast f128 to narrower types" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
|
|
|
|
const S = struct {
|
|
fn doTheTest() !void {
|
|
var x: f128 = 1234.0;
|
|
try expect(@as(f16, 1234.0) == @floatCast(f16, x));
|
|
try expect(@as(f32, 1234.0) == @floatCast(f32, x));
|
|
try expect(@as(f64, 1234.0) == @floatCast(f64, x));
|
|
}
|
|
};
|
|
try S.doTheTest();
|
|
comptime try S.doTheTest();
|
|
}
|
|
|
|
test "peer type resolution: unreachable, null, slice" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_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();
|
|
comptime try S.doTheTest();
|
|
}
|
|
|
|
test "cast compatible optional types" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_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_wasm) 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 = @intToPtr(*[1024]u8, 42);
|
|
const b = @intToPtr(*const [1024]u8, 42);
|
|
try std.testing.expect(@TypeOf(a, b) == *const [1024]u8);
|
|
try std.testing.expect(a == b);
|
|
}
|
|
|
|
test "floatToInt to zero-bit int" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
const a: f32 = 0.0;
|
|
comptime try std.testing.expect(@floatToInt(u0, a) == 0);
|
|
}
|
|
|
|
test "peer type resolution of function pointer and function body" {
|
|
const T = fn () u32;
|
|
const a: T = undefined;
|
|
const b: *const T = undefined;
|
|
try expect(@TypeOf(a, b) == *const fn () u32);
|
|
try expect(@TypeOf(b, a) == *const fn () u32);
|
|
}
|
|
|
|
test "cast typed undefined to int" {
|
|
comptime {
|
|
const a: u16 = undefined;
|
|
const b: u8 = a;
|
|
_ = b;
|
|
}
|
|
}
|
|
|
|
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 = @bitCast(S, @as(u2, 2));
|
|
try expect(s.a == 0);
|
|
try expect(s.b == 2);
|
|
const i = @bitCast(u2, 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 = @intToPtr(*u32, 4);
|
|
q = p;
|
|
try expect(@ptrToInt(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 @intCast(u32, 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 = @intToPtr(*const [2:s]T, 0x1000);
|
|
var b: []T = @intToPtr(*[3]T, 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, @intToPtr(*const [2:s]T, 0x1000)), r1);
|
|
try expectEqual(@as(R, @intToPtr(*const [3]T, 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 = @intToPtr(*const [5:0]u8, 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, @intToPtr([*:0]u8, 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(@ptrCast([*:0]const u8, 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");
|
|
}
|