zig/test/behavior/cast.zig
2022-02-02 10:48:21 +01:00

806 lines
25 KiB
Zig

const std = @import("std");
const expect = std.testing.expect;
const mem = std.mem;
const maxInt = std.math.maxInt;
const builtin = @import("builtin");
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_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
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" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
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 "@floatToInt" {
if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
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_x86_64 or builtin.zig_backend == .stage2_arm) 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_x86_64 or builtin.zig_backend == .stage2_arm) 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_x86_64 or builtin.zig_backend == .stage2_arm) 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_arm) 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" {
if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
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_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
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_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
var array = [_]u8{ 'o', 'k' };
const opt_array_ptr: ?[*]const u8 = &array;
const a: *const ?[*]const u8 = &opt_array_ptr;
const b: [*c]const [*c]const u8 = a;
try expect(b.*[0] == 'o');
try expect(b[0][1] == 'k');
}
test "array coersion to undefined at runtime" {
if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
@setRuntimeSafety(true);
// TODO implement @setRuntimeSafety in stage2
if (builtin.zig_backend != .stage1 and 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_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
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_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_x86_64) 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_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_x86_64) 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 != .stage1) return error.SkipZigTest; // TODO
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 != .stage1) 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 != .stage1) return error.SkipZigTest; // TODO
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;
_ = g catch {};
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_c) 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
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 != .stage1) 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();
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 != .stage1) return error.SkipZigTest; // TODO
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_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
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 != .stage1) return error.SkipZigTest; // TODO
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 != .stage1) 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(@ptrCast([*:0]const u8, x[0].?), 0), "window name"));
}
test "vector casts" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
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 != .stage1) return error.SkipZigTest; // TODO
{
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 != .stage1) 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 *[0]T to E![]const T" {
if (builtin.zig_backend != .stage1) 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;
try expect(mem.eql(u8, "abcde", y catch unreachable));
}
test "peer cast *[0]T to []const T" {
if (builtin.zig_backend != .stage1) 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 resolution of string literals" {
if (builtin.zig_backend != .stage1) 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);
comptime try S.doTheTest(.b);
}
test "type coercion related to sentinel-termination" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
const S = struct {
fn doTheTest() !void {
// [:x]T to []T
{
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 }));
}
// [*:x]T to [*]T
{
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);
}
// [N:x]T to [N]T
{
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 }));
}
// *[N:x]T to *[N]T
{
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 }));
}
// [:x]T to [*:x]T
{
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_wasm) 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
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_wasm) 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
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" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
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 != .stage1) 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(@ptrCast([*]u16, &x)) == 4);
}
};
try S.doTheTest();
}
test "peer type resolve string lit with sentinel-terminated mutable slice" {
if (builtin.zig_backend != .stage1) 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];
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 != .stage1) return error.SkipZigTest; // TODO
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 != .stage1) return error.SkipZigTest; // TODO
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 != .stage1) return error.SkipZigTest; // TODO
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);
}