add tests for fixed stage1 bugs

Closes #1957
Closes #1994
Closes #2140
Closes #2746
Closes #2802
Closes #2855
Closes #2895
Closes #2981
Closes #3054
Closes #3158
Closes #3234
Closes #3259
Closes #3371
Closes #3376
Closes #3387
Closes #3529
Closes #3653
Closes #3750
Closes #3778
Closes #3882
Closes #3915
Closes #3929
Closes #3961
Closes #3988
Closes #4123
Closes #7448
This commit is contained in:
Veikka Tuominen 2022-12-28 15:10:12 +02:00
parent 7350f0d9b5
commit 9a0c593a54
14 changed files with 374 additions and 0 deletions

View file

@ -1604,3 +1604,20 @@ test "std.ArrayList(u0)" {
}
try testing.expectEqual(count, 3);
}
test "std.ArrayList(?u32).popOrNull()" {
const a = testing.allocator;
var list = ArrayList(?u32).init(a);
defer list.deinit();
try list.append(null);
try list.append(1);
try list.append(2);
try testing.expectEqual(list.items.len, 3);
try testing.expect(list.popOrNull().? == @as(u32, 2));
try testing.expect(list.popOrNull().? == @as(u32, 1));
try testing.expect(list.popOrNull().? == null);
try testing.expect(list.popOrNull() == null);
}

View file

@ -1518,3 +1518,13 @@ test "bitcast packed struct with u0" {
const i = @bitCast(u2, s);
try expect(i == 2);
}
test "optional pointer coerced to optional allowzero pointer" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
var p: ?*u32 = undefined;
var q: ?*allowzero u32 = undefined;
p = @intToPtr(*u32, 4);
q = p;
try expect(@ptrToInt(q.?) == 4);
}

View file

@ -1547,3 +1547,77 @@ test "comptime function turns function value to function pointer" {
};
comptime try expect(S.foo[0] == &S.Nil);
}
test "container level const and var have unique addresses" {
const S = struct {
x: i32,
y: i32,
const c = @This(){ .x = 1, .y = 1 };
var v: @This() = c;
};
var p = &S.c;
try std.testing.expect(p.x == S.c.x);
S.v.x = 2;
try std.testing.expect(p.x == S.c.x);
}
test "break from block results in type" {
const S = struct {
fn NewType(comptime T: type) type {
const Padded = blk: {
if (@sizeOf(T) <= @sizeOf(usize)) break :blk void;
break :blk T;
};
return Padded;
}
};
const T = S.NewType(usize);
try expect(T == void);
}
test "struct in comptime false branch is not evaluated" {
const S = struct {
const comptime_const = 2;
fn some(comptime V: type) type {
return switch (comptime_const) {
3 => struct { a: V.foo },
2 => V,
else => unreachable,
};
}
};
try expect(S.some(u32) == u32);
}
test "result of nested switch assigned to variable" {
var zds: u32 = 0;
zds = switch (zds) {
0 => switch (zds) {
0...0 => 1234,
1...1 => zds,
2 => zds,
else => return,
},
else => zds,
};
try expect(zds == 1234);
}
test "inline for loop of functions returning error unions" {
const T1 = struct {
fn v() error{}!usize {
return 1;
}
};
const T2 = struct {
fn v() error{Error}!usize {
return 2;
}
};
var a: usize = 0;
inline for (.{ T1, T2 }) |T| {
a += try T.v();
}
try expect(a == 3);
}

View file

@ -227,3 +227,25 @@ test "else continue outer for" {
} else continue;
}
}
test "for loop with else branch" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
{
var x = [_]u32{ 1, 2 };
const q = for (x) |y| {
if ((y & 1) != 0) continue;
break y * 2;
} else @as(u32, 1);
try expect(q == 4);
}
{
var x = [_]u32{ 1, 2 };
const q = for (x) |y| {
if ((y & 1) != 0) continue;
break y * 2;
} else @panic("");
try expect(q == 4);
}
}

