add tests for fixed stage1 bugs

Closes #4144
Closes #4255
Closes #4372
Closes #4375
Closes #4380
Closes #4417
Closes #4423
Closes #4476
Closes #4528
Closes #4562
Closes #4572
Closes #4597
Closes #4639
Closes #4672
Closes #4782
Closes #4955
Closes #4984
Closes #4997
Closes #5010
Closes #5114
Closes #5166
Closes #5173
Closes #5276
This commit is contained in:
Veikka Tuominen 2022-12-31 14:28:21 +02:00 committed by Andrew Kelley
parent 1c711b0a64
commit 58c1d98c14
14 changed files with 283 additions and 6 deletions

View File

@ -2773,3 +2773,21 @@ test "runtime precision specifier" {
try expectFmt("3.14e+00", "{:1.[1]}", .{ number, precision });
try expectFmt("3.14e+00", "{:1.[precision]}", .{ .number = number, .precision = precision });
}
test "recursive format function" {
const R = union(enum) {
const R = @This();
Leaf: i32,
Branch: struct { left: *const R, right: *const R },
pub fn format(self: R, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
return switch (self) {
.Leaf => |n| std.fmt.format(writer, "Leaf({})", .{n}),
.Branch => |b| std.fmt.format(writer, "Branch({}, {})", .{ b.left, b.right }),
};
}
};
var r = R{ .Leaf = 1 };
try expectFmt("Leaf(1)\n", "{}\n", .{&r});
}

View File

@ -132,6 +132,17 @@ test "FixedBufferStream output" {
try testing.expectEqualSlices(u8, "HelloWorld!", fbs.getWritten());
}
test "FixedBufferStream output at comptime" {
comptime {
var buf: [255]u8 = undefined;
var fbs = fixedBufferStream(&buf);
const stream = fbs.writer();
try stream.print("{s}{s}!", .{ "Hello", "World" });
try testing.expectEqualSlices(u8, "HelloWorld!", fbs.getWritten());
}
}
test "FixedBufferStream output 2" {
var buffer: [10]u8 = undefined;
var fbs = fixedBufferStream(&buffer);

View File

@ -654,3 +654,11 @@ test "array init of container level array variable" {
S.bar(5, 6);
try expectEqual([2]usize{ 5, 6 }, S.pair);
}
test "runtime initialized sentinel-terminated array literal" {
var c: u16 = 300;
const f = &[_:0x9999]u16{c};
const g = @ptrCast(*[4]u8, f);
try std.testing.expect(g[2] == 0x99);
try std.testing.expect(g[3] == 0x99);
}

View File

@ -394,3 +394,20 @@ test "recursive inline call with comptime known argument" {
try expect(S.foo(4) == 20);
}
test "inline while with @call" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
const S = struct {
fn inc(a: *u32) void {
a.* += 1;
}
};
var a: u32 = 0;
comptime var i = 0;
inline while (i < 10) : (i += 1) {
@call(.auto, S.inc, .{&a});
}
try expect(a == 10);
}

View File

@ -1528,3 +1528,19 @@ test "optional pointer coerced to optional allowzero pointer" {
q = p;
try expect(@ptrToInt(q.?) == 4);
}
test "ptrToInt on const inside comptime block" {
var a = comptime blk: {
const b: u8 = 1;
const c = @ptrToInt(&b);
break :blk c;
};
try expect(@intToPtr(*const u8, a).* == 1);
}
test "single item pointer to pointer to array to slice" {
var x: i32 = 1234;
try expect(@as([]const i32, @as(*[1]i32, &x))[0] == 1234);
const z1 = @as([]const i32, @as(*[1]i32, &x));
try expect(z1[0] == 1234);
}

View File

@ -1621,3 +1621,38 @@ test "inline for loop of functions returning error unions" {
}
try expect(a == 3);
}
test "if inside a switch" {
var condition = true;
var wave_type: u32 = 0;
var sample: i32 = switch (wave_type) {
0 => if (condition) 2 else 3,
1 => 100,
2 => 200,
3 => 300,
else => unreachable,
};
try expect(sample == 2);
}
test "function has correct return type when previous return is casted to smaller type" {
const S = struct {
fn foo(b: bool) u16 {
if (b) return @as(u8, 0xFF);
return 0xFFFF;
}
};
try expect(S.foo(true) == 0xFF);
}
test "early exit in container level const" {
const S = struct {
const value = blk: {
if (true) {
break :blk @as(u32, 1);
}
break :blk @as(u32, 0);
};
};
try expect(S.value == 1);
}

View File

@ -484,3 +484,36 @@ test "using @ptrCast on function pointers" {
// https://github.com/ziglang/zig/issues/2626
// try comptime S.run();
}
test "function returns function returning type" {
const S = struct {
fn a() fn () type {
return (struct {
fn b() type {
return u32;
}
}).b;
}
};
try expect(S.a()() == u32);
}
test "peer type resolution of inferred error set with non-void payload" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
const S = struct {
fn openDataFile(mode: enum { read, write }) !u32 {
return switch (mode) {
.read => foo(),
.write => bar(),
};
}
fn foo() error{ a, b }!u32 {
return 1;
}
fn bar() error{ c, d }!u32 {
return 2;
}
};
try expect(try S.openDataFile(.read) == 1);
}

View File

@ -588,3 +588,14 @@ test "overaligned pointer to packed struct" {
},
}
}
test "packed struct initialized in bitcast" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
const T = packed struct { val: u8 };
var val: u8 = 123;
const t = @bitCast(u8, T{ .val = val });
try expect(t == val);
}

View File

