1const std = @import("std");
2const expect = std.testing.expect;
3const mem = std.mem;
4const maxInt = std.math.maxInt;
5
6test "int to ptr cast" {
7    const x = @as(usize, 13);
8    const y = @intToPtr(*u8, x);
9    const z = @ptrToInt(y);
10    try expect(z == 13);
11}
12
13test "integer literal to pointer cast" {
14    const vga_mem = @intToPtr(*u16, 0xB8000);
15    try expect(@ptrToInt(vga_mem) == 0xB8000);
16}
17
18test "peer type resolution: ?T and T" {
19    try expect(peerTypeTAndOptionalT(true, false).? == 0);
20    try expect(peerTypeTAndOptionalT(false, false).? == 3);
21    comptime {
22        try expect(peerTypeTAndOptionalT(true, false).? == 0);
23        try expect(peerTypeTAndOptionalT(false, false).? == 3);
24    }
25}
26fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize {
27    if (c) {
28        return if (b) null else @as(usize, 0);
29    }
30
31    return @as(usize, 3);
32}
33
34test "resolve undefined with integer" {
35    try testResolveUndefWithInt(true, 1234);
36    comptime try testResolveUndefWithInt(true, 1234);
37}
38fn testResolveUndefWithInt(b: bool, x: i32) !void {
39    const value = if (b) x else undefined;
40    if (b) {
41        try expect(value == x);
42    }
43}
44
45test "@intCast i32 to u7" {
46    var x: u128 = maxInt(u128);
47    var y: i32 = 120;
48    var z = x >> @intCast(u7, y);
49    try expect(z == 0xff);
50}
51
52test "@intCast to comptime_int" {
53    try expect(@intCast(comptime_int, 0) == 0);
54}
55
56test "implicit cast comptime numbers to any type when the value fits" {
57    const a: u64 = 255;
58    var b: u8 = a;
59    try expect(b == 255);
60}
61
62test "implicit cast comptime_int to comptime_float" {
63    comptime try expect(@as(comptime_float, 10) == @as(f32, 10));
64    try expect(2 == 2.0);
65}
66
67test "comptime_int @intToFloat" {
68    {
69        const result = @intToFloat(f16, 1234);
70        try expect(@TypeOf(result) == f16);
71        try expect(result == 1234.0);
72    }
73    {
74        const result = @intToFloat(f32, 1234);
75        try expect(@TypeOf(result) == f32);
76        try expect(result == 1234.0);
77    }
78    {
79        const result = @intToFloat(f64, 1234);
80        try expect(@TypeOf(result) == f64);
81        try expect(result == 1234.0);
82    }
83    {
84        const result = @intToFloat(f128, 1234);
85        try expect(@TypeOf(result) == f128);
86        try expect(result == 1234.0);
87    }
88    // big comptime_int (> 64 bits) to f128 conversion
89    {
90        const result = @intToFloat(f128, 0x1_0000_0000_0000_0000);
91        try expect(@TypeOf(result) == f128);
92        try expect(result == 0x1_0000_0000_0000_0000.0);
93    }
94}
95
96test "@floatToInt" {
97    try testFloatToInts();
98    comptime try testFloatToInts();
99}
100
101fn testFloatToInts() !void {
102    const x = @as(i32, 1e4);
103    try expect(x == 10000);
104    const y = @floatToInt(i32, @as(f32, 1e4));
105    try expect(y == 10000);
106    try expectFloatToInt(f32, 255.1, u8, 255);
107    try expectFloatToInt(f32, 127.2, i8, 127);
108    try expectFloatToInt(f32, -128.2, i8, -128);
109}
110
111fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) !void {
112    try expect(@floatToInt(I, f) == i);
113}
114
115test "implicitly cast indirect pointer to maybe-indirect pointer" {
116    const S = struct {
117        const Self = @This();
118        x: u8,
119        fn constConst(p: *const *const Self) u8 {
120            return p.*.x;
121        }
122        fn maybeConstConst(p: ?*const *const Self) u8 {
123            return p.?.*.x;
124        }
125        fn constConstConst(p: *const *const *const Self) u8 {
126            return p.*.*.x;
127        }
128        fn maybeConstConstConst(p: ?*const *const *const Self) u8 {
129            return p.?.*.*.x;
130        }
131    };
132    const s = S{ .x = 42 };
133    const p = &s;
134    const q = &p;
135    const r = &q;
136    try expect(42 == S.constConst(q));
137    try expect(42 == S.maybeConstConst(q));
138    try expect(42 == S.constConstConst(r));
139    try expect(42 == S.maybeConstConstConst(r));
140}
141
142test "@intCast comptime_int" {
143    const result = @intCast(i32, 1234);
144    try expect(@TypeOf(result) == i32);
145    try expect(result == 1234);
146}
147
148test "@floatCast comptime_int and comptime_float" {
149    {
150        const result = @floatCast(f16, 1234);
151        try expect(@TypeOf(result) == f16);
152        try expect(result == 1234.0);
153    }
154    {
155        const result = @floatCast(f16, 1234.0);
156        try expect(@TypeOf(result) == f16);
157        try expect(result == 1234.0);
158    }
159    {
160        const result = @floatCast(f32, 1234);
161        try expect(@TypeOf(result) == f32);
162        try expect(result == 1234.0);
163    }
164    {
165        const result = @floatCast(f32, 1234.0);
166        try expect(@TypeOf(result) == f32);
167        try expect(result == 1234.0);
168    }
169}
170
171test "coerce undefined to optional" {
172    try expect(MakeType(void).getNull() == null);
173    try expect(MakeType(void).getNonNull() != null);
174}
175
176fn MakeType(comptime T: type) type {
177    return struct {
178        fn getNull() ?T {
179            return null;
180        }
181
182        fn getNonNull() ?T {
183            return @as(T, undefined);
184        }
185    };
186}
187
188test "implicit cast from *[N]T to [*c]T" {
189    var x: [4]u16 = [4]u16{ 0, 1, 2, 3 };
190    var y: [*c]u16 = &x;
191
192    try expect(std.mem.eql(u16, x[0..4], y[0..4]));
193    x[0] = 8;
194    y[3] = 6;
195    try expect(std.mem.eql(u16, x[0..4], y[0..4]));
196}
197
198test "*usize to *void" {
199    var i = @as(usize, 0);
200    var v = @ptrCast(*void, &i);
201    v.* = {};
202}
203
204test "@intToEnum passed a comptime_int to an enum with one item" {
205    const E = enum { A };
206    const x = @intToEnum(E, 0);
207    try expect(x == E.A);
208}
209
210test "@intCast to u0 and use the result" {
211    const S = struct {
212        fn doTheTest(zero: u1, one: u1, bigzero: i32) !void {
213            try expect((one << @intCast(u0, bigzero)) == 1);
214            try expect((zero << @intCast(u0, bigzero)) == 0);
215        }
216    };
217    try S.doTheTest(0, 1, 0);
218    comptime try S.doTheTest(0, 1, 0);
219}
220
221test "peer result null and comptime_int" {
222    const S = struct {
223        fn blah(n: i32) ?i32 {
224            if (n == 0) {
225                return null;
226            } else if (n < 0) {
227                return -1;
228            } else {
229                return 1;
230            }
231        }
232    };
233
234    try expect(S.blah(0) == null);
235    comptime try expect(S.blah(0) == null);
236    try expect(S.blah(10).? == 1);
237    comptime try expect(S.blah(10).? == 1);
238    try expect(S.blah(-10).? == -1);
239    comptime try expect(S.blah(-10).? == -1);
240}
241
242test "*const ?[*]const T to [*c]const [*c]const T" {
243    var array = [_]u8{ 'o', 'k' };
244    const opt_array_ptr: ?[*]const u8 = &array;
245    const a: *const ?[*]const u8 = &opt_array_ptr;
246    const b: [*c]const [*c]const u8 = a;
247    try expect(b.*[0] == 'o');
248    try expect(b[0][1] == 'k');
249}
250
251test "array coersion to undefined at runtime" {
252    @setRuntimeSafety(true);
253
254    // TODO implement @setRuntimeSafety in stage2
255    if (@import("builtin").zig_is_stage2 and
256        @import("builtin").mode != .Debug and
257        @import("builtin").mode != .ReleaseSafe)
258    {
259        return error.SkipZigTest;
260    }
261
262    var array = [4]u8{ 3, 4, 5, 6 };
263    var undefined_val = [4]u8{ 0xAA, 0xAA, 0xAA, 0xAA };
264
265    try expect(std.mem.eql(u8, &array, &array));
266    array = undefined;
267    try expect(std.mem.eql(u8, &array, &undefined_val));
268}
269
270test "implicitly cast from int to anyerror!?T" {
271    implicitIntLitToOptional();
272    comptime implicitIntLitToOptional();
273}
274fn implicitIntLitToOptional() void {
275    const f: ?i32 = 1;
276    _ = f;
277    const g: anyerror!?i32 = 1;
278    _ = g catch {};
279}
280
281test "return u8 coercing into ?u32 return type" {
282    const S = struct {
283        fn doTheTest() !void {
284            try expect(foo(123).? == 123);
285        }
286        fn foo(arg: u8) ?u32 {
287            return arg;
288        }
289    };
290    try S.doTheTest();
291    comptime try S.doTheTest();
292}
293
294test "cast from ?[*]T to ??[*]T" {
295    const a: ??[*]u8 = @as(?[*]u8, null);
296    try expect(a != null and a.? == null);
297}
298