test/behavior/eval.zig (49216B) - Raw
1 const builtin = @import("builtin"); 2 const std = @import("std"); 3 const assert = std.debug.assert; 4 const expect = std.testing.expect; 5 const expectEqual = std.testing.expectEqual; 6 7 test "compile time recursion" { 8 try expect(some_data.len == 21); 9 } 10 var some_data: [@as(usize, @intCast(fibonacci(7)))]u8 = undefined; 11 fn fibonacci(x: i32) i32 { 12 if (x <= 1) return 1; 13 return fibonacci(x - 1) + fibonacci(x - 2); 14 } 15 16 fn unwrapAndAddOne(blah: ?i32) i32 { 17 return blah.? + 1; 18 } 19 const should_be_1235 = unwrapAndAddOne(1234); 20 test "static add one" { 21 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 22 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO 23 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 24 25 try expect(should_be_1235 == 1235); 26 } 27 28 test "inlined loop" { 29 comptime var i = 0; 30 comptime var sum = 0; 31 inline while (i <= 5) : (i += 1) 32 sum += i; 33 try expect(sum == 15); 34 } 35 36 fn gimme1or2(comptime a: bool) i32 { 37 const x: i32 = 1; 38 const y: i32 = 2; 39 comptime var z: i32 = if (a) x else y; 40 _ = &z; 41 return z; 42 } 43 test "inline variable gets result of const if" { 44 try expect(gimme1or2(true) == 1); 45 try expect(gimme1or2(false) == 2); 46 } 47 48 test "static function evaluation" { 49 try expect(statically_added_number == 3); 50 } 51 const statically_added_number = staticAdd(1, 2); 52 fn staticAdd(a: i32, b: i32) i32 { 53 return a + b; 54 } 55 56 test "const expr eval on single expr blocks" { 57 try expect(constExprEvalOnSingleExprBlocksFn(1, true) == 3); 58 comptime assert(constExprEvalOnSingleExprBlocksFn(1, true) == 3); 59 } 60 61 fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) i32 { 62 const literal = 3; 63 64 const result = if (b) b: { 65 break :b literal; 66 } else b: { 67 break :b x; 68 }; 69 70 return result; 71 } 72 73 test "constant expressions" { 74 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 75 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 76 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 77 78 var array: [array_size]u8 = undefined; 79 _ = &array; 80 try expect(@sizeOf(@TypeOf(array)) == 20); 81 } 82 const array_size: u8 = 20; 83 84 fn max(comptime T: type, a: T, b: T) T { 85 if (T == bool) { 86 return a or b; 87 } else if (a > b) { 88 return a; 89 } else { 90 return b; 91 } 92 } 93 fn letsTryToCompareBools(a: bool, b: bool) bool { 94 return max(bool, a, b); 95 } 96 test "inlined block and runtime block phi" { 97 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 98 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 99 100 try expect(letsTryToCompareBools(true, true)); 101 try expect(letsTryToCompareBools(true, false)); 102 try expect(letsTryToCompareBools(false, true)); 103 try expect(!letsTryToCompareBools(false, false)); 104 105 comptime { 106 try expect(letsTryToCompareBools(true, true)); 107 try expect(letsTryToCompareBools(true, false)); 108 try expect(letsTryToCompareBools(false, true)); 109 try expect(!letsTryToCompareBools(false, false)); 110 } 111 } 112 113 test "eval @setRuntimeSafety at compile-time" { 114 const result = comptime fnWithSetRuntimeSafety(); 115 try expect(result == 1234); 116 } 117 118 fn fnWithSetRuntimeSafety() i32 { 119 @setRuntimeSafety(true); 120 return 1234; 121 } 122 123 test "compile-time downcast when the bits fit" { 124 comptime { 125 const spartan_count: u16 = 255; 126 const byte = @as(u8, @intCast(spartan_count)); 127 try expect(byte == 255); 128 } 129 } 130 131 test "pointer to type" { 132 comptime { 133 var T: type = i32; 134 try expect(T == i32); 135 const ptr = &T; 136 try expect(@TypeOf(ptr) == *type); 137 ptr.* = f32; 138 try expect(T == f32); 139 try expect(*T == *f32); 140 } 141 } 142 143 test "a type constructed in a global expression" { 144 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 145 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 146 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 147 148 var l: List = undefined; 149 l.array[0] = 10; 150 l.array[1] = 11; 151 l.array[2] = 12; 152 const ptr = @as([*]u8, @ptrCast(&l.array)); 153 try expect(ptr[0] == 10); 154 try expect(ptr[1] == 11); 155 try expect(ptr[2] == 12); 156 } 157 158 const List = blk: { 159 const T = [10]u8; 160 break :blk struct { 161 array: T, 162 }; 163 }; 164 165 test "comptime function with the same args is memoized" { 166 comptime { 167 try expect(MakeType(i32) == MakeType(i32)); 168 try expect(MakeType(i32) != MakeType(f64)); 169 } 170 } 171 172 fn MakeType(comptime T: type) type { 173 return struct { 174 field: T, 175 }; 176 } 177 178 test "try to trick eval with runtime if" { 179 try expect(testTryToTrickEvalWithRuntimeIf(true) == 10); 180 } 181 182 fn testTryToTrickEvalWithRuntimeIf(b: bool) usize { 183 comptime var i: usize = 0; 184 inline while (i < 10) : (i += 1) { 185 const result = if (b) false else true; 186 _ = result; 187 } 188 return comptime i; 189 } 190 191 test "@setEvalBranchQuota" { 192 comptime { 193 // 1001 for the loop and then 1 more for the expect fn call 194 @setEvalBranchQuota(1002); 195 var i = 0; 196 var sum = 0; 197 while (i < 1001) : (i += 1) { 198 sum += i; 199 } 200 try expect(sum == 500500); 201 } 202 } 203 204 test "constant struct with negation" { 205 try expect(vertices[0].x == @as(f32, -0.6)); 206 } 207 const Vertex = struct { 208 x: f32, 209 y: f32, 210 r: f32, 211 g: f32, 212 b: f32, 213 }; 214 const vertices = [_]Vertex{ 215 Vertex{ 216 .x = -0.6, 217 .y = -0.4, 218 .r = 1.0, 219 .g = 0.0, 220 .b = 0.0, 221 }, 222 Vertex{ 223 .x = 0.6, 224 .y = -0.4, 225 .r = 0.0, 226 .g = 1.0, 227 .b = 0.0, 228 }, 229 Vertex{ 230 .x = 0.0, 231 .y = 0.6, 232 .r = 0.0, 233 .g = 0.0, 234 .b = 1.0, 235 }, 236 }; 237 238 test "statically initialized list" { 239 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 240 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 241 242 try expect(static_point_list[0].x == 1); 243 try expect(static_point_list[0].y == 2); 244 try expect(static_point_list[1].x == 3); 245 try expect(static_point_list[1].y == 4); 246 } 247 const Point = struct { 248 x: i32, 249 y: i32, 250 }; 251 const static_point_list = [_]Point{ 252 makePoint(1, 2), 253 makePoint(3, 4), 254 }; 255 fn makePoint(x: i32, y: i32) Point { 256 return Point{ 257 .x = x, 258 .y = y, 259 }; 260 } 261 262 test "statically initialized array literal" { 263 const y: [4]u8 = st_init_arr_lit_x; 264 try expect(y[3] == 4); 265 } 266 const st_init_arr_lit_x = [_]u8{ 1, 2, 3, 4 }; 267 268 const CmdFn = struct { 269 name: []const u8, 270 func: fn (i32) i32, 271 }; 272 273 const cmd_fns = [_]CmdFn{ 274 CmdFn{ 275 .name = "one", 276 .func = one, 277 }, 278 CmdFn{ 279 .name = "two", 280 .func = two, 281 }, 282 CmdFn{ 283 .name = "three", 284 .func = three, 285 }, 286 }; 287 fn one(value: i32) i32 { 288 return value + 1; 289 } 290 fn two(value: i32) i32 { 291 return value + 2; 292 } 293 fn three(value: i32) i32 { 294 return value + 3; 295 } 296 297 fn performFn(comptime prefix_char: u8, start_value: i32) i32 { 298 var result: i32 = start_value; 299 comptime var i = 0; 300 inline while (i < cmd_fns.len) : (i += 1) { 301 if (cmd_fns[i].name[0] == prefix_char) { 302 result = cmd_fns[i].func(result); 303 } 304 } 305 return result; 306 } 307 308 test "comptime iterate over fn ptr list" { 309 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 310 311 try expect(performFn('t', 1) == 6); 312 try expect(performFn('o', 0) == 1); 313 try expect(performFn('w', 99) == 99); 314 } 315 316 test "create global array with for loop" { 317 try expect(global_array[5] == 5 * 5); 318 try expect(global_array[9] == 9 * 9); 319 } 320 321 const global_array = x: { 322 var result: [10]usize = undefined; 323 for (&result, 0..) |*item, index| { 324 item.* = index * index; 325 } 326 break :x result; 327 }; 328 329 fn generateTable(comptime T: type) [1010]T { 330 var res: [1010]T = undefined; 331 var i: usize = 0; 332 while (i < 1010) : (i += 1) { 333 res[i] = @as(T, @intCast(i)); 334 } 335 return res; 336 } 337 338 fn doesAlotT(comptime T: type, value: usize) T { 339 @setEvalBranchQuota(5000); 340 const table = comptime blk: { 341 break :blk generateTable(T); 342 }; 343 return table[value]; 344 } 345 346 test "@setEvalBranchQuota at same scope as generic function call" { 347 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 348 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 349 350 try expect(doesAlotT(u32, 2) == 2); 351 } 352 353 pub const Info = struct { 354 version: u8, 355 }; 356 357 pub const diamond_info = Info{ .version = 0 }; 358 359 test "comptime modification of const struct field" { 360 comptime { 361 var res = diamond_info; 362 res.version = 1; 363 try expect(diamond_info.version == 0); 364 try expect(res.version == 1); 365 } 366 } 367 368 test "refer to the type of a generic function" { 369 const Func = fn (type) void; 370 const f: Func = doNothingWithType; 371 f(i32); 372 } 373 374 fn doNothingWithType(comptime T: type) void { 375 _ = T; 376 } 377 378 test "zero extend from u0 to u1" { 379 var zero_u0: u0 = 0; 380 var zero_u1: u1 = zero_u0; 381 _ = .{ &zero_u0, &zero_u1 }; 382 try expect(zero_u1 == 0); 383 } 384 385 test "return 0 from function that has u0 return type" { 386 const S = struct { 387 fn foo_zero() u0 { 388 return 0; 389 } 390 }; 391 comptime { 392 if (S.foo_zero() != 0) { 393 @compileError("test failed"); 394 } 395 } 396 } 397 398 test "statically initialized struct" { 399 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 400 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 401 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 402 403 st_init_str_foo.x += 1; 404 try expect(st_init_str_foo.x == 14); 405 } 406 const StInitStrFoo = struct { 407 x: i32, 408 y: bool, 409 }; 410 var st_init_str_foo = StInitStrFoo{ 411 .x = 13, 412 .y = true, 413 }; 414 415 test "inline for with same type but different values" { 416 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 417 418 var res: usize = 0; 419 inline for ([_]type{ [2]u8, [1]u8, [2]u8 }) |T| { 420 var a: T = undefined; 421 _ = &a; 422 res += a.len; 423 } 424 try expect(res == 5); 425 } 426 427 test "f32 at compile time is lossy" { 428 try expect(@as(f32, 1 << 24) + 1 == 1 << 24); 429 } 430 431 test "f64 at compile time is lossy" { 432 try expect(@as(f64, 1 << 53) + 1 == 1 << 53); 433 } 434 435 test { 436 comptime assert(@as(f128, 1 << 113) == 10384593717069655257060992658440192); 437 } 438 439 fn copyWithPartialInline(s: []u32, b: []u8) void { 440 comptime var i: usize = 0; 441 inline while (i < 4) : (i += 1) { 442 s[i] = 0; 443 s[i] |= @as(u32, b[i * 4 + 0]) << 24; 444 s[i] |= @as(u32, b[i * 4 + 1]) << 16; 445 s[i] |= @as(u32, b[i * 4 + 2]) << 8; 446 s[i] |= @as(u32, b[i * 4 + 3]) << 0; 447 } 448 } 449 450 test "binary math operator in partially inlined function" { 451 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO 452 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 453 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 454 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 455 456 var s: [4]u32 = undefined; 457 var b: [16]u8 = undefined; 458 459 for (&b, 0..) |*r, i| 460 r.* = @as(u8, @intCast(i + 1)); 461 462 copyWithPartialInline(s[0..], b[0..]); 463 try expect(s[0] == 0x1020304); 464 try expect(s[1] == 0x5060708); 465 try expect(s[2] == 0x90a0b0c); 466 try expect(s[3] == 0xd0e0f10); 467 } 468 469 test "comptime shl" { 470 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 471 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO 472 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 473 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; 474 475 const a: u128 = 3; 476 const b: u7 = 63; 477 const c: u128 = 3 << 63; 478 try expect((a << b) == c); 479 } 480 481 test "comptime bitwise operators" { 482 comptime { 483 try expect(3 & 1 == 1); 484 try expect(3 & -1 == 3); 485 try expect(-3 & -1 == -3); 486 try expect(3 | -1 == -1); 487 try expect(-3 | -1 == -1); 488 try expect(3 ^ -1 == -4); 489 try expect(-3 ^ -1 == 2); 490 try expect(~@as(i8, -1) == 0); 491 try expect(~@as(i128, -1) == 0); 492 try expect(18446744073709551615 & 18446744073709551611 == 18446744073709551611); 493 try expect(-18446744073709551615 & -18446744073709551611 == -18446744073709551615); 494 try expect(~@as(u128, 0) == 0xffffffffffffffffffffffffffffffff); 495 } 496 } 497 498 test "comptime shlWithOverflow" { 499 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO 500 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 501 502 const ct_shifted = @shlWithOverflow(~@as(u64, 0), 16)[0]; 503 var a = ~@as(u64, 0); 504 _ = &a; 505 const rt_shifted = @shlWithOverflow(a, 16)[0]; 506 507 try expect(ct_shifted == rt_shifted); 508 } 509 510 test "const ptr to variable data changes at runtime" { 511 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 512 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 513 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 514 515 try expect(foo_ref.name[0] == 'a'); 516 foo_ref.name = "b"; 517 try expect(foo_ref.name[0] == 'b'); 518 } 519 520 const Foo = struct { 521 name: []const u8, 522 }; 523 524 var foo_contents = Foo{ .name = "a" }; 525 const foo_ref = &foo_contents; 526 527 test "runtime 128 bit integer division" { 528 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO 529 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 530 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO 531 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 532 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; 533 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest; 534 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; 535 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 536 537 var a: u128 = 152313999999999991610955792383; 538 var b: u128 = 10000000000000000000; 539 _ = .{ &a, &b }; 540 const c = a / b; 541 try expect(c == 15231399999); 542 } 543 544 test "@tagName of @typeInfo" { 545 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 546 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 547 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 548 549 const str = @tagName(@typeInfo(u8)); 550 try expect(std.mem.eql(u8, str, "Int")); 551 } 552 553 test "static eval list init" { 554 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 555 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO 556 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 557 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 558 559 try expect(static_vec3.data[2] == 1.0); 560 try expect(vec3(0.0, 0.0, 3.0).data[2] == 3.0); 561 } 562 const static_vec3 = vec3(0.0, 0.0, 1.0); 563 pub const Vec3 = struct { 564 data: [3]f32, 565 }; 566 pub fn vec3(x: f32, y: f32, z: f32) Vec3 { 567 return Vec3{ 568 .data = [_]f32{ x, y, z }, 569 }; 570 } 571 572 test "inlined loop has array literal with elided runtime scope on first iteration but not second iteration" { 573 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 574 575 var runtime = [1]i32{3}; 576 _ = &runtime; 577 comptime var i: usize = 0; 578 inline while (i < 2) : (i += 1) { 579 const result = if (i == 0) [1]i32{2} else runtime; 580 _ = result; 581 } 582 comptime { 583 try expect(i == 2); 584 } 585 } 586 587 test "ptr to local array argument at comptime" { 588 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 589 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 590 591 comptime { 592 var bytes: [10]u8 = undefined; 593 modifySomeBytes(bytes[0..]); 594 try expect(bytes[0] == 'a'); 595 try expect(bytes[9] == 'b'); 596 } 597 } 598 599 fn modifySomeBytes(bytes: []u8) void { 600 bytes[0] = 'a'; 601 bytes[9] = 'b'; 602 } 603 604 test "comparisons 0 <= uint and 0 > uint should be comptime" { 605 testCompTimeUIntComparisons(1234); 606 } 607 fn testCompTimeUIntComparisons(x: u32) void { 608 if (!(0 <= x)) { 609 @compileError("this condition should be comptime-known"); 610 } 611 if (0 > x) { 612 @compileError("this condition should be comptime-known"); 613 } 614 if (!(x >= 0)) { 615 @compileError("this condition should be comptime-known"); 616 } 617 if (x < 0) { 618 @compileError("this condition should be comptime-known"); 619 } 620 } 621 622 const hi1 = "hi"; 623 const hi2 = hi1; 624 test "const global shares pointer with other same one" { 625 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 626 627 try assertEqualPtrs(&hi1[0], &hi2[0]); 628 comptime assert(&hi1[0] == &hi2[0]); 629 } 630 fn assertEqualPtrs(ptr1: *const u8, ptr2: *const u8) !void { 631 try expect(ptr1 == ptr2); 632 } 633 634 // This one is still up for debate in the language specification. 635 // Application code should not rely on this behavior until it is solidified. 636 // Historically, stage1 had special case code to make this pass for string literals 637 // but it did not work if the values are constructed with comptime code, or if 638 // arrays of non-u8 elements are used instead. 639 // The official language specification might not make this guarantee. However, if 640 // it does make this guarantee, it will make it consistently for all types, not 641 // only string literals. This is why Zig currently has a string table for 642 // string literals, to match legacy stage1 behavior and pass this test, however 643 // the end-game once the lang spec issue is settled would be to use a global 644 // InternPool for comptime memoized objects, making this behavior consistent 645 // across all types. 646 test "string literal used as comptime slice is memoized" { 647 const a = "link"; 648 const b = "link"; 649 comptime assert(TypeWithCompTimeSlice(a).Node == TypeWithCompTimeSlice(b).Node); 650 comptime assert(TypeWithCompTimeSlice("link").Node == TypeWithCompTimeSlice("link").Node); 651 } 652 653 pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) type { 654 _ = field_name; 655 return struct { 656 pub const Node = struct {}; 657 }; 658 } 659 660 test "comptime function with mutable pointer is not memoized" { 661 comptime { 662 var x: i32 = 1; 663 const ptr = &x; 664 increment(ptr); 665 increment(ptr); 666 try expect(x == 3); 667 } 668 } 669 670 fn increment(value: *i32) void { 671 value.* += 1; 672 } 673 674 test "const ptr to comptime mutable data is not memoized" { 675 comptime { 676 var foo = SingleFieldStruct{ .x = 1 }; 677 try expect(foo.read_x() == 1); 678 foo.x = 2; 679 try expect(foo.read_x() == 2); 680 } 681 } 682 683 const SingleFieldStruct = struct { 684 x: i32, 685 686 fn read_x(self: *const SingleFieldStruct) i32 { 687 return self.x; 688 } 689 }; 690 691 test "function which returns struct with type field causes implicit comptime" { 692 const ty = wrap(i32).T; 693 try expect(ty == i32); 694 } 695 696 const Wrapper = struct { 697 T: type, 698 }; 699 700 fn wrap(comptime T: type) Wrapper { 701 return Wrapper{ .T = T }; 702 } 703 704 test "call method with comptime pass-by-non-copying-value self parameter" { 705 const S = struct { 706 a: u8, 707 708 fn b(comptime s: @This()) u8 { 709 return s.a; 710 } 711 }; 712 713 const s = S{ .a = 2 }; 714 const b = s.b(); 715 try expect(b == 2); 716 } 717 718 test "setting backward branch quota just before a generic fn call" { 719 @setEvalBranchQuota(1001); 720 loopNTimes(1001); 721 } 722 723 fn loopNTimes(comptime n: usize) void { 724 comptime var i = 0; 725 inline while (i < n) : (i += 1) {} 726 } 727 728 test "variable inside inline loop that has different types on different iterations" { 729 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 730 731 try testVarInsideInlineLoop(.{ true, @as(u32, 42) }); 732 } 733 734 fn testVarInsideInlineLoop(args: anytype) !void { 735 comptime var i = 0; 736 inline while (i < args.len) : (i += 1) { 737 const x = args[i]; 738 if (i == 0) try expect(x); 739 if (i == 1) try expect(x == 42); 740 } 741 } 742 743 test "*align(1) u16 is the same as *align(1:0:2) u16" { 744 comptime { 745 try expect(*align(1:0:2) u16 == *align(1) u16); 746 try expect(*align(2:0:2) u16 == *u16); 747 } 748 } 749 750 test "array concatenation of function calls" { 751 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; 752 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 753 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 754 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 755 756 var a = oneItem(3) ++ oneItem(4); 757 try expect(std.mem.eql(i32, &a, &[_]i32{ 3, 4 })); 758 } 759 760 test "array multiplication of function calls" { 761 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; 762 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 763 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 764 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 765 766 var a = oneItem(3) ** scalar(2); 767 try expect(std.mem.eql(i32, &a, &[_]i32{ 3, 3 })); 768 } 769 770 fn oneItem(x: i32) [1]i32 { 771 return [_]i32{x}; 772 } 773 774 fn scalar(x: u32) u32 { 775 return x; 776 } 777 778 test "array concatenation peer resolves element types - value" { 779 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; 780 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 781 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 782 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 783 784 var a = [2]u3{ 1, 7 }; 785 var b = [3]u8{ 200, 225, 255 }; 786 _ = .{ &a, &b }; 787 const c = a ++ b; 788 comptime assert(@TypeOf(c) == [5]u8); 789 try expect(c[0] == 1); 790 try expect(c[1] == 7); 791 try expect(c[2] == 200); 792 try expect(c[3] == 225); 793 try expect(c[4] == 255); 794 } 795 796 test "array concatenation peer resolves element types - pointer" { 797 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; 798 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 799 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 800 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 801 802 var a = [2]u3{ 1, 7 }; 803 var b = [3]u8{ 200, 225, 255 }; 804 const c = &a ++ &b; 805 comptime assert(@TypeOf(c) == *[5]u8); 806 try expect(c[0] == 1); 807 try expect(c[1] == 7); 808 try expect(c[2] == 200); 809 try expect(c[3] == 225); 810 try expect(c[4] == 255); 811 } 812 813 test "array concatenation sets the sentinel - value" { 814 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; 815 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 816 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 817 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 818 819 var a = [2]u3{ 1, 7 }; 820 var b = [3:69]u8{ 200, 225, 255 }; 821 _ = .{ &a, &b }; 822 const c = a ++ b; 823 comptime assert(@TypeOf(c) == [5:69]u8); 824 try expect(c[0] == 1); 825 try expect(c[1] == 7); 826 try expect(c[2] == 200); 827 try expect(c[3] == 225); 828 try expect(c[4] == 255); 829 const ptr: [*]const u8 = &c; 830 try expect(ptr[5] == 69); 831 } 832 833 test "array concatenation sets the sentinel - pointer" { 834 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 835 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 836 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 837 838 var a = [2]u3{ 1, 7 }; 839 var b = [3:69]u8{ 200, 225, 255 }; 840 const c = &a ++ &b; 841 comptime assert(@TypeOf(c) == *[5:69]u8); 842 try expect(c[0] == 1); 843 try expect(c[1] == 7); 844 try expect(c[2] == 200); 845 try expect(c[3] == 225); 846 try expect(c[4] == 255); 847 const ptr: [*]const u8 = c; 848 try expect(ptr[5] == 69); 849 } 850 851 test "array multiplication sets the sentinel - value" { 852 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; 853 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 854 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 855 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 856 857 var a = [2:7]u3{ 1, 6 }; 858 _ = &a; 859 const b = a ** 2; 860 comptime assert(@TypeOf(b) == [4:7]u3); 861 try expect(b[0] == 1); 862 try expect(b[1] == 6); 863 try expect(b[2] == 1); 864 try expect(b[3] == 6); 865 const ptr: [*]const u3 = &b; 866 try expect(ptr[4] == 7); 867 } 868 869 test "array multiplication sets the sentinel - pointer" { 870 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; 871 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 872 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 873 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 874 875 var a = [2:7]u3{ 1, 6 }; 876 const b = &a ** 2; 877 comptime assert(@TypeOf(b) == *[4:7]u3); 878 try expect(b[0] == 1); 879 try expect(b[1] == 6); 880 try expect(b[2] == 1); 881 try expect(b[3] == 6); 882 const ptr: [*]const u3 = b; 883 try expect(ptr[4] == 7); 884 } 885 886 test "comptime assign int to optional int" { 887 comptime { 888 var x: ?i32 = null; 889 x = 2; 890 x.? *= 10; 891 try expectEqual(20, x.?); 892 } 893 } 894 895 test "two comptime calls with array default initialized to undefined" { 896 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO 897 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 898 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 899 900 const S = struct { 901 const A = struct { 902 c: B = B{}, 903 904 pub fn d() void { 905 var f: A = .{}; 906 f.e(); 907 } 908 909 pub fn e(g: A) void { 910 _ = g; 911 } 912 }; 913 914 const B = struct { 915 buffer: [255]u8 = undefined, 916 }; 917 }; 918 919 comptime { 920 S.A.d(); 921 S.A.d(); 922 } 923 } 924 925 test "const type-annotated local initialized with function call has correct type" { 926 const S = struct { 927 fn foo() comptime_int { 928 return 1234; 929 } 930 }; 931 const x: u64 = S.foo(); 932 try expect(@TypeOf(x) == u64); 933 try expect(x == 1234); 934 } 935 936 test "comptime pointer load through elem_ptr" { 937 const S = struct { 938 x: usize, 939 }; 940 941 comptime { 942 var array: [10]S = undefined; 943 for (&array, 0..) |*elem, i| { 944 elem.* = .{ 945 .x = i, 946 }; 947 } 948 var ptr: [*]S = @ptrCast(&array); 949 const x = ptr[0].x; 950 assert(x == 0); 951 ptr += 1; 952 assert(ptr[1].x == 2); 953 } 954 } 955 956 test "debug variable type resolved through indirect zero-bit types" { 957 const T = struct { key: []void }; 958 const slice: []const T = &[_]T{}; 959 _ = slice; 960 } 961 962 test "const local with comptime init through array init" { 963 const E1 = enum { 964 A, 965 pub fn a() void {} 966 }; 967 968 const S = struct { 969 fn declarations(comptime T: type) []const std.builtin.Type.Declaration { 970 return @typeInfo(T).Enum.decls; 971 } 972 }; 973 974 const decls = comptime [_][]const std.builtin.Type.Declaration{ 975 S.declarations(E1), 976 }; 977 978 comptime assert(decls[0][0].name[0] == 'a'); 979 } 980 981 test "closure capture type of runtime-known parameter" { 982 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 983 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 984 985 const S = struct { 986 fn b(c: anytype) !void { 987 const D = struct { c: @TypeOf(c) }; 988 const d: D = .{ .c = c }; 989 try expect(d.c == 1234); 990 } 991 }; 992 var c: i32 = 1234; 993 _ = &c; 994 try S.b(c); 995 } 996 997 test "closure capture type of runtime-known var" { 998 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 999 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 1000 1001 var x: u32 = 1234; 1002 _ = &x; 1003 const S = struct { val: @TypeOf(x + 100) }; 1004 const s: S = .{ .val = x }; 1005 try expect(s.val == 1234); 1006 } 1007 1008 test "comptime break passing through runtime condition converted to runtime break" { 1009 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 1010 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 1011 1012 const S = struct { 1013 fn doTheTest() !void { 1014 var runtime: u8 = 'b'; 1015 _ = &runtime; 1016 inline for ([3]u8{ 'a', 'b', 'c' }) |byte| { 1017 bar(); 1018 if (byte == runtime) { 1019 foo(byte); 1020 break; 1021 } 1022 } 1023 try expect(ok); 1024 try expect(count == 2); 1025 } 1026 var ok = false; 1027 var count: usize = 0; 1028 1029 fn foo(byte: u8) void { 1030 ok = byte == 'b'; 1031 } 1032 1033 fn bar() void { 1034 count += 1; 1035 } 1036 }; 1037 1038 try S.doTheTest(); 1039 } 1040 1041 test "comptime break to outer loop passing through runtime condition converted to runtime break" { 1042 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 1043 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO 1044 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 1045 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 1046 1047 const S = struct { 1048 fn doTheTest() !void { 1049 var runtime: u8 = 'b'; 1050 _ = &runtime; 1051 outer: inline for ([3]u8{ 'A', 'B', 'C' }) |outer_byte| { 1052 inline for ([3]u8{ 'a', 'b', 'c' }) |byte| { 1053 bar(outer_byte); 1054 if (byte == runtime) { 1055 foo(byte); 1056 break :outer; 1057 } 1058 } 1059 } 1060 try expect(ok); 1061 try expect(count == 2); 1062 } 1063 var ok = false; 1064 var count: usize = 0; 1065 1066 fn foo(byte: u8) void { 1067 ok = byte == 'b'; 1068 } 1069 1070 fn bar(byte: u8) void { 1071 _ = byte; 1072 count += 1; 1073 } 1074 }; 1075 1076 try S.doTheTest(); 1077 } 1078 1079 test "comptime break operand passing through runtime condition converted to runtime break" { 1080 const S = struct { 1081 fn doTheTest(runtime: u8) !void { 1082 const result = inline for ([3]u8{ 'a', 'b', 'c' }) |byte| { 1083 if (byte == runtime) { 1084 break runtime; 1085 } 1086 } else 'z'; 1087 try expect(result == 'b'); 1088 } 1089 }; 1090 1091 try S.doTheTest('b'); 1092 try comptime S.doTheTest('b'); 1093 } 1094 1095 test "comptime break operand passing through runtime switch converted to runtime break" { 1096 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 1097 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 1098 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 1099 1100 const S = struct { 1101 fn doTheTest(runtime: u8) !void { 1102 const result = inline for ([3]u8{ 'a', 'b', 'c' }) |byte| { 1103 switch (runtime) { 1104 byte => break runtime, 1105 else => {}, 1106 } 1107 } else 'z'; 1108 try expect(result == 'b'); 1109 } 1110 }; 1111 1112 try S.doTheTest('b'); 1113 try comptime S.doTheTest('b'); 1114 } 1115 1116 test "no dependency loop for alignment of self struct" { 1117 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 1118 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 1119 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 1120 1121 const S = struct { 1122 fn doTheTest() !void { 1123 var a: namespace.A = undefined; 1124 a.d = .{ .g = &buf }; 1125 a.d.g[3] = 42; 1126 a.d.g[3] += 1; 1127 try expect(a.d.g[3] == 43); 1128 } 1129 1130 var buf: [10]u8 align(@alignOf([*]u8)) = undefined; 1131 1132 const namespace = struct { 1133 const B = struct { a: A }; 1134 const A = C(B); 1135 }; 1136 1137 pub fn C(comptime B: type) type { 1138 return struct { 1139 d: D(F) = .{}, 1140 1141 const F = struct { b: B }; 1142 }; 1143 } 1144 1145 pub fn D(comptime F: type) type { 1146 return struct { 1147 g: [*]align(@alignOf(F)) u8 = undefined, 1148 }; 1149 } 1150 }; 1151 try S.doTheTest(); 1152 } 1153 1154 test "no dependency loop for alignment of self bare union" { 1155 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 1156 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 1157 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 1158 1159 const S = struct { 1160 fn doTheTest() !void { 1161 var a: namespace.A = undefined; 1162 a.d = .{ .g = &buf }; 1163 a.d.g[3] = 42; 1164 a.d.g[3] += 1; 1165 try expect(a.d.g[3] == 43); 1166 } 1167 1168 var buf: [10]u8 align(@alignOf([*]u8)) = undefined; 1169 1170 const namespace = struct { 1171 const B = union { a: A, b: void }; 1172 const A = C(B); 1173 }; 1174 1175 pub fn C(comptime B: type) type { 1176 return struct { 1177 d: D(F) = .{}, 1178 1179 const F = struct { b: B }; 1180 }; 1181 } 1182 1183 pub fn D(comptime F: type) type { 1184 return struct { 1185 g: [*]align(@alignOf(F)) u8 = undefined, 1186 }; 1187 } 1188 }; 1189 try S.doTheTest(); 1190 } 1191 1192 test "no dependency loop for alignment of self tagged union" { 1193 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 1194 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 1195 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 1196 1197 const S = struct { 1198 fn doTheTest() !void { 1199 var a: namespace.A = undefined; 1200 a.d = .{ .g = &buf }; 1201 a.d.g[3] = 42; 1202 a.d.g[3] += 1; 1203 try expect(a.d.g[3] == 43); 1204 } 1205 1206 var buf: [10]u8 align(@alignOf([*]u8)) = undefined; 1207 1208 const namespace = struct { 1209 const B = union(enum) { a: A, b: void }; 1210 const A = C(B); 1211 }; 1212 1213 pub fn C(comptime B: type) type { 1214 return struct { 1215 d: D(F) = .{}, 1216 1217 const F = struct { b: B }; 1218 }; 1219 } 1220 1221 pub fn D(comptime F: type) type { 1222 return struct { 1223 g: [*]align(@alignOf(F)) u8 = undefined, 1224 }; 1225 } 1226 }; 1227 try S.doTheTest(); 1228 } 1229 1230 test "equality of pointers to comptime const" { 1231 const a: i32 = undefined; 1232 comptime assert(&a == &a); 1233 } 1234 1235 test "storing an array of type in a field" { 1236 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 1237 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO 1238 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 1239 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; 1240 1241 const S = struct { 1242 fn doTheTest() void { 1243 const foobar = Foobar.foo(); 1244 foo(foobar.str[0..10]); 1245 } 1246 const Foobar = struct { 1247 myTypes: [128]type, 1248 str: [1024]u8, 1249 1250 fn foo() @This() { 1251 comptime var foobar: Foobar = undefined; 1252 foobar.str = [_]u8{'a'} ** 1024; 1253 return foobar; 1254 } 1255 }; 1256 1257 fn foo(arg: anytype) void { 1258 _ = arg; 1259 } 1260 }; 1261 1262 S.doTheTest(); 1263 } 1264 1265 test "pass pointer to field of comptime-only type as a runtime parameter" { 1266 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 1267 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 1268 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; 1269 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 1270 1271 const S = struct { 1272 const Mixed = struct { 1273 T: type, 1274 x: i32, 1275 }; 1276 const bag: Mixed = .{ 1277 .T = bool, 1278 .x = 1234, 1279 }; 1280 1281 var ok = false; 1282 1283 fn doTheTest() !void { 1284 foo(&bag.x); 1285 try expect(ok); 1286 } 1287 1288 fn foo(ptr: *const i32) void { 1289 ok = ptr.* == 1234; 1290 } 1291 }; 1292 try S.doTheTest(); 1293 } 1294 1295 test "comptime write through extern struct reinterpreted as array" { 1296 comptime { 1297 const S = extern struct { 1298 a: u8, 1299 b: u8, 1300 c: u8, 1301 }; 1302 var s: S = undefined; 1303 @as(*[3]u8, @ptrCast(&s))[0] = 1; 1304 @as(*[3]u8, @ptrCast(&s))[1] = 2; 1305 @as(*[3]u8, @ptrCast(&s))[2] = 3; 1306 assert(s.a == 1); 1307 assert(s.b == 2); 1308 assert(s.c == 3); 1309 } 1310 } 1311 1312 test "continue nested in a conditional in an inline for" { 1313 var x: u32 = 1; 1314 inline for ([_]u8{ 1, 2, 3 }) |_| { 1315 if (1 == 1) { 1316 x = 0; 1317 continue; 1318 } 1319 } 1320 try expect(x == 0); 1321 } 1322 1323 test "optional pointer represented as a pointer value" { 1324 comptime { 1325 var val: u8 = 15; 1326 const opt_ptr: ?*u8 = &val; 1327 1328 const payload_ptr = &opt_ptr.?; 1329 try expect(payload_ptr.*.* == 15); 1330 } 1331 } 1332 1333 test "mutate through pointer-like optional at comptime" { 1334 comptime { 1335 var val: u8 = 15; 1336 var opt_ptr: ?*const u8 = &val; 1337 1338 const payload_ptr = &opt_ptr.?; 1339 payload_ptr.* = &@as(u8, 16); 1340 try expect(payload_ptr.*.* == 16); 1341 } 1342 } 1343 1344 test "repeated value is correctly expanded" { 1345 const S = struct { x: [4]i8 = std.mem.zeroes([4]i8) }; 1346 const M = struct { x: [4]S = std.mem.zeroes([4]S) }; 1347 1348 comptime { 1349 var res = M{}; 1350 for (.{ 1, 2, 3 }) |i| res.x[i].x[i] = i; 1351 1352 try expectEqual(M{ .x = .{ 1353 .{ .x = .{ 0, 0, 0, 0 } }, 1354 .{ .x = .{ 0, 1, 0, 0 } }, 1355 .{ .x = .{ 0, 0, 2, 0 } }, 1356 .{ .x = .{ 0, 0, 0, 3 } }, 1357 } }, res); 1358 } 1359 } 1360 1361 test "value in if block is comptime-known" { 1362 const first = blk: { 1363 const s = if (false) "a" else "b"; 1364 break :blk "foo" ++ s; 1365 }; 1366 const second = blk: { 1367 const S = struct { str: []const u8 }; 1368 const s = if (false) S{ .str = "a" } else S{ .str = "b" }; 1369 break :blk "foo" ++ s.str; 1370 }; 1371 comptime assert(std.mem.eql(u8, first, second)); 1372 } 1373 1374 test "lazy sizeof is resolved in division" { 1375 const A = struct { 1376 a: u32, 1377 }; 1378 const a = 2; 1379 try expect(@sizeOf(A) / a == 2); 1380 try expect(@sizeOf(A) - a == 2); 1381 } 1382 1383 test "lazy value is resolved as slice operand" { 1384 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 1385 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO 1386 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 1387 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 1388 1389 const A = struct { a: u32 }; 1390 var a: [512]u64 = undefined; 1391 1392 const ptr1 = a[0..@sizeOf(A)]; 1393 const ptr2 = @as([*]u8, @ptrCast(&a))[0..@sizeOf(A)]; 1394 try expect(@intFromPtr(ptr1) == @intFromPtr(ptr2)); 1395 try expect(ptr1.len == ptr2.len); 1396 } 1397 1398 test "break from inline loop depends on runtime condition" { 1399 const S = struct { 1400 fn foo(a: u8) bool { 1401 return a == 4; 1402 } 1403 }; 1404 const arr = [_]u8{ 1, 2, 3, 4 }; 1405 { 1406 const blk = blk: { 1407 inline for (arr) |val| { 1408 if (S.foo(val)) { 1409 break :blk val; 1410 } 1411 } 1412 return error.TestFailed; 1413 }; 1414 try expect(blk == 4); 1415 } 1416 1417 { 1418 comptime var i = 0; 1419 const blk = blk: { 1420 inline while (i < arr.len) : (i += 1) { 1421 const val = arr[i]; 1422 if (S.foo(val)) { 1423 break :blk val; 1424 } 1425 } 1426 return error.TestFailed; 1427 }; 1428 try expect(blk == 4); 1429 } 1430 } 1431 1432 test "inline for inside a runtime condition" { 1433 var a = false; 1434 _ = &a; 1435 if (a) { 1436 const arr = .{ 1, 2, 3 }; 1437 inline for (arr) |val| { 1438 if (val < 3) continue; 1439 try expect(val == 3); 1440 } 1441 } 1442 } 1443 1444 test "continue in inline for inside a comptime switch" { 1445 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 1446 1447 const arr = .{ 1, 2, 3 }; 1448 var count: u8 = 0; 1449 switch (arr[1]) { 1450 2 => { 1451 inline for (arr) |val| { 1452 if (val == 2) continue; 1453 1454 count += val; 1455 } 1456 }, 1457 else => {}, 1458 } 1459 try expect(count == 4); 1460 } 1461 1462 test "length of global array is determinable at comptime" { 1463 const S = struct { 1464 var bytes: [1024]u8 = undefined; 1465 1466 fn foo() !void { 1467 try std.testing.expect(bytes.len == 1024); 1468 } 1469 }; 1470 try comptime S.foo(); 1471 } 1472 1473 test "continue nested inline for loop" { 1474 // TODO: https://github.com/ziglang/zig/issues/13175 1475 if (true) return error.SkipZigTest; 1476 1477 var a: u8 = 0; 1478 loop: inline for ([_]u8{ 1, 2 }) |x| { 1479 inline for ([_]u8{1}) |y| { 1480 if (x == y) { 1481 continue :loop; 1482 } 1483 } 1484 a = x; 1485 try expect(x == 2); 1486 } 1487 try expect(a == 2); 1488 } 1489 1490 test "continue nested inline for loop in named block expr" { 1491 // TODO: https://github.com/ziglang/zig/issues/13175 1492 if (true) return error.SkipZigTest; 1493 1494 var a: u8 = 0; 1495 loop: inline for ([_]u8{ 1, 2 }) |x| { 1496 a = b: { 1497 inline for ([_]u8{1}) |y| { 1498 if (x == y) { 1499 continue :loop; 1500 } 1501 } 1502 break :b x; 1503 }; 1504 try expect(x == 2); 1505 } 1506 try expect(a == 2); 1507 } 1508 1509 test "x and false is comptime-known false" { 1510 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 1511 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 1512 1513 const T = struct { 1514 var x: u32 = 0; 1515 1516 fn foo() bool { 1517 x += 1; // Observable side-effect 1518 return true; 1519 } 1520 }; 1521 1522 if (T.foo() and T.foo() and false and T.foo()) { 1523 @compileError("Condition should be comptime-known false"); 1524 } 1525 try expect(T.x == 2); 1526 1527 T.x = 0; 1528 if (T.foo() and T.foo() and b: { 1529 _ = T.foo(); 1530 break :b false; 1531 } and T.foo()) { 1532 @compileError("Condition should be comptime-known false"); 1533 } 1534 try expect(T.x == 3); 1535 } 1536 1537 test "x or true is comptime-known true" { 1538 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 1539 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 1540 1541 const T = struct { 1542 var x: u32 = 0; 1543 1544 fn foo() bool { 1545 x += 1; // Observable side-effect 1546 return false; 1547 } 1548 }; 1549 1550 if (!(T.foo() or T.foo() or true or T.foo())) { 1551 @compileError("Condition should be comptime-known false"); 1552 } 1553 try expect(T.x == 2); 1554 1555 T.x = 0; 1556 if (!(T.foo() or T.foo() or b: { 1557 _ = T.foo(); 1558 break :b true; 1559 } or T.foo())) { 1560 @compileError("Condition should be comptime-known false"); 1561 } 1562 try expect(T.x == 3); 1563 } 1564 1565 test "non-optional and optional array elements concatenated" { 1566 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 1567 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO 1568 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 1569 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 1570 1571 const array = [1]u8{'A'} ++ [1]?u8{null}; 1572 var index: usize = 0; 1573 _ = &index; 1574 try expect(array[index].? == 'A'); 1575 } 1576 1577 test "inline call in @TypeOf inherits is_inline property" { 1578 const S = struct { 1579 inline fn doNothing() void {} 1580 const T = @TypeOf(doNothing()); 1581 }; 1582 try expect(S.T == void); 1583 } 1584 1585 test "comptime function turns function value to function pointer" { 1586 const S = struct { 1587 fn fnPtr(function: anytype) *const @TypeOf(function) { 1588 return &function; 1589 } 1590 fn Nil() u8 { 1591 return 0; 1592 } 1593 const foo = &[_]*const fn () u8{ 1594 fnPtr(Nil), 1595 }; 1596 }; 1597 comptime assert(S.foo[0] == &S.Nil); 1598 } 1599 1600 test "container level const and var have unique addresses" { 1601 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 1602 1603 const S = struct { 1604 x: i32, 1605 y: i32, 1606 const c = @This(){ .x = 1, .y = 1 }; 1607 var v: @This() = c; 1608 }; 1609 var p = &S.c; 1610 _ = &p; 1611 try std.testing.expect(p.x == S.c.x); 1612 S.v.x = 2; 1613 try std.testing.expect(p.x == S.c.x); 1614 } 1615 1616 test "break from block results in type" { 1617 const S = struct { 1618 fn NewType(comptime T: type) type { 1619 const Padded = blk: { 1620 if (@sizeOf(T) <= @sizeOf(usize)) break :blk void; 1621 break :blk T; 1622 }; 1623 1624 return Padded; 1625 } 1626 }; 1627 const T = S.NewType(usize); 1628 try expect(T == void); 1629 } 1630 1631 test "struct in comptime false branch is not evaluated" { 1632 const S = struct { 1633 const comptime_const = 2; 1634 fn some(comptime V: type) type { 1635 return switch (comptime_const) { 1636 3 => struct { a: V.foo }, 1637 2 => V, 1638 else => unreachable, 1639 }; 1640 } 1641 }; 1642 try expect(S.some(u32) == u32); 1643 } 1644 1645 test "result of nested switch assigned to variable" { 1646 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 1647 1648 var zds: u32 = 0; 1649 zds = switch (zds) { 1650 0 => switch (zds) { 1651 0...0 => 1234, 1652 1...1 => zds, 1653 2 => zds, 1654 else => return, 1655 }, 1656 else => zds, 1657 }; 1658 try expect(zds == 1234); 1659 } 1660 1661 test "inline for loop of functions returning error unions" { 1662 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 1663 1664 const T1 = struct { 1665 fn v() error{}!usize { 1666 return 1; 1667 } 1668 }; 1669 const T2 = struct { 1670 fn v() error{Error}!usize { 1671 return 2; 1672 } 1673 }; 1674 var a: usize = 0; 1675 inline for (.{ T1, T2 }) |T| { 1676 a += try T.v(); 1677 } 1678 try expect(a == 3); 1679 } 1680 1681 test "if inside a switch" { 1682 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 1683 1684 var condition = true; 1685 var wave_type: u32 = 0; 1686 _ = .{ &condition, &wave_type }; 1687 const sample: i32 = switch (wave_type) { 1688 0 => if (condition) 2 else 3, 1689 1 => 100, 1690 2 => 200, 1691 3 => 300, 1692 else => unreachable, 1693 }; 1694 try expect(sample == 2); 1695 } 1696 1697 test "function has correct return type when previous return is casted to smaller type" { 1698 const S = struct { 1699 fn foo(b: bool) u16 { 1700 if (b) return @as(u8, 0xFF); 1701 return 0xFFFF; 1702 } 1703 }; 1704 try expect(S.foo(true) == 0xFF); 1705 } 1706 1707 test "early exit in container level const" { 1708 const S = struct { 1709 const value = blk: { 1710 if (true) { 1711 break :blk @as(u32, 1); 1712 } 1713 break :blk @as(u32, 0); 1714 }; 1715 }; 1716 try expect(S.value == 1); 1717 } 1718 1719 test "@inComptime" { 1720 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 1721 1722 const S = struct { 1723 fn inComptime() bool { 1724 return @inComptime(); 1725 } 1726 }; 1727 try expectEqual(false, @inComptime()); 1728 try expectEqual(true, comptime @inComptime()); 1729 try expectEqual(false, S.inComptime()); 1730 try expectEqual(true, comptime S.inComptime()); 1731 } 1732 1733 // comptime partial array assign 1734 comptime { 1735 var foo = [3]u8{ 0x55, 0x55, 0x55 }; 1736 var bar = [2]u8{ 1, 2 }; 1737 _ = .{ &foo, &bar }; 1738 foo[0..2].* = bar; 1739 assert(foo[0] == 1); 1740 assert(foo[1] == 2); 1741 assert(foo[2] == 0x55); 1742 } 1743 1744 test "const with allocation before result is comptime-known" { 1745 const x = blk: { 1746 const y = [1]u32{2}; 1747 _ = y; 1748 break :blk [1]u32{42}; 1749 }; 1750 comptime assert(@TypeOf(x) == [1]u32); 1751 comptime assert(x[0] == 42); 1752 } 1753 1754 test "const with specified type initialized with typed array is comptime-known" { 1755 const x: [3]u16 = [3]u16{ 1, 2, 3 }; 1756 comptime assert(@TypeOf(x) == [3]u16); 1757 comptime assert(x[0] == 1); 1758 comptime assert(x[1] == 2); 1759 comptime assert(x[2] == 3); 1760 } 1761 1762 test "block with comptime-known result but possible runtime exit is comptime-known" { 1763 var t: bool = true; 1764 _ = &t; 1765 1766 const a: comptime_int = a: { 1767 if (!t) return error.TestFailed; 1768 break :a 123; 1769 }; 1770 1771 const b: comptime_int = b: { 1772 if (t) break :b 456; 1773 return error.TestFailed; 1774 }; 1775 1776 comptime assert(a == 123); 1777 comptime assert(b == 456); 1778 }