View file

@ -448,3 +448,46 @@ test "Optional slice size is optimized" {
a = "hello";
try expectEqualStrings(a.?, "hello");
}
test "peer type resolution in nested if expressions" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
const Thing = struct { n: i32 };
var a = false;
var b = false;
var result1 = if (a)
Thing{ .n = 1 }
else
null;
try expect(result1 == null);
try expect(@TypeOf(result1) == ?Thing);
var result2 = if (a)
Thing{ .n = 0 }
else if (b)
Thing{ .n = 1 }
else
null;
try expect(result2 == null);
try expect(@TypeOf(result2) == ?Thing);
}
test "cast slice to const slice nested in error union and optional" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
const S = struct {
fn inner() !?[]u8 {
return error.Foo;
}
fn outer() !?[]const u8 {
return inner();
}
};
try std.testing.expectError(error.Foo, S.outer());
}

View file

@ -567,3 +567,24 @@ test "packed struct passed to callconv(.C) function" {
}, 5, 4, 3, 2, 1);
try expect(result);
}
test "overaligned pointer to packed struct" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
const S = packed struct { a: u32, b: u32 };
var foo: S align(4) = .{ .a = 123, .b = 456 };
const ptr: *align(4) S = &foo;
switch (comptime builtin.cpu.arch.endian()) {
.Little => {
const ptr_to_b: *u32 = &ptr.b;
try expect(ptr_to_b.* == 456);
},
.Big => {
// Byte aligned packed struct field pointers have not been implemented yet.
const ptr_to_a: *align(4:0:8) u32 = &ptr.a;
try expect(ptr_to_a.* == 123);
},
}
}

View file

@ -270,3 +270,15 @@ test "comptime @ptrCast a subset of an array, then write through it" {
std.mem.copy(u8, buff[4..], "abcdef");
}
}
test "@ptrCast undefined value at comptime" {
const S = struct {
fn transmute(comptime T: type, comptime U: type, value: T) U {
return @ptrCast(*const U, &value).*;
}
};
comptime {
var x = S.transmute([]u8, i32, undefined);
_ = x;
}
}

View file

@ -706,3 +706,34 @@ test "global slice field access" {
S.slice.len -= 2;
try expectEqualStrings("trin", S.slice);
}
test "slice of void" {
var n: usize = 10;
var arr: [12]void = undefined;
const slice = @as([]void, &arr)[0..n];
try expect(slice.len == n);
}
test "slice with dereferenced value" {
var a: usize = 0;
var idx: *usize = &a;
_ = blk: {
var array = [_]u8{};
break :blk array[idx.*..];
};
const res = blk: {
var array = [_]u8{};
break :blk array[idx.*..];
};
try expect(res.len == 0);
}
test "empty slice ptr is non null" {
if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64 and (builtin.os.tag == .macos or builtin.os.tag == .windows)) return error.SkipZigTest; // TODO
const empty_slice: []u8 = &[_]u8{};
const p: [*]u8 = empty_slice.ptr + 0;
const t = @ptrCast([*]i8, p);
try expect(@ptrToInt(t) == @ptrToInt(empty_slice.ptr));
}

View file

@ -1458,3 +1458,40 @@ test "struct has only one reference" {
try expectEqual(@sizeOf(struct { x: u16 }), S.optionalComptimeIntParam(@sizeOf(struct { x: u16 })));
try expectEqual(@sizeOf(struct { x: u32 }), S.errorUnionComptimeIntParam(@sizeOf(struct { x: u32 })));
}
test "no dependency loop on pointer to optional struct" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
const S = struct {
const A = struct { b: B };
const B = struct { a: *?A };
};
var a1: ?S.A = null;
var a2: ?S.A = .{ .b = .{ .a = &a1 } };
a1 = .{ .b = .{ .a = &a2 } };
try expect(a1.?.b.a == &a2);
try expect(a2.?.b.a == &a1);
}
test "discarded struct initialization works as expected" {
const S = struct { a: u32 };
_ = S{ .a = 1 };
}
test "function pointer in struct returns the struct" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
const A = struct {
const A = @This();
f: *const fn () A,
fn f() A {
return .{ .f = f };
}
};
var a = A.f();
try expect(a.f == A.f);
}

