Commit 58c1d98c14
Changed files (14)
lib/std/io/fixed_buffer_stream.zig
@@ -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);
lib/std/fmt.zig
@@ -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});
+}
test/behavior/array.zig
@@ -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);
+}
test/behavior/call.zig
@@ -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);
+}
test/behavior/cast.zig
@@ -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);
+}
test/behavior/eval.zig
@@ -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);
+}
test/behavior/fn.zig
@@ -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);
+}
test/behavior/packed-struct.zig
@@ -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);
+}
test/behavior/slice.zig
@@ -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));
+}
test/behavior/struct.zig
@@ -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);
+}
test/behavior/translate_c_macros.zig
@@ -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);
+}
test/behavior/tuple.zig
@@ -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]);
+}
test/behavior/union.zig
@@ -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 };
}
test/cases/compile_errors/comptime_slice-sentinel_does_not_match_target-sentinel.zig
@@ -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'