authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-08-11 13:59:34-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-08-12 10:48:54-07:00
log6eecc4af99e2affc44d153e5f127200f2adf4642
tree736bf309197456d46eb3a5e3a44c011ac1726fb0
parenta0670e748ec4914f7fc198422d0815e71e90a54f

stage2 llvm backend: implement const inttoptr


5 files changed, 921 insertions(+), 906 deletions(-)

src/codegen/llvm.zig+5
...@@ -768,6 +768,11 @@ pub const DeclGen = struct {...@@ -768,6 +768,11 @@ pub const DeclGen = struct {
768 };768 };
769 return self.context.constStruct(&fields, fields.len, .False);769 return self.context.constStruct(&fields, fields.len, .False);
770 },770 },
771 .int_u64 => {
772 const llvm_usize = try self.llvmType(Type.initTag(.usize));
773 const llvm_int = llvm_usize.constInt(tv.val.toUnsignedInt(), .False);
774 return llvm_int.constIntToPtr(try self.llvmType(tv.ty));
775 },
771 else => |tag| return self.todo("implement const of pointer type '{}' ({})", .{ tv.ty, tag }),776 else => |tag| return self.todo("implement const of pointer type '{}' ({})", .{ tv.ty, tag }),
772 },777 },
773 .Array => {778 .Array => {
src/codegen/llvm/bindings.zig+3
...@@ -130,6 +130,9 @@ pub const Value = opaque {...@@ -130,6 +130,9 @@ pub const Value = opaque {
130130
131 pub const constBitCast = LLVMConstBitCast;131 pub const constBitCast = LLVMConstBitCast;
132 extern fn LLVMConstBitCast(ConstantVal: *const Value, ToType: *const Type) *const Value;132 extern fn LLVMConstBitCast(ConstantVal: *const Value, ToType: *const Type) *const Value;
133
134 pub const constIntToPtr = LLVMConstIntToPtr;
135 extern fn LLVMConstIntToPtr(ConstantVal: *const Value, ToType: *const Type) *const Value;
133};136};
134137
135pub const Type = opaque {138pub const Type = opaque {
test/behavior.zig+2-1
...@@ -8,6 +8,7 @@ test {...@@ -8,6 +8,7 @@ test {
8 _ = @import("behavior/eval.zig");8 _ = @import("behavior/eval.zig");
9 _ = @import("behavior/pointers.zig");9 _ = @import("behavior/pointers.zig");
10 _ = @import("behavior/if.zig");10 _ = @import("behavior/if.zig");
11 _ = @import("behavior/cast.zig");
1112
12 if (!builtin.zig_is_stage2) {13 if (!builtin.zig_is_stage2) {
13 // Tests that only pass for stage1.14 // Tests that only pass for stage1.
...@@ -85,7 +86,7 @@ test {...@@ -85,7 +86,7 @@ test {
85 _ = @import("behavior/byteswap.zig");86 _ = @import("behavior/byteswap.zig");
86 _ = @import("behavior/byval_arg_var.zig");87 _ = @import("behavior/byval_arg_var.zig");
87 _ = @import("behavior/call.zig");88 _ = @import("behavior/call.zig");
88 _ = @import("behavior/cast.zig");89 _ = @import("behavior/cast_stage1.zig");
89 _ = @import("behavior/const_slice_child.zig");90 _ = @import("behavior/const_slice_child.zig");
90 _ = @import("behavior/defer.zig");91 _ = @import("behavior/defer.zig");
91 _ = @import("behavior/enum.zig");92 _ = @import("behavior/enum.zig");
test/behavior/cast.zig-905
...@@ -16,908 +16,3 @@ test "integer literal to pointer cast" {...@@ -16,908 +16,3 @@ test "integer literal to pointer cast" {
16 const vga_mem = @intToPtr(*u16, 0xB8000);16 const vga_mem = @intToPtr(*u16, 0xB8000);
17 try expect(@ptrToInt(vga_mem) == 0xB8000);17 try expect(@ptrToInt(vga_mem) == 0xB8000);
18}18}
19
20test "pointer reinterpret const float to int" {
21 // The hex representation is 0x3fe3333333333303.
22 const float: f64 = 5.99999999999994648725e-01;
23 const float_ptr = &float;
24 const int_ptr = @ptrCast(*const i32, float_ptr);
25 const int_val = int_ptr.*;
26 if (native_endian == .Little)
27 try expect(int_val == 0x33333303)
28 else
29 try expect(int_val == 0x3fe33333);
30}
31
32test "implicitly cast indirect pointer to maybe-indirect pointer" {
33 const S = struct {
34 const Self = @This();
35 x: u8,
36 fn constConst(p: *const *const Self) u8 {
37 return p.*.x;
38 }
39 fn maybeConstConst(p: ?*const *const Self) u8 {
40 return p.?.*.x;
41 }
42 fn constConstConst(p: *const *const *const Self) u8 {
43 return p.*.*.x;
44 }
45 fn maybeConstConstConst(p: ?*const *const *const Self) u8 {
46 return p.?.*.*.x;
47 }
48 };
49 const s = S{ .x = 42 };
50 const p = &s;
51 const q = &p;
52 const r = &q;
53 try expect(42 == S.constConst(q));
54 try expect(42 == S.maybeConstConst(q));
55 try expect(42 == S.constConstConst(r));
56 try expect(42 == S.maybeConstConstConst(r));
57}
58
59test "explicit cast from integer to error type" {
60 try testCastIntToErr(error.ItBroke);
61 comptime try testCastIntToErr(error.ItBroke);
62}
63fn testCastIntToErr(err: anyerror) !void {
64 const x = @errorToInt(err);
65 const y = @intToError(x);
66 try expect(error.ItBroke == y);
67}
68
69test "peer resolve arrays of different size to const slice" {
70 try expect(mem.eql(u8, boolToStr(true), "true"));
71 try expect(mem.eql(u8, boolToStr(false), "false"));
72 comptime try expect(mem.eql(u8, boolToStr(true), "true"));
73 comptime try expect(mem.eql(u8, boolToStr(false), "false"));
74}
75fn boolToStr(b: bool) []const u8 {
76 return if (b) "true" else "false";
77}
78
79test "peer resolve array and const slice" {
80 try testPeerResolveArrayConstSlice(true);
81 comptime try testPeerResolveArrayConstSlice(true);
82}
83fn testPeerResolveArrayConstSlice(b: bool) !void {
84 const value1 = if (b) "aoeu" else @as([]const u8, "zz");
85 const value2 = if (b) @as([]const u8, "zz") else "aoeu";
86 try expect(mem.eql(u8, value1, "aoeu"));
87 try expect(mem.eql(u8, value2, "zz"));
88}
89
90test "implicitly cast from T to anyerror!?T" {
91 try castToOptionalTypeError(1);
92 comptime try castToOptionalTypeError(1);
93}
94
95const A = struct {
96 a: i32,
97};
98fn castToOptionalTypeError(z: i32) !void {
99 const x = @as(i32, 1);
100 const y: anyerror!?i32 = x;
101 try expect((try y).? == 1);
102
103 const f = z;
104 const g: anyerror!?i32 = f;
105 _ = g catch {};
106
107 const a = A{ .a = z };
108 const b: anyerror!?A = a;
109 try expect((b catch unreachable).?.a == 1);
110}
111
112test "implicitly cast from int to anyerror!?T" {
113 implicitIntLitToOptional();
114 comptime implicitIntLitToOptional();
115}
116fn implicitIntLitToOptional() void {
117 const f: ?i32 = 1;
118 _ = f;
119 const g: anyerror!?i32 = 1;
120 _ = g catch {};
121}
122
123test "return null from fn() anyerror!?&T" {
124 const a = returnNullFromOptionalTypeErrorRef();
125 const b = returnNullLitFromOptionalTypeErrorRef();
126 try expect((try a) == null and (try b) == null);
127}
128fn returnNullFromOptionalTypeErrorRef() anyerror!?*A {
129 const a: ?*A = null;
130 return a;
131}
132fn returnNullLitFromOptionalTypeErrorRef() anyerror!?*A {
133 return null;
134}
135
136test "peer type resolution: ?T and T" {
137 try expect(peerTypeTAndOptionalT(true, false).? == 0);
138 try expect(peerTypeTAndOptionalT(false, false).? == 3);
139 comptime {
140 try expect(peerTypeTAndOptionalT(true, false).? == 0);
141 try expect(peerTypeTAndOptionalT(false, false).? == 3);
142 }
143}
144fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize {
145 if (c) {
146 return if (b) null else @as(usize, 0);
147 }
148
149 return @as(usize, 3);
150}
151
152test "peer type resolution: [0]u8 and []const u8" {
153 try expect(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
154 try expect(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
155 comptime {
156 try expect(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
157 try expect(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
158 }
159}
160fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 {
161 if (a) {
162 return &[_]u8{};
163 }
164
165 return slice[0..1];
166}
167
168test "implicitly cast from [N]T to ?[]const T" {
169 try expect(mem.eql(u8, castToOptionalSlice().?, "hi"));
170 comptime try expect(mem.eql(u8, castToOptionalSlice().?, "hi"));
171}
172
173fn castToOptionalSlice() ?[]const u8 {
174 return "hi";
175}
176
177test "implicitly cast from [0]T to anyerror![]T" {
178 try testCastZeroArrayToErrSliceMut();
179 comptime try testCastZeroArrayToErrSliceMut();
180}
181
182fn testCastZeroArrayToErrSliceMut() !void {
183 try expect((gimmeErrOrSlice() catch unreachable).len == 0);
184}
185
186fn gimmeErrOrSlice() anyerror![]u8 {
187 return &[_]u8{};
188}
189
190test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {
191 const S = struct {
192 fn doTheTest() anyerror!void {
193 {
194 var data = "hi".*;
195 const slice = data[0..];
196 try expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
197 try expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
198 }
199 {
200 var data: [2]u8 = "hi".*;
201 const slice = data[0..];
202 try expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
203 try expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
204 }
205 }
206 };
207 try S.doTheTest();
208 comptime try S.doTheTest();
209}
210fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 {
211 if (a) {
212 return &[_]u8{};
213 }
214
215 return slice[0..1];
216}
217
218test "resolve undefined with integer" {
219 try testResolveUndefWithInt(true, 1234);
220 comptime try testResolveUndefWithInt(true, 1234);
221}
222fn testResolveUndefWithInt(b: bool, x: i32) !void {
223 const value = if (b) x else undefined;
224 if (b) {
225 try expect(value == x);
226 }
227}
228
229test "implicit cast from &const [N]T to []const T" {
230 try testCastConstArrayRefToConstSlice();
231 comptime try testCastConstArrayRefToConstSlice();
232}
233
234fn testCastConstArrayRefToConstSlice() !void {
235 {
236 const blah = "aoeu".*;
237 const const_array_ref = &blah;
238 try expect(@TypeOf(const_array_ref) == *const [4:0]u8);
239 const slice: []const u8 = const_array_ref;
240 try expect(mem.eql(u8, slice, "aoeu"));
241 }
242 {
243 const blah: [4]u8 = "aoeu".*;
244 const const_array_ref = &blah;
245 try expect(@TypeOf(const_array_ref) == *const [4]u8);
246 const slice: []const u8 = const_array_ref;
247 try expect(mem.eql(u8, slice, "aoeu"));
248 }
249}
250
251test "peer type resolution: error and [N]T" {
252 try expect(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
253 comptime try expect(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
254 try expect(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
255 comptime try expect(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
256}
257
258fn testPeerErrorAndArray(x: u8) anyerror![]const u8 {
259 return switch (x) {
260 0x00 => "OK",
261 else => error.BadValue,
262 };
263}
264fn testPeerErrorAndArray2(x: u8) anyerror![]const u8 {
265 return switch (x) {
266 0x00 => "OK",
267 0x01 => "OKK",
268 else => error.BadValue,
269 };
270}
271
272test "@floatToInt" {
273 try testFloatToInts();
274 comptime try testFloatToInts();
275}
276
277fn testFloatToInts() !void {
278 const x = @as(i32, 1e4);
279 try expect(x == 10000);
280 const y = @floatToInt(i32, @as(f32, 1e4));
281 try expect(y == 10000);
282 try expectFloatToInt(f16, 255.1, u8, 255);
283 try expectFloatToInt(f16, 127.2, i8, 127);
284 try expectFloatToInt(f16, -128.2, i8, -128);
285 try expectFloatToInt(f32, 255.1, u8, 255);
286 try expectFloatToInt(f32, 127.2, i8, 127);
287 try expectFloatToInt(f32, -128.2, i8, -128);
288 try expectFloatToInt(comptime_int, 1234, i16, 1234);
289}
290
291fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) !void {
292 try expect(@floatToInt(I, f) == i);
293}
294
295test "cast u128 to f128 and back" {
296 comptime try testCast128();
297 try testCast128();
298}
299
300fn testCast128() !void {
301 try expect(cast128Int(cast128Float(0x7fff0000000000000000000000000000)) == 0x7fff0000000000000000000000000000);
302}
303
304fn cast128Int(x: f128) u128 {
305 return @bitCast(u128, x);
306}
307
308fn cast128Float(x: u128) f128 {
309 return @bitCast(f128, x);
310}
311
312test "single-item pointer of array to slice and to unknown length pointer" {
313 try testCastPtrOfArrayToSliceAndPtr();
314 comptime try testCastPtrOfArrayToSliceAndPtr();
315}
316
317fn testCastPtrOfArrayToSliceAndPtr() !void {
318 {
319 var array = "aoeu".*;
320 const x: [*]u8 = &array;
321 x[0] += 1;
322 try expect(mem.eql(u8, array[0..], "boeu"));
323 const y: []u8 = &array;
324 y[0] += 1;
325 try expect(mem.eql(u8, array[0..], "coeu"));
326 }
327 {
328 var array: [4]u8 = "aoeu".*;
329 const x: [*]u8 = &array;
330 x[0] += 1;
331 try expect(mem.eql(u8, array[0..], "boeu"));
332 const y: []u8 = &array;
333 y[0] += 1;
334 try expect(mem.eql(u8, array[0..], "coeu"));
335 }
336}
337
338test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
339 const window_name = [1][*]const u8{"window name"};
340 const x: [*]const ?[*]const u8 = &window_name;
341 try expect(mem.eql(u8, std.mem.spanZ(@ptrCast([*:0]const u8, x[0].?)), "window name"));
342}
343
344test "@intCast comptime_int" {
345 const result = @intCast(i32, 1234);
346 try expect(@TypeOf(result) == i32);
347 try expect(result == 1234);
348}
349
350test "@floatCast comptime_int and comptime_float" {
351 {
352 const result = @floatCast(f16, 1234);
353 try expect(@TypeOf(result) == f16);
354 try expect(result == 1234.0);
355 }
356 {
357 const result = @floatCast(f16, 1234.0);
358 try expect(@TypeOf(result) == f16);
359 try expect(result == 1234.0);
360 }
361 {
362 const result = @floatCast(f32, 1234);
363 try expect(@TypeOf(result) == f32);
364 try expect(result == 1234.0);
365 }
366 {
367 const result = @floatCast(f32, 1234.0);
368 try expect(@TypeOf(result) == f32);
369 try expect(result == 1234.0);
370 }
371}
372
373test "vector casts" {
374 const S = struct {
375 fn doTheTest() !void {
376 // Upcast (implicit, equivalent to @intCast)
377 var up0: Vector(2, u8) = [_]u8{ 0x55, 0xaa };
378 var up1 = @as(Vector(2, u16), up0);
379 var up2 = @as(Vector(2, u32), up0);
380 var up3 = @as(Vector(2, u64), up0);
381 // Downcast (safety-checked)
382 var down0 = up3;
383 var down1 = @intCast(Vector(2, u32), down0);
384 var down2 = @intCast(Vector(2, u16), down0);
385 var down3 = @intCast(Vector(2, u8), down0);
386
387 try expect(mem.eql(u16, &@as([2]u16, up1), &[2]u16{ 0x55, 0xaa }));
388 try expect(mem.eql(u32, &@as([2]u32, up2), &[2]u32{ 0x55, 0xaa }));
389 try expect(mem.eql(u64, &@as([2]u64, up3), &[2]u64{ 0x55, 0xaa }));
390
391 try expect(mem.eql(u32, &@as([2]u32, down1), &[2]u32{ 0x55, 0xaa }));
392 try expect(mem.eql(u16, &@as([2]u16, down2), &[2]u16{ 0x55, 0xaa }));
393 try expect(mem.eql(u8, &@as([2]u8, down3), &[2]u8{ 0x55, 0xaa }));
394 }
395
396 fn doTheTestFloat() !void {
397 var vec = @splat(2, @as(f32, 1234.0));
398 var wider: Vector(2, f64) = vec;
399 try expect(wider[0] == 1234.0);
400 try expect(wider[1] == 1234.0);
401 }
402 };
403
404 try S.doTheTest();
405 comptime try S.doTheTest();
406 try S.doTheTestFloat();
407 comptime try S.doTheTestFloat();
408}
409
410test "comptime_int @intToFloat" {
411 {
412 const result = @intToFloat(f16, 1234);
413 try expect(@TypeOf(result) == f16);
414 try expect(result == 1234.0);
415 }
416 {
417 const result = @intToFloat(f32, 1234);
418 try expect(@TypeOf(result) == f32);
419 try expect(result == 1234.0);
420 }
421 {
422 const result = @intToFloat(f64, 1234);
423 try expect(@TypeOf(result) == f64);
424 try expect(result == 1234.0);
425 }
426 {
427 const result = @intToFloat(f128, 1234);
428 try expect(@TypeOf(result) == f128);
429 try expect(result == 1234.0);
430 }
431 // big comptime_int (> 64 bits) to f128 conversion
432 {
433 const result = @intToFloat(f128, 0x1_0000_0000_0000_0000);
434 try expect(@TypeOf(result) == f128);
435 try expect(result == 0x1_0000_0000_0000_0000.0);
436 }
437}
438
439test "@intCast i32 to u7" {
440 var x: u128 = maxInt(u128);
441 var y: i32 = 120;
442 var z = x >> @intCast(u7, y);
443 try expect(z == 0xff);
444}
445
446test "@floatCast cast down" {
447 {
448 var double: f64 = 0.001534;
449 var single = @floatCast(f32, double);
450 try expect(single == 0.001534);
451 }
452 {
453 const double: f64 = 0.001534;
454 const single = @floatCast(f32, double);
455 try expect(single == 0.001534);
456 }
457}
458
459test "implicit cast undefined to optional" {
460 try expect(MakeType(void).getNull() == null);
461 try expect(MakeType(void).getNonNull() != null);
462}
463
464fn MakeType(comptime T: type) type {
465 return struct {
466 fn getNull() ?T {
467 return null;
468 }
469
470 fn getNonNull() ?T {
471 return @as(T, undefined);
472 }
473 };
474}
475
476test "implicit cast from *[N]T to ?[*]T" {
477 var x: ?[*]u16 = null;
478 var y: [4]u16 = [4]u16{ 0, 1, 2, 3 };
479
480 x = &y;
481 try expect(std.mem.eql(u16, x.?[0..4], y[0..4]));
482 x.?[0] = 8;
483 y[3] = 6;
484 try expect(std.mem.eql(u16, x.?[0..4], y[0..4]));
485}
486
487test "implicit cast from *[N]T to [*c]T" {
488 var x: [4]u16 = [4]u16{ 0, 1, 2, 3 };
489 var y: [*c]u16 = &x;
490
491 try expect(std.mem.eql(u16, x[0..4], y[0..4]));
492 x[0] = 8;
493 y[3] = 6;
494 try expect(std.mem.eql(u16, x[0..4], y[0..4]));
495}
496
497test "implicit cast from *T to ?*c_void" {
498 var a: u8 = 1;
499 incrementVoidPtrValue(&a);
500 try std.testing.expect(a == 2);
501}
502
503fn incrementVoidPtrValue(value: ?*c_void) void {
504 @ptrCast(*u8, value.?).* += 1;
505}
506
507test "implicit cast from [*]T to ?*c_void" {
508 var a = [_]u8{ 3, 2, 1 };
509 var runtime_zero: usize = 0;
510 incrementVoidPtrArray(a[runtime_zero..].ptr, 3);
511 try expect(std.mem.eql(u8, &a, &[_]u8{ 4, 3, 2 }));
512}
513
514fn incrementVoidPtrArray(array: ?*c_void, len: usize) void {
515 var n: usize = 0;
516 while (n < len) : (n += 1) {
517 @ptrCast([*]u8, array.?)[n] += 1;
518 }
519}
520
521test "*usize to *void" {
522 var i = @as(usize, 0);
523 var v = @ptrCast(*void, &i);
524 v.* = {};
525}
526
527test "compile time int to ptr of function" {
528 try foobar(FUNCTION_CONSTANT);
529}
530
531pub const FUNCTION_CONSTANT = @intToPtr(PFN_void, maxInt(usize));
532pub const PFN_void = fn (*c_void) callconv(.C) void;
533
534fn foobar(func: PFN_void) !void {
535 try std.testing.expect(@ptrToInt(func) == maxInt(usize));
536}
537
538test "implicit ptr to *c_void" {
539 var a: u32 = 1;
540 var ptr: *align(@alignOf(u32)) c_void = &a;
541 var b: *u32 = @ptrCast(*u32, ptr);
542 try expect(b.* == 1);
543 var ptr2: ?*align(@alignOf(u32)) c_void = &a;
544 var c: *u32 = @ptrCast(*u32, ptr2.?);
545 try expect(c.* == 1);
546}
547
548test "@intCast to comptime_int" {
549 try expect(@intCast(comptime_int, 0) == 0);
550}
551
552test "implicit cast comptime numbers to any type when the value fits" {
553 const a: u64 = 255;
554 var b: u8 = a;
555 try expect(b == 255);
556}
557
558test "@intToEnum passed a comptime_int to an enum with one item" {
559 const E = enum {
560 A,
561 };
562 const x = @intToEnum(E, 0);
563 try expect(x == E.A);
564}
565
566test "@intCast to u0 and use the result" {
567 const S = struct {
568 fn doTheTest(zero: u1, one: u1, bigzero: i32) !void {
569 try expect((one << @intCast(u0, bigzero)) == 1);
570 try expect((zero << @intCast(u0, bigzero)) == 0);
571 }
572 };
573 try S.doTheTest(0, 1, 0);
574 comptime try S.doTheTest(0, 1, 0);
575}
576
577test "peer type resolution: unreachable, null, slice" {
578 const S = struct {
579 fn doTheTest(num: usize, word: []const u8) !void {
580 const result = switch (num) {
581 0 => null,
582 1 => word,
583 else => unreachable,
584 };
585 try expect(mem.eql(u8, result.?, "hi"));
586 }
587 };
588 try S.doTheTest(1, "hi");
589}
590
591test "peer type resolution: unreachable, error set, unreachable" {
592 const Error = error{
593 FileDescriptorAlreadyPresentInSet,
594 OperationCausesCircularLoop,
595 FileDescriptorNotRegistered,
596 SystemResources,
597 UserResourceLimitReached,
598 FileDescriptorIncompatibleWithEpoll,
599 Unexpected,
600 };
601 var err = Error.SystemResources;
602 const transformed_err = switch (err) {
603 error.FileDescriptorAlreadyPresentInSet => unreachable,
604 error.OperationCausesCircularLoop => unreachable,
605 error.FileDescriptorNotRegistered => unreachable,
606 error.SystemResources => error.SystemResources,
607 error.UserResourceLimitReached => error.UserResourceLimitReached,
608 error.FileDescriptorIncompatibleWithEpoll => unreachable,
609 error.Unexpected => unreachable,
610 };
611 try expect(transformed_err == error.SystemResources);
612}
613
614test "implicit cast comptime_int to comptime_float" {
615 comptime try expect(@as(comptime_float, 10) == @as(f32, 10));
616 try expect(2 == 2.0);
617}
618
619test "implicit cast *[0]T to E![]const u8" {
620 var x = @as(anyerror![]const u8, &[0]u8{});
621 try expect((x catch unreachable).len == 0);
622}
623
624test "peer cast *[0]T to E![]const T" {
625 var buffer: [5]u8 = "abcde".*;
626 var buf: anyerror![]const u8 = buffer[0..];
627 var b = false;
628 var y = if (b) &[0]u8{} else buf;
629 try expect(mem.eql(u8, "abcde", y catch unreachable));
630}
631
632test "peer cast *[0]T to []const T" {
633 var buffer: [5]u8 = "abcde".*;
634 var buf: []const u8 = buffer[0..];
635 var b = false;
636 var y = if (b) &[0]u8{} else buf;
637 try expect(mem.eql(u8, "abcde", y));
638}
639
640var global_array: [4]u8 = undefined;
641test "cast from array reference to fn" {
642 const f = @ptrCast(fn () callconv(.C) void, &global_array);
643 try expect(@ptrToInt(f) == @ptrToInt(&global_array));
644}
645
646test "*const [N]null u8 to ?[]const u8" {
647 const S = struct {
648 fn doTheTest() !void {
649 var a = "Hello";
650 var b: ?[]const u8 = a;
651 try expect(mem.eql(u8, b.?, "Hello"));
652 }
653 };
654 try S.doTheTest();
655 comptime try S.doTheTest();
656}
657
658test "peer resolution of string literals" {
659 const S = struct {
660 const E = enum {
661 a,
662 b,
663 c,
664 d,
665 };
666
667 fn doTheTest(e: E) !void {
668 const cmd = switch (e) {
669 .a => "one",
670 .b => "two",
671 .c => "three",
672 .d => "four",
673 };
674 try expect(mem.eql(u8, cmd, "two"));
675 }
676 };
677 try S.doTheTest(.b);
678 comptime try S.doTheTest(.b);
679}
680
681test "type coercion related to sentinel-termination" {
682 const S = struct {
683 fn doTheTest() !void {
684 // [:x]T to []T
685 {
686 var array = [4:0]i32{ 1, 2, 3, 4 };
687 var slice: [:0]i32 = &array;
688 var dest: []i32 = slice;
689 try expect(mem.eql(i32, dest, &[_]i32{ 1, 2, 3, 4 }));
690 }
691
692 // [*:x]T to [*]T
693 {
694 var array = [4:99]i32{ 1, 2, 3, 4 };
695 var dest: [*]i32 = &array;
696 try expect(dest[0] == 1);
697 try expect(dest[1] == 2);
698 try expect(dest[2] == 3);
699 try expect(dest[3] == 4);
700 try expect(dest[4] == 99);
701 }
702
703 // [N:x]T to [N]T
704 {
705 var array = [4:0]i32{ 1, 2, 3, 4 };
706 var dest: [4]i32 = array;
707 try expect(mem.eql(i32, &dest, &[_]i32{ 1, 2, 3, 4 }));
708 }
709
710 // *[N:x]T to *[N]T
711 {
712 var array = [4:0]i32{ 1, 2, 3, 4 };
713 var dest: *[4]i32 = &array;
714 try expect(mem.eql(i32, dest, &[_]i32{ 1, 2, 3, 4 }));
715 }
716
717 // [:x]T to [*:x]T
718 {
719 var array = [4:0]i32{ 1, 2, 3, 4 };
720 var slice: [:0]i32 = &array;
721 var dest: [*:0]i32 = slice;
722 try expect(dest[0] == 1);
723 try expect(dest[1] == 2);
724 try expect(dest[2] == 3);
725 try expect(dest[3] == 4);
726 try expect(dest[4] == 0);
727 }
728 }
729 };
730 try S.doTheTest();
731 comptime try S.doTheTest();
732}
733
734test "cast i8 fn call peers to i32 result" {
735 const S = struct {
736 fn doTheTest() !void {
737 var cond = true;
738 const value: i32 = if (cond) smallBoi() else bigBoi();
739 try expect(value == 123);
740 }
741 fn smallBoi() i8 {
742 return 123;
743 }
744 fn bigBoi() i16 {
745 return 1234;
746 }
747 };
748 try S.doTheTest();
749 comptime try S.doTheTest();
750}
751
752test "return u8 coercing into ?u32 return type" {
753 const S = struct {
754 fn doTheTest() !void {
755 try expect(foo(123).? == 123);
756 }
757 fn foo(arg: u8) ?u32 {
758 return arg;
759 }
760 };
761 try S.doTheTest();
762 comptime try S.doTheTest();
763}
764
765test "peer result null and comptime_int" {
766 const S = struct {
767 fn blah(n: i32) ?i32 {
768 if (n == 0) {
769 return null;
770 } else if (n < 0) {
771 return -1;
772 } else {
773 return 1;
774 }
775 }
776 };
777
778 try expect(S.blah(0) == null);
779 comptime try expect(S.blah(0) == null);
780 try expect(S.blah(10).? == 1);
781 comptime try expect(S.blah(10).? == 1);
782 try expect(S.blah(-10).? == -1);
783 comptime try expect(S.blah(-10).? == -1);
784}
785
786test "peer type resolution implicit cast to return type" {
787 const S = struct {
788 fn doTheTest() !void {
789 for ("hello") |c| _ = f(c);
790 }
791 fn f(c: u8) []const u8 {
792 return switch (c) {
793 'h', 'e' => &[_]u8{c}, // should cast to slice
794 'l', ' ' => &[_]u8{ c, '.' }, // should cast to slice
795 else => ([_]u8{c})[0..], // is a slice
796 };
797 }
798 };
799 try S.doTheTest();
800 comptime try S.doTheTest();
801}
802
803test "peer type resolution implicit cast to variable type" {
804 const S = struct {
805 fn doTheTest() !void {
806 var x: []const u8 = undefined;
807 for ("hello") |c| x = switch (c) {
808 'h', 'e' => &[_]u8{c}, // should cast to slice
809 'l', ' ' => &[_]u8{ c, '.' }, // should cast to slice
810 else => ([_]u8{c})[0..], // is a slice
811 };
812 }
813 };
814 try S.doTheTest();
815 comptime try S.doTheTest();
816}
817
818test "variable initialization uses result locations properly with regards to the type" {
819 var b = true;
820 const x: i32 = if (b) 1 else 2;
821 try expect(x == 1);
822}
823
824test "cast between [*c]T and ?[*:0]T on fn parameter" {
825 const S = struct {
826 const Handler = ?fn ([*c]const u8) callconv(.C) void;
827 fn addCallback(handler: Handler) void {
828 _ = handler;
829 }
830
831 fn myCallback(cstr: ?[*:0]const u8) callconv(.C) void {
832 _ = cstr;
833 }
834
835 fn doTheTest() void {
836 addCallback(myCallback);
837 }
838 };
839 S.doTheTest();
840}
841
842test "cast between C pointer with different but compatible types" {
843 const S = struct {
844 fn foo(arg: [*]c_ushort) u16 {
845 return arg[0];
846 }
847 fn doTheTest() !void {
848 var x = [_]u16{ 4, 2, 1, 3 };
849 try expect(foo(@ptrCast([*]u16, &x)) == 4);
850 }
851 };
852 try S.doTheTest();
853}
854
855var global_struct: struct { f0: usize } = undefined;
856
857test "assignment to optional pointer result loc" {
858 var foo: struct { ptr: ?*c_void } = .{ .ptr = &global_struct };
859 try expect(foo.ptr.? == @ptrCast(*c_void, &global_struct));
860}
861
862test "peer type resolve string lit with sentinel-terminated mutable slice" {
863 var array: [4:0]u8 = undefined;
864 array[4] = 0; // TODO remove this when #4372 is solved
865 var slice: [:0]u8 = array[0..4 :0];
866 comptime try expect(@TypeOf(slice, "hi") == [:0]const u8);
867 comptime try expect(@TypeOf("hi", slice) == [:0]const u8);
868}
869
870test "peer type unsigned int to signed" {
871 var w: u31 = 5;
872 var x: u8 = 7;
873 var y: i32 = -5;
874 var a = w + y + x;
875 comptime try expect(@TypeOf(a) == i32);
876 try expect(a == 7);
877}
878
879test "peer type resolve array pointers, one of them const" {
880 var array1: [4]u8 = undefined;
881 const array2: [5]u8 = undefined;
882 comptime try expect(@TypeOf(&array1, &array2) == []const u8);
883 comptime try expect(@TypeOf(&array2, &array1) == []const u8);
884}
885
886test "peer type resolve array pointer and unknown pointer" {
887 const const_array: [4]u8 = undefined;
888 var array: [4]u8 = undefined;
889 var const_ptr: [*]const u8 = undefined;
890 var ptr: [*]u8 = undefined;
891
892 comptime try expect(@TypeOf(&array, ptr) == [*]u8);
893 comptime try expect(@TypeOf(ptr, &array) == [*]u8);
894
895 comptime try expect(@TypeOf(&const_array, ptr) == [*]const u8);
896 comptime try expect(@TypeOf(ptr, &const_array) == [*]const u8);
897
898 comptime try expect(@TypeOf(&array, const_ptr) == [*]const u8);
899 comptime try expect(@TypeOf(const_ptr, &array) == [*]const u8);
900
901 comptime try expect(@TypeOf(&const_array, const_ptr) == [*]const u8);
902 comptime try expect(@TypeOf(const_ptr, &const_array) == [*]const u8);
903}
904
905test "comptime float casts" {
906 const a = @intToFloat(comptime_float, 1);
907 try expect(a == 1);
908 try expect(@TypeOf(a) == comptime_float);
909 const b = @floatToInt(comptime_int, 2);
910 try expect(b == 2);
911 try expect(@TypeOf(b) == comptime_int);
912}
913
914test "cast from ?[*]T to ??[*]T" {
915 const a: ??[*]u8 = @as(?[*]u8, null);
916 try expect(a != null and a.? == null);
917}
918
919test "cast between *[N]void and []void" {
920 var a: [4]void = undefined;
921 var b: []void = &a;
922 try expect(b.len == 4);
923}
test/behavior/cast_stage1.zig created+911
...@@ -0,0 +1,911 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const mem = std.mem;
4const maxInt = std.math.maxInt;
5const Vector = std.meta.Vector;
6const native_endian = @import("builtin").target.cpu.arch.endian();
7
8test "pointer reinterpret const float to int" {
9 // The hex representation is 0x3fe3333333333303.
10 const float: f64 = 5.99999999999994648725e-01;
11 const float_ptr = &float;
12 const int_ptr = @ptrCast(*const i32, float_ptr);
13 const int_val = int_ptr.*;
14 if (native_endian == .Little)
15 try expect(int_val == 0x33333303)
16 else
17 try expect(int_val == 0x3fe33333);
18}
19
20test "implicitly cast indirect pointer to maybe-indirect pointer" {
21 const S = struct {
22 const Self = @This();
23 x: u8,
24 fn constConst(p: *const *const Self) u8 {
25 return p.*.x;
26 }
27 fn maybeConstConst(p: ?*const *const Self) u8 {
28 return p.?.*.x;
29 }
30 fn constConstConst(p: *const *const *const Self) u8 {
31 return p.*.*.x;
32 }
33 fn maybeConstConstConst(p: ?*const *const *const Self) u8 {
34 return p.?.*.*.x;
35 }
36 };
37 const s = S{ .x = 42 };
38 const p = &s;
39 const q = &p;
40 const r = &q;
41 try expect(42 == S.constConst(q));
42 try expect(42 == S.maybeConstConst(q));
43 try expect(42 == S.constConstConst(r));
44 try expect(42 == S.maybeConstConstConst(r));
45}
46
47test "explicit cast from integer to error type" {
48 try testCastIntToErr(error.ItBroke);
49 comptime try testCastIntToErr(error.ItBroke);
50}
51fn testCastIntToErr(err: anyerror) !void {
52 const x = @errorToInt(err);
53 const y = @intToError(x);
54 try expect(error.ItBroke == y);
55}
56
57test "peer resolve arrays of different size to const slice" {
58 try expect(mem.eql(u8, boolToStr(true), "true"));
59 try expect(mem.eql(u8, boolToStr(false), "false"));
60 comptime try expect(mem.eql(u8, boolToStr(true), "true"));
61 comptime try expect(mem.eql(u8, boolToStr(false), "false"));
62}
63fn boolToStr(b: bool) []const u8 {
64 return if (b) "true" else "false";
65}
66
67test "peer resolve array and const slice" {
68 try testPeerResolveArrayConstSlice(true);
69 comptime try testPeerResolveArrayConstSlice(true);
70}
71fn testPeerResolveArrayConstSlice(b: bool) !void {
72 const value1 = if (b) "aoeu" else @as([]const u8, "zz");
73 const value2 = if (b) @as([]const u8, "zz") else "aoeu";
74 try expect(mem.eql(u8, value1, "aoeu"));
75 try expect(mem.eql(u8, value2, "zz"));
76}
77
78test "implicitly cast from T to anyerror!?T" {
79 try castToOptionalTypeError(1);
80 comptime try castToOptionalTypeError(1);
81}
82
83const A = struct {
84 a: i32,
85};
86fn castToOptionalTypeError(z: i32) !void {
87 const x = @as(i32, 1);
88 const y: anyerror!?i32 = x;
89 try expect((try y).? == 1);
90
91 const f = z;
92 const g: anyerror!?i32 = f;
93 _ = g catch {};
94
95 const a = A{ .a = z };
96 const b: anyerror!?A = a;
97 try expect((b catch unreachable).?.a == 1);
98}
99
100test "implicitly cast from int to anyerror!?T" {
101 implicitIntLitToOptional();
102 comptime implicitIntLitToOptional();
103}
104fn implicitIntLitToOptional() void {
105 const f: ?i32 = 1;
106 _ = f;
107 const g: anyerror!?i32 = 1;
108 _ = g catch {};
109}
110
111test "return null from fn() anyerror!?&T" {
112 const a = returnNullFromOptionalTypeErrorRef();
113 const b = returnNullLitFromOptionalTypeErrorRef();
114 try expect((try a) == null and (try b) == null);
115}
116fn returnNullFromOptionalTypeErrorRef() anyerror!?*A {
117 const a: ?*A = null;
118 return a;
119}
120fn returnNullLitFromOptionalTypeErrorRef() anyerror!?*A {
121 return null;
122}
123
124test "peer type resolution: ?T and T" {
125 try expect(peerTypeTAndOptionalT(true, false).? == 0);
126 try expect(peerTypeTAndOptionalT(false, false).? == 3);
127 comptime {
128 try expect(peerTypeTAndOptionalT(true, false).? == 0);
129 try expect(peerTypeTAndOptionalT(false, false).? == 3);
130 }
131}
132fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize {
133 if (c) {
134 return if (b) null else @as(usize, 0);
135 }
136
137 return @as(usize, 3);
138}
139
140test "peer type resolution: [0]u8 and []const u8" {
141 try expect(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
142 try expect(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
143 comptime {
144 try expect(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
145 try expect(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
146 }
147}
148fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 {
149 if (a) {
150 return &[_]u8{};
151 }
152
153 return slice[0..1];
154}
155
156test "implicitly cast from [N]T to ?[]const T" {
157 try expect(mem.eql(u8, castToOptionalSlice().?, "hi"));
158 comptime try expect(mem.eql(u8, castToOptionalSlice().?, "hi"));
159}
160
161fn castToOptionalSlice() ?[]const u8 {
162 return "hi";
163}
164
165test "implicitly cast from [0]T to anyerror![]T" {
166 try testCastZeroArrayToErrSliceMut();
167 comptime try testCastZeroArrayToErrSliceMut();
168}
169
170fn testCastZeroArrayToErrSliceMut() !void {
171 try expect((gimmeErrOrSlice() catch unreachable).len == 0);
172}
173
174fn gimmeErrOrSlice() anyerror![]u8 {
175 return &[_]u8{};
176}
177
178test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {
179 const S = struct {
180 fn doTheTest() anyerror!void {
181 {
182 var data = "hi".*;
183 const slice = data[0..];
184 try expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
185 try expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
186 }
187 {
188 var data: [2]u8 = "hi".*;
189 const slice = data[0..];
190 try expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
191 try expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
192 }
193 }
194 };
195 try S.doTheTest();
196 comptime try S.doTheTest();
197}
198fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 {
199 if (a) {
200 return &[_]u8{};
201 }
202
203 return slice[0..1];
204}
205
206test "resolve undefined with integer" {
207 try testResolveUndefWithInt(true, 1234);
208 comptime try testResolveUndefWithInt(true, 1234);
209}
210fn testResolveUndefWithInt(b: bool, x: i32) !void {
211 const value = if (b) x else undefined;
212 if (b) {
213 try expect(value == x);
214 }
215}
216
217test "implicit cast from &const [N]T to []const T" {
218 try testCastConstArrayRefToConstSlice();
219 comptime try testCastConstArrayRefToConstSlice();
220}
221
222fn testCastConstArrayRefToConstSlice() !void {
223 {
224 const blah = "aoeu".*;
225 const const_array_ref = &blah;
226 try expect(@TypeOf(const_array_ref) == *const [4:0]u8);
227 const slice: []const u8 = const_array_ref;
228 try expect(mem.eql(u8, slice, "aoeu"));
229 }
230 {
231 const blah: [4]u8 = "aoeu".*;
232 const const_array_ref = &blah;
233 try expect(@TypeOf(const_array_ref) == *const [4]u8);
234 const slice: []const u8 = const_array_ref;
235 try expect(mem.eql(u8, slice, "aoeu"));
236 }
237}
238
239test "peer type resolution: error and [N]T" {
240 try expect(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
241 comptime try expect(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
242 try expect(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
243 comptime try expect(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
244}
245
246fn testPeerErrorAndArray(x: u8) anyerror![]const u8 {
247 return switch (x) {
248 0x00 => "OK",
249 else => error.BadValue,
250 };
251}
252fn testPeerErrorAndArray2(x: u8) anyerror![]const u8 {
253 return switch (x) {
254 0x00 => "OK",
255 0x01 => "OKK",
256 else => error.BadValue,
257 };
258}
259
260test "@floatToInt" {
261 try testFloatToInts();
262 comptime try testFloatToInts();
263}
264
265fn testFloatToInts() !void {
266 const x = @as(i32, 1e4);
267 try expect(x == 10000);
268 const y = @floatToInt(i32, @as(f32, 1e4));
269 try expect(y == 10000);
270 try expectFloatToInt(f16, 255.1, u8, 255);
271 try expectFloatToInt(f16, 127.2, i8, 127);
272 try expectFloatToInt(f16, -128.2, i8, -128);
273 try expectFloatToInt(f32, 255.1, u8, 255);
274 try expectFloatToInt(f32, 127.2, i8, 127);
275 try expectFloatToInt(f32, -128.2, i8, -128);
276 try expectFloatToInt(comptime_int, 1234, i16, 1234);
277}
278
279fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) !void {
280 try expect(@floatToInt(I, f) == i);
281}
282
283test "cast u128 to f128 and back" {
284 comptime try testCast128();
285 try testCast128();
286}
287
288fn testCast128() !void {
289 try expect(cast128Int(cast128Float(0x7fff0000000000000000000000000000)) == 0x7fff0000000000000000000000000000);
290}
291
292fn cast128Int(x: f128) u128 {
293 return @bitCast(u128, x);
294}
295
296fn cast128Float(x: u128) f128 {
297 return @bitCast(f128, x);
298}
299
300test "single-item pointer of array to slice and to unknown length pointer" {
301 try testCastPtrOfArrayToSliceAndPtr();
302 comptime try testCastPtrOfArrayToSliceAndPtr();
303}
304
305fn testCastPtrOfArrayToSliceAndPtr() !void {
306 {
307 var array = "aoeu".*;
308 const x: [*]u8 = &array;
309 x[0] += 1;
310 try expect(mem.eql(u8, array[0..], "boeu"));
311 const y: []u8 = &array;
312 y[0] += 1;
313 try expect(mem.eql(u8, array[0..], "coeu"));
314 }
315 {
316 var array: [4]u8 = "aoeu".*;
317 const x: [*]u8 = &array;
318 x[0] += 1;
319 try expect(mem.eql(u8, array[0..], "boeu"));
320 const y: []u8 = &array;
321 y[0] += 1;
322 try expect(mem.eql(u8, array[0..], "coeu"));
323 }
324}
325
326test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
327 const window_name = [1][*]const u8{"window name"};
328 const x: [*]const ?[*]const u8 = &window_name;
329 try expect(mem.eql(u8, std.mem.spanZ(@ptrCast([*:0]const u8, x[0].?)), "window name"));
330}
331
332test "@intCast comptime_int" {
333 const result = @intCast(i32, 1234);
334 try expect(@TypeOf(result) == i32);
335 try expect(result == 1234);
336}
337
338test "@floatCast comptime_int and comptime_float" {
339 {
340 const result = @floatCast(f16, 1234);
341 try expect(@TypeOf(result) == f16);
342 try expect(result == 1234.0);
343 }
344 {
345 const result = @floatCast(f16, 1234.0);
346 try expect(@TypeOf(result) == f16);
347 try expect(result == 1234.0);
348 }
349 {
350 const result = @floatCast(f32, 1234);
351 try expect(@TypeOf(result) == f32);
352 try expect(result == 1234.0);
353 }
354 {
355 const result = @floatCast(f32, 1234.0);
356 try expect(@TypeOf(result) == f32);
357 try expect(result == 1234.0);
358 }
359}
360
361test "vector casts" {
362 const S = struct {
363 fn doTheTest() !void {
364 // Upcast (implicit, equivalent to @intCast)
365 var up0: Vector(2, u8) = [_]u8{ 0x55, 0xaa };
366 var up1 = @as(Vector(2, u16), up0);
367 var up2 = @as(Vector(2, u32), up0);
368 var up3 = @as(Vector(2, u64), up0);
369 // Downcast (safety-checked)
370 var down0 = up3;
371 var down1 = @intCast(Vector(2, u32), down0);
372 var down2 = @intCast(Vector(2, u16), down0);
373 var down3 = @intCast(Vector(2, u8), down0);
374
375 try expect(mem.eql(u16, &@as([2]u16, up1), &[2]u16{ 0x55, 0xaa }));
376 try expect(mem.eql(u32, &@as([2]u32, up2), &[2]u32{ 0x55, 0xaa }));
377 try expect(mem.eql(u64, &@as([2]u64, up3), &[2]u64{ 0x55, 0xaa }));
378
379 try expect(mem.eql(u32, &@as([2]u32, down1), &[2]u32{ 0x55, 0xaa }));
380 try expect(mem.eql(u16, &@as([2]u16, down2), &[2]u16{ 0x55, 0xaa }));
381 try expect(mem.eql(u8, &@as([2]u8, down3), &[2]u8{ 0x55, 0xaa }));
382 }
383
384 fn doTheTestFloat() !void {
385 var vec = @splat(2, @as(f32, 1234.0));
386 var wider: Vector(2, f64) = vec;
387 try expect(wider[0] == 1234.0);
388 try expect(wider[1] == 1234.0);
389 }
390 };
391
392 try S.doTheTest();
393 comptime try S.doTheTest();
394 try S.doTheTestFloat();
395 comptime try S.doTheTestFloat();
396}
397
398test "comptime_int @intToFloat" {
399 {
400 const result = @intToFloat(f16, 1234);
401 try expect(@TypeOf(result) == f16);
402 try expect(result == 1234.0);
403 }
404 {
405 const result = @intToFloat(f32, 1234);
406 try expect(@TypeOf(result) == f32);
407 try expect(result == 1234.0);
408 }
409 {
410 const result = @intToFloat(f64, 1234);
411 try expect(@TypeOf(result) == f64);
412 try expect(result == 1234.0);
413 }
414 {
415 const result = @intToFloat(f128, 1234);
416 try expect(@TypeOf(result) == f128);
417 try expect(result == 1234.0);
418 }
419 // big comptime_int (> 64 bits) to f128 conversion
420 {
421 const result = @intToFloat(f128, 0x1_0000_0000_0000_0000);
422 try expect(@TypeOf(result) == f128);
423 try expect(result == 0x1_0000_0000_0000_0000.0);
424 }
425}
426
427test "@intCast i32 to u7" {
428 var x: u128 = maxInt(u128);
429 var y: i32 = 120;
430 var z = x >> @intCast(u7, y);
431 try expect(z == 0xff);
432}
433
434test "@floatCast cast down" {
435 {
436 var double: f64 = 0.001534;
437 var single = @floatCast(f32, double);
438 try expect(single == 0.001534);
439 }
440 {
441 const double: f64 = 0.001534;
442 const single = @floatCast(f32, double);
443 try expect(single == 0.001534);
444 }
445}
446
447test "implicit cast undefined to optional" {
448 try expect(MakeType(void).getNull() == null);
449 try expect(MakeType(void).getNonNull() != null);
450}
451
452fn MakeType(comptime T: type) type {
453 return struct {
454 fn getNull() ?T {
455 return null;
456 }
457
458 fn getNonNull() ?T {
459 return @as(T, undefined);
460 }
461 };
462}
463
464test "implicit cast from *[N]T to ?[*]T" {
465 var x: ?[*]u16 = null;
466 var y: [4]u16 = [4]u16{ 0, 1, 2, 3 };
467
468 x = &y;
469 try expect(std.mem.eql(u16, x.?[0..4], y[0..4]));
470 x.?[0] = 8;
471 y[3] = 6;
472 try expect(std.mem.eql(u16, x.?[0..4], y[0..4]));
473}
474
475test "implicit cast from *[N]T to [*c]T" {
476 var x: [4]u16 = [4]u16{ 0, 1, 2, 3 };
477 var y: [*c]u16 = &x;
478
479 try expect(std.mem.eql(u16, x[0..4], y[0..4]));
480 x[0] = 8;
481 y[3] = 6;
482 try expect(std.mem.eql(u16, x[0..4], y[0..4]));
483}
484
485test "implicit cast from *T to ?*c_void" {
486 var a: u8 = 1;
487 incrementVoidPtrValue(&a);
488 try std.testing.expect(a == 2);
489}
490
491fn incrementVoidPtrValue(value: ?*c_void) void {
492 @ptrCast(*u8, value.?).* += 1;
493}
494
495test "implicit cast from [*]T to ?*c_void" {
496 var a = [_]u8{ 3, 2, 1 };
497 var runtime_zero: usize = 0;
498 incrementVoidPtrArray(a[runtime_zero..].ptr, 3);
499 try expect(std.mem.eql(u8, &a, &[_]u8{ 4, 3, 2 }));
500}
501
502fn incrementVoidPtrArray(array: ?*c_void, len: usize) void {
503 var n: usize = 0;
504 while (n < len) : (n += 1) {
505 @ptrCast([*]u8, array.?)[n] += 1;
506 }
507}
508
509test "*usize to *void" {
510 var i = @as(usize, 0);
511 var v = @ptrCast(*void, &i);
512 v.* = {};
513}
514
515test "compile time int to ptr of function" {
516 try foobar(FUNCTION_CONSTANT);
517}
518
519pub const FUNCTION_CONSTANT = @intToPtr(PFN_void, maxInt(usize));
520pub const PFN_void = fn (*c_void) callconv(.C) void;
521
522fn foobar(func: PFN_void) !void {
523 try std.testing.expect(@ptrToInt(func) == maxInt(usize));
524}
525
526test "implicit ptr to *c_void" {
527 var a: u32 = 1;
528 var ptr: *align(@alignOf(u32)) c_void = &a;
529 var b: *u32 = @ptrCast(*u32, ptr);
530 try expect(b.* == 1);
531 var ptr2: ?*align(@alignOf(u32)) c_void = &a;
532 var c: *u32 = @ptrCast(*u32, ptr2.?);
533 try expect(c.* == 1);
534}
535
536test "@intCast to comptime_int" {
537 try expect(@intCast(comptime_int, 0) == 0);
538}
539
540test "implicit cast comptime numbers to any type when the value fits" {
541 const a: u64 = 255;
542 var b: u8 = a;
543 try expect(b == 255);
544}
545
546test "@intToEnum passed a comptime_int to an enum with one item" {
547 const E = enum {
548 A,
549 };
550 const x = @intToEnum(E, 0);
551 try expect(x == E.A);
552}
553
554test "@intCast to u0 and use the result" {
555 const S = struct {
556 fn doTheTest(zero: u1, one: u1, bigzero: i32) !void {
557 try expect((one << @intCast(u0, bigzero)) == 1);
558 try expect((zero << @intCast(u0, bigzero)) == 0);
559 }
560 };
561 try S.doTheTest(0, 1, 0);
562 comptime try S.doTheTest(0, 1, 0);
563}
564
565test "peer type resolution: unreachable, null, slice" {
566 const S = struct {
567 fn doTheTest(num: usize, word: []const u8) !void {
568 const result = switch (num) {
569 0 => null,
570 1 => word,
571 else => unreachable,
572 };
573 try expect(mem.eql(u8, result.?, "hi"));
574 }
575 };
576 try S.doTheTest(1, "hi");
577}
578
579test "peer type resolution: unreachable, error set, unreachable" {
580 const Error = error{
581 FileDescriptorAlreadyPresentInSet,
582 OperationCausesCircularLoop,
583 FileDescriptorNotRegistered,
584 SystemResources,
585 UserResourceLimitReached,
586 FileDescriptorIncompatibleWithEpoll,
587 Unexpected,
588 };
589 var err = Error.SystemResources;
590 const transformed_err = switch (err) {
591 error.FileDescriptorAlreadyPresentInSet => unreachable,
592 error.OperationCausesCircularLoop => unreachable,
593 error.FileDescriptorNotRegistered => unreachable,
594 error.SystemResources => error.SystemResources,
595 error.UserResourceLimitReached => error.UserResourceLimitReached,
596 error.FileDescriptorIncompatibleWithEpoll => unreachable,
597 error.Unexpected => unreachable,
598 };
599 try expect(transformed_err == error.SystemResources);
600}
601
602test "implicit cast comptime_int to comptime_float" {
603 comptime try expect(@as(comptime_float, 10) == @as(f32, 10));
604 try expect(2 == 2.0);
605}
606
607test "implicit cast *[0]T to E![]const u8" {
608 var x = @as(anyerror![]const u8, &[0]u8{});
609 try expect((x catch unreachable).len == 0);
610}
611
612test "peer cast *[0]T to E![]const T" {
613 var buffer: [5]u8 = "abcde".*;
614 var buf: anyerror![]const u8 = buffer[0..];
615 var b = false;
616 var y = if (b) &[0]u8{} else buf;
617 try expect(mem.eql(u8, "abcde", y catch unreachable));
618}
619
620test "peer cast *[0]T to []const T" {
621 var buffer: [5]u8 = "abcde".*;
622 var buf: []const u8 = buffer[0..];
623 var b = false;
624 var y = if (b) &[0]u8{} else buf;
625 try expect(mem.eql(u8, "abcde", y));
626}
627
628var global_array: [4]u8 = undefined;
629test "cast from array reference to fn" {
630 const f = @ptrCast(fn () callconv(.C) void, &global_array);
631 try expect(@ptrToInt(f) == @ptrToInt(&global_array));
632}
633
634test "*const [N]null u8 to ?[]const u8" {
635 const S = struct {
636 fn doTheTest() !void {
637 var a = "Hello";
638 var b: ?[]const u8 = a;
639 try expect(mem.eql(u8, b.?, "Hello"));
640 }
641 };
642 try S.doTheTest();
643 comptime try S.doTheTest();
644}
645
646test "peer resolution of string literals" {
647 const S = struct {
648 const E = enum {
649 a,
650 b,
651 c,
652 d,
653 };
654
655 fn doTheTest(e: E) !void {
656 const cmd = switch (e) {
657 .a => "one",
658 .b => "two",
659 .c => "three",
660 .d => "four",
661 };
662 try expect(mem.eql(u8, cmd, "two"));
663 }
664 };
665 try S.doTheTest(.b);
666 comptime try S.doTheTest(.b);
667}
668
669test "type coercion related to sentinel-termination" {
670 const S = struct {
671 fn doTheTest() !void {
672 // [:x]T to []T
673 {
674 var array = [4:0]i32{ 1, 2, 3, 4 };
675 var slice: [:0]i32 = &array;
676 var dest: []i32 = slice;
677 try expect(mem.eql(i32, dest, &[_]i32{ 1, 2, 3, 4 }));
678 }
679
680 // [*:x]T to [*]T
681 {
682 var array = [4:99]i32{ 1, 2, 3, 4 };
683 var dest: [*]i32 = &array;
684 try expect(dest[0] == 1);
685 try expect(dest[1] == 2);
686 try expect(dest[2] == 3);
687 try expect(dest[3] == 4);
688 try expect(dest[4] == 99);
689 }
690
691 // [N:x]T to [N]T
692 {
693 var array = [4:0]i32{ 1, 2, 3, 4 };
694 var dest: [4]i32 = array;
695 try expect(mem.eql(i32, &dest, &[_]i32{ 1, 2, 3, 4 }));
696 }
697
698 // *[N:x]T to *[N]T
699 {
700 var array = [4:0]i32{ 1, 2, 3, 4 };
701 var dest: *[4]i32 = &array;
702 try expect(mem.eql(i32, dest, &[_]i32{ 1, 2, 3, 4 }));
703 }
704
705 // [:x]T to [*:x]T
706 {
707 var array = [4:0]i32{ 1, 2, 3, 4 };
708 var slice: [:0]i32 = &array;
709 var dest: [*:0]i32 = slice;
710 try expect(dest[0] == 1);
711 try expect(dest[1] == 2);
712 try expect(dest[2] == 3);
713 try expect(dest[3] == 4);
714 try expect(dest[4] == 0);
715 }
716 }
717 };
718 try S.doTheTest();
719 comptime try S.doTheTest();
720}
721
722test "cast i8 fn call peers to i32 result" {
723 const S = struct {
724 fn doTheTest() !void {
725 var cond = true;
726 const value: i32 = if (cond) smallBoi() else bigBoi();
727 try expect(value == 123);
728 }
729 fn smallBoi() i8 {
730 return 123;
731 }
732 fn bigBoi() i16 {
733 return 1234;
734 }
735 };
736 try S.doTheTest();
737 comptime try S.doTheTest();
738}
739
740test "return u8 coercing into ?u32 return type" {
741 const S = struct {
742 fn doTheTest() !void {
743 try expect(foo(123).? == 123);
744 }
745 fn foo(arg: u8) ?u32 {
746 return arg;
747 }
748 };
749 try S.doTheTest();
750 comptime try S.doTheTest();
751}
752
753test "peer result null and comptime_int" {
754 const S = struct {
755 fn blah(n: i32) ?i32 {
756 if (n == 0) {
757 return null;
758 } else if (n < 0) {
759 return -1;
760 } else {
761 return 1;
762 }
763 }
764 };
765
766 try expect(S.blah(0) == null);
767 comptime try expect(S.blah(0) == null);
768 try expect(S.blah(10).? == 1);
769 comptime try expect(S.blah(10).? == 1);
770 try expect(S.blah(-10).? == -1);
771 comptime try expect(S.blah(-10).? == -1);
772}
773
774test "peer type resolution implicit cast to return type" {
775 const S = struct {
776 fn doTheTest() !void {
777 for ("hello") |c| _ = f(c);
778 }
779 fn f(c: u8) []const u8 {
780 return switch (c) {
781 'h', 'e' => &[_]u8{c}, // should cast to slice
782 'l', ' ' => &[_]u8{ c, '.' }, // should cast to slice
783 else => ([_]u8{c})[0..], // is a slice
784 };
785 }
786 };
787 try S.doTheTest();
788 comptime try S.doTheTest();
789}
790
791test "peer type resolution implicit cast to variable type" {
792 const S = struct {
793 fn doTheTest() !void {
794 var x: []const u8 = undefined;
795 for ("hello") |c| x = switch (c) {
796 'h', 'e' => &[_]u8{c}, // should cast to slice
797 'l', ' ' => &[_]u8{ c, '.' }, // should cast to slice
798 else => ([_]u8{c})[0..], // is a slice
799 };
800 }
801 };
802 try S.doTheTest();
803 comptime try S.doTheTest();
804}
805
806test "variable initialization uses result locations properly with regards to the type" {
807 var b = true;
808 const x: i32 = if (b) 1 else 2;
809 try expect(x == 1);
810}
811
812test "cast between [*c]T and ?[*:0]T on fn parameter" {
813 const S = struct {
814 const Handler = ?fn ([*c]const u8) callconv(.C) void;
815 fn addCallback(handler: Handler) void {
816 _ = handler;
817 }
818
819 fn myCallback(cstr: ?[*:0]const u8) callconv(.C) void {
820 _ = cstr;
821 }
822
823 fn doTheTest() void {
824 addCallback(myCallback);
825 }
826 };
827 S.doTheTest();
828}
829
830test "cast between C pointer with different but compatible types" {
831 const S = struct {
832 fn foo(arg: [*]c_ushort) u16 {
833 return arg[0];
834 }
835 fn doTheTest() !void {
836 var x = [_]u16{ 4, 2, 1, 3 };
837 try expect(foo(@ptrCast([*]u16, &x)) == 4);
838 }
839 };
840 try S.doTheTest();
841}
842
843var global_struct: struct { f0: usize } = undefined;
844
845test "assignment to optional pointer result loc" {
846 var foo: struct { ptr: ?*c_void } = .{ .ptr = &global_struct };
847 try expect(foo.ptr.? == @ptrCast(*c_void, &global_struct));
848}
849
850test "peer type resolve string lit with sentinel-terminated mutable slice" {
851 var array: [4:0]u8 = undefined;
852 array[4] = 0; // TODO remove this when #4372 is solved
853 var slice: [:0]u8 = array[0..4 :0];
854 comptime try expect(@TypeOf(slice, "hi") == [:0]const u8);
855 comptime try expect(@TypeOf("hi", slice) == [:0]const u8);
856}
857
858test "peer type unsigned int to signed" {
859 var w: u31 = 5;
860 var x: u8 = 7;
861 var y: i32 = -5;
862 var a = w + y + x;
863 comptime try expect(@TypeOf(a) == i32);
864 try expect(a == 7);
865}
866
867test "peer type resolve array pointers, one of them const" {
868 var array1: [4]u8 = undefined;
869 const array2: [5]u8 = undefined;
870 comptime try expect(@TypeOf(&array1, &array2) == []const u8);
871 comptime try expect(@TypeOf(&array2, &array1) == []const u8);
872}
873
874test "peer type resolve array pointer and unknown pointer" {
875 const const_array: [4]u8 = undefined;
876 var array: [4]u8 = undefined;
877 var const_ptr: [*]const u8 = undefined;
878 var ptr: [*]u8 = undefined;
879
880 comptime try expect(@TypeOf(&array, ptr) == [*]u8);
881 comptime try expect(@TypeOf(ptr, &array) == [*]u8);
882
883 comptime try expect(@TypeOf(&const_array, ptr) == [*]const u8);
884 comptime try expect(@TypeOf(ptr, &const_array) == [*]const u8);
885
886 comptime try expect(@TypeOf(&array, const_ptr) == [*]const u8);
887 comptime try expect(@TypeOf(const_ptr, &array) == [*]const u8);
888
889 comptime try expect(@TypeOf(&const_array, const_ptr) == [*]const u8);
890 comptime try expect(@TypeOf(const_ptr, &const_array) == [*]const u8);
891}
892
893test "comptime float casts" {
894 const a = @intToFloat(comptime_float, 1);
895 try expect(a == 1);
896 try expect(@TypeOf(a) == comptime_float);
897 const b = @floatToInt(comptime_int, 2);
898 try expect(b == 2);
899 try expect(@TypeOf(b) == comptime_int);
900}
901
902test "cast from ?[*]T to ??[*]T" {
903 const a: ??[*]u8 = @as(?[*]u8, null);
904 try expect(a != null and a.? == null);
905}
906
907test "cast between *[N]void and []void" {
908 var a: [4]void = undefined;
909 var b: []void = &a;
910 try expect(b.len == 4);
911}