authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-12-29 15:33:45-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-12-29 15:33:45-05:00
log9b665a59f27b4de0ae648438617b0a1a08a620c1
treebc0cace44659812c5675c985bba382cb8180b80f
parent94780f7cd19701965d9417e8d90dc6ea4d9285be
parente0b6140009eb3e2e53b8c90fe3973d80991bd9b8
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #14101 from Vexu/stage1

add tests for fixed stage1 bugs

20 files changed, 388 insertions(+), 9 deletions(-)

doc/langref.html.in+3-3
......@@ -12075,7 +12075,7 @@ ContainerDeclarations
1207512075 / doc_comment? KEYWORD_pub? Decl ContainerDeclarations
1207612076 /
1207712077
12078TestDecl <- KEYWORD_test STRINGLITERALSINGLE? Block
12078TestDecl <- KEYWORD_test (STRINGLITERALSINGLE / IDENTIFIER)? Block
1207912079
1208012080ComptimeDecl <- KEYWORD_comptime Block
1208112081
......@@ -12089,7 +12089,7 @@ FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? AddrSpa
1208912089VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? AddrSpace? LinkSection? (EQUAL Expr)? SEMICOLON
1209012090
1209112091ContainerField
12092 <- doc_comment? KEYWORD_comptime? IDENTIFIER (COLON TypeExpr ByteAlign?)? (EQUAL Expr)?
12092 <- doc_comment? KEYWORD_comptime? IDENTIFIER (COLON TypeExpr)? ByteAlign? (EQUAL Expr)?
1209312093 / doc_comment? KEYWORD_comptime? (IDENTIFIER COLON)? !KEYWORD_fn TypeExpr ByteAlign? (EQUAL Expr)?
1209412094
1209512095# *** Block Level ***
......@@ -12360,7 +12360,7 @@ PrefixTypeOp
1236012360 <- QUESTIONMARK
1236112361 / KEYWORD_anyframe MINUSRARROW
1236212362 / 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)*
1236412364 / ArrayTypeStart
1236512365
1236612366SuffixOp
lib/std/array_list.zig+17
......@@ -1604,3 +1604,20 @@ test "std.ArrayList(u0)" {
16041604 }
16051605 try testing.expectEqual(count, 3);
16061606}
1607
1608test "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 {
15951595 /// <- QUESTIONMARK
15961596 /// / KEYWORD_anyframe MINUSRARROW
15971597 /// / 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)*
15991599 /// / ArrayTypeStart
16001600 /// SliceTypeStart <- LBRACKET (COLON Expr)? RBRACKET
16011601 /// PtrTypeStart
src/AstGen.zig+2-2
......@@ -3365,7 +3365,7 @@ fn ptrType(
33653365 var trailing_count: u32 = 0;
33663366
33673367 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);
33693369 trailing_count += 1;
33703370 }
33713371 if (ptr_info.ast.align_node != 0) {
......@@ -3468,7 +3468,7 @@ fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.
34683468 }
34693469 const len = try reachableExpr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, len_node, node);
34703470 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);
34723472
34733473 const result = try gz.addPlNode(.array_type_sentinel, node, Zir.Inst.ArrayTypeSentinel{
34743474 .len = len,
src/type.zig+6-1
......@@ -2195,7 +2195,12 @@ pub const Type = extern union {
21952195 .Slice => try writer.writeAll("[]"),
21962196 }
21972197 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 }
21992204
22002205 if (info.bit_offset != 0 or info.host_size != 0) {
22012206 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" {
15181518 const i = @bitCast(u2, s);
15191519 try expect(i == 2);
15201520}
1521
1522test "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" {
15471547 };
15481548 comptime try expect(S.foo[0] == &S.Nil);
15491549}
1550
1551test "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
1564test "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
1579test "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
1593test "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
1607test "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" {
227227 } else continue;
228228 }
229229}
230
231test "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" {
448448 a = "hello";
449449 try expectEqualStrings(a.?, "hello");
450450}
451
452test "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
478test "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" {
567567 }, 5, 4, 3, 2, 1);
568568 try expect(result);
569569}
570
571test "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" {
270270 std.mem.copy(u8, buff[4..], "abcdef");
271271 }
272272}
273
274test "@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" {
706706 S.slice.len -= 2;
707707 try expectEqualStrings("trin", S.slice);
708708}
709
710test "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
717test "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
731test "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" {
14581458 try expectEqual(@sizeOf(struct { x: u16 }), S.optionalComptimeIntParam(@sizeOf(struct { x: u16 })));
14591459 try expectEqual(@sizeOf(struct { x: u32 }), S.errorUnionComptimeIntParam(@sizeOf(struct { x: u32 })));
14601460}
1461
1462test "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
1479test "discarded struct initialization works as expected" {
1480 const S = struct { a: u32 };
1481 _ = S{ .a = 1 };
1482}
1483
1484test "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");
22const std = @import("std");
33const testing = std.testing;
44const expect = testing.expect;
5const expectEqualStrings = std.testing.expectEqualStrings;
56
67test "tuple concatenation" {
78 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -340,3 +341,28 @@ test "tuple type with void field and a runtime field" {
340341 var t: T = .{ 5, {} };
341342 try expect(t[0] == 5);
342343}
344
345test "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
358test "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" {
14711471 };
14721472 try expect(@sizeOf(Bar) + 1 == 3);
14731473}
1474
1475test "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
1493test "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)); }
1818// backend=stage2
1919// target=native
2020//
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'
2222// :8:16: note: pointer host size '1' cannot cast into pointer host size '0'
2323// :8:16: note: pointer bit offset '3' cannot cast into pointer bit offset '0'
2424// :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 {
66}
77
88fn bar() void { }
9export 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
18export 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}
930
1031// error
1132// backend=stage2
......@@ -13,3 +34,7 @@ fn bar() void { }
1334//
1435// :3:24: error: cannot store to comptime variable in non-inline loop
1536// :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 {
2424// backend=stage2
2525// target=native
2626//
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 {
1818 var ptr = &S{.x=1,.y=2};
1919 ptr.x = 2;
2020}
21export fn quux() void {
22 var x = &@returnAddress();
23 x.* = 6;
24}
2125
2226// error
2327// backend=stage2
......@@ -27,3 +31,4 @@ export fn qux() void {
2731// :7:8: error: cannot assign to constant
2832// :11:8: error: cannot assign to constant
2933// :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 @@
1fn A(comptime T: type) type {
2 return struct { a: T };
3}
4fn B(comptime T: type) type {
5 return struct { b: T };
6}
7fn foo() A(u32) {
8 return B(u32){ .b = 1 };
9}
10export 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