| author | |
| committer | |
| log | 2b589d71fbcacb2e8bc8746dd4b675e57b3a53df |
| tree | 83fda2aa57b2f48c958a522a9393c4ba900943ef |
| parent | cb248898ab41378c2e9bcf94d05c7c42577a7bab |
9 files changed, 275 insertions(+), 275 deletions(-)
test/behavior.zig+1-1| ... | ... | @@ -58,6 +58,7 @@ test { |
| 58 | 58 | _ = @import("behavior/floatop.zig"); |
| 59 | 59 | _ = @import("behavior/fn.zig"); |
| 60 | 60 | _ = @import("behavior/for.zig"); |
| 61 | _ = @import("behavior/generics_llvm.zig"); | |
| 61 | 62 | _ = @import("behavior/math.zig"); |
| 62 | 63 | _ = @import("behavior/maximum_minimum.zig"); |
| 63 | 64 | _ = @import("behavior/null_llvm.zig"); |
| ... | ... | @@ -145,7 +146,6 @@ test { |
| 145 | 146 | _ = @import("behavior/fn_delegation.zig"); |
| 146 | 147 | _ = @import("behavior/fn_in_struct_in_comptime.zig"); |
| 147 | 148 | _ = @import("behavior/for_stage1.zig"); |
| 148 | _ = @import("behavior/generics_stage1.zig"); | |
| 149 | 149 | _ = @import("behavior/if_stage1.zig"); |
| 150 | 150 | _ = @import("behavior/import.zig"); |
| 151 | 151 | _ = @import("behavior/incomplete_struct_param_tld.zig"); |
test/behavior/cast.zig+29| ... | ... | @@ -266,3 +266,32 @@ test "array coersion to undefined at runtime" { |
| 266 | 266 | array = undefined; |
| 267 | 267 | try expect(std.mem.eql(u8, &array, &undefined_val)); |
| 268 | 268 | } |
| 269 | ||
| 270 | test "implicitly cast from int to anyerror!?T" { | |
| 271 | implicitIntLitToOptional(); | |
| 272 | comptime implicitIntLitToOptional(); | |
| 273 | } | |
| 274 | fn implicitIntLitToOptional() void { | |
| 275 | const f: ?i32 = 1; | |
| 276 | _ = f; | |
| 277 | const g: anyerror!?i32 = 1; | |
| 278 | _ = g catch {}; | |
| 279 | } | |
| 280 | ||
| 281 | test "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 | ||
| 294 | test "cast from ?[*]T to ??[*]T" { | |
| 295 | const a: ??[*]u8 = @as(?[*]u8, null); | |
| 296 | try expect(a != null and a.? == null); | |
| 297 | } |
test/behavior/cast_llvm.zig+132| ... | ... | @@ -65,3 +65,135 @@ test "implicit ptr to *c_void" { |
| 65 | 65 | var c: *u32 = @ptrCast(*u32, ptr2.?); |
| 66 | 66 | try expect(c.* == 1); |
| 67 | 67 | } |
| 68 | ||
| 69 | const A = struct { | |
| 70 | a: i32, | |
| 71 | }; | |
| 72 | test "return null from fn() anyerror!?&T" { | |
| 73 | const a = returnNullFromOptionalTypeErrorRef(); | |
| 74 | const b = returnNullLitFromOptionalTypeErrorRef(); | |
| 75 | try expect((try a) == null and (try b) == null); | |
| 76 | } | |
| 77 | fn returnNullFromOptionalTypeErrorRef() anyerror!?*A { | |
| 78 | const a: ?*A = null; | |
| 79 | return a; | |
| 80 | } | |
| 81 | fn returnNullLitFromOptionalTypeErrorRef() anyerror!?*A { | |
| 82 | return null; | |
| 83 | } | |
| 84 | ||
| 85 | test "peer type resolution: [0]u8 and []const u8" { | |
| 86 | try expect(peerTypeEmptyArrayAndSlice(true, "hi").len == 0); | |
| 87 | try expect(peerTypeEmptyArrayAndSlice(false, "hi").len == 1); | |
| 88 | comptime { | |
| 89 | try expect(peerTypeEmptyArrayAndSlice(true, "hi").len == 0); | |
| 90 | try expect(peerTypeEmptyArrayAndSlice(false, "hi").len == 1); | |
| 91 | } | |
| 92 | } | |
| 93 | fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 { | |
| 94 | if (a) { | |
| 95 | return &[_]u8{}; | |
| 96 | } | |
| 97 | ||
| 98 | return slice[0..1]; | |
| 99 | } | |
| 100 | ||
| 101 | test "implicitly cast from [N]T to ?[]const T" { | |
| 102 | try expect(mem.eql(u8, castToOptionalSlice().?, "hi")); | |
| 103 | comptime try expect(mem.eql(u8, castToOptionalSlice().?, "hi")); | |
| 104 | } | |
| 105 | ||
| 106 | fn castToOptionalSlice() ?[]const u8 { | |
| 107 | return "hi"; | |
| 108 | } | |
| 109 | ||
| 110 | test "cast u128 to f128 and back" { | |
| 111 | comptime try testCast128(); | |
| 112 | try testCast128(); | |
| 113 | } | |
| 114 | ||
| 115 | fn testCast128() !void { | |
| 116 | try expect(cast128Int(cast128Float(0x7fff0000000000000000000000000000)) == 0x7fff0000000000000000000000000000); | |
| 117 | } | |
| 118 | ||
| 119 | fn cast128Int(x: f128) u128 { | |
| 120 | return @bitCast(u128, x); | |
| 121 | } | |
| 122 | ||
| 123 | fn cast128Float(x: u128) f128 { | |
| 124 | return @bitCast(f128, x); | |
| 125 | } | |
| 126 | ||
| 127 | test "implicit cast from *[N]T to ?[*]T" { | |
| 128 | var x: ?[*]u16 = null; | |
| 129 | var y: [4]u16 = [4]u16{ 0, 1, 2, 3 }; | |
| 130 | ||
| 131 | x = &y; | |
| 132 | try expect(std.mem.eql(u16, x.?[0..4], y[0..4])); | |
| 133 | x.?[0] = 8; | |
| 134 | y[3] = 6; | |
| 135 | try expect(std.mem.eql(u16, x.?[0..4], y[0..4])); | |
| 136 | } | |
| 137 | ||
| 138 | test "implicit cast from *T to ?*c_void" { | |
| 139 | var a: u8 = 1; | |
| 140 | incrementVoidPtrValue(&a); | |
| 141 | try std.testing.expect(a == 2); | |
| 142 | } | |
| 143 | ||
| 144 | fn incrementVoidPtrValue(value: ?*c_void) void { | |
| 145 | @ptrCast(*u8, value.?).* += 1; | |
| 146 | } | |
| 147 | ||
| 148 | test "implicit cast *[0]T to E![]const u8" { | |
| 149 | var x = @as(anyerror![]const u8, &[0]u8{}); | |
| 150 | try expect((x catch unreachable).len == 0); | |
| 151 | } | |
| 152 | ||
| 153 | var global_array: [4]u8 = undefined; | |
| 154 | test "cast from array reference to fn" { | |
| 155 | const f = @ptrCast(fn () callconv(.C) void, &global_array); | |
| 156 | try expect(@ptrToInt(f) == @ptrToInt(&global_array)); | |
| 157 | } | |
| 158 | ||
| 159 | test "*const [N]null u8 to ?[]const u8" { | |
| 160 | const S = struct { | |
| 161 | fn doTheTest() !void { | |
| 162 | var a = "Hello"; | |
| 163 | var b: ?[]const u8 = a; | |
| 164 | try expect(mem.eql(u8, b.?, "Hello")); | |
| 165 | } | |
| 166 | }; | |
| 167 | try S.doTheTest(); | |
| 168 | comptime try S.doTheTest(); | |
| 169 | } | |
| 170 | ||
| 171 | test "cast between [*c]T and ?[*:0]T on fn parameter" { | |
| 172 | const S = struct { | |
| 173 | const Handler = ?fn ([*c]const u8) callconv(.C) void; | |
| 174 | fn addCallback(handler: Handler) void { | |
| 175 | _ = handler; | |
| 176 | } | |
| 177 | ||
| 178 | fn myCallback(cstr: ?[*:0]const u8) callconv(.C) void { | |
| 179 | _ = cstr; | |
| 180 | } | |
| 181 | ||
| 182 | fn doTheTest() void { | |
| 183 | addCallback(myCallback); | |
| 184 | } | |
| 185 | }; | |
| 186 | S.doTheTest(); | |
| 187 | } | |
| 188 | ||
| 189 | var global_struct: struct { f0: usize } = undefined; | |
| 190 | test "assignment to optional pointer result loc" { | |
| 191 | var foo: struct { ptr: ?*c_void } = .{ .ptr = &global_struct }; | |
| 192 | try expect(foo.ptr.? == @ptrCast(*c_void, &global_struct)); | |
| 193 | } | |
| 194 | ||
| 195 | test "cast between *[N]void and []void" { | |
| 196 | var a: [4]void = undefined; | |
| 197 | var b: []void = &a; | |
| 198 | try expect(b.len == 4); | |
| 199 | } |
test/behavior/cast_stage1.zig-159| ... | ... | @@ -58,55 +58,6 @@ fn castToOptionalTypeError(z: i32) !void { |
| 58 | 58 | try expect((b catch unreachable).?.a == 1); |
| 59 | 59 | } |
| 60 | 60 | |
| 61 | test "implicitly cast from int to anyerror!?T" { | |
| 62 | implicitIntLitToOptional(); | |
| 63 | comptime implicitIntLitToOptional(); | |
| 64 | } | |
| 65 | fn implicitIntLitToOptional() void { | |
| 66 | const f: ?i32 = 1; | |
| 67 | _ = f; | |
| 68 | const g: anyerror!?i32 = 1; | |
| 69 | _ = g catch {}; | |
| 70 | } | |
| 71 | ||
| 72 | test "return null from fn() anyerror!?&T" { | |
| 73 | const a = returnNullFromOptionalTypeErrorRef(); | |
| 74 | const b = returnNullLitFromOptionalTypeErrorRef(); | |
| 75 | try expect((try a) == null and (try b) == null); | |
| 76 | } | |
| 77 | fn returnNullFromOptionalTypeErrorRef() anyerror!?*A { | |
| 78 | const a: ?*A = null; | |
| 79 | return a; | |
| 80 | } | |
| 81 | fn returnNullLitFromOptionalTypeErrorRef() anyerror!?*A { | |
| 82 | return null; | |
| 83 | } | |
| 84 | ||
| 85 | test "peer type resolution: [0]u8 and []const u8" { | |
| 86 | try expect(peerTypeEmptyArrayAndSlice(true, "hi").len == 0); | |
| 87 | try expect(peerTypeEmptyArrayAndSlice(false, "hi").len == 1); | |
| 88 | comptime { | |
| 89 | try expect(peerTypeEmptyArrayAndSlice(true, "hi").len == 0); | |
| 90 | try expect(peerTypeEmptyArrayAndSlice(false, "hi").len == 1); | |
| 91 | } | |
| 92 | } | |
| 93 | fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 { | |
| 94 | if (a) { | |
| 95 | return &[_]u8{}; | |
| 96 | } | |
| 97 | ||
| 98 | return slice[0..1]; | |
| 99 | } | |
| 100 | ||
| 101 | test "implicitly cast from [N]T to ?[]const T" { | |
| 102 | try expect(mem.eql(u8, castToOptionalSlice().?, "hi")); | |
| 103 | comptime try expect(mem.eql(u8, castToOptionalSlice().?, "hi")); | |
| 104 | } | |
| 105 | ||
| 106 | fn castToOptionalSlice() ?[]const u8 { | |
| 107 | return "hi"; | |
| 108 | } | |
| 109 | ||
| 110 | 61 | test "implicitly cast from [0]T to anyerror![]T" { |
| 111 | 62 | try testCastZeroArrayToErrSliceMut(); |
| 112 | 63 | comptime try testCastZeroArrayToErrSliceMut(); |
| ... | ... | @@ -191,23 +142,6 @@ fn testPeerErrorAndArray2(x: u8) anyerror![]const u8 { |
| 191 | 142 | }; |
| 192 | 143 | } |
| 193 | 144 | |
| 194 | test "cast u128 to f128 and back" { | |
| 195 | comptime try testCast128(); | |
| 196 | try testCast128(); | |
| 197 | } | |
| 198 | ||
| 199 | fn testCast128() !void { | |
| 200 | try expect(cast128Int(cast128Float(0x7fff0000000000000000000000000000)) == 0x7fff0000000000000000000000000000); | |
| 201 | } | |
| 202 | ||
| 203 | fn cast128Int(x: f128) u128 { | |
| 204 | return @bitCast(u128, x); | |
| 205 | } | |
| 206 | ||
| 207 | fn cast128Float(x: u128) f128 { | |
| 208 | return @bitCast(f128, x); | |
| 209 | } | |
| 210 | ||
| 211 | 145 | test "single-item pointer of array to slice to unknown length pointer" { |
| 212 | 146 | try testCastPtrOfArrayToSliceAndPtr(); |
| 213 | 147 | comptime try testCastPtrOfArrayToSliceAndPtr(); |
| ... | ... | @@ -316,27 +250,6 @@ test "@floatCast cast down" { |
| 316 | 250 | } |
| 317 | 251 | } |
| 318 | 252 | |
| 319 | test "implicit cast from *[N]T to ?[*]T" { | |
| 320 | var x: ?[*]u16 = null; | |
| 321 | var y: [4]u16 = [4]u16{ 0, 1, 2, 3 }; | |
| 322 | ||
| 323 | x = &y; | |
| 324 | try expect(std.mem.eql(u16, x.?[0..4], y[0..4])); | |
| 325 | x.?[0] = 8; | |
| 326 | y[3] = 6; | |
| 327 | try expect(std.mem.eql(u16, x.?[0..4], y[0..4])); | |
| 328 | } | |
| 329 | ||
| 330 | test "implicit cast from *T to ?*c_void" { | |
| 331 | var a: u8 = 1; | |
| 332 | incrementVoidPtrValue(&a); | |
| 333 | try std.testing.expect(a == 2); | |
| 334 | } | |
| 335 | ||
| 336 | fn incrementVoidPtrValue(value: ?*c_void) void { | |
| 337 | @ptrCast(*u8, value.?).* += 1; | |
| 338 | } | |
| 339 | ||
| 340 | 253 | test "peer type resolution: unreachable, null, slice" { |
| 341 | 254 | const S = struct { |
| 342 | 255 | fn doTheTest(num: usize, word: []const u8) !void { |
| ... | ... | @@ -374,11 +287,6 @@ test "peer type resolution: unreachable, error set, unreachable" { |
| 374 | 287 | try expect(transformed_err == error.SystemResources); |
| 375 | 288 | } |
| 376 | 289 | |
| 377 | test "implicit cast *[0]T to E![]const u8" { | |
| 378 | var x = @as(anyerror![]const u8, &[0]u8{}); | |
| 379 | try expect((x catch unreachable).len == 0); | |
| 380 | } | |
| 381 | ||
| 382 | 290 | test "peer cast *[0]T to E![]const T" { |
| 383 | 291 | var buffer: [5]u8 = "abcde".*; |
| 384 | 292 | var buf: anyerror![]const u8 = buffer[0..]; |
| ... | ... | @@ -395,24 +303,6 @@ test "peer cast *[0]T to []const T" { |
| 395 | 303 | try expect(mem.eql(u8, "abcde", y)); |
| 396 | 304 | } |
| 397 | 305 | |
| 398 | var global_array: [4]u8 = undefined; | |
| 399 | test "cast from array reference to fn" { | |
| 400 | const f = @ptrCast(fn () callconv(.C) void, &global_array); | |
| 401 | try expect(@ptrToInt(f) == @ptrToInt(&global_array)); | |
| 402 | } | |
| 403 | ||
| 404 | test "*const [N]null u8 to ?[]const u8" { | |
| 405 | const S = struct { | |
| 406 | fn doTheTest() !void { | |
| 407 | var a = "Hello"; | |
| 408 | var b: ?[]const u8 = a; | |
| 409 | try expect(mem.eql(u8, b.?, "Hello")); | |
| 410 | } | |
| 411 | }; | |
| 412 | try S.doTheTest(); | |
| 413 | comptime try S.doTheTest(); | |
| 414 | } | |
| 415 | ||
| 416 | 306 | test "peer resolution of string literals" { |
| 417 | 307 | const S = struct { |
| 418 | 308 | const E = enum { a, b, c, d }; |
| ... | ... | @@ -502,19 +392,6 @@ test "cast i8 fn call peers to i32 result" { |
| 502 | 392 | comptime try S.doTheTest(); |
| 503 | 393 | } |
| 504 | 394 | |
| 505 | test "return u8 coercing into ?u32 return type" { | |
| 506 | const S = struct { | |
| 507 | fn doTheTest() !void { | |
| 508 | try expect(foo(123).? == 123); | |
| 509 | } | |
| 510 | fn foo(arg: u8) ?u32 { | |
| 511 | return arg; | |
| 512 | } | |
| 513 | }; | |
| 514 | try S.doTheTest(); | |
| 515 | comptime try S.doTheTest(); | |
| 516 | } | |
| 517 | ||
| 518 | 395 | test "peer type resolution implicit cast to return type" { |
| 519 | 396 | const S = struct { |
| 520 | 397 | fn doTheTest() !void { |
| ... | ... | @@ -553,24 +430,6 @@ test "variable initialization uses result locations properly with regards to the |
| 553 | 430 | try expect(x == 1); |
| 554 | 431 | } |
| 555 | 432 | |
| 556 | test "cast between [*c]T and ?[*:0]T on fn parameter" { | |
| 557 | const S = struct { | |
| 558 | const Handler = ?fn ([*c]const u8) callconv(.C) void; | |
| 559 | fn addCallback(handler: Handler) void { | |
| 560 | _ = handler; | |
| 561 | } | |
| 562 | ||
| 563 | fn myCallback(cstr: ?[*:0]const u8) callconv(.C) void { | |
| 564 | _ = cstr; | |
| 565 | } | |
| 566 | ||
| 567 | fn doTheTest() void { | |
| 568 | addCallback(myCallback); | |
| 569 | } | |
| 570 | }; | |
| 571 | S.doTheTest(); | |
| 572 | } | |
| 573 | ||
| 574 | 433 | test "cast between C pointer with different but compatible types" { |
| 575 | 434 | const S = struct { |
| 576 | 435 | fn foo(arg: [*]c_ushort) u16 { |
| ... | ... | @@ -584,13 +443,6 @@ test "cast between C pointer with different but compatible types" { |
| 584 | 443 | try S.doTheTest(); |
| 585 | 444 | } |
| 586 | 445 | |
| 587 | var global_struct: struct { f0: usize } = undefined; | |
| 588 | ||
| 589 | test "assignment to optional pointer result loc" { | |
| 590 | var foo: struct { ptr: ?*c_void } = .{ .ptr = &global_struct }; | |
| 591 | try expect(foo.ptr.? == @ptrCast(*c_void, &global_struct)); | |
| 592 | } | |
| 593 | ||
| 594 | 446 | test "peer type resolve string lit with sentinel-terminated mutable slice" { |
| 595 | 447 | var array: [4:0]u8 = undefined; |
| 596 | 448 | array[4] = 0; // TODO remove this when #4372 is solved |
| ... | ... | @@ -649,14 +501,3 @@ test "comptime float casts" { |
| 649 | 501 | fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) !void { |
| 650 | 502 | try expect(@floatToInt(I, f) == i); |
| 651 | 503 | } |
| 652 | ||
| 653 | test "cast from ?[*]T to ??[*]T" { | |
| 654 | const a: ??[*]u8 = @as(?[*]u8, null); | |
| 655 | try expect(a != null and a.? == null); | |
| 656 | } | |
| 657 | ||
| 658 | test "cast between *[N]void and []void" { | |
| 659 | var a: [4]void = undefined; | |
| 660 | var b: []void = &a; | |
| 661 | try expect(b.len == 4); | |
| 662 | } |
test/behavior/fn.zig+42| ... | ... | @@ -121,3 +121,45 @@ test "inline function call that calls optional function pointer, return pointer |
| 121 | 121 | }; |
| 122 | 122 | try S.doTheTest(); |
| 123 | 123 | } |
| 124 | ||
| 125 | test "implicit cast function unreachable return" { | |
| 126 | wantsFnWithVoid(fnWithUnreachable); | |
| 127 | } | |
| 128 | ||
| 129 | fn wantsFnWithVoid(f: fn () void) void { | |
| 130 | _ = f; | |
| 131 | } | |
| 132 | ||
| 133 | fn fnWithUnreachable() noreturn { | |
| 134 | unreachable; | |
| 135 | } | |
| 136 | ||
| 137 | test "extern struct with stdcallcc fn pointer" { | |
| 138 | const S = extern struct { | |
| 139 | ptr: fn () callconv(if (builtin.target.cpu.arch == .i386) .Stdcall else .C) i32, | |
| 140 | ||
| 141 | fn foo() callconv(if (builtin.target.cpu.arch == .i386) .Stdcall else .C) i32 { | |
| 142 | return 1234; | |
| 143 | } | |
| 144 | }; | |
| 145 | ||
| 146 | var s: S = undefined; | |
| 147 | s.ptr = S.foo; | |
| 148 | try expect(s.ptr() == 1234); | |
| 149 | } | |
| 150 | ||
| 151 | const nComplexCallconv = 100; | |
| 152 | fn fComplexCallconvRet(x: u32) callconv(blk: { | |
| 153 | const s: struct { n: u32 } = .{ .n = nComplexCallconv }; | |
| 154 | break :blk switch (s.n) { | |
| 155 | 0 => .C, | |
| 156 | 1 => .Inline, | |
| 157 | else => .Unspecified, | |
| 158 | }; | |
| 159 | }) struct { x: u32 } { | |
| 160 | return .{ .x = x * x }; | |
| 161 | } | |
| 162 | ||
| 163 | test "function with complex callconv and return type expressions" { | |
| 164 | try expect(fComplexCallconvRet(3).x == 9); | |
| 165 | } |
test/behavior/fn_stage1.zig-42| ... | ... | @@ -23,18 +23,6 @@ fn acceptsString(foo: []u8) void { |
| 23 | 23 | _ = foo; |
| 24 | 24 | } |
| 25 | 25 | |
| 26 | test "implicit cast function unreachable return" { | |
| 27 | wantsFnWithVoid(fnWithUnreachable); | |
| 28 | } | |
| 29 | ||
| 30 | fn wantsFnWithVoid(f: fn () void) void { | |
| 31 | _ = f; | |
| 32 | } | |
| 33 | ||
| 34 | fn fnWithUnreachable() noreturn { | |
| 35 | unreachable; | |
| 36 | } | |
| 37 | ||
| 38 | 26 | test "function pointers" { |
| 39 | 27 | const fns = [_]@TypeOf(fn1){ |
| 40 | 28 | fn1, |
| ... | ... | @@ -126,20 +114,6 @@ test "pass by non-copying value as method, at comptime" { |
| 126 | 114 | } |
| 127 | 115 | } |
| 128 | 116 | |
| 129 | test "extern struct with stdcallcc fn pointer" { | |
| 130 | const S = extern struct { | |
| 131 | ptr: fn () callconv(if (builtin.target.cpu.arch == .i386) .Stdcall else .C) i32, | |
| 132 | ||
| 133 | fn foo() callconv(if (builtin.target.cpu.arch == .i386) .Stdcall else .C) i32 { | |
| 134 | return 1234; | |
| 135 | } | |
| 136 | }; | |
| 137 | ||
| 138 | var s: S = undefined; | |
| 139 | s.ptr = S.foo; | |
| 140 | try expect(s.ptr() == 1234); | |
| 141 | } | |
| 142 | ||
| 143 | 117 | test "implicit cast fn call result to optional in field result" { |
| 144 | 118 | const S = struct { |
| 145 | 119 | fn entry() !void { |
| ... | ... | @@ -204,19 +178,3 @@ test "function with inferred error set but returning no error" { |
| 204 | 178 | const return_ty = @typeInfo(@TypeOf(S.foo)).Fn.return_type.?; |
| 205 | 179 | try expectEqual(0, @typeInfo(@typeInfo(return_ty).ErrorUnion.error_set).ErrorSet.?.len); |
| 206 | 180 | } |
| 207 | ||
| 208 | const nComplexCallconv = 100; | |
| 209 | fn fComplexCallconvRet(x: u32) callconv(blk: { | |
| 210 | const s: struct { n: u32 } = .{ .n = nComplexCallconv }; | |
| 211 | break :blk switch (s.n) { | |
| 212 | 0 => .C, | |
| 213 | 1 => .Inline, | |
| 214 | else => .Unspecified, | |
| 215 | }; | |
| 216 | }) struct { x: u32 } { | |
| 217 | return .{ .x = x * x }; | |
| 218 | } | |
| 219 | ||
| 220 | test "function with complex callconv and return type expressions" { | |
| 221 | try expect(fComplexCallconvRet(3).x == 9); | |
| 222 | } |
test/behavior/generics.zig+29| ... | ... | @@ -134,3 +134,32 @@ test "use generic param in generic param" { |
| 134 | 134 | fn aGenericFn(comptime T: type, comptime a: T, b: T) T { |
| 135 | 135 | return a + b; |
| 136 | 136 | } |
| 137 | ||
| 138 | test "generic fn with implicit cast" { | |
| 139 | try expect(getFirstByte(u8, &[_]u8{13}) == 13); | |
| 140 | try expect(getFirstByte(u16, &[_]u16{ | |
| 141 | 0, | |
| 142 | 13, | |
| 143 | }) == 0); | |
| 144 | } | |
| 145 | fn getByte(ptr: ?*const u8) u8 { | |
| 146 | return ptr.?.*; | |
| 147 | } | |
| 148 | fn getFirstByte(comptime T: type, mem: []const T) u8 { | |
| 149 | return getByte(@ptrCast(*const u8, &mem[0])); | |
| 150 | } | |
| 151 | ||
| 152 | test "generic fn keeps non-generic parameter types" { | |
| 153 | const A = 128; | |
| 154 | ||
| 155 | const S = struct { | |
| 156 | fn f(comptime T: type, s: []T) !void { | |
| 157 | try expect(A != @typeInfo(@TypeOf(s)).Pointer.alignment); | |
| 158 | } | |
| 159 | }; | |
| 160 | ||
| 161 | // The compiler monomorphizes `S.f` for `T=u8` on its first use, check that | |
| 162 | // `x` type not affect `s` parameter type. | |
| 163 | var x: [16]u8 align(A) = undefined; | |
| 164 | try S.f(u8, &x); | |
| 165 | } |
test/behavior/generics_llvm.zig created+42| ... | ... | @@ -0,0 +1,42 @@ |
| 1 | const std = @import("std"); | |
| 2 | const expect = std.testing.expect; | |
| 3 | ||
| 4 | const foos = [_]fn (anytype) bool{ | |
| 5 | foo1, | |
| 6 | foo2, | |
| 7 | }; | |
| 8 | ||
| 9 | fn foo1(arg: anytype) bool { | |
| 10 | return arg; | |
| 11 | } | |
| 12 | fn foo2(arg: anytype) bool { | |
| 13 | return !arg; | |
| 14 | } | |
| 15 | ||
| 16 | test "array of generic fns" { | |
| 17 | try expect(foos[0](true)); | |
| 18 | try expect(!foos[1](true)); | |
| 19 | } | |
| 20 | ||
| 21 | test "generic struct" { | |
| 22 | var a1 = GenNode(i32){ | |
| 23 | .value = 13, | |
| 24 | .next = null, | |
| 25 | }; | |
| 26 | var b1 = GenNode(bool){ | |
| 27 | .value = true, | |
| 28 | .next = null, | |
| 29 | }; | |
| 30 | try expect(a1.value == 13); | |
| 31 | try expect(a1.value == a1.getVal()); | |
| 32 | try expect(b1.getVal()); | |
| 33 | } | |
| 34 | fn GenNode(comptime T: type) type { | |
| 35 | return struct { | |
| 36 | value: T, | |
| 37 | next: ?*GenNode(T), | |
| 38 | fn getVal(n: *const GenNode(T)) T { | |
| 39 | return n.value; | |
| 40 | } | |
| 41 | }; | |
| 42 | } |
test/behavior/generics_stage1.zig deleted-73| ... | ... | @@ -1,73 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const testing = std.testing; | |
| 3 | const expect = testing.expect; | |
| 4 | const expectEqual = testing.expectEqual; | |
| 5 | ||
| 6 | test "generic struct" { | |
| 7 | var a1 = GenNode(i32){ | |
| 8 | .value = 13, | |
| 9 | .next = null, | |
| 10 | }; | |
| 11 | var b1 = GenNode(bool){ | |
| 12 | .value = true, | |
| 13 | .next = null, | |
| 14 | }; | |
| 15 | try expect(a1.value == 13); | |
| 16 | try expect(a1.value == a1.getVal()); | |
| 17 | try expect(b1.getVal()); | |
| 18 | } | |
| 19 | fn GenNode(comptime T: type) type { | |
| 20 | return struct { | |
| 21 | value: T, | |
| 22 | next: ?*GenNode(T), | |
| 23 | fn getVal(n: *const GenNode(T)) T { | |
| 24 | return n.value; | |
| 25 | } | |
| 26 | }; | |
| 27 | } | |
| 28 | ||
| 29 | test "generic fn with implicit cast" { | |
| 30 | try expect(getFirstByte(u8, &[_]u8{13}) == 13); | |
| 31 | try expect(getFirstByte(u16, &[_]u16{ | |
| 32 | 0, | |
| 33 | 13, | |
| 34 | }) == 0); | |
| 35 | } | |
| 36 | fn getByte(ptr: ?*const u8) u8 { | |
| 37 | return ptr.?.*; | |
| 38 | } | |
| 39 | fn getFirstByte(comptime T: type, mem: []const T) u8 { | |
| 40 | return getByte(@ptrCast(*const u8, &mem[0])); | |
| 41 | } | |
| 42 | ||
| 43 | const foos = [_]fn (anytype) bool{ | |
| 44 | foo1, | |
| 45 | foo2, | |
| 46 | }; | |
| 47 | ||
| 48 | fn foo1(arg: anytype) bool { | |
| 49 | return arg; | |
| 50 | } | |
| 51 | fn foo2(arg: anytype) bool { | |
| 52 | return !arg; | |
| 53 | } | |
| 54 | ||
| 55 | test "array of generic fns" { | |
| 56 | try expect(foos[0](true)); | |
| 57 | try expect(!foos[1](true)); | |
| 58 | } | |
| 59 | ||
| 60 | test "generic fn keeps non-generic parameter types" { | |
| 61 | const A = 128; | |
| 62 | ||
| 63 | const S = struct { | |
| 64 | fn f(comptime T: type, s: []T) !void { | |
| 65 | try expect(A != @typeInfo(@TypeOf(s)).Pointer.alignment); | |
| 66 | } | |
| 67 | }; | |
| 68 | ||
| 69 | // The compiler monomorphizes `S.f` for `T=u8` on its first use, check that | |
| 70 | // `x` type not affect `s` parameter type. | |
| 71 | var x: [16]u8 align(A) = undefined; | |
| 72 | try S.f(u8, &x); | |
| 73 | } |