| 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); |
| 3 | const assert = std.debug.assert; |
| 4 | const expect = std.testing.expect; |
| 5 | |
| 6 | test "simple destructure" { |
| 7 | const S = struct { |
| 8 | fn doTheTest() !void { |
| 9 | var x: u32 = undefined; |
| 10 | x, const y, var z: u64 = .{ 1, @as(u16, 2), 3 }; |
| 11 | _ = &z; |
| 12 | |
| 13 | comptime assert(@TypeOf(y) == u16); |
| 14 | |
| 15 | try expect(x == 1); |
| 16 | try expect(y == 2); |
| 17 | try expect(z == 3); |
| 18 | } |
| 19 | }; |
| 20 | |
| 21 | try S.doTheTest(); |
| 22 | try comptime S.doTheTest(); |
| 23 | } |
| 24 | |
| 25 | test "destructure with comptime syntax" { |
| 26 | const S = struct { |
| 27 | fn doTheTest() !void { |
| 28 | { |
| 29 | comptime var x: f32 = undefined; |
| 30 | comptime x, const y, var z, const w: u32 = .{ 0.5, 123, 456, 789 }; // z is a comptime var |
| 31 | _ = &z; |
| 32 | |
| 33 | comptime assert(@TypeOf(y) == comptime_int); |
| 34 | comptime assert(@TypeOf(z) == comptime_int); |
| 35 | comptime assert(@TypeOf(w) == u32); |
| 36 | comptime assert(x == 0.5); |
| 37 | comptime assert(y == 123); |
| 38 | comptime assert(z == 456); |
| 39 | comptime assert(w == 789); |
| 40 | } |
| 41 | { |
| 42 | var w: u8, var x: u8 = .{ 1, 2 }; |
| 43 | w, var y: u8 = .{ 3, 4 }; |
| 44 | var z: u8, x = .{ 5, 6 }; |
| 45 | y, z = .{ 7, 8 }; |
| 46 | { |
| 47 | w += 1; |
| 48 | x -= 2; |
| 49 | y *= 3; |
| 50 | z /= 4; |
| 51 | } |
| 52 | try expect(w == 4); |
| 53 | try expect(x == 4); |
| 54 | try expect(y == 21); |
| 55 | try expect(z == 2); |
| 56 | } |
| 57 | { |
| 58 | comptime var w, var x = .{ 1, 2 }; |
| 59 | comptime w, var y = .{ 3, 4 }; |
| 60 | comptime var z, x = .{ 5, 6 }; |
| 61 | comptime y, z = .{ 7, 8 }; |
| 62 | comptime { |
| 63 | w += 1; |
| 64 | x -= 2; |
| 65 | y *= 3; |
| 66 | z /= 4; |
| 67 | } |
| 68 | comptime assert(w == 4); |
| 69 | comptime assert(x == 4); |
| 70 | comptime assert(y == 21); |
| 71 | comptime assert(z == 2); |
| 72 | } |
| 73 | } |
| 74 | }; |
| 75 | |
| 76 | try S.doTheTest(); |
| 77 | try comptime S.doTheTest(); |
| 78 | } |
| 79 | |
| 80 | test "destructure from labeled block" { |
| 81 | const S = struct { |
| 82 | fn doTheTest(rt_true: bool) !void { |
| 83 | const x: u32, const y: u8, const z: i64 = blk: { |
| 84 | if (rt_true) break :blk .{ 1, 2, 3 }; |
| 85 | break :blk .{ 4, 5, 6 }; |
| 86 | }; |
| 87 | |
| 88 | try expect(x == 1); |
| 89 | try expect(y == 2); |
| 90 | try expect(z == 3); |
| 91 | } |
| 92 | }; |
| 93 | |
| 94 | try S.doTheTest(true); |
| 95 | try comptime S.doTheTest(true); |
| 96 | } |
| 97 | |
| 98 | test "destructure tuple value" { |
| 99 | const tup: struct { f32, u32, i64 } = .{ 10.0, 20, 30 }; |
| 100 | const x, const y, const z = tup; |
| 101 | |
| 102 | comptime assert(@TypeOf(x) == f32); |
| 103 | comptime assert(@TypeOf(y) == u32); |
| 104 | comptime assert(@TypeOf(z) == i64); |
| 105 | |
| 106 | try expect(x == 10.0); |
| 107 | try expect(y == 20); |
| 108 | try expect(z == 30); |
| 109 | } |
| 110 | |
| 111 | test "destructure array value" { |
| 112 | const arr: [3]u32 = .{ 10, 20, 30 }; |
| 113 | const x, const y, const z = arr; |
| 114 | |
| 115 | comptime assert(@TypeOf(x) == u32); |
| 116 | comptime assert(@TypeOf(y) == u32); |
| 117 | comptime assert(@TypeOf(z) == u32); |
| 118 | |
| 119 | try expect(x == 10); |
| 120 | try expect(y == 20); |
| 121 | try expect(z == 30); |
| 122 | } |
| 123 | |
| 124 | test "destructure from struct init with named tuple fields" { |
| 125 | const Tuple = struct { u8, u16, u32 }; |
| 126 | const x, const y, const z = Tuple{ |
| 127 | .@"0" = 100, |
| 128 | .@"1" = 200, |
| 129 | .@"2" = 300, |
| 130 | }; |
| 131 | |
| 132 | comptime assert(@TypeOf(x) == u8); |
| 133 | comptime assert(@TypeOf(y) == u16); |
| 134 | comptime assert(@TypeOf(z) == u32); |
| 135 | |
| 136 | try expect(x == 100); |
| 137 | try expect(y == 200); |
| 138 | try expect(z == 300); |
| 139 | } |
| 140 | |
| 141 | test "destructure of comptime-known tuple is comptime-known" { |
| 142 | const x, const y = .{ 1, 2 }; |
| 143 | |
| 144 | comptime assert(@TypeOf(x) == comptime_int); |
| 145 | comptime assert(x == 1); |
| 146 | |
| 147 | comptime assert(@TypeOf(y) == comptime_int); |
| 148 | comptime assert(y == 2); |
| 149 | } |
| 150 | |
| 151 | test "destructure of comptime-known tuple where some destinations are runtime-known is comptime-known" { |
| 152 | var z: u32 = undefined; |
| 153 | var x: u8, const y, z = .{ 1, 2, 3 }; |
| 154 | _ = &x; |
| 155 | |
| 156 | comptime assert(@TypeOf(y) == comptime_int); |
| 157 | comptime assert(y == 2); |
| 158 | |
| 159 | try expect(x == 1); |
| 160 | try expect(z == 3); |
| 161 | } |
| 162 | |
| 163 | test "destructure of tuple with comptime fields results in some comptime-known values" { |
| 164 | var runtime: u32 = 42; |
| 165 | _ = &runtime; |
| 166 | const a, const b, const c, const d = .{ 123, runtime, 456, runtime }; |
| 167 | |
| 168 | // a, c are comptime-known |
| 169 | // b, d are runtime-known |
| 170 | |
| 171 | comptime assert(@TypeOf(a) == comptime_int); |
| 172 | comptime assert(@TypeOf(b) == u32); |
| 173 | comptime assert(@TypeOf(c) == comptime_int); |
| 174 | comptime assert(@TypeOf(d) == u32); |
| 175 | |
| 176 | comptime assert(a == 123); |
| 177 | comptime assert(c == 456); |
| 178 | |
| 179 | try expect(b == 42); |
| 180 | try expect(d == 42); |
| 181 | } |
| 182 | |
| 183 | test "destructure vector" { |
| 184 | const vec: @Vector(2, i32) = .{ 1, 2 }; |
| 185 | const x, const y = vec; |
| 186 | |
| 187 | comptime assert(@TypeOf(x) == i32); |
| 188 | comptime assert(@TypeOf(y) == i32); |
| 189 | |
| 190 | try expect(x == 1); |
| 191 | try expect(y == 2); |
| 192 | } |