@ -737,3 +737,13 @@ test "empty slice ptr is non null" {
const t = @ptrCast([*]i8, p);
try expect(@ptrToInt(t) == @ptrToInt(empty_slice.ptr));
}
test "slice decays to many pointer" {
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;
var buf: [8]u8 = "abcdefg\x00".*;
const p: [*:0]const u8 = buf[0..7 :0];
try expectEqualStrings(buf[0..7], std.mem.span(p));
}

View File

@ -1495,3 +1495,63 @@ test "function pointer in struct returns the struct" {
var a = A.f();
try expect(a.f == A.f);
}
test "no dependency loop on optional field wrapped in generic function" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
const S = struct {
fn Atomic(comptime T: type) type {
return T;
}
const A = struct { b: Atomic(?*B) };
const B = struct { a: ?*A };
};
var a: S.A = .{ .b = null };
var b: S.B = .{ .a = &a };
a.b = &b;
try expect(a.b == &b);
try expect(b.a == &a);
}
test "optional field init with tuple" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
const S = struct {
a: ?struct { b: u32 },
};
var a: u32 = 0;
var b = S{
.a = .{ .b = a },
};
try expect(b.a.?.b == a);
}
test "if inside struct init inside if" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
const MyStruct = struct { x: u32 };
const b: u32 = 5;
var i: u32 = 1;
var my_var = if (i < 5)
MyStruct{
.x = 1 + if (i > 0) b else 0,
}
else
MyStruct{
.x = 1 + if (i > 0) b else 0,
};
try expect(my_var.x == 6);
}
test "optional generic function label struct field" {
const Options = struct {
isFoo: ?fn (type) u8 = defaultIsFoo,
fn defaultIsFoo(comptime _: type) u8 {
return 123;
}
};
try expect((Options{}).isFoo.?(u8) == 123);
}

View File

@ -221,3 +221,7 @@ test "Macro that uses remainder operator. Issue #13346" {
),
);
}
test "@typeInfo on @cImport result" {
try expect(@typeInfo(h).Struct.decls.len > 1);
}

View File

@ -3,6 +3,7 @@ const std = @import("std");
const testing = std.testing;
const expect = testing.expect;
const expectEqualStrings = std.testing.expectEqualStrings;
const expectEqual = std.testing.expectEqual;
test "tuple concatenation" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
@ -233,31 +234,31 @@ test "fieldParentPtr of anon struct" {
test "offsetOf tuple" {
var x: u32 = 0;
const T = @TypeOf(.{ x, x });
_ = @offsetOf(T, "1");
try expect(@offsetOf(T, "1") == @sizeOf(u32));
}
test "offsetOf anon struct" {
var x: u32 = 0;
const T = @TypeOf(.{ .foo = x, .bar = x });
_ = @offsetOf(T, "bar");
try expect(@offsetOf(T, "bar") == @sizeOf(u32));
}
test "initializing tuple with mixed comptime-runtime fields" {
if (true) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
var x: u32 = 15;
const T = @TypeOf(.{ @as(i32, -1234), @as(u32, 5678), x });
var a: T = .{ -1234, 5678, x + 1 };
_ = a;
try expect(a[2] == 16);
}
test "initializing anon struct with mixed comptime-runtime fields" {
if (true) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
var x: u32 = 15;
const T = @TypeOf(.{ .foo = @as(i32, -1234), .bar = x });
var a: T = .{ .foo = -1234, .bar = x + 1 };
_ = a;
try expect(a.bar == 16);
}
test "tuple in tuple passed to generic function" {
@ -366,3 +367,33 @@ test "tuple initialized with a runtime known value" {
const w = .{W{ .w = e }};
try expectEqualStrings(w[0].w.e, "test");
}
test "tuple of struct concatenation and coercion to array" {
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 StructWithDefault = struct { value: f32 = 42 };
const SomeStruct = struct { array: [4]StructWithDefault };
const value1 = SomeStruct{ .array = .{StructWithDefault{}} ++ [_]StructWithDefault{.{}} ** 3 };
const value2 = SomeStruct{ .array = .{.{}} ++ [_]StructWithDefault{.{}} ** 3 };
try expectEqual(value1, value2);
}
test "nested runtime conditionals in tuple initializer" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
var data: u8 = 0;
const x = .{
if (data != 0) "" else switch (@truncate(u1, data)) {
0 => "up",
1 => "down",
},
};
try expectEqualStrings("up", x[0]);
}

View File

@ -1482,6 +1482,8 @@ test "no dependency loop when function pointer in union returns the union" {
b: *const fn (x: U) void,
c: *const fn (x: U) U,
d: *const fn (x: u8) U,
e: *const fn (x: *U) void,
f: *const fn (x: *U) U,
fn foo(x: u8) U {
return .{ .a = x };
}

View File

@ -53,6 +53,21 @@ export fn foo_slice() void {
_ = slice;
}
}
export fn undefined_slice() void {
const arr: [100]u16 = undefined;
const slice = arr[0..12 :0];
_ = slice;
}
export fn string_slice() void {
const str = "abcdefg";
const slice = str[0..1 :12];
_ = slice;
}
export fn typeName_slice() void {
const arr = @typeName(usize);
const slice = arr[0..2 :0];
_ = slice;
}
// error
// backend=stage2
@ -72,3 +87,9 @@ export fn foo_slice() void {
// :44:29: note: expected '255', found '0'
// :52:29: error: value in memory does not match slice sentinel
// :52:29: note: expected '255', found '0'
// :58:22: error: value in memory does not match slice sentinel
// :58:22: note: expected '0', found 'undefined'
// :63:22: error: value in memory does not match slice sentinel
// :63:22: note: expected '12', found '98'
// :68:22: error: value in memory does not match slice sentinel
// :68:22: note: expected '0', found '105'