| author | |
| committer | |
| log | 9b665a59f27b4de0ae648438617b0a1a08a620c1 |
| tree | bc0cace44659812c5675c985bba382cb8180b80f |
| parent | 94780f7cd19701965d9417e8d90dc6ea4d9285be |
| parent | e0b6140009eb3e2e53b8c90fe3973d80991bd9b8 |
| signature | Signed by PGP key 4AEE18F83AFDEB23 |
add tests for fixed stage1 bugs20 files changed, 388 insertions(+), 9 deletions(-)
doc/langref.html.in+3-3| ... | @@ -12075,7 +12075,7 @@ ContainerDeclarations | ... | @@ -12075,7 +12075,7 @@ ContainerDeclarations |
| 12075 | / doc_comment? KEYWORD_pub? Decl ContainerDeclarations | 12075 | / doc_comment? KEYWORD_pub? Decl ContainerDeclarations |
| 12076 | / | 12076 | / |
| 12077 | 12077 | ||
| 12078 | TestDecl <- KEYWORD_test STRINGLITERALSINGLE? Block | 12078 | TestDecl <- KEYWORD_test (STRINGLITERALSINGLE / IDENTIFIER)? Block |
| 12079 | 12079 | ||
| 12080 | ComptimeDecl <- KEYWORD_comptime Block | 12080 | ComptimeDecl <- KEYWORD_comptime Block |
| 12081 | 12081 | ||
| ... | @@ -12089,7 +12089,7 @@ FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? AddrSpa | ... | @@ -12089,7 +12089,7 @@ FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? AddrSpa |
| 12089 | VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? AddrSpace? LinkSection? (EQUAL Expr)? SEMICOLON | 12089 | VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? AddrSpace? LinkSection? (EQUAL Expr)? SEMICOLON |
| 12090 | 12090 | ||
| 12091 | ContainerField | 12091 | ContainerField |
| 12092 | <- doc_comment? KEYWORD_comptime? IDENTIFIER (COLON TypeExpr ByteAlign?)? (EQUAL Expr)? | 12092 | <- doc_comment? KEYWORD_comptime? IDENTIFIER (COLON TypeExpr)? ByteAlign? (EQUAL Expr)? |
| 12093 | / doc_comment? KEYWORD_comptime? (IDENTIFIER COLON)? !KEYWORD_fn TypeExpr ByteAlign? (EQUAL Expr)? | 12093 | / doc_comment? KEYWORD_comptime? (IDENTIFIER COLON)? !KEYWORD_fn TypeExpr ByteAlign? (EQUAL Expr)? |
| 12094 | 12094 | ||
| 12095 | # *** Block Level *** | 12095 | # *** Block Level *** |
| ... | @@ -12360,7 +12360,7 @@ PrefixTypeOp | ... | @@ -12360,7 +12360,7 @@ PrefixTypeOp |
| 12360 | <- QUESTIONMARK | 12360 | <- QUESTIONMARK |
| 12361 | / KEYWORD_anyframe MINUSRARROW | 12361 | / KEYWORD_anyframe MINUSRARROW |
| 12362 | / SliceTypeStart (ByteAlign / AddrSpace / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)* | 12362 | / SliceTypeStart (ByteAlign / AddrSpace / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)* |
| 12363 | / PtrTypeStart (AddrSpace / KEYWORD_align LPAREN Expr (COLON INTEGER COLON INTEGER)? RPAREN / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)* | 12363 | / PtrTypeStart (AddrSpace / KEYWORD_align LPAREN Expr (COLON Expr COLON Expr)? RPAREN / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)* |
| 12364 | / ArrayTypeStart | 12364 | / ArrayTypeStart |
| 12365 | 12365 | ||
| 12366 | SuffixOp | 12366 | SuffixOp |
lib/std/array_list.zig+17| ... | @@ -1604,3 +1604,20 @@ test "std.ArrayList(u0)" { | ... | @@ -1604,3 +1604,20 @@ test "std.ArrayList(u0)" { |
| 1604 | } | 1604 | } |
| 1605 | try testing.expectEqual(count, 3); | 1605 | try testing.expectEqual(count, 3); |
| 1606 | } | 1606 | } |
| 1607 | |||
| 1608 | test "std.ArrayList(?u32).popOrNull()" { | ||
| 1609 | const a = testing.allocator; | ||
| 1610 | |||
| 1611 | var list = ArrayList(?u32).init(a); | ||
| 1612 | defer list.deinit(); | ||
| 1613 | |||
| 1614 | try list.append(null); | ||
| 1615 | try list.append(1); | ||
| 1616 | try list.append(2); | ||
| 1617 | try testing.expectEqual(list.items.len, 3); | ||
| 1618 | |||
| 1619 | try testing.expect(list.popOrNull().? == @as(u32, 2)); | ||
| 1620 | try testing.expect(list.popOrNull().? == @as(u32, 1)); | ||
| 1621 | try testing.expect(list.popOrNull().? == null); | ||
| 1622 | try testing.expect(list.popOrNull() == null); | ||
| 1623 | } |
lib/std/zig/parse.zig+1-1| ... | @@ -1595,7 +1595,7 @@ const Parser = struct { | ... | @@ -1595,7 +1595,7 @@ const Parser = struct { |
| 1595 | /// <- QUESTIONMARK | 1595 | /// <- QUESTIONMARK |
| 1596 | /// / KEYWORD_anyframe MINUSRARROW | 1596 | /// / KEYWORD_anyframe MINUSRARROW |
| 1597 | /// / SliceTypeStart (ByteAlign / AddrSpace / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)* | 1597 | /// / SliceTypeStart (ByteAlign / AddrSpace / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)* |
| 1598 | /// / PtrTypeStart (AddrSpace / KEYWORD_align LPAREN Expr (COLON INTEGER COLON INTEGER)? RPAREN / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)* | 1598 | /// / PtrTypeStart (AddrSpace / KEYWORD_align LPAREN Expr (COLON Expr COLON Expr)? RPAREN / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)* |
| 1599 | /// / ArrayTypeStart | 1599 | /// / ArrayTypeStart |
| 1600 | /// SliceTypeStart <- LBRACKET (COLON Expr)? RBRACKET | 1600 | /// SliceTypeStart <- LBRACKET (COLON Expr)? RBRACKET |
| 1601 | /// PtrTypeStart | 1601 | /// PtrTypeStart |
src/AstGen.zig+2-2| ... | @@ -3365,7 +3365,7 @@ fn ptrType( | ... | @@ -3365,7 +3365,7 @@ fn ptrType( |
| 3365 | var trailing_count: u32 = 0; | 3365 | var trailing_count: u32 = 0; |
| 3366 | 3366 | ||
| 3367 | if (ptr_info.ast.sentinel != 0) { | 3367 | if (ptr_info.ast.sentinel != 0) { |
| 3368 | sentinel_ref = try expr(gz, scope, .{ .rl = .{ .ty = elem_type } }, ptr_info.ast.sentinel); | 3368 | sentinel_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, ptr_info.ast.sentinel); |
| 3369 | trailing_count += 1; | 3369 | trailing_count += 1; |
| 3370 | } | 3370 | } |
| 3371 | if (ptr_info.ast.align_node != 0) { | 3371 | if (ptr_info.ast.align_node != 0) { |
| ... | @@ -3468,7 +3468,7 @@ fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node. | ... | @@ -3468,7 +3468,7 @@ fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node. |
| 3468 | } | 3468 | } |
| 3469 | const len = try reachableExpr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, len_node, node); | 3469 | const len = try reachableExpr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, len_node, node); |
| 3470 | const elem_type = try typeExpr(gz, scope, extra.elem_type); | 3470 | const elem_type = try typeExpr(gz, scope, extra.elem_type); |
| 3471 | const sentinel = try reachableExpr(gz, scope, .{ .rl = .{ .coerced_ty = elem_type } }, extra.sentinel, node); | 3471 | const sentinel = try reachableExprComptime(gz, scope, .{ .rl = .{ .coerced_ty = elem_type } }, extra.sentinel, node, true); |
| 3472 | 3472 | ||
| 3473 | const result = try gz.addPlNode(.array_type_sentinel, node, Zir.Inst.ArrayTypeSentinel{ | 3473 | const result = try gz.addPlNode(.array_type_sentinel, node, Zir.Inst.ArrayTypeSentinel{ |
| 3474 | .len = len, | 3474 | .len = len, |
src/type.zig+6-1| ... | @@ -2195,7 +2195,12 @@ pub const Type = extern union { | ... | @@ -2195,7 +2195,12 @@ pub const Type = extern union { |
| 2195 | .Slice => try writer.writeAll("[]"), | 2195 | .Slice => try writer.writeAll("[]"), |
| 2196 | } | 2196 | } |
| 2197 | if (info.@"align" != 0 or info.host_size != 0 or info.vector_index != .none) { | 2197 | if (info.@"align" != 0 or info.host_size != 0 or info.vector_index != .none) { |
| 2198 | try writer.print("align({d}", .{info.@"align"}); | 2198 | if (info.@"align" != 0) { |
| 2199 | try writer.print("align({d}", .{info.@"align"}); | ||
| 2200 | } else { | ||
| 2201 | const alignment = info.pointee_type.abiAlignment(mod.getTarget()); | ||
| 2202 | try writer.print("align({d}", .{alignment}); | ||
| 2203 | } | ||
| 2199 | 2204 | ||
| 2200 | if (info.bit_offset != 0 or info.host_size != 0) { | 2205 | if (info.bit_offset != 0 or info.host_size != 0) { |
| 2201 | try writer.print(":{d}:{d}", .{ info.bit_offset, info.host_size }); | 2206 | try writer.print(":{d}:{d}", .{ info.bit_offset, info.host_size }); |
test/behavior/cast.zig+10| ... | @@ -1518,3 +1518,13 @@ test "bitcast packed struct with u0" { | ... | @@ -1518,3 +1518,13 @@ test "bitcast packed struct with u0" { |
| 1518 | const i = @bitCast(u2, s); | 1518 | const i = @bitCast(u2, s); |
| 1519 | try expect(i == 2); | 1519 | try expect(i == 2); |
| 1520 | } | 1520 | } |
| 1521 | |||
| 1522 | test "optional pointer coerced to optional allowzero pointer" { | ||
| 1523 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | ||
| 1524 | |||
| 1525 | var p: ?*u32 = undefined; | ||
| 1526 | var q: ?*allowzero u32 = undefined; | ||
| 1527 | p = @intToPtr(*u32, 4); | ||
| 1528 | q = p; | ||
| 1529 | try expect(@ptrToInt(q.?) == 4); | ||
| 1530 | } |
test/behavior/eval.zig+74| ... | @@ -1547,3 +1547,77 @@ test "comptime function turns function value to function pointer" { | ... | @@ -1547,3 +1547,77 @@ test "comptime function turns function value to function pointer" { |
| 1547 | }; | 1547 | }; |
| 1548 | comptime try expect(S.foo[0] == &S.Nil); | 1548 | comptime try expect(S.foo[0] == &S.Nil); |
| 1549 | } | 1549 | } |
| 1550 | |||
| 1551 | test "container level const and var have unique addresses" { | ||
| 1552 | const S = struct { | ||
| 1553 | x: i32, | ||
| 1554 | y: i32, | ||
| 1555 | const c = @This(){ .x = 1, .y = 1 }; | ||
| 1556 | var v: @This() = c; | ||
| 1557 | }; | ||
| 1558 | var p = &S.c; | ||
| 1559 | try std.testing.expect(p.x == S.c.x); | ||
| 1560 | S.v.x = 2; | ||
| 1561 | try std.testing.expect(p.x == S.c.x); | ||
| 1562 | } | ||
| 1563 | |||
| 1564 | test "break from block results in type" { | ||
| 1565 | const S = struct { | ||
| 1566 | fn NewType(comptime T: type) type { | ||
| 1567 | const Padded = blk: { | ||
| 1568 | if (@sizeOf(T) <= @sizeOf(usize)) break :blk void; | ||
| 1569 | break :blk T; | ||
| 1570 | }; | ||
| 1571 | |||
| 1572 | return Padded; | ||
| 1573 | } | ||
| 1574 | }; | ||
| 1575 | const T = S.NewType(usize); | ||
| 1576 | try expect(T == void); | ||
| 1577 | } | ||
| 1578 | |||
| 1579 | test "struct in comptime false branch is not evaluated" { | ||
| 1580 | const S = struct { | ||
| 1581 | const comptime_const = 2; | ||
| 1582 | fn some(comptime V: type) type { | ||
| 1583 | return switch (comptime_const) { | ||
| 1584 | 3 => struct { a: V.foo }, | ||
| 1585 | 2 => V, | ||
| 1586 | else => unreachable, | ||
| 1587 | }; | ||
| 1588 | } | ||
| 1589 | }; | ||
| 1590 | try expect(S.some(u32) == u32); | ||
| 1591 | } | ||
| 1592 | |||
| 1593 | test "result of nested switch assigned to variable" { | ||
| 1594 | var zds: u32 = 0; | ||
| 1595 | zds = switch (zds) { | ||
| 1596 | 0 => switch (zds) { | ||
| 1597 | 0...0 => 1234, | ||
| 1598 | 1...1 => zds, | ||
| 1599 | 2 => zds, | ||
| 1600 | else => return, | ||
| 1601 | }, | ||
| 1602 | else => zds, | ||
| 1603 | }; | ||
| 1604 | try expect(zds == 1234); | ||
| 1605 | } | ||
| 1606 | |||
| 1607 | test "inline for loop of functions returning error unions" { | ||
| 1608 | const T1 = struct { | ||
| 1609 | fn v() error{}!usize { | ||
| 1610 | return 1; | ||
| 1611 | } | ||
| 1612 | }; | ||
| 1613 | const T2 = struct { | ||
| 1614 | fn v() error{Error}!usize { | ||
| 1615 | return 2; | ||
| 1616 | } | ||
| 1617 | }; | ||
| 1618 | var a: usize = 0; | ||
| 1619 | inline for (.{ T1, T2 }) |T| { | ||
| 1620 | a += try T.v(); | ||
| 1621 | } | ||
| 1622 | try expect(a == 3); | ||
| 1623 | } |
test/behavior/for.zig+22| ... | @@ -227,3 +227,25 @@ test "else continue outer for" { | ... | @@ -227,3 +227,25 @@ test "else continue outer for" { |
| 227 | } else continue; | 227 | } else continue; |
| 228 | } | 228 | } |
| 229 | } | 229 | } |
| 230 | |||
| 231 | test "for loop with else branch" { | ||
| 232 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | ||
| 233 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | ||
| 234 | |||
| 235 | { | ||
| 236 | var x = [_]u32{ 1, 2 }; | ||
| 237 | const q = for (x) |y| { | ||
| 238 | if ((y & 1) != 0) continue; | ||
| 239 | break y * 2; | ||
| 240 | } else @as(u32, 1); | ||
| 241 | try expect(q == 4); | ||
| 242 | } | ||
| 243 | { | ||
| 244 | var x = [_]u32{ 1, 2 }; | ||
| 245 | const q = for (x) |y| { | ||
| 246 | if ((y & 1) != 0) continue; | ||
| 247 | break y * 2; | ||
| 248 | } else @panic(""); | ||
| 249 | try expect(q == 4); | ||
| 250 | } | ||
| 251 | } |
test/behavior/optional.zig+43| ... | @@ -448,3 +448,46 @@ test "Optional slice size is optimized" { | ... | @@ -448,3 +448,46 @@ test "Optional slice size is optimized" { |
| 448 | a = "hello"; | 448 | a = "hello"; |
| 449 | try expectEqualStrings(a.?, "hello"); | 449 | try expectEqualStrings(a.?, "hello"); |
| 450 | } | 450 | } |
| 451 | |||
| 452 | test "peer type resolution in nested if expressions" { | ||
| 453 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 454 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | ||
| 455 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 456 | |||
| 457 | const Thing = struct { n: i32 }; | ||
| 458 | var a = false; | ||
| 459 | var b = false; | ||
| 460 | |||
| 461 | var result1 = if (a) | ||
| 462 | Thing{ .n = 1 } | ||
| 463 | else | ||
| 464 | null; | ||
| 465 | try expect(result1 == null); | ||
| 466 | try expect(@TypeOf(result1) == ?Thing); | ||
| 467 | |||
| 468 | var result2 = if (a) | ||
| 469 | Thing{ .n = 0 } | ||
| 470 | else if (b) | ||
| 471 | Thing{ .n = 1 } | ||
| 472 | else | ||
| 473 | null; | ||
| 474 | try expect(result2 == null); | ||
| 475 | try expect(@TypeOf(result2) == ?Thing); | ||
| 476 | } | ||
| 477 | |||
| 478 | test "cast slice to const slice nested in error union and optional" { | ||
| 479 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 480 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | ||
| 481 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 482 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | ||
| 483 | |||
| 484 | const S = struct { | ||
| 485 | fn inner() !?[]u8 { | ||
| 486 | return error.Foo; | ||
| 487 | } | ||
| 488 | fn outer() !?[]const u8 { | ||
| 489 | return inner(); | ||
| 490 | } | ||
| 491 | }; | ||
| 492 | try std.testing.expectError(error.Foo, S.outer()); | ||
| 493 | } |
test/behavior/packed-struct.zig+21| ... | @@ -567,3 +567,24 @@ test "packed struct passed to callconv(.C) function" { | ... | @@ -567,3 +567,24 @@ test "packed struct passed to callconv(.C) function" { |
| 567 | }, 5, 4, 3, 2, 1); | 567 | }, 5, 4, 3, 2, 1); |
| 568 | try expect(result); | 568 | try expect(result); |
| 569 | } | 569 | } |
| 570 | |||
| 571 | test "overaligned pointer to packed struct" { | ||
| 572 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 573 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | ||
| 574 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 575 | |||
| 576 | const S = packed struct { a: u32, b: u32 }; | ||
| 577 | var foo: S align(4) = .{ .a = 123, .b = 456 }; | ||
| 578 | const ptr: *align(4) S = &foo; | ||
| 579 | switch (comptime builtin.cpu.arch.endian()) { | ||
| 580 | .Little => { | ||
| 581 | const ptr_to_b: *u32 = &ptr.b; | ||
| 582 | try expect(ptr_to_b.* == 456); | ||
| 583 | }, | ||
| 584 | .Big => { | ||
| 585 | // Byte aligned packed struct field pointers have not been implemented yet. | ||
| 586 | const ptr_to_a: *align(4:0:8) u32 = &ptr.a; | ||
| 587 | try expect(ptr_to_a.* == 123); | ||
| 588 | }, | ||
| 589 | } | ||
| 590 | } |
test/behavior/ptrcast.zig+12| ... | @@ -270,3 +270,15 @@ test "comptime @ptrCast a subset of an array, then write through it" { | ... | @@ -270,3 +270,15 @@ test "comptime @ptrCast a subset of an array, then write through it" { |
| 270 | std.mem.copy(u8, buff[4..], "abcdef"); | 270 | std.mem.copy(u8, buff[4..], "abcdef"); |
| 271 | } | 271 | } |
| 272 | } | 272 | } |
| 273 | |||
| 274 | test "@ptrCast undefined value at comptime" { | ||
| 275 | const S = struct { | ||
| 276 | fn transmute(comptime T: type, comptime U: type, value: T) U { | ||
| 277 | return @ptrCast(*const U, &value).*; | ||
| 278 | } | ||
| 279 | }; | ||
| 280 | comptime { | ||
| 281 | var x = S.transmute([]u8, i32, undefined); | ||
| 282 | _ = x; | ||
| 283 | } | ||
| 284 | } |
test/behavior/slice.zig+31| ... | @@ -706,3 +706,34 @@ test "global slice field access" { | ... | @@ -706,3 +706,34 @@ test "global slice field access" { |
| 706 | S.slice.len -= 2; | 706 | S.slice.len -= 2; |
| 707 | try expectEqualStrings("trin", S.slice); | 707 | try expectEqualStrings("trin", S.slice); |
| 708 | } | 708 | } |
| 709 | |||
| 710 | test "slice of void" { | ||
| 711 | var n: usize = 10; | ||
| 712 | var arr: [12]void = undefined; | ||
| 713 | const slice = @as([]void, &arr)[0..n]; | ||
| 714 | try expect(slice.len == n); | ||
| 715 | } | ||
| 716 | |||
| 717 | test "slice with dereferenced value" { | ||
| 718 | var a: usize = 0; | ||
| 719 | var idx: *usize = &a; | ||
| 720 | _ = blk: { | ||
| 721 | var array = [_]u8{}; | ||
| 722 | break :blk array[idx.*..]; | ||
| 723 | }; | ||
| 724 | const res = blk: { | ||
| 725 | var array = [_]u8{}; | ||
| 726 | break :blk array[idx.*..]; | ||
| 727 | }; | ||
| 728 | try expect(res.len == 0); | ||
| 729 | } | ||
| 730 | |||
| 731 | test "empty slice ptr is non null" { | ||
| 732 | if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; // TODO | ||
| 733 | if (builtin.zig_backend == .stage2_x86_64 and (builtin.os.tag == .macos or builtin.os.tag == .windows)) return error.SkipZigTest; // TODO | ||
| 734 | |||
| 735 | const empty_slice: []u8 = &[_]u8{}; | ||
| 736 | const p: [*]u8 = empty_slice.ptr + 0; | ||
| 737 | const t = @ptrCast([*]i8, p); | ||
| 738 | try expect(@ptrToInt(t) == @ptrToInt(empty_slice.ptr)); | ||
| 739 | } |
test/behavior/struct.zig+37| ... | @@ -1458,3 +1458,40 @@ test "struct has only one reference" { | ... | @@ -1458,3 +1458,40 @@ test "struct has only one reference" { |
| 1458 | try expectEqual(@sizeOf(struct { x: u16 }), S.optionalComptimeIntParam(@sizeOf(struct { x: u16 }))); | 1458 | try expectEqual(@sizeOf(struct { x: u16 }), S.optionalComptimeIntParam(@sizeOf(struct { x: u16 }))); |
| 1459 | try expectEqual(@sizeOf(struct { x: u32 }), S.errorUnionComptimeIntParam(@sizeOf(struct { x: u32 }))); | 1459 | try expectEqual(@sizeOf(struct { x: u32 }), S.errorUnionComptimeIntParam(@sizeOf(struct { x: u32 }))); |
| 1460 | } | 1460 | } |
| 1461 | |||
| 1462 | test "no dependency loop on pointer to optional struct" { | ||
| 1463 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 1464 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | ||
| 1465 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | ||
| 1466 | |||
| 1467 | const S = struct { | ||
| 1468 | const A = struct { b: B }; | ||
| 1469 | const B = struct { a: *?A }; | ||
| 1470 | }; | ||
| 1471 | var a1: ?S.A = null; | ||
| 1472 | var a2: ?S.A = .{ .b = .{ .a = &a1 } }; | ||
| 1473 | a1 = .{ .b = .{ .a = &a2 } }; | ||
| 1474 | |||
| 1475 | try expect(a1.?.b.a == &a2); | ||
| 1476 | try expect(a2.?.b.a == &a1); | ||
| 1477 | } | ||
| 1478 | |||
| 1479 | test "discarded struct initialization works as expected" { | ||
| 1480 | const S = struct { a: u32 }; | ||
| 1481 | _ = S{ .a = 1 }; | ||
| 1482 | } | ||
| 1483 | |||
| 1484 | test "function pointer in struct returns the struct" { | ||
| 1485 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | ||
| 1486 | |||
| 1487 | const A = struct { | ||
| 1488 | const A = @This(); | ||
| 1489 | f: *const fn () A, | ||
| 1490 | |||
| 1491 | fn f() A { | ||
| 1492 | return .{ .f = f }; | ||
| 1493 | } | ||
| 1494 | }; | ||
| 1495 | var a = A.f(); | ||
| 1496 | try expect(a.f == A.f); | ||
| 1497 | } |
test/behavior/tuple.zig+26| ... | @@ -2,6 +2,7 @@ const builtin = @import("builtin"); | ... | @@ -2,6 +2,7 @@ const builtin = @import("builtin"); |
| 2 | const std = @import("std"); | 2 | const std = @import("std"); |
| 3 | const testing = std.testing; | 3 | const testing = std.testing; |
| 4 | const expect = testing.expect; | 4 | const expect = testing.expect; |
| 5 | const expectEqualStrings = std.testing.expectEqualStrings; | ||
| 5 | 6 | ||
| 6 | test "tuple concatenation" { | 7 | test "tuple concatenation" { |
| 7 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 8 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| ... | @@ -340,3 +341,28 @@ test "tuple type with void field and a runtime field" { | ... | @@ -340,3 +341,28 @@ test "tuple type with void field and a runtime field" { |
| 340 | var t: T = .{ 5, {} }; | 341 | var t: T = .{ 5, {} }; |
| 341 | try expect(t[0] == 5); | 342 | try expect(t[0] == 5); |
| 342 | } | 343 | } |
| 344 | |||
| 345 | test "branching inside tuple literal" { | ||
| 346 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | ||
| 347 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | ||
| 348 | |||
| 349 | const S = struct { | ||
| 350 | fn foo(a: anytype) !void { | ||
| 351 | try expect(a[0] == 1234); | ||
| 352 | } | ||
| 353 | }; | ||
| 354 | var a = false; | ||
| 355 | try S.foo(.{if (a) @as(u32, 5678) else @as(u32, 1234)}); | ||
| 356 | } | ||
| 357 | |||
| 358 | test "tuple initialized with a runtime known value" { | ||
| 359 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 360 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | ||
| 361 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 362 | |||
| 363 | const E = union(enum) { e: []const u8 }; | ||
| 364 | const W = union(enum) { w: E }; | ||
| 365 | var e = E{ .e = "test" }; | ||
| 366 | const w = .{W{ .w = e }}; | ||
| 367 | try expectEqualStrings(w[0].w.e, "test"); | ||
| 368 | } |
test/behavior/union.zig+31| ... | @@ -1471,3 +1471,34 @@ test "union int tag type is properly managed" { | ... | @@ -1471,3 +1471,34 @@ test "union int tag type is properly managed" { |
| 1471 | }; | 1471 | }; |
| 1472 | try expect(@sizeOf(Bar) + 1 == 3); | 1472 | try expect(@sizeOf(Bar) + 1 == 3); |
| 1473 | } | 1473 | } |
| 1474 | |||
| 1475 | test "no dependency loop when function pointer in union returns the union" { | ||
| 1476 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | ||
| 1477 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | ||
| 1478 | |||
| 1479 | const U = union(enum) { | ||
| 1480 | const U = @This(); | ||
| 1481 | a: u8, | ||
| 1482 | b: *const fn (x: U) void, | ||
| 1483 | c: *const fn (x: U) U, | ||
| 1484 | d: *const fn (x: u8) U, | ||
| 1485 | fn foo(x: u8) U { | ||
| 1486 | return .{ .a = x }; | ||
| 1487 | } | ||
| 1488 | }; | ||
| 1489 | var b: U = .{ .d = U.foo }; | ||
| 1490 | try expect(b.d(2).a == 2); | ||
| 1491 | } | ||
| 1492 | |||
| 1493 | test "union reassignment can use previous value" { | ||
| 1494 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | ||
| 1495 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | ||
| 1496 | |||
| 1497 | const U = union { | ||
| 1498 | a: u32, | ||
| 1499 | b: u32, | ||
| 1500 | }; | ||
| 1501 | var a = U{ .a = 32 }; | ||
| 1502 | a = U{ .b = a.a }; | ||
| 1503 | try expect(a.b == 32); | ||
| 1504 | } |
test/cases/compile_errors/casting_bit_offset_pointer_to_regular_pointer.zig+1-1| ... | @@ -18,7 +18,7 @@ export fn entry() usize { return @sizeOf(@TypeOf(&foo)); } | ... | @@ -18,7 +18,7 @@ export fn entry() usize { return @sizeOf(@TypeOf(&foo)); } |
| 18 | // backend=stage2 | 18 | // backend=stage2 |
| 19 | // target=native | 19 | // target=native |
| 20 | // | 20 | // |
| 21 | // :8:16: error: expected type '*const u3', found '*align(0:3:1) const u3' | 21 | // :8:16: error: expected type '*const u3', found '*align(1:3:1) const u3' |
| 22 | // :8:16: note: pointer host size '1' cannot cast into pointer host size '0' | 22 | // :8:16: note: pointer host size '1' cannot cast into pointer host size '0' |
| 23 | // :8:16: note: pointer bit offset '3' cannot cast into pointer bit offset '0' | 23 | // :8:16: note: pointer bit offset '3' cannot cast into pointer bit offset '0' |
| 24 | // :11:11: note: parameter type declared here | 24 | // :11:11: note: parameter type declared here |
test/cases/compile_errors/control_flow_uses_comptime_var_at_runtime.zig+25| ... | @@ -6,6 +6,27 @@ export fn foo() void { | ... | @@ -6,6 +6,27 @@ export fn foo() void { |
| 6 | } | 6 | } |
| 7 | 7 | ||
| 8 | fn bar() void { } | 8 | fn bar() void { } |
| 9 | export fn baz() void { | ||
| 10 | comptime var idx: u32 = 0; | ||
| 11 | while (idx < 1) { | ||
| 12 | const not_null: ?u32 = 1; | ||
| 13 | _ = not_null orelse return; | ||
| 14 | idx += 1; | ||
| 15 | } | ||
| 16 | } | ||
| 17 | |||
| 18 | export fn qux() void { | ||
| 19 | comptime var i = 0; | ||
| 20 | while (i < 3) : (i += 1) { | ||
| 21 | const T = switch (i) { | ||
| 22 | 0 => f32, | ||
| 23 | 1 => i8, | ||
| 24 | 2 => bool, | ||
| 25 | else => unreachable, | ||
| 26 | }; | ||
| 27 | _ = T; | ||
| 28 | } | ||
| 29 | } | ||
| 9 | 30 | ||
| 10 | // error | 31 | // error |
| 11 | // backend=stage2 | 32 | // backend=stage2 |
| ... | @@ -13,3 +34,7 @@ fn bar() void { } | ... | @@ -13,3 +34,7 @@ fn bar() void { } |
| 13 | // | 34 | // |
| 14 | // :3:24: error: cannot store to comptime variable in non-inline loop | 35 | // :3:24: error: cannot store to comptime variable in non-inline loop |
| 15 | // :3:5: note: non-inline loop here | 36 | // :3:5: note: non-inline loop here |
| 37 | // :14:13: error: cannot store to comptime variable in non-inline loop | ||
| 38 | // :11:5: note: non-inline loop here | ||
| 39 | // :20:24: error: cannot store to comptime variable in non-inline loop | ||
| 40 | // :20:5: note: non-inline loop here |
test/cases/compile_errors/incompatible sub-byte fields.zig	+1-1| ... | @@ -24,4 +24,4 @@ export fn entry() void { | ... | @@ -24,4 +24,4 @@ export fn entry() void { |
| 24 | // backend=stage2 | 24 | // backend=stage2 |
| 25 | // target=native | 25 | // target=native |
| 26 | // | 26 | // |
| 27 | // :14:17: error: incompatible types: '*align(0:0:1) u2' and '*align(2:8:2) u2' | 27 | // :14:17: error: incompatible types: '*align(1:0:1) u2' and '*align(2:8:2) u2' |
test/cases/compile_errors/reference_to_const_data.zig+5| ... | @@ -18,6 +18,10 @@ export fn qux() void { | ... | @@ -18,6 +18,10 @@ export fn qux() void { |
| 18 | var ptr = &S{.x=1,.y=2}; | 18 | var ptr = &S{.x=1,.y=2}; |
| 19 | ptr.x = 2; | 19 | ptr.x = 2; |
| 20 | } | 20 | } |
| 21 | export fn quux() void { | ||
| 22 | var x = &@returnAddress(); | ||
| 23 | x.* = 6; | ||
| 24 | } | ||
| 21 | 25 | ||
| 22 | // error | 26 | // error |
| 23 | // backend=stage2 | 27 | // backend=stage2 |
| ... | @@ -27,3 +31,4 @@ export fn qux() void { | ... | @@ -27,3 +31,4 @@ export fn qux() void { |
| 27 | // :7:8: error: cannot assign to constant | 31 | // :7:8: error: cannot assign to constant |
| 28 | // :11:8: error: cannot assign to constant | 32 | // :11:8: error: cannot assign to constant |
| 29 | // :19:8: error: cannot assign to constant | 33 | // :19:8: error: cannot assign to constant |
| 34 | // :23:6: error: cannot assign to constant |
test/cases/compile_errors/return_incompatible_generic_struct.zig created+20| ... | @@ -0,0 +1,20 @@ | ||
| 1 | fn A(comptime T: type) type { | ||
| 2 | return struct { a: T }; | ||
| 3 | } | ||
| 4 | fn B(comptime T: type) type { | ||
| 5 | return struct { b: T }; | ||
| 6 | } | ||
| 7 | fn foo() A(u32) { | ||
| 8 | return B(u32){ .b = 1 }; | ||
| 9 | } | ||
| 10 | export fn entry() void { | ||
| 11 | _ = foo(); | ||
| 12 | } | ||
| 13 | |||
| 14 | // error | ||
| 15 | // backend=stage2 | ||
| 16 | // target=native | ||
| 17 | // | ||
| 18 | // :8:18: error: expected type 'tmp.A(u32)', found 'tmp.B(u32)' | ||
| 19 | // :5:12: note: struct declared here | ||
| 20 | // :2:12: note: struct declared here | ||