mirror of
https://github.com/ziglang/zig.git
synced 2026-02-14 05:20:34 +00:00
move behavior tests that are passing for stage2
This commit is contained in:
parent
0d4a94f32f
commit
ed5a5e2293
@ -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");
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
284
test/behavior/optional_stage1.zig
Normal file
284
test/behavior/optional_stage1.zig
Normal file
@ -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);
|
||||
}
|
||||
@ -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" {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user