diff --git a/test/behavior.zig b/test/behavior.zig index 923c54b400..b251c418e7 100644 --- a/test/behavior.zig +++ b/test/behavior.zig @@ -10,41 +10,32 @@ test { _ = @import("behavior/bugs/655.zig"); _ = @import("behavior/bugs/679.zig"); _ = @import("behavior/bugs/704.zig"); - _ = @import("behavior/bugs/1111.zig"); _ = @import("behavior/bugs/1486.zig"); _ = @import("behavior/bugs/2346.zig"); _ = @import("behavior/bugs/2692.zig"); _ = @import("behavior/bugs/2889.zig"); - _ = @import("behavior/bugs/3046.zig"); _ = @import("behavior/bugs/3586.zig"); _ = @import("behavior/bugs/4560.zig"); _ = @import("behavior/bugs/4769_a.zig"); _ = @import("behavior/bugs/4769_b.zig"); - _ = @import("behavior/bugs/4954.zig"); _ = @import("behavior/bugs/6850.zig"); - _ = @import("behavior/byval_arg_var.zig"); _ = @import("behavior/call.zig"); _ = @import("behavior/cast.zig"); _ = @import("behavior/defer.zig"); _ = @import("behavior/enum.zig"); _ = @import("behavior/error.zig"); - _ = @import("behavior/fn_in_struct_in_comptime.zig"); _ = @import("behavior/generics.zig"); _ = @import("behavior/hasdecl.zig"); _ = @import("behavior/hasfield.zig"); _ = @import("behavior/if.zig"); _ = @import("behavior/import.zig"); - _ = @import("behavior/incomplete_struct_param_tld.zig"); _ = @import("behavior/int128.zig"); - _ = @import("behavior/inttoptr.zig"); _ = @import("behavior/member_func.zig"); _ = @import("behavior/null.zig"); _ = @import("behavior/optional.zig"); _ = @import("behavior/pointers.zig"); _ = @import("behavior/ptrcast.zig"); _ = @import("behavior/pub_enum.zig"); - _ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig"); - _ = @import("behavior/slice_sentinel_comptime.zig"); _ = @import("behavior/struct.zig"); _ = @import("behavior/this.zig"); _ = @import("behavior/translate_c_macros.zig"); @@ -56,22 +47,17 @@ test { if (builtin.object_format != .c) { // Tests that pass for stage1 and stage2 but not the C backend. _ = @import("behavior/align_llvm.zig"); - _ = @import("behavior/alignof.zig"); _ = @import("behavior/array.zig"); _ = @import("behavior/atomics.zig"); _ = @import("behavior/basic_llvm.zig"); _ = @import("behavior/bugs/394.zig"); - _ = @import("behavior/bugs/656.zig"); _ = @import("behavior/bugs/1277.zig"); - _ = @import("behavior/bugs/1381.zig"); _ = @import("behavior/bugs/1500.zig"); _ = @import("behavior/bugs/1741.zig"); _ = @import("behavior/bugs/2006.zig"); - _ = @import("behavior/bugs/2578.zig"); - _ = @import("behavior/bugs/3007.zig"); _ = @import("behavior/bugs/3112.zig"); - _ = @import("behavior/bugs/7250.zig"); _ = @import("behavior/cast_llvm.zig"); + _ = @import("behavior/error.zig"); _ = @import("behavior/eval.zig"); _ = @import("behavior/floatop.zig"); _ = @import("behavior/fn.zig"); @@ -79,7 +65,6 @@ test { _ = @import("behavior/generics_llvm.zig"); _ = @import("behavior/math.zig"); _ = @import("behavior/maximum_minimum.zig"); - _ = @import("behavior/namespace_depends_on_compile_var.zig"); _ = @import("behavior/null_llvm.zig"); _ = @import("behavior/optional_llvm.zig"); _ = @import("behavior/popcount.zig"); @@ -99,6 +84,7 @@ test { _ = @import("behavior/slice_stage2.zig"); } else { _ = @import("behavior/align_stage1.zig"); + _ = @import("behavior/alignof.zig"); _ = @import("behavior/array_stage1.zig"); if (builtin.os.tag != .wasi) { _ = @import("behavior/asm.zig"); @@ -110,15 +96,18 @@ test { _ = @import("behavior/bitreverse.zig"); _ = @import("behavior/bugs/421.zig"); _ = @import("behavior/bugs/529.zig"); + _ = @import("behavior/bugs/656.zig"); _ = @import("behavior/bugs/718.zig"); _ = @import("behavior/bugs/726.zig"); _ = @import("behavior/bugs/828.zig"); _ = @import("behavior/bugs/920.zig"); _ = @import("behavior/bugs/1025.zig"); _ = @import("behavior/bugs/1076.zig"); + _ = @import("behavior/bugs/1111.zig"); _ = @import("behavior/bugs/1120.zig"); _ = @import("behavior/bugs/1310.zig"); _ = @import("behavior/bugs/1322.zig"); + _ = @import("behavior/bugs/1381.zig"); _ = @import("behavior/bugs/1421.zig"); _ = @import("behavior/bugs/1442.zig"); _ = @import("behavior/bugs/1607.zig"); @@ -126,11 +115,15 @@ test { _ = @import("behavior/bugs/1851.zig"); _ = @import("behavior/bugs/1914.zig"); _ = @import("behavior/bugs/2114.zig"); + _ = @import("behavior/bugs/2578.zig"); + _ = @import("behavior/bugs/3007.zig"); + _ = @import("behavior/bugs/3046.zig"); _ = @import("behavior/bugs/3367.zig"); _ = @import("behavior/bugs/3384.zig"); _ = @import("behavior/bugs/3742.zig"); _ = @import("behavior/bugs/3779.zig"); _ = @import("behavior/bugs/4328.zig"); + _ = @import("behavior/bugs/4954.zig"); _ = @import("behavior/bugs/5398.zig"); _ = @import("behavior/bugs/5413.zig"); _ = @import("behavior/bugs/5474.zig"); @@ -140,10 +133,12 @@ test { _ = @import("behavior/bugs/7003.zig"); _ = @import("behavior/bugs/7027.zig"); _ = @import("behavior/bugs/7047.zig"); + _ = @import("behavior/bugs/7250.zig"); _ = @import("behavior/bugs/9584.zig"); _ = @import("behavior/bugs/9967.zig"); _ = @import("behavior/bugs/10147.zig"); _ = @import("behavior/byteswap.zig"); + _ = @import("behavior/byval_arg_var.zig"); _ = @import("behavior/call_stage1.zig"); _ = @import("behavior/cast_stage1.zig"); _ = @import("behavior/const_slice_child.zig"); @@ -155,22 +150,28 @@ test { _ = @import("behavior/floatop_stage1.zig"); _ = @import("behavior/fn_stage1.zig"); _ = @import("behavior/fn_delegation.zig"); + _ = @import("behavior/fn_in_struct_in_comptime.zig"); _ = @import("behavior/for_stage1.zig"); _ = @import("behavior/if_stage1.zig"); + _ = @import("behavior/incomplete_struct_param_tld.zig"); + _ = @import("behavior/inttoptr.zig"); _ = @import("behavior/ir_block_deps.zig"); _ = @import("behavior/math_stage1.zig"); _ = @import("behavior/merge_error_sets.zig"); _ = @import("behavior/misc.zig"); _ = @import("behavior/muladd.zig"); + _ = @import("behavior/namespace_depends_on_compile_var.zig"); _ = @import("behavior/null_stage1.zig"); _ = @import("behavior/optional_stage1.zig"); _ = @import("behavior/pointers_stage1.zig"); _ = @import("behavior/popcount_stage1.zig"); _ = @import("behavior/ptrcast_stage1.zig"); + _ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig"); _ = @import("behavior/reflection.zig"); _ = @import("behavior/select.zig"); _ = @import("behavior/shuffle.zig"); _ = @import("behavior/sizeof_and_typeof_stage1.zig"); + _ = @import("behavior/slice_sentinel_comptime.zig"); _ = @import("behavior/slice_stage1.zig"); _ = @import("behavior/struct_contains_null_ptr_itself.zig"); _ = @import("behavior/struct_contains_slice_of_itself.zig"); @@ -185,6 +186,7 @@ test { _ = @import("behavior/typename.zig"); _ = @import("behavior/union_stage1.zig"); _ = @import("behavior/union_with_members.zig"); + _ = @import("behavior/usingnamespace_stage1.zig"); _ = @import("behavior/var_args.zig"); _ = @import("behavior/vector.zig"); if (builtin.target.cpu.arch == .wasm32) { diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig index 1e47877fd6..eeaa80ed69 100644 --- a/test/behavior/struct.zig +++ b/test/behavior/struct.zig @@ -6,55 +6,12 @@ const expectEqual = std.testing.expectEqual; const expectEqualSlices = std.testing.expectEqualSlices; const maxInt = std.math.maxInt; -top_level_field: i32, - -test "top level fields" { - var instance = @This(){ - .top_level_field = 1234, - }; - instance.top_level_field += 1; - try expect(@as(i32, 1235) == instance.top_level_field); -} - const StructWithNoFields = struct { fn add(a: i32, b: i32) i32 { return a + b; } }; -const StructFoo = struct { - a: i32, - b: bool, - c: f32, -}; - -test "structs" { - var foo: StructFoo = undefined; - @memset(@ptrCast([*]u8, &foo), 0, @sizeOf(StructFoo)); - foo.a += 1; - foo.b = foo.a == 1; - try testFoo(foo); - testMutation(&foo); - try expect(foo.c == 100); -} -fn testFoo(foo: StructFoo) !void { - try expect(foo.b); -} -fn testMutation(foo: *StructFoo) void { - foo.c = 100; -} - -test "struct byval assign" { - var foo1: StructFoo = undefined; - var foo2: StructFoo = undefined; - - foo1.a = 1234; - foo2.a = 0; - try expect(foo2.a == 0); - foo2 = foo1; - try expect(foo2.a == 1234); -} - test "call struct static method" { const result = StructWithNoFields.add(3, 4); try expect(result == 7); @@ -84,23 +41,6 @@ const Val = struct { x: i32, }; -test "fn call of struct field" { - const Foo = struct { - ptr: fn () i32, - }; - const S = struct { - fn aFunc() i32 { - return 13; - } - - fn callStructField(foo: Foo) i32 { - return foo.ptr(); - } - }; - - try expect(S.callStructField(Foo{ .ptr = S.aFunc }) == 13); -} - test "struct initializer" { const val = Val{ .x = 42 }; try expect(val.x == 42); @@ -118,84 +58,3 @@ test "call member function directly" { const result = MemberFnTestFoo.member(instance); try expect(result == 1234); } - -test "store member function in variable" { - const instance = MemberFnTestFoo{ .x = 1234 }; - const memberFn = MemberFnTestFoo.member; - const result = memberFn(instance); - try expect(result == 1234); -} - -test "member functions" { - const r = MemberFnRand{ .seed = 1234 }; - try expect(r.getSeed() == 1234); -} -const MemberFnRand = struct { - seed: u32, - pub fn getSeed(r: *const MemberFnRand) u32 { - return r.seed; - } -}; - -test "return struct byval from function" { - const bar = makeBar2(1234, 5678); - try expect(bar.y == 5678); -} -const Bar = struct { - x: i32, - y: i32, -}; -fn makeBar2(x: i32, y: i32) Bar { - return Bar{ - .x = x, - .y = y, - }; -} - -test "call method with mutable reference to struct with no fields" { - const S = struct { - fn doC(s: *const @This()) bool { - _ = s; - return true; - } - fn do(s: *@This()) bool { - _ = s; - return true; - } - }; - - var s = S{}; - try expect(S.doC(&s)); - try expect(s.doC()); - try expect(S.do(&s)); - try expect(s.do()); -} - -test "usingnamespace within struct scope" { - const S = struct { - usingnamespace struct { - pub fn inner() i32 { - return 42; - } - }; - }; - try expect(@as(i32, 42) == S.inner()); -} - -test "struct field init with catch" { - const S = struct { - fn doTheTest() !void { - var x: anyerror!isize = 1; - var req = Foo{ - .field = x catch undefined, - }; - try expect(req.field == 1); - } - - pub const Foo = extern struct { - field: isize, - }; - }; - try S.doTheTest(); - comptime try S.doTheTest(); -} diff --git a/test/behavior/struct_llvm.zig b/test/behavior/struct_llvm.zig index 35c71fe7a2..a809905cef 100644 --- a/test/behavior/struct_llvm.zig +++ b/test/behavior/struct_llvm.zig @@ -6,6 +6,44 @@ const expectEqual = std.testing.expectEqual; const expectEqualSlices = std.testing.expectEqualSlices; const maxInt = std.math.maxInt; +const StructWithNoFields = struct { + fn add(a: i32, b: i32) i32 { + return a + b; + } +}; + +const StructFoo = struct { + a: i32, + b: bool, + c: f32, +}; +test "structs" { + var foo: StructFoo = undefined; + @memset(@ptrCast([*]u8, &foo), 0, @sizeOf(StructFoo)); + foo.a += 1; + foo.b = foo.a == 1; + try testFoo(foo); + testMutation(&foo); + try expect(foo.c == 100); +} +fn testFoo(foo: StructFoo) !void { + try expect(foo.b); +} +fn testMutation(foo: *StructFoo) void { + foo.c = 100; +} + +test "struct byval assign" { + var foo1: StructFoo = undefined; + var foo2: StructFoo = undefined; + + foo1.a = 1234; + foo2.a = 0; + try expect(foo2.a == 0); + foo2 = foo1; + try expect(foo2.a == 1234); +} + const Node = struct { val: Val, next: *Node, @@ -43,6 +81,32 @@ const VoidStructFieldsFoo = struct { c: void, }; +test "member functions" { + const r = MemberFnRand{ .seed = 1234 }; + try expect(r.getSeed() == 1234); +} +const MemberFnRand = struct { + seed: u32, + pub fn getSeed(r: *const MemberFnRand) u32 { + return r.seed; + } +}; + +test "return struct byval from function" { + const bar = makeBar2(1234, 5678); + try expect(bar.y == 5678); +} +const Bar = struct { + x: i32, + y: i32, +}; +fn makeBar2(x: i32, y: i32) Bar { + return Bar{ + .x = x, + .y = y, + }; +} + test "return empty struct from fn" { _ = testReturnEmptyStructFromFn(); } @@ -50,54 +114,3 @@ const EmptyStruct2 = struct {}; fn testReturnEmptyStructFromFn() EmptyStruct2 { return EmptyStruct2{}; } - -test "pass slice of empty struct to fn" { - try expect(testPassSliceOfEmptyStructToFn(&[_]EmptyStruct2{EmptyStruct2{}}) == 1); -} -fn testPassSliceOfEmptyStructToFn(slice: []const EmptyStruct2) usize { - return slice.len; -} - -test "for loop over pointers to struct, getting field from struct pointer" { - const S = struct { - const Foo = struct { - name: []const u8, - }; - - var ok = true; - - fn eql(a: []const u8) bool { - _ = a; - return true; - } - - const ArrayList = struct { - fn toSlice(self: *ArrayList) []*Foo { - _ = self; - return @as([*]*Foo, undefined)[0..0]; - } - }; - - fn doTheTest() !void { - var objects: ArrayList = undefined; - - for (objects.toSlice()) |obj| { - if (eql(obj.name)) { - ok = false; - } - } - - try expect(ok); - } - }; - try S.doTheTest(); -} - -test "self-referencing struct via array member" { - const T = struct { - children: [1]*@This(), - }; - var x: T = undefined; - x = T{ .children = .{&x} }; - try expect(x.children[0] == &x); -} diff --git a/test/behavior/struct_stage1.zig b/test/behavior/struct_stage1.zig index 4b78bd13d3..a04e54e89b 100644 --- a/test/behavior/struct_stage1.zig +++ b/test/behavior/struct_stage1.zig @@ -6,6 +6,16 @@ const expectEqual = std.testing.expectEqual; const expectEqualSlices = std.testing.expectEqualSlices; const maxInt = std.math.maxInt; +top_level_field: i32, + +test "top level fields" { + var instance = @This(){ + .top_level_field = 1234, + }; + instance.top_level_field += 1; + try expectEqual(@as(i32, 1235), instance.top_level_field); +} + const StructFoo = struct { a: i32, b: bool, @@ -21,6 +31,36 @@ const Val = struct { x: i32, }; +test "fn call of struct field" { + const Foo = struct { + ptr: fn () i32, + }; + const S = struct { + fn aFunc() i32 { + return 13; + } + + fn callStructField(foo: Foo) i32 { + return foo.ptr(); + } + }; + + try expect(S.callStructField(Foo{ .ptr = S.aFunc }) == 13); +} + +const MemberFnTestFoo = struct { + x: i32, + fn member(foo: MemberFnTestFoo) i32 { + return foo.x; + } +}; +test "store member function in variable" { + const instance = MemberFnTestFoo{ .x = 1234 }; + const memberFn = MemberFnTestFoo.member; + const result = memberFn(instance); + try expect(result == 1234); +} + test "empty struct method call" { const es = EmptyStruct{}; try expect(es.method() == 1234); @@ -37,6 +77,13 @@ fn testReturnEmptyStructFromFn() EmptyStruct2 { return EmptyStruct2{}; } +test "pass slice of empty struct to fn" { + try expect(testPassSliceOfEmptyStructToFn(&[_]EmptyStruct2{EmptyStruct2{}}) == 1); +} +fn testPassSliceOfEmptyStructToFn(slice: []const EmptyStruct2) usize { + return slice.len; +} + const APackedStruct = packed struct { x: u8, y: u8, @@ -285,6 +332,25 @@ fn alloc(comptime T: type) []T { return &[_]T{}; } +test "call method with mutable reference to struct with no fields" { + const S = struct { + fn doC(s: *const @This()) bool { + _ = s; + return true; + } + fn do(s: *@This()) bool { + _ = s; + return true; + } + }; + + var s = S{}; + try expect(S.doC(&s)); + try expect(s.doC()); + try expect(S.do(&s)); + try expect(s.do()); +} + test "implicit cast packed struct field to const ptr" { const LevelUpMove = packed struct { move_id: u9, @@ -384,6 +450,17 @@ test "packed struct with fp fields" { try expectEqual(@as(f32, 20.0), s.data[2]); } +test "use within struct scope" { + const S = struct { + usingnamespace struct { + pub fn inner() i32 { + return 42; + } + }; + }; + try expectEqual(@as(i32, 42), S.inner()); +} + test "default struct initialization fields" { const S = struct { a: i32 = 1234, @@ -424,6 +501,41 @@ test "fn with C calling convention returns struct by value" { comptime try S.entry(); } +test "for loop over pointers to struct, getting field from struct pointer" { + const S = struct { + const Foo = struct { + name: []const u8, + }; + + var ok = true; + + fn eql(a: []const u8) bool { + _ = a; + return true; + } + + const ArrayList = struct { + fn toSlice(self: *ArrayList) []*Foo { + _ = self; + return @as([*]*Foo, undefined)[0..0]; + } + }; + + fn doTheTest() !void { + var objects: ArrayList = undefined; + + for (objects.toSlice()) |obj| { + if (eql(obj.name)) { + ok = false; + } + } + + try expect(ok); + } + }; + try S.doTheTest(); +} + test "zero-bit field in packed struct" { const S = packed struct { x: u10, @@ -433,6 +545,24 @@ test "zero-bit field in packed struct" { _ = x; } +test "struct field init with catch" { + const S = struct { + fn doTheTest() !void { + var x: anyerror!isize = 1; + var req = Foo{ + .field = x catch undefined, + }; + try expect(req.field == 1); + } + + pub const Foo = extern struct { + field: isize, + }; + }; + try S.doTheTest(); + comptime try S.doTheTest(); +} + test "packed struct with non-ABI-aligned field" { const S = packed struct { x: u9, @@ -587,6 +717,15 @@ test "anon struct literal field value initialized with fn call" { comptime try S.doTheTest(); } +test "self-referencing struct via array member" { + const T = struct { + children: [1]*@This(), + }; + var x: T = undefined; + x = T{ .children = .{&x} }; + try expect(x.children[0] == &x); +} + test "struct with union field" { const Value = struct { ref: u32 = 2, diff --git a/test/behavior/usingnamespace.zig b/test/behavior/usingnamespace.zig index ad47762c16..e819566002 100644 --- a/test/behavior/usingnamespace.zig +++ b/test/behavior/usingnamespace.zig @@ -1,5 +1,4 @@ const std = @import("std"); -const expect = std.testing.expect; const A = struct { pub const B = bool; @@ -12,42 +11,3 @@ const C = struct { test "basic usingnamespace" { try std.testing.expect(C.B == bool); } - -fn Foo(comptime T: type) type { - return struct { - usingnamespace T; - }; -} - -test "usingnamespace inside a generic struct" { - const std2 = Foo(std); - const testing2 = Foo(std.testing); - try std2.testing.expect(true); - try testing2.expect(true); -} - -usingnamespace struct { - pub const foo = 42; -}; - -test "usingnamespace does not redeclare an imported variable" { - comptime try std.testing.expect(@This().foo == 42); -} - -usingnamespace @import("usingnamespace/foo.zig"); -test "usingnamespace omits mixing in private functions" { - try expect(@This().privateFunction()); - try expect(!@This().printText()); -} -fn privateFunction() bool { - return true; -} - -test { - _ = @import("usingnamespace/import_segregation.zig"); -} - -usingnamespace @import("usingnamespace/a.zig"); -test "two files usingnamespace import each other" { - try expect(@This().ok()); -} diff --git a/test/behavior/usingnamespace_stage1.zig b/test/behavior/usingnamespace_stage1.zig new file mode 100644 index 0000000000..142df21549 --- /dev/null +++ b/test/behavior/usingnamespace_stage1.zig @@ -0,0 +1,41 @@ +const std = @import("std"); +const expect = std.testing.expect; + +fn Foo(comptime T: type) type { + return struct { + usingnamespace T; + }; +} + +test "usingnamespace inside a generic struct" { + const std2 = Foo(std); + const testing2 = Foo(std.testing); + try std2.testing.expect(true); + try testing2.expect(true); +} + +usingnamespace struct { + pub const foo = 42; +}; + +test "usingnamespace does not redeclare an imported variable" { + comptime try std.testing.expect(@This().foo == 42); +} + +usingnamespace @import("usingnamespace/foo.zig"); +test "usingnamespace omits mixing in private functions" { + try expect(@This().privateFunction()); + try expect(!@This().printText()); +} +fn privateFunction() bool { + return true; +} + +test { + _ = @import("usingnamespace/import_segregation.zig"); +} + +usingnamespace @import("usingnamespace/a.zig"); +test "two files usingnamespace import each other" { + try expect(@This().ok()); +}