Commit ed5a5e2293
Changed files (6)
test/behavior/basic.zig
@@ -1,4 +1,5 @@
const std = @import("std");
+const builtin = @import("builtin");
const mem = std.mem;
const expect = std.testing.expect;
@@ -192,6 +193,14 @@ fn testMemcpyMemset() !void {
const OpaqueA = opaque {};
const OpaqueB = opaque {};
+test "opaque types" {
+ try expect(*OpaqueA != *OpaqueB);
+ if (!builtin.zig_is_stage2) {
+ try expect(mem.eql(u8, @typeName(OpaqueA), "OpaqueA"));
+ try expect(mem.eql(u8, @typeName(OpaqueB), "OpaqueB"));
+ }
+}
+
test "variable is allowed to be a pointer to an opaque type" {
var x: i32 = 1234;
_ = hereIsAnOpaqueType(@ptrCast(*OpaqueA, &x));
@@ -200,3 +209,205 @@ fn hereIsAnOpaqueType(ptr: *OpaqueA) *OpaqueA {
var a = ptr;
return a;
}
+
+const global_a: i32 = 1234;
+const global_b: *const i32 = &global_a;
+const global_c: *const f32 = @ptrCast(*const f32, global_b);
+test "compile time global reinterpret" {
+ const d = @ptrCast(*const i32, global_c);
+ try expect(d.* == 1234);
+}
+
+test "cast undefined" {
+ const array: [100]u8 = undefined;
+ const slice = @as([]const u8, &array);
+ testCastUndefined(slice);
+}
+fn testCastUndefined(x: []const u8) void {
+ _ = x;
+}
+
+test "implicit cast after unreachable" {
+ try expect(outer() == 1234);
+}
+fn inner() i32 {
+ return 1234;
+}
+fn outer() i64 {
+ return inner();
+}
+
+test "take address of parameter" {
+ try testTakeAddressOfParameter(12.34);
+}
+fn testTakeAddressOfParameter(f: f32) !void {
+ const f_ptr = &f;
+ try expect(f_ptr.* == 12.34);
+}
+
+test "pointer to void return type" {
+ testPointerToVoidReturnType() catch unreachable;
+}
+fn testPointerToVoidReturnType() anyerror!void {
+ const a = testPointerToVoidReturnType2();
+ return a.*;
+}
+const test_pointer_to_void_return_type_x = void{};
+fn testPointerToVoidReturnType2() *const void {
+ return &test_pointer_to_void_return_type_x;
+}
+
+test "array 2D const double ptr" {
+ const rect_2d_vertexes = [_][1]f32{
+ [_]f32{1.0},
+ [_]f32{2.0},
+ };
+ try testArray2DConstDoublePtr(&rect_2d_vertexes[0][0]);
+}
+
+fn testArray2DConstDoublePtr(ptr: *const f32) !void {
+ const ptr2 = @ptrCast([*]const f32, ptr);
+ try expect(ptr2[0] == 1.0);
+ try expect(ptr2[1] == 2.0);
+}
+
+test "double implicit cast in same expression" {
+ var x = @as(i32, @as(u16, nine()));
+ try expect(x == 9);
+}
+fn nine() u8 {
+ return 9;
+}
+
+test "comptime if inside runtime while which unconditionally breaks" {
+ testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true);
+ comptime testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true);
+}
+fn testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(cond: bool) void {
+ while (cond) {
+ if (false) {}
+ break;
+ }
+}
+
+test "implicit comptime while" {
+ while (false) {
+ @compileError("bad");
+ }
+}
+
+fn fnThatClosesOverLocalConst() type {
+ const c = 1;
+ return struct {
+ fn g() i32 {
+ return c;
+ }
+ };
+}
+
+test "function closes over local const" {
+ const x = fnThatClosesOverLocalConst().g();
+ try expect(x == 1);
+}
+
+test "volatile load and store" {
+ var number: i32 = 1234;
+ const ptr = @as(*volatile i32, &number);
+ ptr.* += 1;
+ try expect(ptr.* == 1235);
+}
+
+test "struct inside function" {
+ try testStructInFn();
+ comptime try testStructInFn();
+}
+
+fn testStructInFn() !void {
+ const BlockKind = u32;
+
+ const Block = struct {
+ kind: BlockKind,
+ };
+
+ var block = Block{ .kind = 1234 };
+
+ block.kind += 1;
+
+ try expect(block.kind == 1235);
+}
+
+test "fn call returning scalar optional in equality expression" {
+ try expect(getNull() == null);
+}
+
+fn getNull() ?*i32 {
+ return null;
+}
+
+var global_foo: *i32 = undefined;
+
+test "global variable assignment with optional unwrapping with var initialized to undefined" {
+ const S = struct {
+ var data: i32 = 1234;
+ fn foo() ?*i32 {
+ return &data;
+ }
+ };
+ global_foo = S.foo() orelse {
+ @panic("bad");
+ };
+ try expect(global_foo.* == 1234);
+}
+
+test "peer result location with typed parent, runtime condition, comptime prongs" {
+ const S = struct {
+ fn doTheTest(arg: i32) i32 {
+ const st = Structy{
+ .bleh = if (arg == 1) 1 else 1,
+ };
+
+ if (st.bleh == 1)
+ return 1234;
+ return 0;
+ }
+
+ const Structy = struct {
+ bleh: i32,
+ };
+ };
+ try expect(S.doTheTest(0) == 1234);
+ try expect(S.doTheTest(1) == 1234);
+}
+
+fn ZA() type {
+ return struct {
+ b: B(),
+
+ const Self = @This();
+
+ fn B() type {
+ return struct {
+ const Self = @This();
+ };
+ }
+ };
+}
+test "non-ambiguous reference of shadowed decls" {
+ try expect(ZA().B().Self != ZA().Self);
+}
+
+test "use of declaration with same name as primitive" {
+ const S = struct {
+ const @"u8" = u16;
+ const alias = @"u8";
+ };
+ const a: S.u8 = 300;
+ try expect(a == 300);
+
+ const b: S.alias = 300;
+ try expect(b == 300);
+
+ const @"u8" = u16;
+ const c: @"u8" = 300;
+ try expect(c == 300);
+}
test/behavior/misc.zig
@@ -5,6 +5,8 @@ const expectEqualStrings = std.testing.expectEqualStrings;
const mem = std.mem;
const builtin = @import("builtin");
+fn emptyFn() void {}
+
test "constant equal function pointers" {
const alias = emptyFn;
try expect(comptime x: {
@@ -12,7 +14,16 @@ test "constant equal function pointers" {
});
}
-fn emptyFn() void {}
+const addr1 = @ptrCast(*const u8, emptyFn);
+test "comptime cast fn to ptr" {
+ const addr2 = @ptrCast(*const u8, emptyFn);
+ comptime try expect(addr1 == addr2);
+}
+
+test "equality compare fn ptrs" {
+ var a = emptyFn;
+ try expect(a == a);
+}
test "string escapes" {
try expectEqualStrings("\"", "\x22");
@@ -34,51 +45,12 @@ test "multiline string literal is null terminated" {
try expect(std.cstr.cmp(s1, s2) == 0);
}
-const global_a: i32 = 1234;
-const global_b: *const i32 = &global_a;
-const global_c: *const f32 = @ptrCast(*const f32, global_b);
-test "compile time global reinterpret" {
- const d = @ptrCast(*const i32, global_c);
- try expect(d.* == 1234);
-}
-
test "explicit cast maybe pointers" {
const a: ?*i32 = undefined;
const b: ?*f32 = @ptrCast(?*f32, a);
_ = b;
}
-test "generic malloc free" {
- const a = memAlloc(u8, 10) catch unreachable;
- memFree(u8, a);
-}
-var some_mem: [100]u8 = undefined;
-fn memAlloc(comptime T: type, n: usize) anyerror![]T {
- return @ptrCast([*]T, &some_mem[0])[0..n];
-}
-fn memFree(comptime T: type, memory: []T) void {
- _ = memory;
-}
-
-test "cast undefined" {
- const array: [100]u8 = undefined;
- const slice = @as([]const u8, &array);
- testCastUndefined(slice);
-}
-fn testCastUndefined(x: []const u8) void {
- _ = x;
-}
-
-test "implicit cast after unreachable" {
- try expect(outer() == 1234);
-}
-fn inner() i32 {
- return 1234;
-}
-fn outer() i64 {
- return inner();
-}
-
test "constant enum initialization with differing sizes" {
try test3_1(test3_foo);
try test3_2(test3_bar);
@@ -117,14 +89,6 @@ fn test3_2(f: Test3Foo) !void {
}
}
-test "take address of parameter" {
- try testTakeAddressOfParameter(12.34);
-}
-fn testTakeAddressOfParameter(f: f32) !void {
- const f_ptr = &f;
- try expect(f_ptr.* == 12.34);
-}
-
test "pointer comparison" {
const a = @as([]const u8, "a");
const b = &a;
@@ -153,40 +117,6 @@ test "string concatenation" {
try expect(b[len] == 0);
}
-test "pointer to void return type" {
- testPointerToVoidReturnType() catch unreachable;
-}
-fn testPointerToVoidReturnType() anyerror!void {
- const a = testPointerToVoidReturnType2();
- return a.*;
-}
-const test_pointer_to_void_return_type_x = void{};
-fn testPointerToVoidReturnType2() *const void {
- return &test_pointer_to_void_return_type_x;
-}
-
-test "array 2D const double ptr" {
- const rect_2d_vertexes = [_][1]f32{
- [_]f32{1.0},
- [_]f32{2.0},
- };
- try testArray2DConstDoublePtr(&rect_2d_vertexes[0][0]);
-}
-
-fn testArray2DConstDoublePtr(ptr: *const f32) !void {
- const ptr2 = @ptrCast([*]const f32, ptr);
- try expect(ptr2[0] == 1.0);
- try expect(ptr2[1] == 2.0);
-}
-
-test "double implicit cast in same expression" {
- var x = @as(i32, @as(u16, nine()));
- try expect(x == 9);
-}
-fn nine() u8 {
- return 9;
-}
-
test "global variable initialized to global variable array element" {
try expect(global_ptr == &gdt[0]);
}
@@ -206,45 +136,6 @@ export fn writeToVRam() void {
vram[0] = 'X';
}
-const OpaqueA = opaque {};
-const OpaqueB = opaque {};
-test "opaque types" {
- try expect(*OpaqueA != *OpaqueB);
- try expect(mem.eql(u8, @typeName(OpaqueA), "OpaqueA"));
- try expect(mem.eql(u8, @typeName(OpaqueB), "OpaqueB"));
-}
-
-test "comptime if inside runtime while which unconditionally breaks" {
- testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true);
- comptime testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true);
-}
-fn testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(cond: bool) void {
- while (cond) {
- if (false) {}
- break;
- }
-}
-
-test "implicit comptime while" {
- while (false) {
- @compileError("bad");
- }
-}
-
-fn fnThatClosesOverLocalConst() type {
- const c = 1;
- return struct {
- fn g() i32 {
- return c;
- }
- };
-}
-
-test "function closes over local const" {
- const x = fnThatClosesOverLocalConst().g();
- try expect(x == 1);
-}
-
const PackedStruct = packed struct {
a: u8,
b: u8,
@@ -268,26 +159,6 @@ export fn testPackedStuff(a: *const PackedStruct, b: *const PackedUnion) void {
}
}
-test "slicing zero length array" {
- const s1 = ""[0..];
- const s2 = ([_]u32{})[0..];
- try expect(s1.len == 0);
- try expect(s2.len == 0);
- try expect(mem.eql(u8, s1, ""));
- try expect(mem.eql(u32, s2, &[_]u32{}));
-}
-
-const addr1 = @ptrCast(*const u8, emptyFn);
-test "comptime cast fn to ptr" {
- const addr2 = @ptrCast(*const u8, emptyFn);
- comptime try expect(addr1 == addr2);
-}
-
-test "equality compare fn ptrs" {
- var a = emptyFn;
- try expect(a == a);
-}
-
test "self reference through fn ptr field" {
const S = struct {
const A = struct {
@@ -304,52 +175,6 @@ test "self reference through fn ptr field" {
try expect(a.f(a) == 12);
}
-test "volatile load and store" {
- var number: i32 = 1234;
- const ptr = @as(*volatile i32, &number);
- ptr.* += 1;
- try expect(ptr.* == 1235);
-}
-
-test "slice string literal has correct type" {
- comptime {
- try expect(@TypeOf("aoeu"[0..]) == *const [4:0]u8);
- const array = [_]i32{ 1, 2, 3, 4 };
- try expect(@TypeOf(array[0..]) == *const [4]i32);
- }
- var runtime_zero: usize = 0;
- comptime try expect(@TypeOf("aoeu"[runtime_zero..]) == [:0]const u8);
- const array = [_]i32{ 1, 2, 3, 4 };
- comptime try expect(@TypeOf(array[runtime_zero..]) == []const i32);
-}
-
-test "struct inside function" {
- try testStructInFn();
- comptime try testStructInFn();
-}
-
-fn testStructInFn() !void {
- const BlockKind = u32;
-
- const Block = struct {
- kind: BlockKind,
- };
-
- var block = Block{ .kind = 1234 };
-
- block.kind += 1;
-
- try expect(block.kind == 1235);
-}
-
-test "fn call returning scalar optional in equality expression" {
- try expect(getNull() == null);
-}
-
-fn getNull() ?*i32 {
- return null;
-}
-
test "thread local variable" {
const S = struct {
threadlocal var t: i32 = 1234;
@@ -358,49 +183,6 @@ test "thread local variable" {
try expect(S.t == 1235);
}
-test "result location zero sized array inside struct field implicit cast to slice" {
- const E = struct {
- entries: []u32,
- };
- var foo = E{ .entries = &[_]u32{} };
- try expect(foo.entries.len == 0);
-}
-
-var global_foo: *i32 = undefined;
-
-test "global variable assignment with optional unwrapping with var initialized to undefined" {
- const S = struct {
- var data: i32 = 1234;
- fn foo() ?*i32 {
- return &data;
- }
- };
- global_foo = S.foo() orelse {
- @panic("bad");
- };
- try expect(global_foo.* == 1234);
-}
-
-test "peer result location with typed parent, runtime condition, comptime prongs" {
- const S = struct {
- fn doTheTest(arg: i32) i32 {
- const st = Structy{
- .bleh = if (arg == 1) 1 else 1,
- };
-
- if (st.bleh == 1)
- return 1234;
- return 0;
- }
-
- const Structy = struct {
- bleh: i32,
- };
- };
- try expect(S.doTheTest(0) == 1234);
- try expect(S.doTheTest(1) == 1234);
-}
-
test "nested optional field in struct" {
const S2 = struct {
y: u8,
@@ -462,36 +244,3 @@ test "lazy typeInfo value as generic parameter" {
};
S.foo(@typeInfo(@TypeOf(.{})));
}
-
-fn ZA() type {
- return struct {
- b: B(),
-
- const Self = @This();
-
- fn B() type {
- return struct {
- const Self = @This();
- };
- }
- };
-}
-test "non-ambiguous reference of shadowed decls" {
- try expect(ZA().B().Self != ZA().Self);
-}
-
-test "use of declaration with same name as primitive" {
- const S = struct {
- const @"u8" = u16;
- const alias = @"u8";
- };
- const a: S.u8 = 300;
- try expect(a == 300);
-
- const b: S.alias = 300;
- try expect(b == 300);
-
- const @"u8" = u16;
- const c: @"u8" = 300;
- try expect(c == 300);
-}
test/behavior/optional.zig
@@ -2,270 +2,3 @@ const std = @import("std");
const testing = std.testing;
const expect = testing.expect;
const expectEqual = testing.expectEqual;
-
-pub const EmptyStruct = struct {};
-
-test "optional pointer to size zero struct" {
- var e = EmptyStruct{};
- var o: ?*EmptyStruct = &e;
- try expect(o != null);
-}
-
-test "equality compare nullable pointers" {
- try testNullPtrsEql();
- comptime try testNullPtrsEql();
-}
-
-fn testNullPtrsEql() !void {
- var number: i32 = 1234;
-
- var x: ?*i32 = null;
- var y: ?*i32 = null;
- try expect(x == y);
- y = &number;
- try expect(x != y);
- try expect(x != &number);
- try expect(&number != x);
- x = &number;
- try expect(x == y);
- try expect(x == &number);
- try expect(&number == x);
-}
-
-test "address of unwrap optional" {
- const S = struct {
- const Foo = struct {
- a: i32,
- };
-
- var global: ?Foo = null;
-
- pub fn getFoo() anyerror!*Foo {
- return &global.?;
- }
- };
- S.global = S.Foo{ .a = 1234 };
- const foo = S.getFoo() catch unreachable;
- try expect(foo.a == 1234);
-}
-
-test "equality compare optional with non-optional" {
- try test_cmp_optional_non_optional();
- comptime try test_cmp_optional_non_optional();
-}
-
-fn test_cmp_optional_non_optional() !void {
- var ten: i32 = 10;
- var opt_ten: ?i32 = 10;
- var five: i32 = 5;
- var int_n: ?i32 = null;
-
- try expect(int_n != ten);
- try expect(opt_ten == ten);
- try expect(opt_ten != five);
-
- // test evaluation is always lexical
- // ensure that the optional isn't always computed before the non-optional
- var mutable_state: i32 = 0;
- _ = blk1: {
- mutable_state += 1;
- break :blk1 @as(?f64, 10.0);
- } != blk2: {
- try expect(mutable_state == 1);
- break :blk2 @as(f64, 5.0);
- };
- _ = blk1: {
- mutable_state += 1;
- break :blk1 @as(f64, 10.0);
- } != blk2: {
- try expect(mutable_state == 2);
- break :blk2 @as(?f64, 5.0);
- };
-}
-
-test "passing an optional integer as a parameter" {
- const S = struct {
- fn entry() bool {
- var x: i32 = 1234;
- return foo(x);
- }
-
- fn foo(x: ?i32) bool {
- return x.? == 1234;
- }
- };
- try expect(S.entry());
- comptime try expect(S.entry());
-}
-
-test "unwrap function call with optional pointer return value" {
- const S = struct {
- fn entry() !void {
- try expect(foo().?.* == 1234);
- try expect(bar() == null);
- }
- const global: i32 = 1234;
- fn foo() ?*const i32 {
- return &global;
- }
- fn bar() ?*i32 {
- return null;
- }
- };
- try S.entry();
- comptime try S.entry();
-}
-
-test "nested orelse" {
- const S = struct {
- fn entry() !void {
- try expect(func() == null);
- }
- fn maybe() ?Foo {
- return null;
- }
- fn func() ?Foo {
- const x = maybe() orelse
- maybe() orelse
- return null;
- _ = x;
- unreachable;
- }
- const Foo = struct {
- field: i32,
- };
- };
- try S.entry();
- comptime try S.entry();
-}
-
-test "self-referential struct through a slice of optional" {
- const S = struct {
- const Node = struct {
- children: []?Node,
- data: ?u8,
-
- fn new() Node {
- return Node{
- .children = undefined,
- .data = null,
- };
- }
- };
- };
-
- var n = S.Node.new();
- try expect(n.data == null);
-}
-
-test "assigning to an unwrapped optional field in an inline loop" {
- comptime var maybe_pos_arg: ?comptime_int = null;
- inline for ("ab") |x| {
- _ = x;
- maybe_pos_arg = 0;
- if (maybe_pos_arg.? != 0) {
- @compileError("bad");
- }
- maybe_pos_arg.? = 10;
- }
-}
-
-test "coerce an anon struct literal to optional struct" {
- const S = struct {
- const Struct = struct {
- field: u32,
- };
- fn doTheTest() !void {
- var maybe_dims: ?Struct = null;
- maybe_dims = .{ .field = 1 };
- try expect(maybe_dims.?.field == 1);
- }
- };
- try S.doTheTest();
- comptime try S.doTheTest();
-}
-
-test "optional with void type" {
- const Foo = struct {
- x: ?void,
- };
- var x = Foo{ .x = null };
- try expect(x.x == null);
-}
-
-test "0-bit child type coerced to optional return ptr result location" {
- const S = struct {
- fn doTheTest() !void {
- var y = Foo{};
- var z = y.thing();
- try expect(z != null);
- }
-
- const Foo = struct {
- pub const Bar = struct {
- field: *Foo,
- };
-
- pub fn thing(self: *Foo) ?Bar {
- return Bar{ .field = self };
- }
- };
- };
- try S.doTheTest();
- comptime try S.doTheTest();
-}
-
-test "0-bit child type coerced to optional" {
- const S = struct {
- fn doTheTest() !void {
- var it: Foo = .{
- .list = undefined,
- };
- try expect(it.foo() != null);
- }
-
- const Empty = struct {};
- const Foo = struct {
- list: [10]Empty,
-
- fn foo(self: *Foo) ?*Empty {
- const data = &self.list[0];
- return data;
- }
- };
- };
- try S.doTheTest();
- comptime try S.doTheTest();
-}
-
-test "array of optional unaligned types" {
- const Enum = enum { one, two, three };
-
- const SomeUnion = union(enum) {
- Num: Enum,
- Other: u32,
- };
-
- const values = [_]?SomeUnion{
- SomeUnion{ .Num = .one },
- SomeUnion{ .Num = .two },
- SomeUnion{ .Num = .three },
- SomeUnion{ .Num = .one },
- SomeUnion{ .Num = .two },
- SomeUnion{ .Num = .three },
- };
-
- // The index must be a runtime value
- var i: usize = 0;
- try expectEqual(Enum.one, values[i].?.Num);
- i += 1;
- try expectEqual(Enum.two, values[i].?.Num);
- i += 1;
- try expectEqual(Enum.three, values[i].?.Num);
- i += 1;
- try expectEqual(Enum.one, values[i].?.Num);
- i += 1;
- try expectEqual(Enum.two, values[i].?.Num);
- i += 1;
- try expectEqual(Enum.three, values[i].?.Num);
-}
test/behavior/optional_stage1.zig
@@ -0,0 +1,284 @@
+const std = @import("std");
+const testing = std.testing;
+const expect = testing.expect;
+const expectEqual = testing.expectEqual;
+
+pub const EmptyStruct = struct {};
+
+test "optional pointer to size zero struct" {
+ var e = EmptyStruct{};
+ var o: ?*EmptyStruct = &e;
+ try expect(o != null);
+}
+
+test "equality compare nullable pointers" {
+ try testNullPtrsEql();
+ comptime try testNullPtrsEql();
+}
+
+fn testNullPtrsEql() !void {
+ var number: i32 = 1234;
+
+ var x: ?*i32 = null;
+ var y: ?*i32 = null;
+ try expect(x == y);
+ y = &number;
+ try expect(x != y);
+ try expect(x != &number);
+ try expect(&number != x);
+ x = &number;
+ try expect(x == y);
+ try expect(x == &number);
+ try expect(&number == x);
+}
+
+test "address of unwrap optional" {
+ const S = struct {
+ const Foo = struct {
+ a: i32,
+ };
+
+ var global: ?Foo = null;
+
+ pub fn getFoo() anyerror!*Foo {
+ return &global.?;
+ }
+ };
+ S.global = S.Foo{ .a = 1234 };
+ const foo = S.getFoo() catch unreachable;
+ try expect(foo.a == 1234);
+}
+
+test "equality compare optional with non-optional" {
+ try test_cmp_optional_non_optional();
+ comptime try test_cmp_optional_non_optional();
+}
+
+fn test_cmp_optional_non_optional() !void {
+ var ten: i32 = 10;
+ var opt_ten: ?i32 = 10;
+ var five: i32 = 5;
+ var int_n: ?i32 = null;
+
+ try expect(int_n != ten);
+ try expect(opt_ten == ten);
+ try expect(opt_ten != five);
+
+ // test evaluation is always lexical
+ // ensure that the optional isn't always computed before the non-optional
+ var mutable_state: i32 = 0;
+ _ = blk1: {
+ mutable_state += 1;
+ break :blk1 @as(?f64, 10.0);
+ } != blk2: {
+ try expect(mutable_state == 1);
+ break :blk2 @as(f64, 5.0);
+ };
+ _ = blk1: {
+ mutable_state += 1;
+ break :blk1 @as(f64, 10.0);
+ } != blk2: {
+ try expect(mutable_state == 2);
+ break :blk2 @as(?f64, 5.0);
+ };
+}
+
+test "passing an optional integer as a parameter" {
+ const S = struct {
+ fn entry() bool {
+ var x: i32 = 1234;
+ return foo(x);
+ }
+
+ fn foo(x: ?i32) bool {
+ return x.? == 1234;
+ }
+ };
+ try expect(S.entry());
+ comptime try expect(S.entry());
+}
+
+test "unwrap function call with optional pointer return value" {
+ const S = struct {
+ fn entry() !void {
+ try expect(foo().?.* == 1234);
+ try expect(bar() == null);
+ }
+ const global: i32 = 1234;
+ fn foo() ?*const i32 {
+ return &global;
+ }
+ fn bar() ?*i32 {
+ return null;
+ }
+ };
+ try S.entry();
+ comptime try S.entry();
+}
+
+test "nested orelse" {
+ const S = struct {
+ fn entry() !void {
+ try expect(func() == null);
+ }
+ fn maybe() ?Foo {
+ return null;
+ }
+ fn func() ?Foo {
+ const x = maybe() orelse
+ maybe() orelse
+ return null;
+ _ = x;
+ unreachable;
+ }
+ const Foo = struct {
+ field: i32,
+ };
+ };
+ try S.entry();
+ comptime try S.entry();
+}
+
+test "self-referential struct through a slice of optional" {
+ const S = struct {
+ const Node = struct {
+ children: []?Node,
+ data: ?u8,
+
+ fn new() Node {
+ return Node{
+ .children = undefined,
+ .data = null,
+ };
+ }
+ };
+ };
+
+ var n = S.Node.new();
+ try expect(n.data == null);
+}
+
+test "assigning to an unwrapped optional field in an inline loop" {
+ comptime var maybe_pos_arg: ?comptime_int = null;
+ inline for ("ab") |x| {
+ _ = x;
+ maybe_pos_arg = 0;
+ if (maybe_pos_arg.? != 0) {
+ @compileError("bad");
+ }
+ maybe_pos_arg.? = 10;
+ }
+}
+
+test "coerce an anon struct literal to optional struct" {
+ const S = struct {
+ const Struct = struct {
+ field: u32,
+ };
+ fn doTheTest() !void {
+ var maybe_dims: ?Struct = null;
+ maybe_dims = .{ .field = 1 };
+ try expect(maybe_dims.?.field == 1);
+ }
+ };
+ try S.doTheTest();
+ comptime try S.doTheTest();
+}
+
+test "optional with void type" {
+ const Foo = struct {
+ x: ?void,
+ };
+ var x = Foo{ .x = null };
+ try expect(x.x == null);
+}
+
+test "0-bit child type coerced to optional return ptr result location" {
+ const S = struct {
+ fn doTheTest() !void {
+ var y = Foo{};
+ var z = y.thing();
+ try expect(z != null);
+ }
+
+ const Foo = struct {
+ pub const Bar = struct {
+ field: *Foo,
+ };
+
+ pub fn thing(self: *Foo) ?Bar {
+ return Bar{ .field = self };
+ }
+ };
+ };
+ try S.doTheTest();
+ comptime try S.doTheTest();
+}
+
+test "0-bit child type coerced to optional" {
+ const S = struct {
+ fn doTheTest() !void {
+ var it: Foo = .{
+ .list = undefined,
+ };
+ try expect(it.foo() != null);
+ }
+
+ const Empty = struct {};
+ const Foo = struct {
+ list: [10]Empty,
+
+ fn foo(self: *Foo) ?*Empty {
+ const data = &self.list[0];
+ return data;
+ }
+ };
+ };
+ try S.doTheTest();
+ comptime try S.doTheTest();
+}
+
+test "array of optional unaligned types" {
+ const Enum = enum { one, two, three };
+
+ const SomeUnion = union(enum) {
+ Num: Enum,
+ Other: u32,
+ };
+
+ const values = [_]?SomeUnion{
+ SomeUnion{ .Num = .one },
+ SomeUnion{ .Num = .two },
+ SomeUnion{ .Num = .three },
+ SomeUnion{ .Num = .one },
+ SomeUnion{ .Num = .two },
+ SomeUnion{ .Num = .three },
+ };
+
+ // The index must be a runtime value
+ var i: usize = 0;
+ try expectEqual(Enum.one, values[i].?.Num);
+ i += 1;
+ try expectEqual(Enum.two, values[i].?.Num);
+ i += 1;
+ try expectEqual(Enum.three, values[i].?.Num);
+ i += 1;
+ try expectEqual(Enum.one, values[i].?.Num);
+ i += 1;
+ try expectEqual(Enum.two, values[i].?.Num);
+ i += 1;
+ try expectEqual(Enum.three, values[i].?.Num);
+}
+
+test "nested optional field in struct" {
+ const S2 = struct {
+ y: u8,
+ };
+ const S1 = struct {
+ x: ?S2,
+ };
+ var s = S1{
+ .x = S2{ .y = 127 },
+ };
+ try expect(s.x.?.y == 127);
+}
test/behavior/slice_stage1.zig
@@ -20,6 +20,47 @@ test "slicing" {
if (slice_rest.len != 10) unreachable;
}
+test "slicing zero length array" {
+ const s1 = ""[0..];
+ const s2 = ([_]u32{})[0..];
+ try expect(s1.len == 0);
+ try expect(s2.len == 0);
+ try expect(mem.eql(u8, s1, ""));
+ try expect(mem.eql(u32, s2, &[_]u32{}));
+}
+
+test "slice string literal has correct type" {
+ comptime {
+ try expect(@TypeOf("aoeu"[0..]) == *const [4:0]u8);
+ const array = [_]i32{ 1, 2, 3, 4 };
+ try expect(@TypeOf(array[0..]) == *const [4]i32);
+ }
+ var runtime_zero: usize = 0;
+ comptime try expect(@TypeOf("aoeu"[runtime_zero..]) == [:0]const u8);
+ const array = [_]i32{ 1, 2, 3, 4 };
+ comptime try expect(@TypeOf(array[runtime_zero..]) == []const i32);
+}
+
+test "generic malloc free" {
+ const a = memAlloc(u8, 10) catch unreachable;
+ memFree(u8, a);
+}
+var some_mem: [100]u8 = undefined;
+fn memAlloc(comptime T: type, n: usize) anyerror![]T {
+ return @ptrCast([*]T, &some_mem[0])[0..n];
+}
+fn memFree(comptime T: type, memory: []T) void {
+ _ = memory;
+}
+
+test "result location zero sized array inside struct field implicit cast to slice" {
+ const E = struct {
+ entries: []u32,
+ };
+ var foo = E{ .entries = &[_]u32{} };
+ try expect(foo.entries.len == 0);
+}
+
const x = @intToPtr([*]i32, 0x1000)[0..0x500];
const y = x[0x100..];
test "compile time slice of pointer to hard coded address" {
test/behavior.zig
@@ -25,6 +25,7 @@ test {
_ = @import("behavior/if.zig");
_ = @import("behavior/math.zig");
_ = @import("behavior/member_func.zig");
+ _ = @import("behavior/optional.zig");
_ = @import("behavior/pointers.zig");
_ = @import("behavior/slice.zig");
_ = @import("behavior/sizeof_and_typeof.zig");
@@ -135,7 +136,7 @@ test {
_ = @import("behavior/muladd.zig");
_ = @import("behavior/namespace_depends_on_compile_var.zig");
_ = @import("behavior/null.zig");
- _ = @import("behavior/optional.zig");
+ _ = @import("behavior/optional_stage1.zig");
_ = @import("behavior/pointers_stage1.zig");
_ = @import("behavior/popcount.zig");
_ = @import("behavior/ptrcast.zig");