aboutsummaryrefslogtreecommitdiff
path: root/test/behavior
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-08-11 13:59:34 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-08-12 10:48:54 -0700
commit6eecc4af99e2affc44d153e5f127200f2adf4642 (patch)
tree736bf309197456d46eb3a5e3a44c011ac1726fb0 /test/behavior
parenta0670e748ec4914f7fc198422d0815e71e90a54f (diff)
downloadzig-6eecc4af99e2affc44d153e5f127200f2adf4642.tar.gz
zig-6eecc4af99e2affc44d153e5f127200f2adf4642.zip
stage2 llvm backend: implement const inttoptr
Diffstat (limited to 'test/behavior')
-rw-r--r--test/behavior/cast.zig905
-rw-r--r--test/behavior/cast_stage1.zig911
2 files changed, 911 insertions, 905 deletions
diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig
index e9e2df991e..6a6f02908a 100644
--- a/test/behavior/cast.zig
+++ b/test/behavior/cast.zig
@@ -16,908 +16,3 @@ test "integer literal to pointer cast" {
const vga_mem = @intToPtr(*u16, 0xB8000);
try expect(@ptrToInt(vga_mem) == 0xB8000);
}
-
-test "pointer reinterpret const float to int" {
- // 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 "implicitly cast indirect pointer to maybe-indirect pointer" {
- 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 "explicit cast from integer to error type" {
- 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 arrays of different size to const slice" {
- 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 "peer resolve array and const slice" {
- 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" {
- 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 int to anyerror!?T" {
- implicitIntLitToOptional();
- comptime implicitIntLitToOptional();
-}
-fn implicitIntLitToOptional() void {
- const f: ?i32 = 1;
- _ = f;
- const g: anyerror!?i32 = 1;
- _ = g catch {};
-}
-
-test "return null from fn() anyerror!?&T" {
- 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: ?T and T" {
- 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 "peer type resolution: [0]u8 and []const u8" {
- 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" {
- try expect(mem.eql(u8, castToOptionalSlice().?, "hi"));
- comptime try expect(mem.eql(u8, castToOptionalSlice().?, "hi"));
-}
-
-fn castToOptionalSlice() ?[]const u8 {
- return "hi";
-}
-
-test "implicitly cast from [0]T to anyerror![]T" {
- 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" {
- 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 "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 "implicit cast from &const [N]T to []const T" {
- 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" {
- 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 "@floatToInt" {
- 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(f16, 255.1, u8, 255);
- try expectFloatToInt(f16, 127.2, i8, 127);
- try expectFloatToInt(f16, -128.2, i8, -128);
- try expectFloatToInt(f32, 255.1, u8, 255);
- try expectFloatToInt(f32, 127.2, i8, 127);
- try expectFloatToInt(f32, -128.2, i8, -128);
- try expectFloatToInt(comptime_int, 1234, i16, 1234);
-}
-
-fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) !void {
- try expect(@floatToInt(I, f) == i);
-}
-
-test "cast u128 to f128 and back" {
- 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 "single-item pointer of array to slice and to unknown length pointer" {
- 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" {
- const window_name = [1][*]const u8{"window name"};
- const x: [*]const ?[*]const u8 = &window_name;
- try expect(mem.eql(u8, std.mem.spanZ(@ptrCast([*:0]const u8, x[0].?)), "window name"));
-}
-
-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 "vector casts" {
- 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 "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 "@intCast i32 to u7" {
- var x: u128 = maxInt(u128);
- var y: i32 = 120;
- var z = x >> @intCast(u7, y);
- try expect(z == 0xff);
-}
-
-test "@floatCast cast down" {
- {
- 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 "implicit cast undefined to optional" {
- 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 ?[*]T" {
- 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 *[N]T to [*c]T" {
- 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 "implicit cast from *T to ?*c_void" {
- var a: u8 = 1;
- incrementVoidPtrValue(&a);
- try std.testing.expect(a == 2);
-}
-
-fn incrementVoidPtrValue(value: ?*c_void) void {
- @ptrCast(*u8, value.?).* += 1;
-}
-
-test "implicit cast from [*]T to ?*c_void" {
- 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: ?*c_void, len: usize) void {
- var n: usize = 0;
- while (n < len) : (n += 1) {
- @ptrCast([*]u8, array.?)[n] += 1;
- }
-}
-
-test "*usize to *void" {
- var i = @as(usize, 0);
- var v = @ptrCast(*void, &i);
- v.* = {};
-}
-
-test "compile time int to ptr of function" {
- try foobar(FUNCTION_CONSTANT);
-}
-
-pub const FUNCTION_CONSTANT = @intToPtr(PFN_void, maxInt(usize));
-pub const PFN_void = fn (*c_void) callconv(.C) void;
-
-fn foobar(func: PFN_void) !void {
- try std.testing.expect(@ptrToInt(func) == maxInt(usize));
-}
-
-test "implicit ptr to *c_void" {
- var a: u32 = 1;
- var ptr: *align(@alignOf(u32)) c_void = &a;
- var b: *u32 = @ptrCast(*u32, ptr);
- try expect(b.* == 1);
- var ptr2: ?*align(@alignOf(u32)) c_void = &a;
- var c: *u32 = @ptrCast(*u32, ptr2.?);
- try expect(c.* == 1);
-}
-
-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 "@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 type resolution: unreachable, null, slice" {
- 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 "peer type resolution: unreachable, error set, unreachable" {
- 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 "implicit cast comptime_int to comptime_float" {
- comptime try expect(@as(comptime_float, 10) == @as(f32, 10));
- try expect(2 == 2.0);
-}
-
-test "implicit cast *[0]T to E![]const u8" {
- var x = @as(anyerror![]const u8, &[0]u8{});
- try expect((x catch unreachable).len == 0);
-}
-
-test "peer cast *[0]T to E![]const T" {
- 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" {
- 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));
-}
-
-var global_array: [4]u8 = undefined;
-test "cast from array reference to fn" {
- const f = @ptrCast(fn () callconv(.C) void, &global_array);
- try expect(@ptrToInt(f) == @ptrToInt(&global_array));
-}
-
-test "*const [N]null u8 to ?[]const u8" {
- 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 "peer resolution of string literals" {
- 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" {
- 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 "cast i8 fn call peers to i32 result" {
- 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 "return u8 coercing into ?u32 return type" {
- 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 "peer result null and comptime_int" {
- 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 "peer type resolution implicit cast to return type" {
- 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" {
- 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]T and ?[*:0]T on fn parameter" {
- const S = struct {
- const Handler = ?fn ([*c]const u8) callconv(.C) void;
- fn addCallback(handler: Handler) void {
- _ = handler;
- }
-
- fn myCallback(cstr: ?[*:0]const u8) callconv(.C) void {
- _ = cstr;
- }
-
- fn doTheTest() void {
- addCallback(myCallback);
- }
- };
- S.doTheTest();
-}
-
-test "cast between C pointer with different but compatible types" {
- 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();
-}
-
-var global_struct: struct { f0: usize } = undefined;
-
-test "assignment to optional pointer result loc" {
- var foo: struct { ptr: ?*c_void } = .{ .ptr = &global_struct };
- try expect(foo.ptr.? == @ptrCast(*c_void, &global_struct));
-}
-
-test "peer type resolve string lit with sentinel-terminated mutable slice" {
- 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 unsigned int to signed" {
- 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 "peer type resolve array pointers, one of them const" {
- 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" {
- 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" {
- 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);
-}
-
-test "cast from ?[*]T to ??[*]T" {
- const a: ??[*]u8 = @as(?[*]u8, null);
- try expect(a != null and a.? == null);
-}
-
-test "cast between *[N]void and []void" {
- var a: [4]void = undefined;
- var b: []void = &a;
- try expect(b.len == 4);
-}
diff --git a/test/behavior/cast_stage1.zig b/test/behavior/cast_stage1.zig
new file mode 100644
index 0000000000..d924dfde6c
--- /dev/null
+++ b/test/behavior/cast_stage1.zig
@@ -0,0 +1,911 @@
+const std = @import("std");
+const expect = std.testing.expect;
+const mem = std.mem;
+const maxInt = std.math.maxInt;
+const Vector = std.meta.Vector;
+const native_endian = @import("builtin").target.cpu.arch.endian();
+
+test "pointer reinterpret const float to int" {
+ // 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 "implicitly cast indirect pointer to maybe-indirect pointer" {
+ 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 "explicit cast from integer to error type" {
+ 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 arrays of different size to const slice" {
+ 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 "peer resolve array and const slice" {
+ 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" {
+ 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 int to anyerror!?T" {
+ implicitIntLitToOptional();
+ comptime implicitIntLitToOptional();
+}
+fn implicitIntLitToOptional() void {
+ const f: ?i32 = 1;
+ _ = f;
+ const g: anyerror!?i32 = 1;
+ _ = g catch {};
+}
+
+test "return null from fn() anyerror!?&T" {
+ 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: ?T and T" {
+ 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 "peer type resolution: [0]u8 and []const u8" {
+ 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" {
+ try expect(mem.eql(u8, castToOptionalSlice().?, "hi"));
+ comptime try expect(mem.eql(u8, castToOptionalSlice().?, "hi"));
+}
+
+fn castToOptionalSlice() ?[]const u8 {
+ return "hi";
+}
+
+test "implicitly cast from [0]T to anyerror![]T" {
+ 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" {
+ 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 "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 "implicit cast from &const [N]T to []const T" {
+ 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" {
+ 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 "@floatToInt" {
+ 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(f16, 255.1, u8, 255);
+ try expectFloatToInt(f16, 127.2, i8, 127);
+ try expectFloatToInt(f16, -128.2, i8, -128);
+ try expectFloatToInt(f32, 255.1, u8, 255);
+ try expectFloatToInt(f32, 127.2, i8, 127);
+ try expectFloatToInt(f32, -128.2, i8, -128);
+ try expectFloatToInt(comptime_int, 1234, i16, 1234);
+}
+
+fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) !void {
+ try expect(@floatToInt(I, f) == i);
+}
+
+test "cast u128 to f128 and back" {
+ 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 "single-item pointer of array to slice and to unknown length pointer" {
+ 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" {
+ const window_name = [1][*]const u8{"window name"};
+ const x: [*]const ?[*]const u8 = &window_name;
+ try expect(mem.eql(u8, std.mem.spanZ(@ptrCast([*:0]const u8, x[0].?)), "window name"));
+}
+
+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 "vector casts" {
+ 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 "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 "@intCast i32 to u7" {
+ var x: u128 = maxInt(u128);
+ var y: i32 = 120;
+ var z = x >> @intCast(u7, y);
+ try expect(z == 0xff);
+}
+
+test "@floatCast cast down" {
+ {
+ 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 "implicit cast undefined to optional" {
+ 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 ?[*]T" {
+ 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 *[N]T to [*c]T" {
+ 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 "implicit cast from *T to ?*c_void" {
+ var a: u8 = 1;
+ incrementVoidPtrValue(&a);
+ try std.testing.expect(a == 2);
+}
+
+fn incrementVoidPtrValue(value: ?*c_void) void {
+ @ptrCast(*u8, value.?).* += 1;
+}
+
+test "implicit cast from [*]T to ?*c_void" {
+ 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: ?*c_void, len: usize) void {
+ var n: usize = 0;
+ while (n < len) : (n += 1) {
+ @ptrCast([*]u8, array.?)[n] += 1;
+ }
+}
+
+test "*usize to *void" {
+ var i = @as(usize, 0);
+ var v = @ptrCast(*void, &i);
+ v.* = {};
+}
+
+test "compile time int to ptr of function" {
+ try foobar(FUNCTION_CONSTANT);
+}
+
+pub const FUNCTION_CONSTANT = @intToPtr(PFN_void, maxInt(usize));
+pub const PFN_void = fn (*c_void) callconv(.C) void;
+
+fn foobar(func: PFN_void) !void {
+ try std.testing.expect(@ptrToInt(func) == maxInt(usize));
+}
+
+test "implicit ptr to *c_void" {
+ var a: u32 = 1;
+ var ptr: *align(@alignOf(u32)) c_void = &a;
+ var b: *u32 = @ptrCast(*u32, ptr);
+ try expect(b.* == 1);
+ var ptr2: ?*align(@alignOf(u32)) c_void = &a;
+ var c: *u32 = @ptrCast(*u32, ptr2.?);
+ try expect(c.* == 1);
+}
+
+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 "@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 type resolution: unreachable, null, slice" {
+ 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 "peer type resolution: unreachable, error set, unreachable" {
+ 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 "implicit cast comptime_int to comptime_float" {
+ comptime try expect(@as(comptime_float, 10) == @as(f32, 10));
+ try expect(2 == 2.0);
+}
+
+test "implicit cast *[0]T to E![]const u8" {
+ var x = @as(anyerror![]const u8, &[0]u8{});
+ try expect((x catch unreachable).len == 0);
+}
+
+test "peer cast *[0]T to E![]const T" {
+ 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" {
+ 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));
+}
+
+var global_array: [4]u8 = undefined;
+test "cast from array reference to fn" {
+ const f = @ptrCast(fn () callconv(.C) void, &global_array);
+ try expect(@ptrToInt(f) == @ptrToInt(&global_array));
+}
+
+test "*const [N]null u8 to ?[]const u8" {
+ 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 "peer resolution of string literals" {
+ 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" {
+ 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 "cast i8 fn call peers to i32 result" {
+ 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 "return u8 coercing into ?u32 return type" {
+ 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 "peer result null and comptime_int" {
+ 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 "peer type resolution implicit cast to return type" {
+ 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" {
+ 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]T and ?[*:0]T on fn parameter" {
+ const S = struct {
+ const Handler = ?fn ([*c]const u8) callconv(.C) void;
+ fn addCallback(handler: Handler) void {
+ _ = handler;
+ }
+
+ fn myCallback(cstr: ?[*:0]const u8) callconv(.C) void {
+ _ = cstr;
+ }
+
+ fn doTheTest() void {
+ addCallback(myCallback);
+ }
+ };
+ S.doTheTest();
+}
+
+test "cast between C pointer with different but compatible types" {
+ 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();
+}
+
+var global_struct: struct { f0: usize } = undefined;
+
+test "assignment to optional pointer result loc" {
+ var foo: struct { ptr: ?*c_void } = .{ .ptr = &global_struct };
+ try expect(foo.ptr.? == @ptrCast(*c_void, &global_struct));
+}
+
+test "peer type resolve string lit with sentinel-terminated mutable slice" {
+ 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 unsigned int to signed" {
+ 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 "peer type resolve array pointers, one of them const" {
+ 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" {
+ 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" {
+ 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);
+}
+
+test "cast from ?[*]T to ??[*]T" {
+ const a: ??[*]u8 = @as(?[*]u8, null);
+ try expect(a != null and a.? == null);
+}
+
+test "cast between *[N]void and []void" {
+ var a: [4]void = undefined;
+ var b: []void = &a;
+ try expect(b.len == 4);
+}