| author | |
| committer | |
| log | 0a9b4d092f58595888f9e4be8ef683b2ed8a0da1 |
| tree | eceadc8b9eb451fa4952cffe92638f0e0c5d707e |
| parent | 20e19e75fd3030e1b567044ef02cc3958ed9f73a |
6 files changed, 248 insertions(+), 262 deletions(-)
test/behavior.zig+16-18| ... | @@ -10,32 +10,41 @@ test { | ... | @@ -10,32 +10,41 @@ test { |
| 10 | _ = @import("behavior/bugs/655.zig"); | 10 | _ = @import("behavior/bugs/655.zig"); |
| 11 | _ = @import("behavior/bugs/679.zig"); | 11 | _ = @import("behavior/bugs/679.zig"); |
| 12 | _ = @import("behavior/bugs/704.zig"); | 12 | _ = @import("behavior/bugs/704.zig"); |
| 13 | _ = @import("behavior/bugs/1111.zig"); | ||
| 13 | _ = @import("behavior/bugs/1486.zig"); | 14 | _ = @import("behavior/bugs/1486.zig"); |
| 14 | _ = @import("behavior/bugs/2346.zig"); | 15 | _ = @import("behavior/bugs/2346.zig"); |
| 15 | _ = @import("behavior/bugs/2692.zig"); | 16 | _ = @import("behavior/bugs/2692.zig"); |
| 16 | _ = @import("behavior/bugs/2889.zig"); | 17 | _ = @import("behavior/bugs/2889.zig"); |
| 18 | _ = @import("behavior/bugs/3046.zig"); | ||
| 17 | _ = @import("behavior/bugs/3586.zig"); | 19 | _ = @import("behavior/bugs/3586.zig"); |
| 18 | _ = @import("behavior/bugs/4560.zig"); | 20 | _ = @import("behavior/bugs/4560.zig"); |
| 19 | _ = @import("behavior/bugs/4769_a.zig"); | 21 | _ = @import("behavior/bugs/4769_a.zig"); |
| 20 | _ = @import("behavior/bugs/4769_b.zig"); | 22 | _ = @import("behavior/bugs/4769_b.zig"); |
| 23 | _ = @import("behavior/bugs/4954.zig"); | ||
| 21 | _ = @import("behavior/bugs/6850.zig"); | 24 | _ = @import("behavior/bugs/6850.zig"); |
| 25 | _ = @import("behavior/byval_arg_var.zig"); | ||
| 22 | _ = @import("behavior/call.zig"); | 26 | _ = @import("behavior/call.zig"); |
| 23 | _ = @import("behavior/cast.zig"); | 27 | _ = @import("behavior/cast.zig"); |
| 24 | _ = @import("behavior/defer.zig"); | 28 | _ = @import("behavior/defer.zig"); |
| 25 | _ = @import("behavior/enum.zig"); | 29 | _ = @import("behavior/enum.zig"); |
| 26 | _ = @import("behavior/error.zig"); | 30 | _ = @import("behavior/error.zig"); |
| 31 | _ = @import("behavior/fn_in_struct_in_comptime.zig"); | ||
| 27 | _ = @import("behavior/generics.zig"); | 32 | _ = @import("behavior/generics.zig"); |
| 28 | _ = @import("behavior/hasdecl.zig"); | 33 | _ = @import("behavior/hasdecl.zig"); |
| 29 | _ = @import("behavior/hasfield.zig"); | 34 | _ = @import("behavior/hasfield.zig"); |
| 30 | _ = @import("behavior/if.zig"); | 35 | _ = @import("behavior/if.zig"); |
| 31 | _ = @import("behavior/import.zig"); | 36 | _ = @import("behavior/import.zig"); |
| 37 | _ = @import("behavior/incomplete_struct_param_tld.zig"); | ||
| 32 | _ = @import("behavior/int128.zig"); | 38 | _ = @import("behavior/int128.zig"); |
| 39 | _ = @import("behavior/inttoptr.zig"); | ||
| 33 | _ = @import("behavior/member_func.zig"); | 40 | _ = @import("behavior/member_func.zig"); |
| 34 | _ = @import("behavior/null.zig"); | 41 | _ = @import("behavior/null.zig"); |
| 35 | _ = @import("behavior/optional.zig"); | 42 | _ = @import("behavior/optional.zig"); |
| 36 | _ = @import("behavior/pointers.zig"); | 43 | _ = @import("behavior/pointers.zig"); |
| 37 | _ = @import("behavior/ptrcast.zig"); | 44 | _ = @import("behavior/ptrcast.zig"); |
| 38 | _ = @import("behavior/pub_enum.zig"); | 45 | _ = @import("behavior/pub_enum.zig"); |
| 46 | _ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig"); | ||
| 47 | _ = @import("behavior/slice_sentinel_comptime.zig"); | ||
| 39 | _ = @import("behavior/struct.zig"); | 48 | _ = @import("behavior/struct.zig"); |
| 40 | _ = @import("behavior/this.zig"); | 49 | _ = @import("behavior/this.zig"); |
| 41 | _ = @import("behavior/translate_c_macros.zig"); | 50 | _ = @import("behavior/translate_c_macros.zig"); |
| ... | @@ -47,17 +56,22 @@ test { | ... | @@ -47,17 +56,22 @@ test { |
| 47 | if (builtin.object_format != .c) { | 56 | if (builtin.object_format != .c) { |
| 48 | // Tests that pass for stage1 and stage2 but not the C backend. | 57 | // Tests that pass for stage1 and stage2 but not the C backend. |
| 49 | _ = @import("behavior/align_llvm.zig"); | 58 | _ = @import("behavior/align_llvm.zig"); |
| 59 | _ = @import("behavior/alignof.zig"); | ||
| 50 | _ = @import("behavior/array.zig"); | 60 | _ = @import("behavior/array.zig"); |
| 51 | _ = @import("behavior/atomics.zig"); | 61 | _ = @import("behavior/atomics.zig"); |
| 52 | _ = @import("behavior/basic_llvm.zig"); | 62 | _ = @import("behavior/basic_llvm.zig"); |
| 53 | _ = @import("behavior/bugs/394.zig"); | 63 | _ = @import("behavior/bugs/394.zig"); |
| 64 | _ = @import("behavior/bugs/656.zig"); | ||
| 54 | _ = @import("behavior/bugs/1277.zig"); | 65 | _ = @import("behavior/bugs/1277.zig"); |
| 66 | _ = @import("behavior/bugs/1381.zig"); | ||
| 55 | _ = @import("behavior/bugs/1500.zig"); | 67 | _ = @import("behavior/bugs/1500.zig"); |
| 56 | _ = @import("behavior/bugs/1741.zig"); | 68 | _ = @import("behavior/bugs/1741.zig"); |
| 57 | _ = @import("behavior/bugs/2006.zig"); | 69 | _ = @import("behavior/bugs/2006.zig"); |
| 70 | _ = @import("behavior/bugs/2578.zig"); | ||
| 71 | _ = @import("behavior/bugs/3007.zig"); | ||
| 58 | _ = @import("behavior/bugs/3112.zig"); | 72 | _ = @import("behavior/bugs/3112.zig"); |
| 73 | _ = @import("behavior/bugs/7250.zig"); | ||
| 59 | _ = @import("behavior/cast_llvm.zig"); | 74 | _ = @import("behavior/cast_llvm.zig"); |
| 60 | _ = @import("behavior/error.zig"); | ||
| 61 | _ = @import("behavior/eval.zig"); | 75 | _ = @import("behavior/eval.zig"); |
| 62 | _ = @import("behavior/floatop.zig"); | 76 | _ = @import("behavior/floatop.zig"); |
| 63 | _ = @import("behavior/fn.zig"); | 77 | _ = @import("behavior/fn.zig"); |
| ... | @@ -65,6 +79,7 @@ test { | ... | @@ -65,6 +79,7 @@ test { |
| 65 | _ = @import("behavior/generics_llvm.zig"); | 79 | _ = @import("behavior/generics_llvm.zig"); |
| 66 | _ = @import("behavior/math.zig"); | 80 | _ = @import("behavior/math.zig"); |
| 67 | _ = @import("behavior/maximum_minimum.zig"); | 81 | _ = @import("behavior/maximum_minimum.zig"); |
| 82 | _ = @import("behavior/namespace_depends_on_compile_var.zig"); | ||
| 68 | _ = @import("behavior/null_llvm.zig"); | 83 | _ = @import("behavior/null_llvm.zig"); |
| 69 | _ = @import("behavior/optional_llvm.zig"); | 84 | _ = @import("behavior/optional_llvm.zig"); |
| 70 | _ = @import("behavior/popcount.zig"); | 85 | _ = @import("behavior/popcount.zig"); |
| ... | @@ -84,7 +99,6 @@ test { | ... | @@ -84,7 +99,6 @@ test { |
| 84 | _ = @import("behavior/slice_stage2.zig"); | 99 | _ = @import("behavior/slice_stage2.zig"); |
| 85 | } else { | 100 | } else { |
| 86 | _ = @import("behavior/align_stage1.zig"); | 101 | _ = @import("behavior/align_stage1.zig"); |
| 87 | _ = @import("behavior/alignof.zig"); | ||
| 88 | _ = @import("behavior/array_stage1.zig"); | 102 | _ = @import("behavior/array_stage1.zig"); |
| 89 | if (builtin.os.tag != .wasi) { | 103 | if (builtin.os.tag != .wasi) { |
| 90 | _ = @import("behavior/asm.zig"); | 104 | _ = @import("behavior/asm.zig"); |
| ... | @@ -96,18 +110,15 @@ test { | ... | @@ -96,18 +110,15 @@ test { |
| 96 | _ = @import("behavior/bitreverse.zig"); | 110 | _ = @import("behavior/bitreverse.zig"); |
| 97 | _ = @import("behavior/bugs/421.zig"); | 111 | _ = @import("behavior/bugs/421.zig"); |
| 98 | _ = @import("behavior/bugs/529.zig"); | 112 | _ = @import("behavior/bugs/529.zig"); |
| 99 | _ = @import("behavior/bugs/656.zig"); | ||
| 100 | _ = @import("behavior/bugs/718.zig"); | 113 | _ = @import("behavior/bugs/718.zig"); |
| 101 | _ = @import("behavior/bugs/726.zig"); | 114 | _ = @import("behavior/bugs/726.zig"); |
| 102 | _ = @import("behavior/bugs/828.zig"); | 115 | _ = @import("behavior/bugs/828.zig"); |
| 103 | _ = @import("behavior/bugs/920.zig"); | 116 | _ = @import("behavior/bugs/920.zig"); |
| 104 | _ = @import("behavior/bugs/1025.zig"); | 117 | _ = @import("behavior/bugs/1025.zig"); |
| 105 | _ = @import("behavior/bugs/1076.zig"); | 118 | _ = @import("behavior/bugs/1076.zig"); |
| 106 | _ = @import("behavior/bugs/1111.zig"); | ||
| 107 | _ = @import("behavior/bugs/1120.zig"); | 119 | _ = @import("behavior/bugs/1120.zig"); |
| 108 | _ = @import("behavior/bugs/1310.zig"); | 120 | _ = @import("behavior/bugs/1310.zig"); |
| 109 | _ = @import("behavior/bugs/1322.zig"); | 121 | _ = @import("behavior/bugs/1322.zig"); |
| 110 | _ = @import("behavior/bugs/1381.zig"); | ||
| 111 | _ = @import("behavior/bugs/1421.zig"); | 122 | _ = @import("behavior/bugs/1421.zig"); |
| 112 | _ = @import("behavior/bugs/1442.zig"); | 123 | _ = @import("behavior/bugs/1442.zig"); |
| 113 | _ = @import("behavior/bugs/1607.zig"); | 124 | _ = @import("behavior/bugs/1607.zig"); |
| ... | @@ -115,15 +126,11 @@ test { | ... | @@ -115,15 +126,11 @@ test { |
| 115 | _ = @import("behavior/bugs/1851.zig"); | 126 | _ = @import("behavior/bugs/1851.zig"); |
| 116 | _ = @import("behavior/bugs/1914.zig"); | 127 | _ = @import("behavior/bugs/1914.zig"); |
| 117 | _ = @import("behavior/bugs/2114.zig"); | 128 | _ = @import("behavior/bugs/2114.zig"); |
| 118 | _ = @import("behavior/bugs/2578.zig"); | ||
| 119 | _ = @import("behavior/bugs/3007.zig"); | ||
| 120 | _ = @import("behavior/bugs/3046.zig"); | ||
| 121 | _ = @import("behavior/bugs/3367.zig"); | 129 | _ = @import("behavior/bugs/3367.zig"); |
| 122 | _ = @import("behavior/bugs/3384.zig"); | 130 | _ = @import("behavior/bugs/3384.zig"); |
| 123 | _ = @import("behavior/bugs/3742.zig"); | 131 | _ = @import("behavior/bugs/3742.zig"); |
| 124 | _ = @import("behavior/bugs/3779.zig"); | 132 | _ = @import("behavior/bugs/3779.zig"); |
| 125 | _ = @import("behavior/bugs/4328.zig"); | 133 | _ = @import("behavior/bugs/4328.zig"); |
| 126 | _ = @import("behavior/bugs/4954.zig"); | ||
| 127 | _ = @import("behavior/bugs/5398.zig"); | 134 | _ = @import("behavior/bugs/5398.zig"); |
| 128 | _ = @import("behavior/bugs/5413.zig"); | 135 | _ = @import("behavior/bugs/5413.zig"); |
| 129 | _ = @import("behavior/bugs/5474.zig"); | 136 | _ = @import("behavior/bugs/5474.zig"); |
| ... | @@ -133,12 +140,10 @@ test { | ... | @@ -133,12 +140,10 @@ test { |
| 133 | _ = @import("behavior/bugs/7003.zig"); | 140 | _ = @import("behavior/bugs/7003.zig"); |
| 134 | _ = @import("behavior/bugs/7027.zig"); | 141 | _ = @import("behavior/bugs/7027.zig"); |
| 135 | _ = @import("behavior/bugs/7047.zig"); | 142 | _ = @import("behavior/bugs/7047.zig"); |
| 136 | _ = @import("behavior/bugs/7250.zig"); | ||
| 137 | _ = @import("behavior/bugs/9584.zig"); | 143 | _ = @import("behavior/bugs/9584.zig"); |
| 138 | _ = @import("behavior/bugs/9967.zig"); | 144 | _ = @import("behavior/bugs/9967.zig"); |
| 139 | _ = @import("behavior/bugs/10147.zig"); | 145 | _ = @import("behavior/bugs/10147.zig"); |
| 140 | _ = @import("behavior/byteswap.zig"); | 146 | _ = @import("behavior/byteswap.zig"); |
| 141 | _ = @import("behavior/byval_arg_var.zig"); | ||
| 142 | _ = @import("behavior/call_stage1.zig"); | 147 | _ = @import("behavior/call_stage1.zig"); |
| 143 | _ = @import("behavior/cast_stage1.zig"); | 148 | _ = @import("behavior/cast_stage1.zig"); |
| 144 | _ = @import("behavior/const_slice_child.zig"); | 149 | _ = @import("behavior/const_slice_child.zig"); |
| ... | @@ -150,28 +155,22 @@ test { | ... | @@ -150,28 +155,22 @@ test { |
| 150 | _ = @import("behavior/floatop_stage1.zig"); | 155 | _ = @import("behavior/floatop_stage1.zig"); |
| 151 | _ = @import("behavior/fn_stage1.zig"); | 156 | _ = @import("behavior/fn_stage1.zig"); |
| 152 | _ = @import("behavior/fn_delegation.zig"); | 157 | _ = @import("behavior/fn_delegation.zig"); |
| 153 | _ = @import("behavior/fn_in_struct_in_comptime.zig"); | ||
| 154 | _ = @import("behavior/for_stage1.zig"); | 158 | _ = @import("behavior/for_stage1.zig"); |
| 155 | _ = @import("behavior/if_stage1.zig"); | 159 | _ = @import("behavior/if_stage1.zig"); |
| 156 | _ = @import("behavior/incomplete_struct_param_tld.zig"); | ||
| 157 | _ = @import("behavior/inttoptr.zig"); | ||
| 158 | _ = @import("behavior/ir_block_deps.zig"); | 160 | _ = @import("behavior/ir_block_deps.zig"); |
| 159 | _ = @import("behavior/math_stage1.zig"); | 161 | _ = @import("behavior/math_stage1.zig"); |
| 160 | _ = @import("behavior/merge_error_sets.zig"); | 162 | _ = @import("behavior/merge_error_sets.zig"); |
| 161 | _ = @import("behavior/misc.zig"); | 163 | _ = @import("behavior/misc.zig"); |
| 162 | _ = @import("behavior/muladd.zig"); | 164 | _ = @import("behavior/muladd.zig"); |
| 163 | _ = @import("behavior/namespace_depends_on_compile_var.zig"); | ||
| 164 | _ = @import("behavior/null_stage1.zig"); | 165 | _ = @import("behavior/null_stage1.zig"); |
| 165 | _ = @import("behavior/optional_stage1.zig"); | 166 | _ = @import("behavior/optional_stage1.zig"); |
| 166 | _ = @import("behavior/pointers_stage1.zig"); | 167 | _ = @import("behavior/pointers_stage1.zig"); |
| 167 | _ = @import("behavior/popcount_stage1.zig"); | 168 | _ = @import("behavior/popcount_stage1.zig"); |
| 168 | _ = @import("behavior/ptrcast_stage1.zig"); | 169 | _ = @import("behavior/ptrcast_stage1.zig"); |
| 169 | _ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig"); | ||
| 170 | _ = @import("behavior/reflection.zig"); | 170 | _ = @import("behavior/reflection.zig"); |
| 171 | _ = @import("behavior/select.zig"); | 171 | _ = @import("behavior/select.zig"); |
| 172 | _ = @import("behavior/shuffle.zig"); | 172 | _ = @import("behavior/shuffle.zig"); |
| 173 | _ = @import("behavior/sizeof_and_typeof_stage1.zig"); | 173 | _ = @import("behavior/sizeof_and_typeof_stage1.zig"); |
| 174 | _ = @import("behavior/slice_sentinel_comptime.zig"); | ||
| 175 | _ = @import("behavior/slice_stage1.zig"); | 174 | _ = @import("behavior/slice_stage1.zig"); |
| 176 | _ = @import("behavior/struct_contains_null_ptr_itself.zig"); | 175 | _ = @import("behavior/struct_contains_null_ptr_itself.zig"); |
| 177 | _ = @import("behavior/struct_contains_slice_of_itself.zig"); | 176 | _ = @import("behavior/struct_contains_slice_of_itself.zig"); |
| ... | @@ -186,7 +185,6 @@ test { | ... | @@ -186,7 +185,6 @@ test { |
| 186 | _ = @import("behavior/typename.zig"); | 185 | _ = @import("behavior/typename.zig"); |
| 187 | _ = @import("behavior/union_stage1.zig"); | 186 | _ = @import("behavior/union_stage1.zig"); |
| 188 | _ = @import("behavior/union_with_members.zig"); | 187 | _ = @import("behavior/union_with_members.zig"); |
| 189 | _ = @import("behavior/usingnamespace_stage1.zig"); | ||
| 190 | _ = @import("behavior/var_args.zig"); | 188 | _ = @import("behavior/var_args.zig"); |
| 191 | _ = @import("behavior/vector.zig"); | 189 | _ = @import("behavior/vector.zig"); |
| 192 | if (builtin.target.cpu.arch == .wasm32) { | 190 | if (builtin.target.cpu.arch == .wasm32) { |
test/behavior/struct.zig+141| ... | @@ -6,12 +6,55 @@ const expectEqual = std.testing.expectEqual; | ... | @@ -6,12 +6,55 @@ const expectEqual = std.testing.expectEqual; |
| 6 | const expectEqualSlices = std.testing.expectEqualSlices; | 6 | const expectEqualSlices = std.testing.expectEqualSlices; |
| 7 | const maxInt = std.math.maxInt; | 7 | const maxInt = std.math.maxInt; |
| 8 | 8 | ||
| 9 | top_level_field: i32, | ||
| 10 | |||
| 11 | test "top level fields" { | ||
| 12 | var instance = @This(){ | ||
| 13 | .top_level_field = 1234, | ||
| 14 | }; | ||
| 15 | instance.top_level_field += 1; | ||
| 16 | try expect(@as(i32, 1235) == instance.top_level_field); | ||
| 17 | } | ||
| 18 | |||
| 9 | const StructWithNoFields = struct { | 19 | const StructWithNoFields = struct { |
| 10 | fn add(a: i32, b: i32) i32 { | 20 | fn add(a: i32, b: i32) i32 { |
| 11 | return a + b; | 21 | return a + b; |
| 12 | } | 22 | } |
| 13 | }; | 23 | }; |
| 14 | 24 | ||
| 25 | const StructFoo = struct { | ||
| 26 | a: i32, | ||
| 27 | b: bool, | ||
| 28 | c: f32, | ||
| 29 | }; | ||
| 30 | |||
| 31 | test "structs" { | ||
| 32 | var foo: StructFoo = undefined; | ||
| 33 | @memset(@ptrCast([*]u8, &foo), 0, @sizeOf(StructFoo)); | ||
| 34 | foo.a += 1; | ||
| 35 | foo.b = foo.a == 1; | ||
| 36 | try testFoo(foo); | ||
| 37 | testMutation(&foo); | ||
| 38 | try expect(foo.c == 100); | ||
| 39 | } | ||
| 40 | fn testFoo(foo: StructFoo) !void { | ||
| 41 | try expect(foo.b); | ||
| 42 | } | ||
| 43 | fn testMutation(foo: *StructFoo) void { | ||
| 44 | foo.c = 100; | ||
| 45 | } | ||
| 46 | |||
| 47 | test "struct byval assign" { | ||
| 48 | var foo1: StructFoo = undefined; | ||
| 49 | var foo2: StructFoo = undefined; | ||
| 50 | |||
| 51 | foo1.a = 1234; | ||
| 52 | foo2.a = 0; | ||
| 53 | try expect(foo2.a == 0); | ||
| 54 | foo2 = foo1; | ||
| 55 | try expect(foo2.a == 1234); | ||
| 56 | } | ||
| 57 | |||
| 15 | test "call struct static method" { | 58 | test "call struct static method" { |
| 16 | const result = StructWithNoFields.add(3, 4); | 59 | const result = StructWithNoFields.add(3, 4); |
| 17 | try expect(result == 7); | 60 | try expect(result == 7); |
| ... | @@ -41,6 +84,23 @@ const Val = struct { | ... | @@ -41,6 +84,23 @@ const Val = struct { |
| 41 | x: i32, | 84 | x: i32, |
| 42 | }; | 85 | }; |
| 43 | 86 | ||
| 87 | test "fn call of struct field" { | ||
| 88 | const Foo = struct { | ||
| 89 | ptr: fn () i32, | ||
| 90 | }; | ||
| 91 | const S = struct { | ||
| 92 | fn aFunc() i32 { | ||
| 93 | return 13; | ||
| 94 | } | ||
| 95 | |||
| 96 | fn callStructField(foo: Foo) i32 { | ||
| 97 | return foo.ptr(); | ||
| 98 | } | ||
| 99 | }; | ||
| 100 | |||
| 101 | try expect(S.callStructField(Foo{ .ptr = S.aFunc }) == 13); | ||
| 102 | } | ||
| 103 | |||
| 44 | test "struct initializer" { | 104 | test "struct initializer" { |
| 45 | const val = Val{ .x = 42 }; | 105 | const val = Val{ .x = 42 }; |
| 46 | try expect(val.x == 42); | 106 | try expect(val.x == 42); |
| ... | @@ -58,3 +118,84 @@ test "call member function directly" { | ... | @@ -58,3 +118,84 @@ test "call member function directly" { |
| 58 | const result = MemberFnTestFoo.member(instance); | 118 | const result = MemberFnTestFoo.member(instance); |
| 59 | try expect(result == 1234); | 119 | try expect(result == 1234); |
| 60 | } | 120 | } |
| 121 | |||
| 122 | test "store member function in variable" { | ||
| 123 | const instance = MemberFnTestFoo{ .x = 1234 }; | ||
| 124 | const memberFn = MemberFnTestFoo.member; | ||
| 125 | const result = memberFn(instance); | ||
| 126 | try expect(result == 1234); | ||
| 127 | } | ||
| 128 | |||
| 129 | test "member functions" { | ||
| 130 | const r = MemberFnRand{ .seed = 1234 }; | ||
| 131 | try expect(r.getSeed() == 1234); | ||
| 132 | } | ||
| 133 | const MemberFnRand = struct { | ||
| 134 | seed: u32, | ||
| 135 | pub fn getSeed(r: *const MemberFnRand) u32 { | ||
| 136 | return r.seed; | ||
| 137 | } | ||
| 138 | }; | ||
| 139 | |||
| 140 | test "return struct byval from function" { | ||
| 141 | const bar = makeBar2(1234, 5678); | ||
| 142 | try expect(bar.y == 5678); | ||
| 143 | } | ||
| 144 | const Bar = struct { | ||
| 145 | x: i32, | ||
| 146 | y: i32, | ||
| 147 | }; | ||
| 148 | fn makeBar2(x: i32, y: i32) Bar { | ||
| 149 | return Bar{ | ||
| 150 | .x = x, | ||
| 151 | .y = y, | ||
| 152 | }; | ||
| 153 | } | ||
| 154 | |||
| 155 | test "call method with mutable reference to struct with no fields" { | ||
| 156 | const S = struct { | ||
| 157 | fn doC(s: *const @This()) bool { | ||
| 158 | _ = s; | ||
| 159 | return true; | ||
| 160 | } | ||
| 161 | fn do(s: *@This()) bool { | ||
| 162 | _ = s; | ||
| 163 | return true; | ||
| 164 | } | ||
| 165 | }; | ||
| 166 | |||
| 167 | var s = S{}; | ||
| 168 | try expect(S.doC(&s)); | ||
| 169 | try expect(s.doC()); | ||
| 170 | try expect(S.do(&s)); | ||
| 171 | try expect(s.do()); | ||
| 172 | } | ||
| 173 | |||
| 174 | test "usingnamespace within struct scope" { | ||
| 175 | const S = struct { | ||
| 176 | usingnamespace struct { | ||
| 177 | pub fn inner() i32 { | ||
| 178 | return 42; | ||
| 179 | } | ||
| 180 | }; | ||
| 181 | }; | ||
| 182 | try expect(@as(i32, 42) == S.inner()); | ||
| 183 | } | ||
| 184 | |||
| 185 | test "struct field init with catch" { | ||
| 186 | const S = struct { | ||
| 187 | fn doTheTest() !void { | ||
| 188 | var x: anyerror!isize = 1; | ||
| 189 | var req = Foo{ | ||
| 190 | .field = x catch undefined, | ||
| 191 | }; | ||
| 192 | try expect(req.field == 1); | ||
| 193 | } | ||
| 194 | |||
| 195 | pub const Foo = extern struct { | ||
| 196 | field: isize, | ||
| 197 | }; | ||
| 198 | }; | ||
| 199 | try S.doTheTest(); | ||
| 200 | comptime try S.doTheTest(); | ||
| 201 | } |
test/behavior/struct_llvm.zig+51-64| ... | @@ -6,44 +6,6 @@ const expectEqual = std.testing.expectEqual; | ... | @@ -6,44 +6,6 @@ const expectEqual = std.testing.expectEqual; |
| 6 | const expectEqualSlices = std.testing.expectEqualSlices; | 6 | const expectEqualSlices = std.testing.expectEqualSlices; |
| 7 | const maxInt = std.math.maxInt; | 7 | const maxInt = std.math.maxInt; |
| 8 | 8 | ||
| 9 | const StructWithNoFields = struct { | ||
| 10 | fn add(a: i32, b: i32) i32 { | ||
| 11 | return a + b; | ||
| 12 | } | ||
| 13 | }; | ||
| 14 | |||
| 15 | const StructFoo = struct { | ||
| 16 | a: i32, | ||
| 17 | b: bool, | ||
| 18 | c: f32, | ||
| 19 | }; | ||
| 20 | test "structs" { | ||
| 21 | var foo: StructFoo = undefined; | ||
| 22 | @memset(@ptrCast([*]u8, &foo), 0, @sizeOf(StructFoo)); | ||
| 23 | foo.a += 1; | ||
| 24 | foo.b = foo.a == 1; | ||
| 25 | try testFoo(foo); | ||
| 26 | testMutation(&foo); | ||
| 27 | try expect(foo.c == 100); | ||
| 28 | } | ||
| 29 | fn testFoo(foo: StructFoo) !void { | ||
| 30 | try expect(foo.b); | ||
| 31 | } | ||
| 32 | fn testMutation(foo: *StructFoo) void { | ||
| 33 | foo.c = 100; | ||
| 34 | } | ||
| 35 | |||
| 36 | test "struct byval assign" { | ||
| 37 | var foo1: StructFoo = undefined; | ||
| 38 | var foo2: StructFoo = undefined; | ||
| 39 | |||
| 40 | foo1.a = 1234; | ||
| 41 | foo2.a = 0; | ||
| 42 | try expect(foo2.a == 0); | ||
| 43 | foo2 = foo1; | ||
| 44 | try expect(foo2.a == 1234); | ||
| 45 | } | ||
| 46 | |||
| 47 | const Node = struct { | 9 | const Node = struct { |
| 48 | val: Val, | 10 | val: Val, |
| 49 | next: *Node, | 11 | next: *Node, |
| ... | @@ -81,32 +43,6 @@ const VoidStructFieldsFoo = struct { | ... | @@ -81,32 +43,6 @@ const VoidStructFieldsFoo = struct { |
| 81 | c: void, | 43 | c: void, |
| 82 | }; | 44 | }; |
| 83 | 45 | ||
| 84 | test "member functions" { | ||
| 85 | const r = MemberFnRand{ .seed = 1234 }; | ||
| 86 | try expect(r.getSeed() == 1234); | ||
| 87 | } | ||
| 88 | const MemberFnRand = struct { | ||
| 89 | seed: u32, | ||
| 90 | pub fn getSeed(r: *const MemberFnRand) u32 { | ||
| 91 | return r.seed; | ||
| 92 | } | ||
| 93 | }; | ||
| 94 | |||
| 95 | test "return struct byval from function" { | ||
| 96 | const bar = makeBar2(1234, 5678); | ||
| 97 | try expect(bar.y == 5678); | ||
| 98 | } | ||
| 99 | const Bar = struct { | ||
| 100 | x: i32, | ||
| 101 | y: i32, | ||
| 102 | }; | ||
| 103 | fn makeBar2(x: i32, y: i32) Bar { | ||
| 104 | return Bar{ | ||
| 105 | .x = x, | ||
| 106 | .y = y, | ||
| 107 | }; | ||
| 108 | } | ||
| 109 | |||
| 110 | test "return empty struct from fn" { | 46 | test "return empty struct from fn" { |
| 111 | _ = testReturnEmptyStructFromFn(); | 47 | _ = testReturnEmptyStructFromFn(); |
| 112 | } | 48 | } |
| ... | @@ -114,3 +50,54 @@ const EmptyStruct2 = struct {}; | ... | @@ -114,3 +50,54 @@ const EmptyStruct2 = struct {}; |
| 114 | fn testReturnEmptyStructFromFn() EmptyStruct2 { | 50 | fn testReturnEmptyStructFromFn() EmptyStruct2 { |
| 115 | return EmptyStruct2{}; | 51 | return EmptyStruct2{}; |
| 116 | } | 52 | } |
| 53 | |||
| 54 | test "pass slice of empty struct to fn" { | ||
| 55 | try expect(testPassSliceOfEmptyStructToFn(&[_]EmptyStruct2{EmptyStruct2{}}) == 1); | ||
| 56 | } | ||
| 57 | fn testPassSliceOfEmptyStructToFn(slice: []const EmptyStruct2) usize { | ||
| 58 | return slice.len; | ||
| 59 | } | ||
| 60 | |||
| 61 | test "for loop over pointers to struct, getting field from struct pointer" { | ||
| 62 | const S = struct { | ||
| 63 | const Foo = struct { | ||
| 64 | name: []const u8, | ||
| 65 | }; | ||
| 66 | |||
| 67 | var ok = true; | ||
| 68 | |||
| 69 | fn eql(a: []const u8) bool { | ||
| 70 | _ = a; | ||
| 71 | return true; | ||
| 72 | } | ||
| 73 | |||
| 74 | const ArrayList = struct { | ||
| 75 | fn toSlice(self: *ArrayList) []*Foo { | ||
| 76 | _ = self; | ||
| 77 | return @as([*]*Foo, undefined)[0..0]; | ||
| 78 | } | ||
| 79 | }; | ||
| 80 | |||
| 81 | fn doTheTest() !void { | ||
| 82 | var objects: ArrayList = undefined; | ||
| 83 | |||
| 84 | for (objects.toSlice()) |obj| { | ||
| 85 | if (eql(obj.name)) { | ||
| 86 | ok = false; | ||
| 87 | } | ||
| 88 | } | ||
| 89 | |||
| 90 | try expect(ok); | ||
| 91 | } | ||
| 92 | }; | ||
| 93 | try S.doTheTest(); | ||
| 94 | } | ||
| 95 | |||
| 96 | test "self-referencing struct via array member" { | ||
| 97 | const T = struct { | ||
| 98 | children: [1]*@This(), | ||
| 99 | }; | ||
| 100 | var x: T = undefined; | ||
| 101 | x = T{ .children = .{&x} }; | ||
| 102 | try expect(x.children[0] == &x); | ||
| 103 | } |
test/behavior/struct_stage1.zig-139| ... | @@ -6,16 +6,6 @@ const expectEqual = std.testing.expectEqual; | ... | @@ -6,16 +6,6 @@ const expectEqual = std.testing.expectEqual; |
| 6 | const expectEqualSlices = std.testing.expectEqualSlices; | 6 | const expectEqualSlices = std.testing.expectEqualSlices; |
| 7 | const maxInt = std.math.maxInt; | 7 | const maxInt = std.math.maxInt; |
| 8 | 8 | ||
| 9 | top_level_field: i32, | ||
| 10 | |||
| 11 | test "top level fields" { | ||
| 12 | var instance = @This(){ | ||
| 13 | .top_level_field = 1234, | ||
| 14 | }; | ||
| 15 | instance.top_level_field += 1; | ||
| 16 | try expectEqual(@as(i32, 1235), instance.top_level_field); | ||
| 17 | } | ||
| 18 | |||
| 19 | const StructFoo = struct { | 9 | const StructFoo = struct { |
| 20 | a: i32, | 10 | a: i32, |
| 21 | b: bool, | 11 | b: bool, |
| ... | @@ -31,36 +21,6 @@ const Val = struct { | ... | @@ -31,36 +21,6 @@ const Val = struct { |
| 31 | x: i32, | 21 | x: i32, |
| 32 | }; | 22 | }; |
| 33 | 23 | ||
| 34 | test "fn call of struct field" { | ||
| 35 | const Foo = struct { | ||
| 36 | ptr: fn () i32, | ||
| 37 | }; | ||
| 38 | const S = struct { | ||
| 39 | fn aFunc() i32 { | ||
| 40 | return 13; | ||
| 41 | } | ||
| 42 | |||
| 43 | fn callStructField(foo: Foo) i32 { | ||
| 44 | return foo.ptr(); | ||
| 45 | } | ||
| 46 | }; | ||
| 47 | |||
| 48 | try expect(S.callStructField(Foo{ .ptr = S.aFunc }) == 13); | ||
| 49 | } | ||
| 50 | |||
| 51 | const MemberFnTestFoo = struct { | ||
| 52 | x: i32, | ||
| 53 | fn member(foo: MemberFnTestFoo) i32 { | ||
| 54 | return foo.x; | ||
| 55 | } | ||
| 56 | }; | ||
| 57 | test "store member function in variable" { | ||
| 58 | const instance = MemberFnTestFoo{ .x = 1234 }; | ||
| 59 | const memberFn = MemberFnTestFoo.member; | ||
| 60 | const result = memberFn(instance); | ||
| 61 | try expect(result == 1234); | ||
| 62 | } | ||
| 63 | |||
| 64 | test "empty struct method call" { | 24 | test "empty struct method call" { |
| 65 | const es = EmptyStruct{}; | 25 | const es = EmptyStruct{}; |
| 66 | try expect(es.method() == 1234); | 26 | try expect(es.method() == 1234); |
| ... | @@ -77,13 +37,6 @@ fn testReturnEmptyStructFromFn() EmptyStruct2 { | ... | @@ -77,13 +37,6 @@ fn testReturnEmptyStructFromFn() EmptyStruct2 { |
| 77 | return EmptyStruct2{}; | 37 | return EmptyStruct2{}; |
| 78 | } | 38 | } |
| 79 | 39 | ||
| 80 | test "pass slice of empty struct to fn" { | ||
| 81 | try expect(testPassSliceOfEmptyStructToFn(&[_]EmptyStruct2{EmptyStruct2{}}) == 1); | ||
| 82 | } | ||
| 83 | fn testPassSliceOfEmptyStructToFn(slice: []const EmptyStruct2) usize { | ||
| 84 | return slice.len; | ||
| 85 | } | ||
| 86 | |||
| 87 | const APackedStruct = packed struct { | 40 | const APackedStruct = packed struct { |
| 88 | x: u8, | 41 | x: u8, |
| 89 | y: u8, | 42 | y: u8, |
| ... | @@ -332,25 +285,6 @@ fn alloc(comptime T: type) []T { | ... | @@ -332,25 +285,6 @@ fn alloc(comptime T: type) []T { |
| 332 | return &[_]T{}; | 285 | return &[_]T{}; |
| 333 | } | 286 | } |
| 334 | 287 | ||
| 335 | test "call method with mutable reference to struct with no fields" { | ||
| 336 | const S = struct { | ||
| 337 | fn doC(s: *const @This()) bool { | ||
| 338 | _ = s; | ||
| 339 | return true; | ||
| 340 | } | ||
| 341 | fn do(s: *@This()) bool { | ||
| 342 | _ = s; | ||
| 343 | return true; | ||
| 344 | } | ||
| 345 | }; | ||
| 346 | |||
| 347 | var s = S{}; | ||
| 348 | try expect(S.doC(&s)); | ||
| 349 | try expect(s.doC()); | ||
| 350 | try expect(S.do(&s)); | ||
| 351 | try expect(s.do()); | ||
| 352 | } | ||
| 353 | |||
| 354 | test "implicit cast packed struct field to const ptr" { | 288 | test "implicit cast packed struct field to const ptr" { |
| 355 | const LevelUpMove = packed struct { | 289 | const LevelUpMove = packed struct { |
| 356 | move_id: u9, | 290 | move_id: u9, |
| ... | @@ -450,17 +384,6 @@ test "packed struct with fp fields" { | ... | @@ -450,17 +384,6 @@ test "packed struct with fp fields" { |
| 450 | try expectEqual(@as(f32, 20.0), s.data[2]); | 384 | try expectEqual(@as(f32, 20.0), s.data[2]); |
| 451 | } | 385 | } |
| 452 | 386 | ||
| 453 | test "use within struct scope" { | ||
| 454 | const S = struct { | ||
| 455 | usingnamespace struct { | ||
| 456 | pub fn inner() i32 { | ||
| 457 | return 42; | ||
| 458 | } | ||
| 459 | }; | ||
| 460 | }; | ||
| 461 | try expectEqual(@as(i32, 42), S.inner()); | ||
| 462 | } | ||
| 463 | |||
| 464 | test "default struct initialization fields" { | 387 | test "default struct initialization fields" { |
| 465 | const S = struct { | 388 | const S = struct { |
| 466 | a: i32 = 1234, | 389 | a: i32 = 1234, |
| ... | @@ -501,41 +424,6 @@ test "fn with C calling convention returns struct by value" { | ... | @@ -501,41 +424,6 @@ test "fn with C calling convention returns struct by value" { |
| 501 | comptime try S.entry(); | 424 | comptime try S.entry(); |
| 502 | } | 425 | } |
| 503 | 426 | ||
| 504 | test "for loop over pointers to struct, getting field from struct pointer" { | ||
| 505 | const S = struct { | ||
| 506 | const Foo = struct { | ||
| 507 | name: []const u8, | ||
| 508 | }; | ||
| 509 | |||
| 510 | var ok = true; | ||
| 511 | |||
| 512 | fn eql(a: []const u8) bool { | ||
| 513 | _ = a; | ||
| 514 | return true; | ||
| 515 | } | ||
| 516 | |||
| 517 | const ArrayList = struct { | ||
| 518 | fn toSlice(self: *ArrayList) []*Foo { | ||
| 519 | _ = self; | ||
| 520 | return @as([*]*Foo, undefined)[0..0]; | ||
| 521 | } | ||
| 522 | }; | ||
| 523 | |||
| 524 | fn doTheTest() !void { | ||
| 525 | var objects: ArrayList = undefined; | ||
| 526 | |||
| 527 | for (objects.toSlice()) |obj| { | ||
| 528 | if (eql(obj.name)) { | ||
| 529 | ok = false; | ||
| 530 | } | ||
| 531 | } | ||
| 532 | |||
| 533 | try expect(ok); | ||
| 534 | } | ||
| 535 | }; | ||
| 536 | try S.doTheTest(); | ||
| 537 | } | ||
| 538 | |||
| 539 | test "zero-bit field in packed struct" { | 427 | test "zero-bit field in packed struct" { |
| 540 | const S = packed struct { | 428 | const S = packed struct { |
| 541 | x: u10, | 429 | x: u10, |
| ... | @@ -545,24 +433,6 @@ test "zero-bit field in packed struct" { | ... | @@ -545,24 +433,6 @@ test "zero-bit field in packed struct" { |
| 545 | _ = x; | 433 | _ = x; |
| 546 | } | 434 | } |
| 547 | 435 | ||
| 548 | test "struct field init with catch" { | ||
| 549 | const S = struct { | ||
| 550 | fn doTheTest() !void { | ||
| 551 | var x: anyerror!isize = 1; | ||
| 552 | var req = Foo{ | ||
| 553 | .field = x catch undefined, | ||
| 554 | }; | ||
| 555 | try expect(req.field == 1); | ||
| 556 | } | ||
| 557 | |||
| 558 | pub const Foo = extern struct { | ||
| 559 | field: isize, | ||
| 560 | }; | ||
| 561 | }; | ||
| 562 | try S.doTheTest(); | ||
| 563 | comptime try S.doTheTest(); | ||
| 564 | } | ||
| 565 | |||
| 566 | test "packed struct with non-ABI-aligned field" { | 436 | test "packed struct with non-ABI-aligned field" { |
| 567 | const S = packed struct { | 437 | const S = packed struct { |
| 568 | x: u9, | 438 | x: u9, |
| ... | @@ -717,15 +587,6 @@ test "anon struct literal field value initialized with fn call" { | ... | @@ -717,15 +587,6 @@ test "anon struct literal field value initialized with fn call" { |
| 717 | comptime try S.doTheTest(); | 587 | comptime try S.doTheTest(); |
| 718 | } | 588 | } |
| 719 | 589 | ||
| 720 | test "self-referencing struct via array member" { | ||
| 721 | const T = struct { | ||
| 722 | children: [1]*@This(), | ||
| 723 | }; | ||
| 724 | var x: T = undefined; | ||
| 725 | x = T{ .children = .{&x} }; | ||
| 726 | try expect(x.children[0] == &x); | ||
| 727 | } | ||
| 728 | |||
| 729 | test "struct with union field" { | 590 | test "struct with union field" { |
| 730 | const Value = struct { | 591 | const Value = struct { |
| 731 | ref: u32 = 2, | 592 | ref: u32 = 2, |
test/behavior/usingnamespace.zig+40| ... | @@ -1,4 +1,5 @@ | ... | @@ -1,4 +1,5 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const expect = std.testing.expect; | ||
| 2 | 3 | ||
| 3 | const A = struct { | 4 | const A = struct { |
| 4 | pub const B = bool; | 5 | pub const B = bool; |
| ... | @@ -11,3 +12,42 @@ const C = struct { | ... | @@ -11,3 +12,42 @@ const C = struct { |
| 11 | test "basic usingnamespace" { | 12 | test "basic usingnamespace" { |
| 12 | try std.testing.expect(C.B == bool); | 13 | try std.testing.expect(C.B == bool); |
| 13 | } | 14 | } |
| 15 | |||
| 16 | fn Foo(comptime T: type) type { | ||
| 17 | return struct { | ||
| 18 | usingnamespace T; | ||
| 19 | }; | ||
| 20 | } | ||
| 21 | |||
| 22 | test "usingnamespace inside a generic struct" { | ||
| 23 | const std2 = Foo(std); | ||
| 24 | const testing2 = Foo(std.testing); | ||
| 25 | try std2.testing.expect(true); | ||
| 26 | try testing2.expect(true); | ||
| 27 | } | ||
| 28 | |||
| 29 | usingnamespace struct { | ||
| 30 | pub const foo = 42; | ||
| 31 | }; | ||
| 32 | |||
| 33 | test "usingnamespace does not redeclare an imported variable" { | ||
| 34 | comptime try std.testing.expect(@This().foo == 42); | ||
| 35 | } | ||
| 36 | |||
| 37 | usingnamespace @import("usingnamespace/foo.zig"); | ||
| 38 | test "usingnamespace omits mixing in private functions" { | ||
| 39 | try expect(@This().privateFunction()); | ||
| 40 | try expect(!@This().printText()); | ||
| 41 | } | ||
| 42 | fn privateFunction() bool { | ||
| 43 | return true; | ||
| 44 | } | ||
| 45 | |||
| 46 | test { | ||
| 47 | _ = @import("usingnamespace/import_segregation.zig"); | ||
| 48 | } | ||
| 49 | |||
| 50 | usingnamespace @import("usingnamespace/a.zig"); | ||
| 51 | test "two files usingnamespace import each other" { | ||
| 52 | try expect(@This().ok()); | ||
| 53 | } |
test/behavior/usingnamespace_stage1.zig deleted-41| ... | @@ -1,41 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const expect = std.testing.expect; | ||
| 3 | |||
| 4 | fn Foo(comptime T: type) type { | ||
| 5 | return struct { | ||
| 6 | usingnamespace T; | ||
| 7 | }; | ||
| 8 | } | ||
| 9 | |||
| 10 | test "usingnamespace inside a generic struct" { | ||
| 11 | const std2 = Foo(std); | ||
| 12 | const testing2 = Foo(std.testing); | ||
| 13 | try std2.testing.expect(true); | ||
| 14 | try testing2.expect(true); | ||
| 15 | } | ||
| 16 | |||
| 17 | usingnamespace struct { | ||
| 18 | pub const foo = 42; | ||
| 19 | }; | ||
| 20 | |||
| 21 | test "usingnamespace does not redeclare an imported variable" { | ||
| 22 | comptime try std.testing.expect(@This().foo == 42); | ||
| 23 | } | ||
| 24 | |||
| 25 | usingnamespace @import("usingnamespace/foo.zig"); | ||
| 26 | test "usingnamespace omits mixing in private functions" { | ||
| 27 | try expect(@This().privateFunction()); | ||
| 28 | try expect(!@This().printText()); | ||
| 29 | } | ||
| 30 | fn privateFunction() bool { | ||
| 31 | return true; | ||
| 32 | } | ||
| 33 | |||
| 34 | test { | ||
| 35 | _ = @import("usingnamespace/import_segregation.zig"); | ||
| 36 | } | ||
| 37 | |||
| 38 | usingnamespace @import("usingnamespace/a.zig"); | ||
| 39 | test "two files usingnamespace import each other" { | ||
| 40 | try expect(@This().ok()); | ||
| 41 | } | ||