View file

@ -2,6 +2,7 @@ const builtin = @import("builtin");
const std = @import("std");
const testing = std.testing;
const expect = testing.expect;
const expectEqualStrings = std.testing.expectEqualStrings;
test "tuple concatenation" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
@ -340,3 +341,28 @@ test "tuple type with void field and a runtime field" {
var t: T = .{ 5, {} };
try expect(t[0] == 5);
}
test "branching inside tuple literal" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
const S = struct {
fn foo(a: anytype) !void {
try expect(a[0] == 1234);
}
};
var a = false;
try S.foo(.{if (a) @as(u32, 5678) else @as(u32, 1234)});
}
test "tuple initialized with a runtime known value" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
const E = union(enum) { e: []const u8 };
const W = union(enum) { w: E };
var e = E{ .e = "test" };
const w = .{W{ .w = e }};
try expectEqualStrings(w[0].w.e, "test");
}

View file

@ -1471,3 +1471,34 @@ test "union int tag type is properly managed" {
};
try expect(@sizeOf(Bar) + 1 == 3);
}
test "no dependency loop when function pointer in union returns the union" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
const U = union(enum) {
const U = @This();
a: u8,
b: *const fn (x: U) void,
c: *const fn (x: U) U,
d: *const fn (x: u8) U,
fn foo(x: u8) U {
return .{ .a = x };
}
};
var b: U = .{ .d = U.foo };
try expect(b.d(2).a == 2);
}
test "union reassignment can use previous value" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
const U = union {
a: u32,
b: u32,
};
var a = U{ .a = 32 };
a = U{ .b = a.a };
try expect(a.b == 32);
}

View file

@ -6,6 +6,27 @@ export fn foo() void {
}
fn bar() void { }
export fn baz() void {
comptime var idx: u32 = 0;
while (idx < 1) {
const not_null: ?u32 = 1;
_ = not_null orelse return;
idx += 1;
}
}
export fn qux() void {
comptime var i = 0;
while (i < 3) : (i += 1) {
const T = switch (i) {
0 => f32,
1 => i8,
2 => bool,
else => unreachable,
};
_ = T;
}
}
// error
// backend=stage2
@ -13,3 +34,7 @@ fn bar() void { }
//
// :3:24: error: cannot store to comptime variable in non-inline loop
// :3:5: note: non-inline loop here
// :14:13: error: cannot store to comptime variable in non-inline loop
// :11:5: note: non-inline loop here
// :20:24: error: cannot store to comptime variable in non-inline loop
// :20:5: note: non-inline loop here

View file

@ -18,6 +18,10 @@ export fn qux() void {
var ptr = &S{.x=1,.y=2};
ptr.x = 2;
}
export fn quux() void {
var x = &@returnAddress();
x.* = 6;
}
// error
// backend=stage2
@ -27,3 +31,4 @@ export fn qux() void {
// :7:8: error: cannot assign to constant
// :11:8: error: cannot assign to constant
// :19:8: error: cannot assign to constant
// :23:6: error: cannot assign to constant

View file

@ -0,0 +1,20 @@
fn A(comptime T: type) type {
return struct { a: T };
}
fn B(comptime T: type) type {
return struct { b: T };
}
fn foo() A(u32) {
return B(u32){ .b = 1 };
}
export fn entry() void {
_ = foo();
}
// error
// backend=stage2
// target=native
//
// :8:18: error: expected type 'tmp.A(u32)', found 'tmp.B(u32)'
// :5:12: note: struct declared here
// :2:12: note: struct declared here