| author | |
| committer | |
| log | ffa700ee58cd29dafe2bbdfe78a4bd4f7bab0674 |
| tree | affe8b6dc716051f32259ad171f93d7009855c0f |
| parent | 6e42d45dccf4ba6fa07082db1cb820897d36924f |
| parent | 0a9d6956e7cac96c870ad062b4125b0a0a3b0143 |
| signature |
Fix (nearly) all stage2 crashes when testing stdlib43 files changed, 501 insertions(+), 626 deletions(-)
ci/zinc/linux_test.sh+1| ... | ... | @@ -59,6 +59,7 @@ stage2/bin/zig build -Dtarget=arm-linux-musleabihf # test building self-hosted f |
| 59 | 59 | # * https://github.com/ziglang/zig/issues/11367 (and corresponding workaround in compiler source) |
| 60 | 60 | # * https://github.com/ziglang/zig/pull/11492#issuecomment-1112871321 |
| 61 | 61 | stage2/bin/zig build test-behavior -fqemu -fwasmtime |
| 62 | stage2/bin/zig test lib/std/std.zig --zig-lib-dir lib | |
| 62 | 63 | |
| 63 | 64 | $ZIG build test-behavior -fqemu -fwasmtime -Domit-stage2 |
| 64 | 65 | $ZIG build test-compiler-rt -fqemu -fwasmtime |
lib/std/bit_set.zig+4| ... | ... | @@ -1330,6 +1330,7 @@ fn testStaticBitSet(comptime Set: type) !void { |
| 1330 | 1330 | } |
| 1331 | 1331 | |
| 1332 | 1332 | test "IntegerBitSet" { |
| 1333 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 1333 | 1334 | try testStaticBitSet(IntegerBitSet(0)); |
| 1334 | 1335 | try testStaticBitSet(IntegerBitSet(1)); |
| 1335 | 1336 | try testStaticBitSet(IntegerBitSet(2)); |
| ... | ... | @@ -1341,6 +1342,7 @@ test "IntegerBitSet" { |
| 1341 | 1342 | } |
| 1342 | 1343 | |
| 1343 | 1344 | test "ArrayBitSet" { |
| 1345 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 1344 | 1346 | if (@import("builtin").cpu.arch == .aarch64) { |
| 1345 | 1347 | // https://github.com/ziglang/zig/issues/9879 |
| 1346 | 1348 | return error.SkipZigTest; |
| ... | ... | @@ -1355,6 +1357,7 @@ test "ArrayBitSet" { |
| 1355 | 1357 | } |
| 1356 | 1358 | |
| 1357 | 1359 | test "DynamicBitSetUnmanaged" { |
| 1360 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 1358 | 1361 | const allocator = std.testing.allocator; |
| 1359 | 1362 | var a = try DynamicBitSetUnmanaged.initEmpty(allocator, 300); |
| 1360 | 1363 | try testing.expectEqual(@as(usize, 0), a.count()); |
| ... | ... | @@ -1395,6 +1398,7 @@ test "DynamicBitSetUnmanaged" { |
| 1395 | 1398 | } |
| 1396 | 1399 | |
| 1397 | 1400 | test "DynamicBitSet" { |
| 1401 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 1398 | 1402 | const allocator = std.testing.allocator; |
| 1399 | 1403 | var a = try DynamicBitSet.initEmpty(allocator, 300); |
| 1400 | 1404 | try testing.expectEqual(@as(usize, 0), a.count()); |
lib/std/compress.zig-1| ... | ... | @@ -5,7 +5,6 @@ pub const gzip = @import("compress/gzip.zig"); |
| 5 | 5 | pub const zlib = @import("compress/zlib.zig"); |
| 6 | 6 | |
| 7 | 7 | test { |
| 8 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; | |
| 9 | 8 | _ = deflate; |
| 10 | 9 | _ = gzip; |
| 11 | 10 | _ = zlib; |
lib/std/compress/deflate/compressor.zig+4-1| ... | ... | @@ -254,7 +254,10 @@ pub fn Compressor(comptime WriterType: anytype) type { |
| 254 | 254 | |
| 255 | 255 | // Inner writer wrapped in a HuffmanBitWriter |
| 256 | 256 | hm_bw: hm_bw.HuffmanBitWriter(WriterType) = undefined, |
| 257 | bulk_hasher: fn ([]u8, []u32) u32, | |
| 257 | bulk_hasher: if (@import("builtin").zig_backend == .stage1) | |
| 258 | fn ([]u8, []u32) u32 | |
| 259 | else | |
| 260 | *const fn ([]u8, []u32) u32, | |
| 258 | 261 | |
| 259 | 262 | sync: bool, // requesting flush |
| 260 | 263 | best_speed_enc: *fast.DeflateFast, // Encoder for best_speed |
lib/std/compress/deflate/compressor_test.zig+13-24| ... | ... | @@ -122,11 +122,8 @@ fn testToFromWithLevelAndLimit(level: deflate.Compression, input: []const u8, li |
| 122 | 122 | try expect(compressed.items.len <= limit); |
| 123 | 123 | } |
| 124 | 124 | |
| 125 | var decomp = try decompressor( | |
| 126 | testing.allocator, | |
| 127 | io.fixedBufferStream(compressed.items).reader(), | |
| 128 | null, | |
| 129 | ); | |
| 125 | var fib = io.fixedBufferStream(compressed.items); | |
| 126 | var decomp = try decompressor(testing.allocator, fib.reader(), null); | |
| 130 | 127 | defer decomp.deinit(); |
| 131 | 128 | |
| 132 | 129 | var decompressed = try testing.allocator.alloc(u8, input.len); |
| ... | ... | @@ -136,7 +133,9 @@ fn testToFromWithLevelAndLimit(level: deflate.Compression, input: []const u8, li |
| 136 | 133 | try expect(read == input.len); |
| 137 | 134 | try expect(mem.eql(u8, input, decompressed)); |
| 138 | 135 | |
| 139 | try testSync(level, input); | |
| 136 | if (builtin.zig_backend == .stage1) { | |
| 137 | try testSync(level, input); | |
| 138 | } | |
| 140 | 139 | } |
| 141 | 140 | |
| 142 | 141 | fn testToFromWithLimit(input: []const u8, limit: [11]u32) !void { |
| ... | ... | @@ -475,21 +474,16 @@ test "inflate reset" { |
| 475 | 474 | try comp.close(); |
| 476 | 475 | } |
| 477 | 476 | |
| 478 | var decomp = try decompressor( | |
| 479 | testing.allocator, | |
| 480 | io.fixedBufferStream(compressed_strings[0].items).reader(), | |
| 481 | null, | |
| 482 | ); | |
| 477 | var fib = io.fixedBufferStream(compressed_strings[0].items); | |
| 478 | var decomp = try decompressor(testing.allocator, fib.reader(), null); | |
| 483 | 479 | defer decomp.deinit(); |
| 484 | 480 | |
| 485 | 481 | var decompressed_0: []u8 = try decomp.reader() |
| 486 | 482 | .readAllAlloc(testing.allocator, math.maxInt(usize)); |
| 487 | 483 | defer testing.allocator.free(decompressed_0); |
| 488 | 484 | |
| 489 | try decomp.reset( | |
| 490 | io.fixedBufferStream(compressed_strings[1].items).reader(), | |
| 491 | null, | |
| 492 | ); | |
| 485 | fib = io.fixedBufferStream(compressed_strings[1].items); | |
| 486 | try decomp.reset(fib.reader(), null); | |
| 493 | 487 | |
| 494 | 488 | var decompressed_1: []u8 = try decomp.reader() |
| 495 | 489 | .readAllAlloc(testing.allocator, math.maxInt(usize)); |
| ... | ... | @@ -530,21 +524,16 @@ test "inflate reset dictionary" { |
| 530 | 524 | try comp.close(); |
| 531 | 525 | } |
| 532 | 526 | |
| 533 | var decomp = try decompressor( | |
| 534 | testing.allocator, | |
| 535 | io.fixedBufferStream(compressed_strings[0].items).reader(), | |
| 536 | dict, | |
| 537 | ); | |
| 527 | var fib = io.fixedBufferStream(compressed_strings[0].items); | |
| 528 | var decomp = try decompressor(testing.allocator, fib.reader(), dict); | |
| 538 | 529 | defer decomp.deinit(); |
| 539 | 530 | |
| 540 | 531 | var decompressed_0: []u8 = try decomp.reader() |
| 541 | 532 | .readAllAlloc(testing.allocator, math.maxInt(usize)); |
| 542 | 533 | defer testing.allocator.free(decompressed_0); |
| 543 | 534 | |
| 544 | try decomp.reset( | |
| 545 | io.fixedBufferStream(compressed_strings[1].items).reader(), | |
| 546 | dict, | |
| 547 | ); | |
| 535 | fib = io.fixedBufferStream(compressed_strings[1].items); | |
| 536 | try decomp.reset(fib.reader(), dict); | |
| 548 | 537 | |
| 549 | 538 | var decompressed_1: []u8 = try decomp.reader() |
| 550 | 539 | .readAllAlloc(testing.allocator, math.maxInt(usize)); |
lib/std/compress/deflate/decompressor.zig+19-6| ... | ... | @@ -334,7 +334,10 @@ pub fn Decompressor(comptime ReaderType: type) type { |
| 334 | 334 | |
| 335 | 335 | // Next step in the decompression, |
| 336 | 336 | // and decompression state. |
| 337 | step: fn (*Self) Error!void, | |
| 337 | step: if (@import("builtin").zig_backend == .stage1) | |
| 338 | fn (*Self) Error!void | |
| 339 | else | |
| 340 | *const fn (*Self) Error!void, | |
| 338 | 341 | step_state: DecompressorState, |
| 339 | 342 | final: bool, |
| 340 | 343 | err: ?Error, |
| ... | ... | @@ -479,7 +482,13 @@ pub fn Decompressor(comptime ReaderType: type) type { |
| 479 | 482 | } |
| 480 | 483 | |
| 481 | 484 | pub fn close(self: *Self) ?Error { |
| 482 | if (self.err == Error.EndOfStreamWithNoError) { | |
| 485 | if (@import("builtin").zig_backend == .stage1) { | |
| 486 | if (self.err == Error.EndOfStreamWithNoError) { | |
| 487 | return null; | |
| 488 | } | |
| 489 | return self.err; | |
| 490 | } | |
| 491 | if (self.err == @as(?Error, error.EndOfStreamWithNoError)) { | |
| 483 | 492 | return null; |
| 484 | 493 | } |
| 485 | 494 | return self.err; |
| ... | ... | @@ -920,7 +929,8 @@ test "truncated input" { |
| 920 | 929 | }; |
| 921 | 930 | |
| 922 | 931 | for (tests) |t| { |
| 923 | var r = io.fixedBufferStream(t.input).reader(); | |
| 932 | var fib = io.fixedBufferStream(t.input); | |
| 933 | const r = fib.reader(); | |
| 924 | 934 | var z = try decompressor(testing.allocator, r, null); |
| 925 | 935 | defer z.deinit(); |
| 926 | 936 | var zr = z.reader(); |
| ... | ... | @@ -959,7 +969,8 @@ test "Go non-regression test for 9842" { |
| 959 | 969 | }; |
| 960 | 970 | |
| 961 | 971 | for (tests) |t| { |
| 962 | const reader = std.io.fixedBufferStream(t.input).reader(); | |
| 972 | var fib = std.io.fixedBufferStream(t.input); | |
| 973 | const reader = fib.reader(); | |
| 963 | 974 | var decomp = try decompressor(testing.allocator, reader, null); |
| 964 | 975 | defer decomp.deinit(); |
| 965 | 976 | |
| ... | ... | @@ -1017,7 +1028,8 @@ test "inflate A Tale of Two Cities (1859) intro" { |
| 1017 | 1028 | \\ |
| 1018 | 1029 | ; |
| 1019 | 1030 | |
| 1020 | const reader = std.io.fixedBufferStream(&compressed).reader(); | |
| 1031 | var fib = std.io.fixedBufferStream(&compressed); | |
| 1032 | const reader = fib.reader(); | |
| 1021 | 1033 | var decomp = try decompressor(testing.allocator, reader, null); |
| 1022 | 1034 | defer decomp.deinit(); |
| 1023 | 1035 | |
| ... | ... | @@ -1082,7 +1094,8 @@ test "fuzzing" { |
| 1082 | 1094 | |
| 1083 | 1095 | fn decompress(input: []const u8) !void { |
| 1084 | 1096 | const allocator = testing.allocator; |
| 1085 | const reader = std.io.fixedBufferStream(input).reader(); | |
| 1097 | var fib = std.io.fixedBufferStream(input); | |
| 1098 | const reader = fib.reader(); | |
| 1086 | 1099 | var decomp = try decompressor(allocator, reader, null); |
| 1087 | 1100 | defer decomp.deinit(); |
| 1088 | 1101 | var output = try decomp.reader().readAllAlloc(allocator, math.maxInt(usize)); |
lib/std/compress/deflate/deflate_fast_test.zig+6-12| ... | ... | @@ -78,11 +78,8 @@ test "best speed" { |
| 78 | 78 | var decompressed = try testing.allocator.alloc(u8, want.items.len); |
| 79 | 79 | defer testing.allocator.free(decompressed); |
| 80 | 80 | |
| 81 | var decomp = try inflate.decompressor( | |
| 82 | testing.allocator, | |
| 83 | io.fixedBufferStream(compressed.items).reader(), | |
| 84 | null, | |
| 85 | ); | |
| 81 | var fib = io.fixedBufferStream(compressed.items); | |
| 82 | var decomp = try inflate.decompressor(testing.allocator, fib.reader(), null); | |
| 86 | 83 | defer decomp.deinit(); |
| 87 | 84 | |
| 88 | 85 | var read = try decomp.reader().readAll(decompressed); |
| ... | ... | @@ -122,13 +119,13 @@ test "best speed max match offset" { |
| 122 | 119 | //	zeros1 is between 0 and 30 zeros. |
| 123 | 120 | // The difference between the two abc's will be offset, which |
| 124 | 121 | // is max_match_offset plus or minus a small adjustment. |
| 125 | var src_len: usize = @intCast(usize, offset + abc.len + @intCast(i32, extra)); | |
| 122 | var src_len: usize = @intCast(usize, offset + @as(i32, abc.len) + @intCast(i32, extra)); | |
| 126 | 123 | var src = try testing.allocator.alloc(u8, src_len); |
| 127 | 124 | defer testing.allocator.free(src); |
| 128 | 125 | |
| 129 | 126 | mem.copy(u8, src, abc); |
| 130 | 127 | if (!do_match_before) { |
| 131 | var src_offset: usize = @intCast(usize, offset - xyz.len); | |
| 128 | var src_offset: usize = @intCast(usize, offset - @as(i32, xyz.len)); | |
| 132 | 129 | mem.copy(u8, src[src_offset..], xyz); |
| 133 | 130 | } |
| 134 | 131 | var src_offset: usize = @intCast(usize, offset); |
| ... | ... | @@ -149,11 +146,8 @@ test "best speed max match offset" { |
| 149 | 146 | var decompressed = try testing.allocator.alloc(u8, src.len); |
| 150 | 147 | defer testing.allocator.free(decompressed); |
| 151 | 148 | |
| 152 | var decomp = try inflate.decompressor( | |
| 153 | testing.allocator, | |
| 154 | io.fixedBufferStream(compressed.items).reader(), | |
| 155 | null, | |
| 156 | ); | |
| 149 | var fib = io.fixedBufferStream(compressed.items); | |
| 150 | var decomp = try inflate.decompressor(testing.allocator, fib.reader(), null); | |
| 157 | 151 | defer decomp.deinit(); |
| 158 | 152 | var read = try decomp.reader().readAll(decompressed); |
| 159 | 153 | _ = decomp.close(); |
lib/std/crypto/argon2.zig+2| ... | ... | @@ -897,6 +897,7 @@ test "kdf" { |
| 897 | 897 | } |
| 898 | 898 | |
| 899 | 899 | test "phc format hasher" { |
| 900 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 900 | 901 | const allocator = std.testing.allocator; |
| 901 | 902 | const password = "testpass"; |
| 902 | 903 | |
| ... | ... | @@ -912,6 +913,7 @@ test "phc format hasher" { |
| 912 | 913 | } |
| 913 | 914 | |
| 914 | 915 | test "password hash and password verify" { |
| 916 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 915 | 917 | const allocator = std.testing.allocator; |
| 916 | 918 | const password = "testpass"; |
| 917 | 919 |
lib/std/crypto/bcrypt.zig+1| ... | ... | @@ -802,6 +802,7 @@ test "bcrypt crypt format" { |
| 802 | 802 | } |
| 803 | 803 | |
| 804 | 804 | test "bcrypt phc format" { |
| 805 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 805 | 806 | const hash_options = HashOptions{ |
| 806 | 807 | .params = .{ .rounds_log = 5 }, |
| 807 | 808 | .encoding = .phc, |
lib/std/crypto/phc_encoding.zig+1| ... | ... | @@ -260,6 +260,7 @@ fn kvSplit(str: []const u8) !struct { key: []const u8, value: []const u8 } { |
| 260 | 260 | } |
| 261 | 261 | |
| 262 | 262 | test "phc format - encoding/decoding" { |
| 263 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 263 | 264 | const Input = struct { |
| 264 | 265 | str: []const u8, |
| 265 | 266 | HashResult: type, |
lib/std/crypto/scrypt.zig+1| ... | ... | @@ -683,6 +683,7 @@ test "unix-scrypt" { |
| 683 | 683 | } |
| 684 | 684 | |
| 685 | 685 | test "crypt format" { |
| 686 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 686 | 687 | const str = "$7$C6..../....SodiumChloride$kBGj9fHznVYFQMEn/qDCfrDevf9YDtcDdKvEqHJLV8D"; |
| 687 | 688 | const params = try crypt_format.deserialize(crypt_format.HashResult(32), str); |
| 688 | 689 | var buf: [str.len]u8 = undefined; |
lib/std/fmt.zig+48-22| ... | ... | @@ -2111,7 +2111,6 @@ test "slice" { |
| 2111 | 2111 | } |
| 2112 | 2112 | |
| 2113 | 2113 | test "escape non-printable" { |
| 2114 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; | |
| 2115 | 2114 | try expectFmt("abc", "{s}", .{fmtSliceEscapeLower("abc")}); |
| 2116 | 2115 | try expectFmt("ab\\xffc", "{s}", .{fmtSliceEscapeLower("ab\xffc")}); |
| 2117 | 2116 | try expectFmt("ab\\xFFc", "{s}", .{fmtSliceEscapeUpper("ab\xffc")}); |
| ... | ... | @@ -2148,7 +2147,6 @@ test "cstr" { |
| 2148 | 2147 | } |
| 2149 | 2148 | |
| 2150 | 2149 | test "filesize" { |
| 2151 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; | |
| 2152 | 2150 | try expectFmt("file size: 42B\n", "file size: {}\n", .{fmtIntSizeDec(42)}); |
| 2153 | 2151 | try expectFmt("file size: 42B\n", "file size: {}\n", .{fmtIntSizeBin(42)}); |
| 2154 | 2152 | try expectFmt("file size: 63MB\n", "file size: {}\n", .{fmtIntSizeDec(63 * 1000 * 1000)}); |
| ... | ... | @@ -2192,18 +2190,22 @@ test "enum" { |
| 2192 | 2190 | } |
| 2193 | 2191 | |
| 2194 | 2192 | test "non-exhaustive enum" { |
| 2193 | if (builtin.zig_backend == .stage1) { | |
| 2194 | // stage1 fails to return fully qualified namespaces. | |
| 2195 | return error.SkipZigTest; | |
| 2196 | } | |
| 2195 | 2197 | const Enum = enum(u16) { |
| 2196 | 2198 | One = 0x000f, |
| 2197 | 2199 | Two = 0xbeef, |
| 2198 | 2200 | _, |
| 2199 | 2201 | }; |
| 2200 | try expectFmt("enum: Enum.One\n", "enum: {}\n", .{Enum.One}); | |
| 2201 | try expectFmt("enum: Enum.Two\n", "enum: {}\n", .{Enum.Two}); | |
| 2202 | try expectFmt("enum: Enum(4660)\n", "enum: {}\n", .{@intToEnum(Enum, 0x1234)}); | |
| 2203 | try expectFmt("enum: Enum.One\n", "enum: {x}\n", .{Enum.One}); | |
| 2204 | try expectFmt("enum: Enum.Two\n", "enum: {x}\n", .{Enum.Two}); | |
| 2205 | try expectFmt("enum: Enum.Two\n", "enum: {X}\n", .{Enum.Two}); | |
| 2206 | try expectFmt("enum: Enum(1234)\n", "enum: {x}\n", .{@intToEnum(Enum, 0x1234)}); | |
| 2202 | try expectFmt("enum: fmt.test.non-exhaustive enum.Enum.One\n", "enum: {}\n", .{Enum.One}); | |
| 2203 | try expectFmt("enum: fmt.test.non-exhaustive enum.Enum.Two\n", "enum: {}\n", .{Enum.Two}); | |
| 2204 | try expectFmt("enum: fmt.test.non-exhaustive enum.Enum(4660)\n", "enum: {}\n", .{@intToEnum(Enum, 0x1234)}); | |
| 2205 | try expectFmt("enum: fmt.test.non-exhaustive enum.Enum.One\n", "enum: {x}\n", .{Enum.One}); | |
| 2206 | try expectFmt("enum: fmt.test.non-exhaustive enum.Enum.Two\n", "enum: {x}\n", .{Enum.Two}); | |
| 2207 | try expectFmt("enum: fmt.test.non-exhaustive enum.Enum.Two\n", "enum: {X}\n", .{Enum.Two}); | |
| 2208 | try expectFmt("enum: fmt.test.non-exhaustive enum.Enum(1234)\n", "enum: {x}\n", .{@intToEnum(Enum, 0x1234)}); | |
| 2207 | 2209 | } |
| 2208 | 2210 | |
| 2209 | 2211 | test "float.scientific" { |
| ... | ... | @@ -2223,6 +2225,7 @@ test "float.scientific.precision" { |
| 2223 | 2225 | } |
| 2224 | 2226 | |
| 2225 | 2227 | test "float.special" { |
| 2228 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 2226 | 2229 | try expectFmt("f64: nan", "f64: {}", .{math.nan_f64}); |
| 2227 | 2230 | // negative nan is not defined by IEE 754, |
| 2228 | 2231 | // and ARM thus normalizes it to positive nan |
| ... | ... | @@ -2234,6 +2237,7 @@ test "float.special" { |
| 2234 | 2237 | } |
| 2235 | 2238 | |
| 2236 | 2239 | test "float.hexadecimal.special" { |
| 2240 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 2237 | 2241 | try expectFmt("f64: nan", "f64: {x}", .{math.nan_f64}); |
| 2238 | 2242 | // negative nan is not defined by IEE 754, |
| 2239 | 2243 | // and ARM thus normalizes it to positive nan |
| ... | ... | @@ -2359,6 +2363,10 @@ test "custom" { |
| 2359 | 2363 | } |
| 2360 | 2364 | |
| 2361 | 2365 | test "struct" { |
| 2366 | if (builtin.zig_backend == .stage1) { | |
| 2367 | // stage1 fails to return fully qualified namespaces. | |
| 2368 | return error.SkipZigTest; | |
| 2369 | } | |
| 2362 | 2370 | const S = struct { |
| 2363 | 2371 | a: u32, |
| 2364 | 2372 | b: anyerror, |
| ... | ... | @@ -2369,7 +2377,7 @@ test "struct" { |
| 2369 | 2377 | .b = error.Unused, |
| 2370 | 2378 | }; |
| 2371 | 2379 | |
| 2372 | try expectFmt("S{ .a = 456, .b = error.Unused }", "{}", .{inst}); | |
| 2380 | try expectFmt("fmt.test.struct.S{ .a = 456, .b = error.Unused }", "{}", .{inst}); | |
| 2373 | 2381 | // Tuples |
| 2374 | 2382 | try expectFmt("{ }", "{}", .{.{}}); |
| 2375 | 2383 | try expectFmt("{ -1 }", "{}", .{.{-1}}); |
| ... | ... | @@ -2377,6 +2385,10 @@ test "struct" { |
| 2377 | 2385 | } |
| 2378 | 2386 | |
| 2379 | 2387 | test "union" { |
| 2388 | if (builtin.zig_backend == .stage1) { | |
| 2389 | // stage1 fails to return fully qualified namespaces. | |
| 2390 | return error.SkipZigTest; | |
| 2391 | } | |
| 2380 | 2392 | const TU = union(enum) { |
| 2381 | 2393 | float: f32, |
| 2382 | 2394 | int: u32, |
| ... | ... | @@ -2396,17 +2408,21 @@ test "union" { |
| 2396 | 2408 | const uu_inst = UU{ .int = 456 }; |
| 2397 | 2409 | const eu_inst = EU{ .float = 321.123 }; |
| 2398 | 2410 | |
| 2399 | try expectFmt("TU{ .int = 123 }", "{}", .{tu_inst}); | |
| 2411 | try expectFmt("fmt.test.union.TU{ .int = 123 }", "{}", .{tu_inst}); | |
| 2400 | 2412 | |
| 2401 | 2413 | var buf: [100]u8 = undefined; |
| 2402 | 2414 | const uu_result = try bufPrint(buf[0..], "{}", .{uu_inst}); |
| 2403 | try std.testing.expect(mem.eql(u8, uu_result[0..3], "UU@")); | |
| 2415 | try std.testing.expect(mem.eql(u8, uu_result[0..18], "fmt.test.union.UU@")); | |
| 2404 | 2416 | |
| 2405 | 2417 | const eu_result = try bufPrint(buf[0..], "{}", .{eu_inst}); |
| 2406 | try std.testing.expect(mem.eql(u8, eu_result[0..3], "EU@")); | |
| 2418 | try std.testing.expect(mem.eql(u8, eu_result[0..18], "fmt.test.union.EU@")); | |
| 2407 | 2419 | } |
| 2408 | 2420 | |
| 2409 | 2421 | test "enum" { |
| 2422 | if (builtin.zig_backend == .stage1) { | |
| 2423 | // stage1 fails to return fully qualified namespaces. | |
| 2424 | return error.SkipZigTest; | |
| 2425 | } | |
| 2410 | 2426 | const E = enum { |
| 2411 | 2427 | One, |
| 2412 | 2428 | Two, |
| ... | ... | @@ -2415,10 +2431,14 @@ test "enum" { |
| 2415 | 2431 | |
| 2416 | 2432 | const inst = E.Two; |
| 2417 | 2433 | |
| 2418 | try expectFmt("E.Two", "{}", .{inst}); | |
| 2434 | try expectFmt("fmt.test.enum.E.Two", "{}", .{inst}); | |
| 2419 | 2435 | } |
| 2420 | 2436 | |
| 2421 | 2437 | test "struct.self-referential" { |
| 2438 | if (builtin.zig_backend == .stage1) { | |
| 2439 | // stage1 fails to return fully qualified namespaces. | |
| 2440 | return error.SkipZigTest; | |
| 2441 | } | |
| 2422 | 2442 | const S = struct { |
| 2423 | 2443 | const SelfType = @This(); |
| 2424 | 2444 | a: ?*SelfType, |
| ... | ... | @@ -2429,10 +2449,14 @@ test "struct.self-referential" { |
| 2429 | 2449 | }; |
| 2430 | 2450 | inst.a = &inst; |
| 2431 | 2451 | |
| 2432 | try expectFmt("S{ .a = S{ .a = S{ .a = S{ ... } } } }", "{}", .{inst}); | |
| 2452 | try expectFmt("fmt.test.struct.self-referential.S{ .a = fmt.test.struct.self-referential.S{ .a = fmt.test.struct.self-referential.S{ .a = fmt.test.struct.self-referential.S{ ... } } } }", "{}", .{inst}); | |
| 2433 | 2453 | } |
| 2434 | 2454 | |
| 2435 | 2455 | test "struct.zero-size" { |
| 2456 | if (builtin.zig_backend == .stage1) { | |
| 2457 | // stage1 fails to return fully qualified namespaces. | |
| 2458 | return error.SkipZigTest; | |
| 2459 | } | |
| 2436 | 2460 | const A = struct { |
| 2437 | 2461 | fn foo() void {} |
| 2438 | 2462 | }; |
| ... | ... | @@ -2444,11 +2468,10 @@ test "struct.zero-size" { |
| 2444 | 2468 | const a = A{}; |
| 2445 | 2469 | const b = B{ .a = a, .c = 0 }; |
| 2446 | 2470 | |
| 2447 | try expectFmt("B{ .a = A{ }, .c = 0 }", "{}", .{b}); | |
| 2471 | try expectFmt("fmt.test.struct.zero-size.B{ .a = fmt.test.struct.zero-size.A{ }, .c = 0 }", "{}", .{b}); | |
| 2448 | 2472 | } |
| 2449 | 2473 | |
| 2450 | 2474 | test "bytes.hex" { |
| 2451 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; | |
| 2452 | 2475 | const some_bytes = "\xCA\xFE\xBA\xBE"; |
| 2453 | 2476 | try expectFmt("lowercase: cafebabe\n", "lowercase: {x}\n", .{fmtSliceHexLower(some_bytes)}); |
| 2454 | 2477 | try expectFmt("uppercase: CAFEBABE\n", "uppercase: {X}\n", .{fmtSliceHexUpper(some_bytes)}); |
| ... | ... | @@ -2480,7 +2503,6 @@ pub fn hexToBytes(out: []u8, input: []const u8) ![]u8 { |
| 2480 | 2503 | } |
| 2481 | 2504 | |
| 2482 | 2505 | test "hexToBytes" { |
| 2483 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; | |
| 2484 | 2506 | var buf: [32]u8 = undefined; |
| 2485 | 2507 | try expectFmt("90" ** 32, "{s}", .{fmtSliceHexUpper(try hexToBytes(&buf, "90" ** 32))}); |
| 2486 | 2508 | try expectFmt("ABCD", "{s}", .{fmtSliceHexUpper(try hexToBytes(&buf, "ABCD"))}); |
| ... | ... | @@ -2512,6 +2534,10 @@ test "formatFloatValue with comptime_float" { |
| 2512 | 2534 | } |
| 2513 | 2535 | |
| 2514 | 2536 | test "formatType max_depth" { |
| 2537 | if (builtin.zig_backend == .stage1) { | |
| 2538 | // stage1 fails to return fully qualified namespaces. | |
| 2539 | return error.SkipZigTest; | |
| 2540 | } | |
| 2515 | 2541 | const Vec2 = struct { |
| 2516 | 2542 | const SelfType = @This(); |
| 2517 | 2543 | x: f32, |
| ... | ... | @@ -2562,19 +2588,19 @@ test "formatType max_depth" { |
| 2562 | 2588 | var buf: [1000]u8 = undefined; |
| 2563 | 2589 | var fbs = std.io.fixedBufferStream(&buf); |
| 2564 | 2590 | try formatType(inst, "", FormatOptions{}, fbs.writer(), 0); |
| 2565 | try std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ ... }")); | |
| 2591 | try std.testing.expect(mem.eql(u8, fbs.getWritten(), "fmt.test.formatType max_depth.S{ ... }")); | |
| 2566 | 2592 | |
| 2567 | 2593 | fbs.reset(); |
| 2568 | 2594 | try formatType(inst, "", FormatOptions{}, fbs.writer(), 1); |
| 2569 | try std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }")); | |
| 2595 | try std.testing.expect(mem.eql(u8, fbs.getWritten(), "fmt.test.formatType max_depth.S{ .a = fmt.test.formatType max_depth.S{ ... }, .tu = fmt.test.formatType max_depth.TU{ ... }, .e = fmt.test.formatType max_depth.E.Two, .vec = (10.200,2.220) }")); | |
| 2570 | 2596 | |
| 2571 | 2597 | fbs.reset(); |
| 2572 | 2598 | try formatType(inst, "", FormatOptions{}, fbs.writer(), 2); |
| 2573 | try std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }")); | |
| 2599 | try std.testing.expect(mem.eql(u8, fbs.getWritten(), "fmt.test.formatType max_depth.S{ .a = fmt.test.formatType max_depth.S{ .a = fmt.test.formatType max_depth.S{ ... }, .tu = fmt.test.formatType max_depth.TU{ ... }, .e = fmt.test.formatType max_depth.E.Two, .vec = (10.200,2.220) }, .tu = fmt.test.formatType max_depth.TU{ .ptr = fmt.test.formatType max_depth.TU{ ... } }, .e = fmt.test.formatType max_depth.E.Two, .vec = (10.200,2.220) }")); | |
| 2574 | 2600 | |
| 2575 | 2601 | fbs.reset(); |
| 2576 | 2602 | try formatType(inst, "", FormatOptions{}, fbs.writer(), 3); |
| 2577 | try std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ .a = S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ .ptr = TU{ ... } } }, .e = E.Two, .vec = (10.200,2.220) }")); | |
| 2603 | try std.testing.expect(mem.eql(u8, fbs.getWritten(), "fmt.test.formatType max_depth.S{ .a = fmt.test.formatType max_depth.S{ .a = fmt.test.formatType max_depth.S{ .a = fmt.test.formatType max_depth.S{ ... }, .tu = fmt.test.formatType max_depth.TU{ ... }, .e = fmt.test.formatType max_depth.E.Two, .vec = (10.200,2.220) }, .tu = fmt.test.formatType max_depth.TU{ .ptr = fmt.test.formatType max_depth.TU{ ... } }, .e = fmt.test.formatType max_depth.E.Two, .vec = (10.200,2.220) }, .tu = fmt.test.formatType max_depth.TU{ .ptr = fmt.test.formatType max_depth.TU{ .ptr = fmt.test.formatType max_depth.TU{ ... } } }, .e = fmt.test.formatType max_depth.E.Two, .vec = (10.200,2.220) }")); | |
| 2578 | 2604 | } |
| 2579 | 2605 | |
| 2580 | 2606 | test "positional" { |
lib/std/io/stream_source.zig-1| ... | ... | @@ -114,7 +114,6 @@ test "StreamSource (mutable buffer)" { |
| 114 | 114 | } |
| 115 | 115 | |
| 116 | 116 | test "StreamSource (const buffer)" { |
| 117 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; | |
| 118 | 117 | const buffer: [64]u8 = "Hello, World!".* ++ ([1]u8{0xAA} ** 51); |
| 119 | 118 | var source = StreamSource{ .const_buffer = std.io.fixedBufferStream(&buffer) }; |
| 120 | 119 |
lib/std/math/copysign.zig+1| ... | ... | @@ -13,6 +13,7 @@ pub fn copysign(magnitude: anytype, sign: @TypeOf(magnitude)) @TypeOf(magnitude) |
| 13 | 13 | } |
| 14 | 14 | |
| 15 | 15 | test "math.copysign" { |
| 16 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 16 | 17 | inline for ([_]type{ f16, f32, f64, f80, f128 }) |T| { |
| 17 | 18 | try expect(copysign(@as(T, 1.0), @as(T, 1.0)) == 1.0); |
| 18 | 19 | try expect(copysign(@as(T, 2.0), @as(T, -2.0)) == -2.0); |
lib/std/math/signbit.zig+1| ... | ... | @@ -10,6 +10,7 @@ pub fn signbit(x: anytype) bool { |
| 10 | 10 | } |
| 11 | 11 | |
| 12 | 12 | test "math.signbit" { |
| 13 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 13 | 14 | inline for ([_]type{ f16, f32, f64, f80, f128 }) |T| { |
| 14 | 15 | try expect(!signbit(@as(T, 0.0))); |
| 15 | 16 | try expect(!signbit(@as(T, 1.0))); |
lib/std/mem.zig+1| ... | ... | @@ -2080,6 +2080,7 @@ fn testReadIntImpl() !void { |
| 2080 | 2080 | } |
| 2081 | 2081 | |
| 2082 | 2082 | test "writeIntSlice" { |
| 2083 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 2083 | 2084 | try testWriteIntImpl(); |
| 2084 | 2085 | comptime try testWriteIntImpl(); |
| 2085 | 2086 | } |
lib/std/priority_queue.zig+14| ... | ... | @@ -286,6 +286,7 @@ const PQlt = PriorityQueue(u32, void, lessThan); |
| 286 | 286 | const PQgt = PriorityQueue(u32, void, greaterThan); |
| 287 | 287 | |
| 288 | 288 | test "std.PriorityQueue: add and remove min heap" { |
| 289 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 289 | 290 | var queue = PQlt.init(testing.allocator, {}); |
| 290 | 291 | defer queue.deinit(); |
| 291 | 292 | |
| ... | ... | @@ -304,6 +305,7 @@ test "std.PriorityQueue: add and remove min heap" { |
| 304 | 305 | } |
| 305 | 306 | |
| 306 | 307 | test "std.PriorityQueue: add and remove same min heap" { |
| 308 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 307 | 309 | var queue = PQlt.init(testing.allocator, {}); |
| 308 | 310 | defer queue.deinit(); |
| 309 | 311 | |
| ... | ... | @@ -353,6 +355,7 @@ test "std.PriorityQueue: peek" { |
| 353 | 355 | } |
| 354 | 356 | |
| 355 | 357 | test "std.PriorityQueue: sift up with odd indices" { |
| 358 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 356 | 359 | var queue = PQlt.init(testing.allocator, {}); |
| 357 | 360 | defer queue.deinit(); |
| 358 | 361 | const items = [_]u32{ 15, 7, 21, 14, 13, 22, 12, 6, 7, 25, 5, 24, 11, 16, 15, 24, 2, 1 }; |
| ... | ... | @@ -367,6 +370,7 @@ test "std.PriorityQueue: sift up with odd indices" { |
| 367 | 370 | } |
| 368 | 371 | |
| 369 | 372 | test "std.PriorityQueue: addSlice" { |
| 373 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 370 | 374 | var queue = PQlt.init(testing.allocator, {}); |
| 371 | 375 | defer queue.deinit(); |
| 372 | 376 | const items = [_]u32{ 15, 7, 21, 14, 13, 22, 12, 6, 7, 25, 5, 24, 11, 16, 15, 24, 2, 1 }; |
| ... | ... | @@ -412,6 +416,7 @@ test "std.PriorityQueue: fromOwnedSlice" { |
| 412 | 416 | } |
| 413 | 417 | |
| 414 | 418 | test "std.PriorityQueue: add and remove max heap" { |
| 419 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 415 | 420 | var queue = PQgt.init(testing.allocator, {}); |
| 416 | 421 | defer queue.deinit(); |
| 417 | 422 | |
| ... | ... | @@ -430,6 +435,7 @@ test "std.PriorityQueue: add and remove max heap" { |
| 430 | 435 | } |
| 431 | 436 | |
| 432 | 437 | test "std.PriorityQueue: add and remove same max heap" { |
| 438 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 433 | 439 | var queue = PQgt.init(testing.allocator, {}); |
| 434 | 440 | defer queue.deinit(); |
| 435 | 441 | |
| ... | ... | @@ -470,6 +476,7 @@ test "std.PriorityQueue: iterator" { |
| 470 | 476 | } |
| 471 | 477 | |
| 472 | 478 | test "std.PriorityQueue: remove at index" { |
| 479 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 473 | 480 | var queue = PQlt.init(testing.allocator, {}); |
| 474 | 481 | defer queue.deinit(); |
| 475 | 482 | |
| ... | ... | @@ -505,6 +512,7 @@ test "std.PriorityQueue: iterator while empty" { |
| 505 | 512 | } |
| 506 | 513 | |
| 507 | 514 | test "std.PriorityQueue: shrinkAndFree" { |
| 515 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 508 | 516 | var queue = PQlt.init(testing.allocator, {}); |
| 509 | 517 | defer queue.deinit(); |
| 510 | 518 | |
| ... | ... | @@ -528,6 +536,7 @@ test "std.PriorityQueue: shrinkAndFree" { |
| 528 | 536 | } |
| 529 | 537 | |
| 530 | 538 | test "std.PriorityQueue: update min heap" { |
| 539 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 531 | 540 | var queue = PQlt.init(testing.allocator, {}); |
| 532 | 541 | defer queue.deinit(); |
| 533 | 542 | |
| ... | ... | @@ -543,6 +552,7 @@ test "std.PriorityQueue: update min heap" { |
| 543 | 552 | } |
| 544 | 553 | |
| 545 | 554 | test "std.PriorityQueue: update same min heap" { |
| 555 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 546 | 556 | var queue = PQlt.init(testing.allocator, {}); |
| 547 | 557 | defer queue.deinit(); |
| 548 | 558 | |
| ... | ... | @@ -559,6 +569,7 @@ test "std.PriorityQueue: update same min heap" { |
| 559 | 569 | } |
| 560 | 570 | |
| 561 | 571 | test "std.PriorityQueue: update max heap" { |
| 572 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 562 | 573 | var queue = PQgt.init(testing.allocator, {}); |
| 563 | 574 | defer queue.deinit(); |
| 564 | 575 | |
| ... | ... | @@ -574,6 +585,7 @@ test "std.PriorityQueue: update max heap" { |
| 574 | 585 | } |
| 575 | 586 | |
| 576 | 587 | test "std.PriorityQueue: update same max heap" { |
| 588 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 577 | 589 | var queue = PQgt.init(testing.allocator, {}); |
| 578 | 590 | defer queue.deinit(); |
| 579 | 591 | |
| ... | ... | @@ -590,6 +602,7 @@ test "std.PriorityQueue: update same max heap" { |
| 590 | 602 | } |
| 591 | 603 | |
| 592 | 604 | test "std.PriorityQueue: siftUp in remove" { |
| 605 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 593 | 606 | var queue = PQlt.init(testing.allocator, {}); |
| 594 | 607 | defer queue.deinit(); |
| 595 | 608 | |
| ... | ... | @@ -610,6 +623,7 @@ fn contextLessThan(context: []const u32, a: usize, b: usize) Order { |
| 610 | 623 | const CPQlt = PriorityQueue(usize, []const u32, contextLessThan); |
| 611 | 624 | |
| 612 | 625 | test "std.PriorityQueue: add and remove min heap with contextful comparator" { |
| 626 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 613 | 627 | const context = [_]u32{ 5, 3, 4, 2, 2, 8, 0 }; |
| 614 | 628 | |
| 615 | 629 | var queue = CPQlt.init(testing.allocator, context[0..]); |
lib/std/tz.zig+3| ... | ... | @@ -214,6 +214,7 @@ pub const Tz = struct { |
| 214 | 214 | }; |
| 215 | 215 | |
| 216 | 216 | test "slim" { |
| 217 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 217 | 218 | const data = @embedFile("tz/asia_tokyo.tzif"); |
| 218 | 219 | var in_stream = std.io.fixedBufferStream(data); |
| 219 | 220 | |
| ... | ... | @@ -227,6 +228,7 @@ test "slim" { |
| 227 | 228 | } |
| 228 | 229 | |
| 229 | 230 | test "fat" { |
| 231 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 230 | 232 | const data = @embedFile("tz/antarctica_davis.tzif"); |
| 231 | 233 | var in_stream = std.io.fixedBufferStream(data); |
| 232 | 234 | |
| ... | ... | @@ -239,6 +241,7 @@ test "fat" { |
| 239 | 241 | } |
| 240 | 242 | |
| 241 | 243 | test "legacy" { |
| 244 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 242 | 245 | // Taken from Slackware 8.0, from 2001 |
| 243 | 246 | const data = @embedFile("tz/europe_vatican.tzif"); |
| 244 | 247 | var in_stream = std.io.fixedBufferStream(data); |
lib/std/unicode.zig-1| ... | ... | @@ -804,7 +804,6 @@ pub fn fmtUtf16le(utf16le: []const u16) std.fmt.Formatter(formatUtf16le) { |
| 804 | 804 | } |
| 805 | 805 | |
| 806 | 806 | test "fmtUtf16le" { |
| 807 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; | |
| 808 | 807 | const expectFmt = std.testing.expectFmt; |
| 809 | 808 | try expectFmt("", "{}", .{fmtUtf16le(utf8ToUtf16LeStringLiteral(""))}); |
| 810 | 809 | try expectFmt("foo", "{}", .{fmtUtf16le(utf8ToUtf16LeStringLiteral("foo"))}); |
lib/std/x.zig-1| ... | ... | @@ -13,7 +13,6 @@ pub const net = struct { |
| 13 | 13 | }; |
| 14 | 14 | |
| 15 | 15 | test { |
| 16 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; | |
| 17 | 16 | inline for (.{ os, net }) |module| { |
| 18 | 17 | std.testing.refAllDecls(module); |
| 19 | 18 | } |
lib/std/x/os/io.zig+1| ... | ... | @@ -117,6 +117,7 @@ pub const Reactor = struct { |
| 117 | 117 | }; |
| 118 | 118 | |
| 119 | 119 | test "reactor/linux: drive async tcp client/listener pair" { |
| 120 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; | |
| 120 | 121 | if (native_os.tag != .linux) return error.SkipZigTest; |
| 121 | 122 | |
| 122 | 123 | const ip = std.x.net.ip; |
lib/std/x/os/net.zig+1-1| ... | ... | @@ -381,7 +381,7 @@ pub const IPv6 = extern struct { |
| 381 | 381 | }); |
| 382 | 382 | } |
| 383 | 383 | |
| 384 | const zero_span = span: { | |
| 384 | const zero_span: struct { from: usize, to: usize } = span: { | |
| 385 | 385 | var i: usize = 0; |
| 386 | 386 | while (i < self.octets.len) : (i += 2) { |
| 387 | 387 | if (self.octets[i] == 0 and self.octets[i + 1] == 0) break; |
src/AstGen.zig+7| ... | ... | @@ -2753,7 +2753,10 @@ fn varDecl( |
| 2753 | 2753 | const result_loc: ResultLoc = if (type_node != 0) .{ |
| 2754 | 2754 | .ty = try typeExpr(gz, scope, type_node), |
| 2755 | 2755 | } else .none; |
| 2756 | const prev_anon_name_strategy = gz.anon_name_strategy; | |
| 2757 | gz.anon_name_strategy = .dbg_var; | |
| 2756 | 2758 | const init_inst = try reachableExpr(gz, scope, result_loc, var_decl.ast.init_node, node); |
| 2759 | gz.anon_name_strategy = prev_anon_name_strategy; | |
| 2757 | 2760 | |
| 2758 | 2761 | try gz.addDbgVar(.dbg_var_val, ident_name, init_inst); |
| 2759 | 2762 | |
| ... | ... | @@ -2777,6 +2780,7 @@ fn varDecl( |
| 2777 | 2780 | var init_scope = gz.makeSubBlock(scope); |
| 2778 | 2781 | // we may add more instructions to gz before stacking init_scope |
| 2779 | 2782 | init_scope.instructions_top = GenZir.unstacked_top; |
| 2783 | init_scope.anon_name_strategy = .dbg_var; | |
| 2780 | 2784 | defer init_scope.unstack(); |
| 2781 | 2785 | |
| 2782 | 2786 | var resolve_inferred_alloc: Zir.Inst.Ref = .none; |
| ... | ... | @@ -2956,7 +2960,10 @@ fn varDecl( |
| 2956 | 2960 | resolve_inferred_alloc = alloc; |
| 2957 | 2961 | break :a .{ .alloc = alloc, .result_loc = .{ .inferred_ptr = alloc } }; |
| 2958 | 2962 | }; |
| 2963 | const prev_anon_name_strategy = gz.anon_name_strategy; | |
| 2964 | gz.anon_name_strategy = .dbg_var; | |
| 2959 | 2965 | _ = try reachableExprComptime(gz, scope, var_data.result_loc, var_decl.ast.init_node, node, is_comptime); |
| 2966 | gz.anon_name_strategy = prev_anon_name_strategy; | |
| 2960 | 2967 | if (resolve_inferred_alloc != .none) { |
| 2961 | 2968 | _ = try gz.addUnNode(.resolve_inferred_alloc, resolve_inferred_alloc, node); |
| 2962 | 2969 | } |
src/Module.zig+5-2| ... | ... | @@ -3790,9 +3790,12 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void { |
| 3790 | 3790 | defer liveness.deinit(gpa); |
| 3791 | 3791 | |
| 3792 | 3792 | if (builtin.mode == .Debug and mod.comp.verbose_air) { |
| 3793 | std.debug.print("# Begin Function AIR: {s}:\n", .{decl.name}); | |
| 3793 | const fqn = try decl.getFullyQualifiedName(mod); | |
| 3794 | defer mod.gpa.free(fqn); | |
| 3795 | ||
| 3796 | std.debug.print("# Begin Function AIR: {s}:\n", .{fqn}); | |
| 3794 | 3797 | @import("print_air.zig").dump(mod, air, liveness); |
| 3795 | std.debug.print("# End Function AIR: {s}\n\n", .{decl.name}); | |
| 3798 | std.debug.print("# End Function AIR: {s}\n\n", .{fqn}); | |
| 3796 | 3799 | } |
| 3797 | 3800 | |
| 3798 | 3801 | mod.comp.bin_file.updateFunc(mod, func, air, liveness) catch |err| switch (err) { |
src/Sema.zig+82-60| ... | ... | @@ -914,9 +914,9 @@ fn analyzeBodyInner( |
| 914 | 914 | // zig fmt: off |
| 915 | 915 | .variable => try sema.zirVarExtended( block, extended), |
| 916 | 916 | .struct_decl => try sema.zirStructDecl( block, extended, inst), |
| 917 | .enum_decl => try sema.zirEnumDecl( block, extended), | |
| 917 | .enum_decl => try sema.zirEnumDecl( block, extended, inst), | |
| 918 | 918 | .union_decl => try sema.zirUnionDecl( block, extended, inst), |
| 919 | .opaque_decl => try sema.zirOpaqueDecl( block, extended), | |
| 919 | .opaque_decl => try sema.zirOpaqueDecl( block, extended, inst), | |
| 920 | 920 | .this => try sema.zirThis( block, extended), |
| 921 | 921 | .ret_addr => try sema.zirRetAddr( block, extended), |
| 922 | 922 | .builtin_src => try sema.zirBuiltinSrc( block, extended), |
| ... | ... | @@ -2101,7 +2101,7 @@ fn zirStructDecl( |
| 2101 | 2101 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, .{ |
| 2102 | 2102 | .ty = Type.type, |
| 2103 | 2103 | .val = struct_val, |
| 2104 | }, small.name_strategy, "struct"); | |
| 2104 | }, small.name_strategy, "struct", inst); | |
| 2105 | 2105 | const new_decl = mod.declPtr(new_decl_index); |
| 2106 | 2106 | new_decl.owns_tv = true; |
| 2107 | 2107 | errdefer mod.abortAnonDecl(new_decl_index); |
| ... | ... | @@ -2133,6 +2133,7 @@ fn createAnonymousDeclTypeNamed( |
| 2133 | 2133 | typed_value: TypedValue, |
| 2134 | 2134 | name_strategy: Zir.Inst.NameStrategy, |
| 2135 | 2135 | anon_prefix: []const u8, |
| 2136 | inst: ?Zir.Inst.Index, | |
| 2136 | 2137 | ) !Decl.Index { |
| 2137 | 2138 | const mod = sema.mod; |
| 2138 | 2139 | const namespace = block.namespace; |
| ... | ... | @@ -2152,11 +2153,13 @@ fn createAnonymousDeclTypeNamed( |
| 2152 | 2153 | const name = try std.fmt.allocPrintZ(sema.gpa, "{s}__{s}_{d}", .{ |
| 2153 | 2154 | src_decl.name, anon_prefix, @enumToInt(new_decl_index), |
| 2154 | 2155 | }); |
| 2156 | errdefer sema.gpa.free(name); | |
| 2155 | 2157 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name); |
| 2156 | 2158 | return new_decl_index; |
| 2157 | 2159 | }, |
| 2158 | 2160 | .parent => { |
| 2159 | 2161 | const name = try sema.gpa.dupeZ(u8, mem.sliceTo(sema.mod.declPtr(block.src_decl).name, 0)); |
| 2162 | errdefer sema.gpa.free(name); | |
| 2160 | 2163 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name); |
| 2161 | 2164 | return new_decl_index; |
| 2162 | 2165 | }, |
| ... | ... | @@ -2188,9 +2191,31 @@ fn createAnonymousDeclTypeNamed( |
| 2188 | 2191 | |
| 2189 | 2192 | try buf.appendSlice(")"); |
| 2190 | 2193 | const name = try buf.toOwnedSliceSentinel(0); |
| 2194 | errdefer sema.gpa.free(name); | |
| 2191 | 2195 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name); |
| 2192 | 2196 | return new_decl_index; |
| 2193 | 2197 | }, |
| 2198 | .dbg_var => { | |
| 2199 | const ref = Zir.indexToRef(inst.?); | |
| 2200 | const zir_tags = sema.code.instructions.items(.tag); | |
| 2201 | const zir_data = sema.code.instructions.items(.data); | |
| 2202 | var i = inst.?; | |
| 2203 | while (i < zir_tags.len) : (i += 1) switch (zir_tags[i]) { | |
| 2204 | .dbg_var_ptr, .dbg_var_val => { | |
| 2205 | if (zir_data[i].str_op.operand != ref) continue; | |
| 2206 | ||
| 2207 | const name = try std.fmt.allocPrintZ(sema.gpa, "{s}.{s}", .{ | |
| 2208 | src_decl.name, zir_data[i].str_op.getStr(sema.code), | |
| 2209 | }); | |
| 2210 | errdefer sema.gpa.free(name); | |
| 2211 | ||
| 2212 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name); | |
| 2213 | return new_decl_index; | |
| 2214 | }, | |
| 2215 | else => {}, | |
| 2216 | }; | |
| 2217 | return sema.createAnonymousDeclTypeNamed(block, typed_value, .anon, anon_prefix, null); | |
| 2218 | }, | |
| 2194 | 2219 | } |
| 2195 | 2220 | } |
| 2196 | 2221 | |
| ... | ... | @@ -2198,6 +2223,7 @@ fn zirEnumDecl( |
| 2198 | 2223 | sema: *Sema, |
| 2199 | 2224 | block: *Block, |
| 2200 | 2225 | extended: Zir.Inst.Extended.InstData, |
| 2226 | inst: Zir.Inst.Index, | |
| 2201 | 2227 | ) CompileError!Air.Inst.Ref { |
| 2202 | 2228 | const tracy = trace(@src()); |
| 2203 | 2229 | defer tracy.end(); |
| ... | ... | @@ -2252,7 +2278,7 @@ fn zirEnumDecl( |
| 2252 | 2278 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, .{ |
| 2253 | 2279 | .ty = Type.type, |
| 2254 | 2280 | .val = enum_val, |
| 2255 | }, small.name_strategy, "enum"); | |
| 2281 | }, small.name_strategy, "enum", inst); | |
| 2256 | 2282 | const new_decl = mod.declPtr(new_decl_index); |
| 2257 | 2283 | new_decl.owns_tv = true; |
| 2258 | 2284 | errdefer mod.abortAnonDecl(new_decl_index); |
| ... | ... | @@ -2472,7 +2498,7 @@ fn zirUnionDecl( |
| 2472 | 2498 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, .{ |
| 2473 | 2499 | .ty = Type.type, |
| 2474 | 2500 | .val = union_val, |
| 2475 | }, small.name_strategy, "union"); | |
| 2501 | }, small.name_strategy, "union", inst); | |
| 2476 | 2502 | const new_decl = mod.declPtr(new_decl_index); |
| 2477 | 2503 | new_decl.owns_tv = true; |
| 2478 | 2504 | errdefer mod.abortAnonDecl(new_decl_index); |
| ... | ... | @@ -2504,6 +2530,7 @@ fn zirOpaqueDecl( |
| 2504 | 2530 | sema: *Sema, |
| 2505 | 2531 | block: *Block, |
| 2506 | 2532 | extended: Zir.Inst.Extended.InstData, |
| 2533 | inst: Zir.Inst.Index, | |
| 2507 | 2534 | ) CompileError!Air.Inst.Ref { |
| 2508 | 2535 | const tracy = trace(@src()); |
| 2509 | 2536 | defer tracy.end(); |
| ... | ... | @@ -2540,7 +2567,7 @@ fn zirOpaqueDecl( |
| 2540 | 2567 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, .{ |
| 2541 | 2568 | .ty = Type.type, |
| 2542 | 2569 | .val = opaque_val, |
| 2543 | }, small.name_strategy, "opaque"); | |
| 2570 | }, small.name_strategy, "opaque", inst); | |
| 2544 | 2571 | const new_decl = mod.declPtr(new_decl_index); |
| 2545 | 2572 | new_decl.owns_tv = true; |
| 2546 | 2573 | errdefer mod.abortAnonDecl(new_decl_index); |
| ... | ... | @@ -2589,7 +2616,7 @@ fn zirErrorSetDecl( |
| 2589 | 2616 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, .{ |
| 2590 | 2617 | .ty = Type.type, |
| 2591 | 2618 | .val = error_set_val, |
| 2592 | }, name_strategy, "error"); | |
| 2619 | }, name_strategy, "error", inst); | |
| 2593 | 2620 | const new_decl = mod.declPtr(new_decl_index); |
| 2594 | 2621 | new_decl.owns_tv = true; |
| 2595 | 2622 | errdefer mod.abortAnonDecl(new_decl_index); |
| ... | ... | @@ -4967,6 +4994,8 @@ fn lookupInNamespace( |
| 4967 | 4994 | var it = check_ns.usingnamespace_set.iterator(); |
| 4968 | 4995 | while (it.next()) |entry| { |
| 4969 | 4996 | const sub_usingnamespace_decl_index = entry.key_ptr.*; |
| 4997 | // Skip the decl we're currently analysing. | |
| 4998 | if (sub_usingnamespace_decl_index == sema.owner_decl_index) continue; | |
| 4970 | 4999 | const sub_usingnamespace_decl = mod.declPtr(sub_usingnamespace_decl_index); |
| 4971 | 5000 | const sub_is_pub = entry.value_ptr.*; |
| 4972 | 5001 | if (!sub_is_pub and src_file != sub_usingnamespace_decl.getFileScope()) { |
| ... | ... | @@ -6180,6 +6209,17 @@ fn zirErrorToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 6180 | 6209 | } |
| 6181 | 6210 | } |
| 6182 | 6211 | |
| 6212 | const op_ty = sema.typeOf(op); | |
| 6213 | try sema.resolveInferredErrorSetTy(block, src, op_ty); | |
| 6214 | if (!op_ty.isAnyError()) { | |
| 6215 | const names = op_ty.errorSetNames(); | |
| 6216 | switch (names.len) { | |
| 6217 | 0 => return sema.addConstant(result_ty, Value.zero), | |
| 6218 | 1 => return sema.addIntUnsigned(result_ty, sema.mod.global_error_set.get(names[0]).?), | |
| 6219 | else => {}, | |
| 6220 | } | |
| 6221 | } | |
| 6222 | ||
| 6183 | 6223 | try sema.requireRuntimeBlock(block, src); |
| 6184 | 6224 | return block.addBitCast(result_ty, op_coerced); |
| 6185 | 6225 | } |
| ... | ... | @@ -6558,7 +6598,7 @@ fn analyzeErrUnionPayload( |
| 6558 | 6598 | |
| 6559 | 6599 | // If the error set has no fields then no safety check is needed. |
| 6560 | 6600 | if (safety_check and block.wantSafety() and |
| 6561 | err_union_ty.errorUnionSet().errorSetCardinality() != .zero) | |
| 6601 | !err_union_ty.errorUnionSet().errorSetIsEmpty()) | |
| 6562 | 6602 | { |
| 6563 | 6603 | try sema.panicUnwrapError(block, src, operand, .unwrap_errunion_err, .is_non_err); |
| 6564 | 6604 | } |
| ... | ... | @@ -6644,7 +6684,7 @@ fn analyzeErrUnionPayloadPtr( |
| 6644 | 6684 | |
| 6645 | 6685 | // If the error set has no fields then no safety check is needed. |
| 6646 | 6686 | if (safety_check and block.wantSafety() and |
| 6647 | err_union_ty.errorUnionSet().errorSetCardinality() != .zero) | |
| 6687 | !err_union_ty.errorUnionSet().errorSetIsEmpty()) | |
| 6648 | 6688 | { |
| 6649 | 6689 | try sema.panicUnwrapError(block, src, operand, .unwrap_errunion_err_ptr, .is_non_err_ptr); |
| 6650 | 6690 | } |
| ... | ... | @@ -11859,10 +11899,14 @@ fn zirBuiltinSrc( |
| 11859 | 11899 | const file_name_val = blk: { |
| 11860 | 11900 | var anon_decl = try block.startAnonDecl(src); |
| 11861 | 11901 | defer anon_decl.deinit(); |
| 11862 | const name = try fn_owner_decl.getFileScope().fullPathZ(anon_decl.arena()); | |
| 11902 | const relative_path = try fn_owner_decl.getFileScope().fullPath(sema.arena); | |
| 11903 | const absolute_path = std.fs.realpathAlloc(sema.arena, relative_path) catch |err| { | |
| 11904 | return sema.fail(block, src, "failed to get absolute path of file '{s}': {s}", .{ relative_path, @errorName(err) }); | |
| 11905 | }; | |
| 11906 | const aboslute_duped = try anon_decl.arena().dupeZ(u8, absolute_path); | |
| 11863 | 11907 | const new_decl = try anon_decl.finish( |
| 11864 | try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), name.len), | |
| 11865 | try Value.Tag.bytes.create(anon_decl.arena(), name[0 .. name.len + 1]), | |
| 11908 | try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), aboslute_duped.len), | |
| 11909 | try Value.Tag.bytes.create(anon_decl.arena(), aboslute_duped[0 .. aboslute_duped.len + 1]), | |
| 11866 | 11910 | 0, // default alignment |
| 11867 | 11911 | ); |
| 11868 | 11912 | break :blk try Value.Tag.decl_ref.create(sema.arena, new_decl); |
| ... | ... | @@ -11873,6 +11917,7 @@ fn zirBuiltinSrc( |
| 11873 | 11917 | field_values[0] = file_name_val; |
| 11874 | 11918 | // fn_name: [:0]const u8, |
| 11875 | 11919 | field_values[1] = func_name_val; |
| 11920 | // TODO these should be runtime only! | |
| 11876 | 11921 | // line: u32 |
| 11877 | 11922 | field_values[2] = try Value.Tag.int_u64.create(sema.arena, extra.line + 1); |
| 11878 | 11923 | // column: u32, |
| ... | ... | @@ -13712,10 +13757,10 @@ fn zirStructInit( |
| 13712 | 13757 | const field_type_extra = sema.code.extraData(Zir.Inst.FieldType, field_type_data.payload_index).data; |
| 13713 | 13758 | const field_name = sema.code.nullTerminatedString(field_type_extra.name_start); |
| 13714 | 13759 | const field_index = try sema.unionFieldIndex(block, resolved_ty, field_name, field_src); |
| 13760 | const tag_val = try Value.Tag.enum_field_index.create(sema.arena, field_index); | |
| 13715 | 13761 | |
| 13716 | 13762 | const init_inst = try sema.resolveInst(item.data.init); |
| 13717 | 13763 | if (try sema.resolveMaybeUndefVal(block, field_src, init_inst)) |val| { |
| 13718 | const tag_val = try Value.Tag.enum_field_index.create(sema.arena, field_index); | |
| 13719 | 13764 | return sema.addConstantMaybeRef( |
| 13720 | 13765 | block, |
| 13721 | 13766 | src, |
| ... | ... | @@ -13734,6 +13779,8 @@ fn zirStructInit( |
| 13734 | 13779 | const alloc = try block.addTy(.alloc, alloc_ty); |
| 13735 | 13780 | const field_ptr = try sema.unionFieldPtr(block, field_src, alloc, field_name, field_src, resolved_ty); |
| 13736 | 13781 | try sema.storePtr(block, src, field_ptr, init_inst); |
| 13782 | const new_tag = try sema.addConstant(resolved_ty.unionTagTypeHypothetical(), tag_val); | |
| 13783 | _ = try block.addBinOp(.set_union_tag, alloc, new_tag); | |
| 13737 | 13784 | return alloc; |
| 13738 | 13785 | } |
| 13739 | 13786 | |
| ... | ... | @@ -14614,7 +14661,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 14614 | 14661 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, .{ |
| 14615 | 14662 | .ty = Type.type, |
| 14616 | 14663 | .val = enum_val, |
| 14617 | }, .anon, "enum"); | |
| 14664 | }, .anon, "enum", null); | |
| 14618 | 14665 | const new_decl = mod.declPtr(new_decl_index); |
| 14619 | 14666 | new_decl.owns_tv = true; |
| 14620 | 14667 | errdefer mod.abortAnonDecl(new_decl_index); |
| ... | ... | @@ -14704,7 +14751,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 14704 | 14751 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, .{ |
| 14705 | 14752 | .ty = Type.type, |
| 14706 | 14753 | .val = opaque_val, |
| 14707 | }, .anon, "opaque"); | |
| 14754 | }, .anon, "opaque", null); | |
| 14708 | 14755 | const new_decl = mod.declPtr(new_decl_index); |
| 14709 | 14756 | new_decl.owns_tv = true; |
| 14710 | 14757 | errdefer mod.abortAnonDecl(new_decl_index); |
| ... | ... | @@ -14755,7 +14802,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 14755 | 14802 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, .{ |
| 14756 | 14803 | .ty = Type.type, |
| 14757 | 14804 | .val = new_union_val, |
| 14758 | }, .anon, "union"); | |
| 14805 | }, .anon, "union", null); | |
| 14759 | 14806 | const new_decl = mod.declPtr(new_decl_index); |
| 14760 | 14807 | new_decl.owns_tv = true; |
| 14761 | 14808 | errdefer mod.abortAnonDecl(new_decl_index); |
| ... | ... | @@ -14923,7 +14970,7 @@ fn reifyStruct( |
| 14923 | 14970 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, .{ |
| 14924 | 14971 | .ty = Type.type, |
| 14925 | 14972 | .val = new_struct_val, |
| 14926 | }, .anon, "struct"); | |
| 14973 | }, .anon, "struct", null); | |
| 14927 | 14974 | const new_decl = mod.declPtr(new_decl_index); |
| 14928 | 14975 | new_decl.owns_tv = true; |
| 14929 | 14976 | errdefer mod.abortAnonDecl(new_decl_index); |
| ... | ... | @@ -19700,7 +19747,8 @@ fn coerce( |
| 19700 | 19747 | // pointer to tuple to slice |
| 19701 | 19748 | if (inst_ty.isSinglePointer() and |
| 19702 | 19749 | inst_ty.childType().isTuple() and |
| 19703 | !dest_info.mutable and dest_info.size == .Slice) | |
| 19750 | (!dest_info.mutable or inst_ty.ptrIsMutable() or inst_ty.childType().tupleFields().types.len == 0) and | |
| 19751 | dest_info.size == .Slice) | |
| 19704 | 19752 | { |
| 19705 | 19753 | return sema.coerceTupleToSlicePtrs(block, dest_ty, dest_ty_src, inst, inst_src); |
| 19706 | 19754 | } |
| ... | ... | @@ -23540,7 +23588,17 @@ pub fn resolveTypeFully( |
| 23540 | 23588 | const child_ty = try sema.resolveTypeFields(block, src, ty.childType()); |
| 23541 | 23589 | return resolveTypeFully(sema, block, src, child_ty); |
| 23542 | 23590 | }, |
| 23543 | .Struct => return resolveStructFully(sema, block, src, ty), | |
| 23591 | .Struct => switch (ty.tag()) { | |
| 23592 | .@"struct" => return resolveStructFully(sema, block, src, ty), | |
| 23593 | .tuple, .anon_struct => { | |
| 23594 | const tuple = ty.tupleFields(); | |
| 23595 | ||
| 23596 | for (tuple.types) |field_ty| { | |
| 23597 | try sema.resolveTypeFully(block, src, field_ty); | |
| 23598 | } | |
| 23599 | }, | |
| 23600 | else => {}, | |
| 23601 | }, | |
| 23544 | 23602 | .Union => return resolveUnionFully(sema, block, src, ty), |
| 23545 | 23603 | .Array => return resolveTypeFully(sema, block, src, ty.childType()), |
| 23546 | 23604 | .Optional => { |
| ... | ... | @@ -23575,7 +23633,7 @@ fn resolveStructFully( |
| 23575 | 23633 | try resolveStructLayout(sema, block, src, ty); |
| 23576 | 23634 | |
| 23577 | 23635 | const resolved_ty = try sema.resolveTypeFields(block, src, ty); |
| 23578 | const payload = resolved_ty.castTag(.@"struct") orelse return; | |
| 23636 | const payload = resolved_ty.castTag(.@"struct").?; | |
| 23579 | 23637 | const struct_obj = payload.data; |
| 23580 | 23638 | |
| 23581 | 23639 | switch (struct_obj.status) { |
| ... | ... | @@ -24425,6 +24483,10 @@ pub fn typeHasOnePossibleValue( |
| 24425 | 24483 | .bool, |
| 24426 | 24484 | .type, |
| 24427 | 24485 | .anyerror, |
| 24486 | .error_set_single, | |
| 24487 | .error_set, | |
| 24488 | .error_set_merged, | |
| 24489 | .error_union, | |
| 24428 | 24490 | .fn_noreturn_no_args, |
| 24429 | 24491 | .fn_void_no_args, |
| 24430 | 24492 | .fn_naked_noreturn_no_args, |
| ... | ... | @@ -24481,46 +24543,6 @@ pub fn typeHasOnePossibleValue( |
| 24481 | 24543 | } |
| 24482 | 24544 | }, |
| 24483 | 24545 | |
| 24484 | .error_union => { | |
| 24485 | const error_ty = ty.errorUnionSet(); | |
| 24486 | switch (error_ty.errorSetCardinality()) { | |
| 24487 | .zero => { | |
| 24488 | const payload_ty = ty.errorUnionPayload(); | |
| 24489 | if (try typeHasOnePossibleValue(sema, block, src, payload_ty)) |payload_val| { | |
| 24490 | return try Value.Tag.eu_payload.create(sema.arena, payload_val); | |
| 24491 | } else { | |
| 24492 | return null; | |
| 24493 | } | |
| 24494 | }, | |
| 24495 | .one => { | |
| 24496 | if (ty.errorUnionPayload().isNoReturn()) { | |
| 24497 | const error_val = (try typeHasOnePossibleValue(sema, block, src, error_ty)).?; | |
| 24498 | return error_val; | |
| 24499 | } else { | |
| 24500 | return null; | |
| 24501 | } | |
| 24502 | }, | |
| 24503 | .many => return null, | |
| 24504 | } | |
| 24505 | }, | |
| 24506 | ||
| 24507 | .error_set_single => { | |
| 24508 | const name = ty.castTag(.error_set_single).?.data; | |
| 24509 | return try Value.Tag.@"error".create(sema.arena, .{ .name = name }); | |
| 24510 | }, | |
| 24511 | .error_set => { | |
| 24512 | const err_set_obj = ty.castTag(.error_set).?.data; | |
| 24513 | const names = err_set_obj.names.keys(); | |
| 24514 | if (names.len > 1) return null; | |
| 24515 | return try Value.Tag.@"error".create(sema.arena, .{ .name = names[0] }); | |
| 24516 | }, | |
| 24517 | .error_set_merged => { | |
| 24518 | const name_map = ty.castTag(.error_set_merged).?.data; | |
| 24519 | const names = name_map.keys(); | |
| 24520 | if (names.len > 1) return null; | |
| 24521 | return try Value.Tag.@"error".create(sema.arena, .{ .name = names[0] }); | |
| 24522 | }, | |
| 24523 | ||
| 24524 | 24546 | .@"struct" => { |
| 24525 | 24547 | const resolved_ty = try sema.resolveTypeFields(block, src, ty); |
| 24526 | 24548 | const s = resolved_ty.castTag(.@"struct").?.data; |
src/TypedValue.zig+64-11| ... | ... | @@ -144,7 +144,41 @@ pub fn print( |
| 144 | 144 | return writer.writeAll(".{ ... }"); |
| 145 | 145 | } |
| 146 | 146 | const vals = val.castTag(.aggregate).?.data; |
| 147 | if (ty.zigTypeTag() == .Struct) { | |
| 147 | if (ty.castTag(.anon_struct)) |anon_struct| { | |
| 148 | const field_names = anon_struct.data.names; | |
| 149 | const types = anon_struct.data.types; | |
| 150 | const max_len = std.math.min(types.len, max_aggregate_items); | |
| 151 | ||
| 152 | var i: u32 = 0; | |
| 153 | while (i < max_len) : (i += 1) { | |
| 154 | if (i != 0) try writer.writeAll(", "); | |
| 155 | try writer.print(".{s} = ", .{field_names[i]}); | |
| 156 | try print(.{ | |
| 157 | .ty = types[i], | |
| 158 | .val = vals[i], | |
| 159 | }, writer, level - 1, mod); | |
| 160 | } | |
| 161 | if (types.len > max_aggregate_items) { | |
| 162 | try writer.writeAll(", ..."); | |
| 163 | } | |
| 164 | return writer.writeAll(" }"); | |
| 165 | } else if (ty.isTuple()) { | |
| 166 | const fields = ty.tupleFields(); | |
| 167 | const max_len = std.math.min(fields.types.len, max_aggregate_items); | |
| 168 | ||
| 169 | var i: u32 = 0; | |
| 170 | while (i < max_len) : (i += 1) { | |
| 171 | if (i != 0) try writer.writeAll(", "); | |
| 172 | try print(.{ | |
| 173 | .ty = fields.types[i], | |
| 174 | .val = vals[i], | |
| 175 | }, writer, level - 1, mod); | |
| 176 | } | |
| 177 | if (fields.types.len > max_aggregate_items) { | |
| 178 | try writer.writeAll(", ..."); | |
| 179 | } | |
| 180 | return writer.writeAll(" }"); | |
| 181 | } else if (ty.zigTypeTag() == .Struct) { | |
| 148 | 182 | try writer.writeAll(".{ "); |
| 149 | 183 | const struct_fields = ty.structFields(); |
| 150 | 184 | const len = struct_fields.count(); |
| ... | ... | @@ -194,7 +228,7 @@ pub fn print( |
| 194 | 228 | try writer.writeAll(".{ "); |
| 195 | 229 | |
| 196 | 230 | try print(.{ |
| 197 | .ty = ty.unionTagType().?, | |
| 231 | .ty = ty.cast(Type.Payload.Union).?.data.tag_ty, | |
| 198 | 232 | .val = union_val.tag, |
| 199 | 233 | }, writer, level - 1, mod); |
| 200 | 234 | try writer.writeAll(" = "); |
| ... | ... | @@ -278,19 +312,27 @@ pub fn print( |
| 278 | 312 | .elem_ptr => { |
| 279 | 313 | const elem_ptr = val.castTag(.elem_ptr).?.data; |
| 280 | 314 | try writer.writeAll("&"); |
| 281 | try print(.{ | |
| 282 | .ty = elem_ptr.elem_ty, | |
| 283 | .val = elem_ptr.array_ptr, | |
| 284 | }, writer, level - 1, mod); | |
| 315 | if (level == 0) { | |
| 316 | try writer.writeAll("(ptr)"); | |
| 317 | } else { | |
| 318 | try print(.{ | |
| 319 | .ty = elem_ptr.elem_ty, | |
| 320 | .val = elem_ptr.array_ptr, | |
| 321 | }, writer, level - 1, mod); | |
| 322 | } | |
| 285 | 323 | return writer.print("[{}]", .{elem_ptr.index}); |
| 286 | 324 | }, |
| 287 | 325 | .field_ptr => { |
| 288 | 326 | const field_ptr = val.castTag(.field_ptr).?.data; |
| 289 | 327 | try writer.writeAll("&"); |
| 290 | try print(.{ | |
| 291 | .ty = field_ptr.container_ty, | |
| 292 | .val = field_ptr.container_ptr, | |
| 293 | }, writer, level - 1, mod); | |
| 328 | if (level == 0) { | |
| 329 | try writer.writeAll("(ptr)"); | |
| 330 | } else { | |
| 331 | try print(.{ | |
| 332 | .ty = field_ptr.container_ty, | |
| 333 | .val = field_ptr.container_ptr, | |
| 334 | }, writer, level - 1, mod); | |
| 335 | } | |
| 294 | 336 | |
| 295 | 337 | if (field_ptr.container_ty.zigTypeTag() == .Struct) { |
| 296 | 338 | const field_name = field_ptr.container_ty.structFields().keys()[field_ptr.field_index]; |
| ... | ... | @@ -344,6 +386,9 @@ pub fn print( |
| 344 | 386 | return writer.writeAll(" }"); |
| 345 | 387 | }, |
| 346 | 388 | .slice => { |
| 389 | if (level == 0) { | |
| 390 | return writer.writeAll(".{ ... }"); | |
| 391 | } | |
| 347 | 392 | const payload = val.castTag(.slice).?.data; |
| 348 | 393 | try writer.writeAll(".{ "); |
| 349 | 394 | const elem_ty = ty.elemType2(); |
| ... | ... | @@ -372,17 +417,25 @@ pub fn print( |
| 372 | 417 | .@"error" => return writer.print("error.{s}", .{val.castTag(.@"error").?.data.name}), |
| 373 | 418 | .eu_payload => { |
| 374 | 419 | val = val.castTag(.eu_payload).?.data; |
| 420 | ty = ty.errorUnionPayload(); | |
| 375 | 421 | }, |
| 376 | 422 | .opt_payload => { |
| 377 | 423 | val = val.castTag(.opt_payload).?.data; |
| 424 | var buf: Type.Payload.ElemType = undefined; | |
| 425 | ty = ty.optionalChild(&buf); | |
| 426 | return print(.{ .ty = ty, .val = val }, writer, level, mod); | |
| 378 | 427 | }, |
| 379 | 428 | .eu_payload_ptr => { |
| 380 | 429 | try writer.writeAll("&"); |
| 381 | 430 | val = val.castTag(.eu_payload_ptr).?.data.container_ptr; |
| 431 | ty = ty.elemType2().errorUnionPayload(); | |
| 382 | 432 | }, |
| 383 | 433 | .opt_payload_ptr => { |
| 384 | 434 | try writer.writeAll("&"); |
| 385 | val = val.castTag(.opt_payload_ptr).?.data.container_ptr; | |
| 435 | val = val.castTag(.opt_payload).?.data; | |
| 436 | var buf: Type.Payload.ElemType = undefined; | |
| 437 | ty = ty.elemType2().optionalChild(&buf); | |
| 438 | return print(.{ .ty = ty, .val = val }, writer, level, mod); | |
| 386 | 439 | }, |
| 387 | 440 | |
| 388 | 441 | // TODO these should not appear in this function |
src/Zir.zig+2| ... | ... | @@ -3156,6 +3156,8 @@ pub const Inst = struct { |
| 3156 | 3156 | /// Create an anonymous name for this declaration. |
| 3157 | 3157 | /// Like this: "ParentDeclName_struct_69" |
| 3158 | 3158 | anon, |
| 3159 | /// Use the name specified in the next `dbg_var_{val,ptr}` instruction. | |
| 3160 | dbg_var, | |
| 3159 | 3161 | }; |
| 3160 | 3162 | |
| 3161 | 3163 | /// Trailing: |
src/arch/aarch64/CodeGen.zig+3-8| ... | ... | @@ -2277,7 +2277,7 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { |
| 2277 | 2277 | fn errUnionErr(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCValue { |
| 2278 | 2278 | const err_ty = error_union_ty.errorUnionSet(); |
| 2279 | 2279 | const payload_ty = error_union_ty.errorUnionPayload(); |
| 2280 | if (err_ty.errorSetCardinality() == .zero) { | |
| 2280 | if (err_ty.errorSetIsEmpty()) { | |
| 2281 | 2281 | return MCValue{ .immediate = 0 }; |
| 2282 | 2282 | } |
| 2283 | 2283 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { |
| ... | ... | @@ -2311,7 +2311,7 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void { |
| 2311 | 2311 | fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCValue { |
| 2312 | 2312 | const err_ty = error_union_ty.errorUnionSet(); |
| 2313 | 2313 | const payload_ty = error_union_ty.errorUnionPayload(); |
| 2314 | if (err_ty.errorSetCardinality() == .zero) { | |
| 2314 | if (err_ty.errorSetIsEmpty()) { | |
| 2315 | 2315 | return error_union_mcv; |
| 2316 | 2316 | } |
| 2317 | 2317 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { |
| ... | ... | @@ -3590,7 +3590,7 @@ fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue { |
| 3590 | 3590 | const error_type = ty.errorUnionSet(); |
| 3591 | 3591 | const payload_type = ty.errorUnionPayload(); |
| 3592 | 3592 | |
| 3593 | if (error_type.errorSetCardinality() == .zero) { | |
| 3593 | if (error_type.errorSetIsEmpty()) { | |
| 3594 | 3594 | return MCValue{ .immediate = 0 }; // always false |
| 3595 | 3595 | } |
| 3596 | 3596 | |
| ... | ... | @@ -4687,11 +4687,6 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { |
| 4687 | 4687 | const error_type = typed_value.ty.errorUnionSet(); |
| 4688 | 4688 | const payload_type = typed_value.ty.errorUnionPayload(); |
| 4689 | 4689 | |
| 4690 | if (error_type.errorSetCardinality() == .zero) { | |
| 4691 | const payload_val = typed_value.val.castTag(.eu_payload).?.data; | |
| 4692 | return self.genTypedValue(.{ .ty = payload_type, .val = payload_val }); | |
| 4693 | } | |
| 4694 | ||
| 4695 | 4690 | const is_pl = typed_value.val.errorUnionIsPayload(); |
| 4696 | 4691 | |
| 4697 | 4692 | if (!payload_type.hasRuntimeBitsIgnoreComptime()) { |
src/arch/arm/CodeGen.zig+3-9| ... | ... | @@ -1773,7 +1773,7 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { |
| 1773 | 1773 | fn errUnionErr(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCValue { |
| 1774 | 1774 | const err_ty = error_union_ty.errorUnionSet(); |
| 1775 | 1775 | const payload_ty = error_union_ty.errorUnionPayload(); |
| 1776 | if (err_ty.errorSetCardinality() == .zero) { | |
| 1776 | if (err_ty.errorSetIsEmpty()) { | |
| 1777 | 1777 | return MCValue{ .immediate = 0 }; |
| 1778 | 1778 | } |
| 1779 | 1779 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { |
| ... | ... | @@ -1810,7 +1810,7 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void { |
| 1810 | 1810 | fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCValue { |
| 1811 | 1811 | const err_ty = error_union_ty.errorUnionSet(); |
| 1812 | 1812 | const payload_ty = error_union_ty.errorUnionPayload(); |
| 1813 | if (err_ty.errorSetCardinality() == .zero) { | |
| 1813 | if (err_ty.errorSetIsEmpty()) { | |
| 1814 | 1814 | return error_union_mcv; |
| 1815 | 1815 | } |
| 1816 | 1816 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { |
| ... | ... | @@ -3922,7 +3922,7 @@ fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue { |
| 3922 | 3922 | const error_type = ty.errorUnionSet(); |
| 3923 | 3923 | const error_int_type = Type.initTag(.u16); |
| 3924 | 3924 | |
| 3925 | if (error_type.errorSetCardinality() == .zero) { | |
| 3925 | if (error_type.errorSetIsEmpty()) { | |
| 3926 | 3926 | return MCValue{ .immediate = 0 }; // always false |
| 3927 | 3927 | } |
| 3928 | 3928 | |
| ... | ... | @@ -5368,12 +5368,6 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { |
| 5368 | 5368 | .ErrorUnion => { |
| 5369 | 5369 | const error_type = typed_value.ty.errorUnionSet(); |
| 5370 | 5370 | const payload_type = typed_value.ty.errorUnionPayload(); |
| 5371 | ||
| 5372 | if (error_type.errorSetCardinality() == .zero) { | |
| 5373 | const payload_val = typed_value.val.castTag(.eu_payload).?.data; | |
| 5374 | return self.genTypedValue(.{ .ty = payload_type, .val = payload_val }); | |
| 5375 | } | |
| 5376 | ||
| 5377 | 5371 | const is_pl = typed_value.val.errorUnionIsPayload(); |
| 5378 | 5372 | |
| 5379 | 5373 | if (!payload_type.hasRuntimeBitsIgnoreComptime()) { |
src/arch/wasm/CodeGen.zig+19-41| ... | ... | @@ -1377,11 +1377,7 @@ fn isByRef(ty: Type, target: std.Target) bool { |
| 1377 | 1377 | .Int => return ty.intInfo(target).bits > 64, |
| 1378 | 1378 | .Float => return ty.floatBits(target) > 64, |
| 1379 | 1379 | .ErrorUnion => { |
| 1380 | const err_ty = ty.errorUnionSet(); | |
| 1381 | 1380 | const pl_ty = ty.errorUnionPayload(); |
| 1382 | if (err_ty.errorSetCardinality() == .zero) { | |
| 1383 | return isByRef(pl_ty, target); | |
| 1384 | } | |
| 1385 | 1381 | if (!pl_ty.hasRuntimeBitsIgnoreComptime()) { |
| 1386 | 1382 | return false; |
| 1387 | 1383 | } |
| ... | ... | @@ -1817,11 +1813,7 @@ fn airStore(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 1817 | 1813 | fn store(self: *Self, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerError!void { |
| 1818 | 1814 | switch (ty.zigTypeTag()) { |
| 1819 | 1815 | .ErrorUnion => { |
| 1820 | const err_ty = ty.errorUnionSet(); | |
| 1821 | 1816 | const pl_ty = ty.errorUnionPayload(); |
| 1822 | if (err_ty.errorSetCardinality() == .zero) { | |
| 1823 | return self.store(lhs, rhs, pl_ty, 0); | |
| 1824 | } | |
| 1825 | 1817 | if (!pl_ty.hasRuntimeBitsIgnoreComptime()) { |
| 1826 | 1818 | return self.store(lhs, rhs, Type.anyerror, 0); |
| 1827 | 1819 | } |
| ... | ... | @@ -2357,10 +2349,6 @@ fn lowerConstant(self: *Self, val: Value, ty: Type) InnerError!WValue { |
| 2357 | 2349 | }, |
| 2358 | 2350 | .ErrorUnion => { |
| 2359 | 2351 | const error_type = ty.errorUnionSet(); |
| 2360 | if (error_type.errorSetCardinality() == .zero) { | |
| 2361 | const pl_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.initTag(.undef); | |
| 2362 | return self.lowerConstant(pl_val, ty.errorUnionPayload()); | |
| 2363 | } | |
| 2364 | 2352 | const is_pl = val.errorUnionIsPayload(); |
| 2365 | 2353 | const err_val = if (!is_pl) val else Value.initTag(.zero); |
| 2366 | 2354 | return self.lowerConstant(err_val, error_type); |
| ... | ... | @@ -2929,7 +2917,7 @@ fn airIsErr(self: *Self, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerError!W |
| 2929 | 2917 | const err_union_ty = self.air.typeOf(un_op); |
| 2930 | 2918 | const pl_ty = err_union_ty.errorUnionPayload(); |
| 2931 | 2919 | |
| 2932 | if (err_union_ty.errorUnionSet().errorSetCardinality() == .zero) { | |
| 2920 | if (err_union_ty.errorUnionSet().errorSetIsEmpty()) { | |
| 2933 | 2921 | switch (opcode) { |
| 2934 | 2922 | .i32_ne => return WValue{ .imm32 = 0 }, |
| 2935 | 2923 | .i32_eq => return WValue{ .imm32 = 1 }, |
| ... | ... | @@ -2962,10 +2950,6 @@ fn airUnwrapErrUnionPayload(self: *Self, inst: Air.Inst.Index, op_is_ptr: bool) |
| 2962 | 2950 | const err_ty = if (op_is_ptr) op_ty.childType() else op_ty; |
| 2963 | 2951 | const payload_ty = err_ty.errorUnionPayload(); |
| 2964 | 2952 | |
| 2965 | if (err_ty.errorUnionSet().errorSetCardinality() == .zero) { | |
| 2966 | return operand; | |
| 2967 | } | |
| 2968 | ||
| 2969 | 2953 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) return WValue{ .none = {} }; |
| 2970 | 2954 | |
| 2971 | 2955 | const pl_offset = @intCast(u32, errUnionPayloadOffset(payload_ty, self.target)); |
| ... | ... | @@ -2984,7 +2968,7 @@ fn airUnwrapErrUnionError(self: *Self, inst: Air.Inst.Index, op_is_ptr: bool) In |
| 2984 | 2968 | const err_ty = if (op_is_ptr) op_ty.childType() else op_ty; |
| 2985 | 2969 | const payload_ty = err_ty.errorUnionPayload(); |
| 2986 | 2970 | |
| 2987 | if (err_ty.errorUnionSet().errorSetCardinality() == .zero) { | |
| 2971 | if (err_ty.errorUnionSet().errorSetIsEmpty()) { | |
| 2988 | 2972 | return WValue{ .imm32 = 0 }; |
| 2989 | 2973 | } |
| 2990 | 2974 | |
| ... | ... | @@ -3002,10 +2986,6 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 3002 | 2986 | const operand = try self.resolveInst(ty_op.operand); |
| 3003 | 2987 | const err_ty = self.air.typeOfIndex(inst); |
| 3004 | 2988 | |
| 3005 | if (err_ty.errorUnionSet().errorSetCardinality() == .zero) { | |
| 3006 | return operand; | |
| 3007 | } | |
| 3008 | ||
| 3009 | 2989 | const pl_ty = self.air.typeOf(ty_op.operand); |
| 3010 | 2990 | if (!pl_ty.hasRuntimeBitsIgnoreComptime()) { |
| 3011 | 2991 | return operand; |
| ... | ... | @@ -4633,29 +4613,27 @@ fn lowerTry( |
| 4633 | 4613 | return self.fail("TODO: lowerTry for pointers", .{}); |
| 4634 | 4614 | } |
| 4635 | 4615 | |
| 4636 | if (err_union_ty.errorUnionSet().errorSetCardinality() == .zero) { | |
| 4637 | return err_union; | |
| 4638 | } | |
| 4639 | ||
| 4640 | 4616 | const pl_ty = err_union_ty.errorUnionPayload(); |
| 4641 | 4617 | const pl_has_bits = pl_ty.hasRuntimeBitsIgnoreComptime(); |
| 4642 | 4618 | |
| 4643 | // Block we can jump out of when error is not set | |
| 4644 | try self.startBlock(.block, wasm.block_empty); | |
| 4645 | ||
| 4646 | // check if the error tag is set for the error union. | |
| 4647 | try self.emitWValue(err_union); | |
| 4648 | if (pl_has_bits) { | |
| 4649 | const err_offset = @intCast(u32, errUnionErrorOffset(pl_ty, self.target)); | |
| 4650 | try self.addMemArg(.i32_load16_u, .{ | |
| 4651 | .offset = err_union.offset() + err_offset, | |
| 4652 | .alignment = Type.anyerror.abiAlignment(self.target), | |
| 4653 | }); | |
| 4619 | if (!err_union_ty.errorUnionSet().errorSetIsEmpty()) { | |
| 4620 | // Block we can jump out of when error is not set | |
| 4621 | try self.startBlock(.block, wasm.block_empty); | |
| 4622 | ||
| 4623 | // check if the error tag is set for the error union. | |
| 4624 | try self.emitWValue(err_union); | |
| 4625 | if (pl_has_bits) { | |
| 4626 | const err_offset = @intCast(u32, errUnionErrorOffset(pl_ty, self.target)); | |
| 4627 | try self.addMemArg(.i32_load16_u, .{ | |
| 4628 | .offset = err_union.offset() + err_offset, | |
| 4629 | .alignment = Type.anyerror.abiAlignment(self.target), | |
| 4630 | }); | |
| 4631 | } | |
| 4632 | try self.addTag(.i32_eqz); | |
| 4633 | try self.addLabel(.br_if, 0); // jump out of block when error is '0' | |
| 4634 | try self.genBody(body); | |
| 4635 | try self.endBlock(); | |
| 4654 | 4636 | } |
| 4655 | try self.addTag(.i32_eqz); | |
| 4656 | try self.addLabel(.br_if, 0); // jump out of block when error is '0' | |
| 4657 | try self.genBody(body); | |
| 4658 | try self.endBlock(); | |
| 4659 | 4637 | |
| 4660 | 4638 | // if we reach here it means error was not set, and we want the payload |
| 4661 | 4639 | if (!pl_has_bits) { |
src/arch/x86_64/CodeGen.zig+2-19| ... | ... | @@ -1806,7 +1806,7 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void { |
| 1806 | 1806 | const operand = try self.resolveInst(ty_op.operand); |
| 1807 | 1807 | |
| 1808 | 1808 | const result: MCValue = result: { |
| 1809 | if (err_ty.errorSetCardinality() == .zero) { | |
| 1809 | if (err_ty.errorSetIsEmpty()) { | |
| 1810 | 1810 | break :result MCValue{ .immediate = 0 }; |
| 1811 | 1811 | } |
| 1812 | 1812 | |
| ... | ... | @@ -1857,14 +1857,8 @@ fn genUnwrapErrorUnionPayloadMir( |
| 1857 | 1857 | err_union: MCValue, |
| 1858 | 1858 | ) !MCValue { |
| 1859 | 1859 | const payload_ty = err_union_ty.errorUnionPayload(); |
| 1860 | const err_ty = err_union_ty.errorUnionSet(); | |
| 1861 | 1860 | |
| 1862 | 1861 | const result: MCValue = result: { |
| 1863 | if (err_ty.errorSetCardinality() == .zero) { | |
| 1864 | // TODO check if we can reuse | |
| 1865 | break :result err_union; | |
| 1866 | } | |
| 1867 | ||
| 1868 | 1862 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { |
| 1869 | 1863 | break :result MCValue.none; |
| 1870 | 1864 | } |
| ... | ... | @@ -1991,15 +1985,10 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 1991 | 1985 | } |
| 1992 | 1986 | |
| 1993 | 1987 | const error_union_ty = self.air.getRefType(ty_op.ty); |
| 1994 | const error_ty = error_union_ty.errorUnionSet(); | |
| 1995 | 1988 | const payload_ty = error_union_ty.errorUnionPayload(); |
| 1996 | 1989 | const operand = try self.resolveInst(ty_op.operand); |
| 1997 | 1990 | |
| 1998 | 1991 | const result: MCValue = result: { |
| 1999 | if (error_ty.errorSetCardinality() == .zero) { | |
| 2000 | break :result operand; | |
| 2001 | } | |
| 2002 | ||
| 2003 | 1992 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { |
| 2004 | 1993 | break :result operand; |
| 2005 | 1994 | } |
| ... | ... | @@ -4651,7 +4640,7 @@ fn isNonNull(self: *Self, inst: Air.Inst.Index, ty: Type, operand: MCValue) !MCV |
| 4651 | 4640 | fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, ty: Type, operand: MCValue) !MCValue { |
| 4652 | 4641 | const err_type = ty.errorUnionSet(); |
| 4653 | 4642 | |
| 4654 | if (err_type.errorSetCardinality() == .zero) { | |
| 4643 | if (err_type.errorSetIsEmpty()) { | |
| 4655 | 4644 | return MCValue{ .immediate = 0 }; // always false |
| 4656 | 4645 | } |
| 4657 | 4646 | |
| ... | ... | @@ -6909,12 +6898,6 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { |
| 6909 | 6898 | .ErrorUnion => { |
| 6910 | 6899 | const error_type = typed_value.ty.errorUnionSet(); |
| 6911 | 6900 | const payload_type = typed_value.ty.errorUnionPayload(); |
| 6912 | ||
| 6913 | if (error_type.errorSetCardinality() == .zero) { | |
| 6914 | const payload_val = typed_value.val.castTag(.eu_payload).?.data; | |
| 6915 | return self.genTypedValue(.{ .ty = payload_type, .val = payload_val }); | |
| 6916 | } | |
| 6917 | ||
| 6918 | 6901 | const is_pl = typed_value.val.errorUnionIsPayload(); |
| 6919 | 6902 | |
| 6920 | 6903 | if (!payload_type.hasRuntimeBitsIgnoreComptime()) { |
src/codegen.zig-9| ... | ... | @@ -705,15 +705,6 @@ pub fn generateSymbol( |
| 705 | 705 | .ErrorUnion => { |
| 706 | 706 | const error_ty = typed_value.ty.errorUnionSet(); |
| 707 | 707 | const payload_ty = typed_value.ty.errorUnionPayload(); |
| 708 | ||
| 709 | if (error_ty.errorSetCardinality() == .zero) { | |
| 710 | const payload_val = typed_value.val.castTag(.eu_payload).?.data; | |
| 711 | return generateSymbol(bin_file, src_loc, .{ | |
| 712 | .ty = payload_ty, | |
| 713 | .val = payload_val, | |
| 714 | }, code, debug_output, reloc_info); | |
| 715 | } | |
| 716 | ||
| 717 | 708 | const is_payload = typed_value.val.errorUnionIsPayload(); |
| 718 | 709 | |
| 719 | 710 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { |
src/codegen/c.zig+24-52| ... | ... | @@ -752,12 +752,6 @@ pub const DeclGen = struct { |
| 752 | 752 | const error_type = ty.errorUnionSet(); |
| 753 | 753 | const payload_type = ty.errorUnionPayload(); |
| 754 | 754 | |
| 755 | if (error_type.errorSetCardinality() == .zero) { | |
| 756 | // We use the payload directly as the type. | |
| 757 | const payload_val = val.castTag(.eu_payload).?.data; | |
| 758 | return dg.renderValue(writer, payload_type, payload_val, location); | |
| 759 | } | |
| 760 | ||
| 761 | 755 | if (!payload_type.hasRuntimeBits()) { |
| 762 | 756 | // We use the error type directly as the type. |
| 763 | 757 | const err_val = if (val.errorUnionIsPayload()) Value.initTag(.zero) else val; |
| ... | ... | @@ -1381,13 +1375,8 @@ pub const DeclGen = struct { |
| 1381 | 1375 | return w.writeAll("uint16_t"); |
| 1382 | 1376 | }, |
| 1383 | 1377 | .ErrorUnion => { |
| 1384 | const error_ty = t.errorUnionSet(); | |
| 1385 | 1378 | const payload_ty = t.errorUnionPayload(); |
| 1386 | 1379 | |
| 1387 | if (error_ty.errorSetCardinality() == .zero) { | |
| 1388 | return dg.renderType(w, payload_ty); | |
| 1389 | } | |
| 1390 | ||
| 1391 | 1380 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { |
| 1392 | 1381 | return dg.renderType(w, Type.anyerror); |
| 1393 | 1382 | } |
| ... | ... | @@ -2892,41 +2881,36 @@ fn lowerTry( |
| 2892 | 2881 | operand_is_ptr: bool, |
| 2893 | 2882 | result_ty: Type, |
| 2894 | 2883 | ) !CValue { |
| 2895 | if (err_union_ty.errorUnionSet().errorSetCardinality() == .zero) { | |
| 2896 | // If the error set has no fields, then the payload and the error | |
| 2897 | // union are the same value. | |
| 2898 | return err_union; | |
| 2899 | } | |
| 2900 | ||
| 2884 | const writer = f.object.writer(); | |
| 2901 | 2885 | const payload_ty = err_union_ty.errorUnionPayload(); |
| 2902 | 2886 | const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(); |
| 2903 | 2887 | |
| 2904 | const writer = f.object.writer(); | |
| 2905 | ||
| 2906 | err: { | |
| 2907 | if (!payload_has_bits) { | |
| 2908 | if (operand_is_ptr) { | |
| 2909 | try writer.writeAll("if(*"); | |
| 2910 | } else { | |
| 2888 | if (!err_union_ty.errorUnionSet().errorSetIsEmpty()) { | |
| 2889 | err: { | |
| 2890 | if (!payload_has_bits) { | |
| 2891 | if (operand_is_ptr) { | |
| 2892 | try writer.writeAll("if(*"); | |
| 2893 | } else { | |
| 2894 | try writer.writeAll("if("); | |
| 2895 | } | |
| 2896 | try f.writeCValue(writer, err_union); | |
| 2897 | try writer.writeAll(")"); | |
| 2898 | break :err; | |
| 2899 | } | |
| 2900 | if (operand_is_ptr or isByRef(err_union_ty)) { | |
| 2911 | 2901 | try writer.writeAll("if("); |
| 2902 | try f.writeCValue(writer, err_union); | |
| 2903 | try writer.writeAll("->error)"); | |
| 2904 | break :err; | |
| 2912 | 2905 | } |
| 2913 | try f.writeCValue(writer, err_union); | |
| 2914 | try writer.writeAll(")"); | |
| 2915 | break :err; | |
| 2916 | } | |
| 2917 | if (operand_is_ptr or isByRef(err_union_ty)) { | |
| 2918 | 2906 | try writer.writeAll("if("); |
| 2919 | 2907 | try f.writeCValue(writer, err_union); |
| 2920 | try writer.writeAll("->error)"); | |
| 2921 | break :err; | |
| 2908 | try writer.writeAll(".error)"); | |
| 2922 | 2909 | } |
| 2923 | try writer.writeAll("if("); | |
| 2924 | try f.writeCValue(writer, err_union); | |
| 2925 | try writer.writeAll(".error)"); | |
| 2926 | } | |
| 2927 | 2910 | |
| 2928 | try genBody(f, body); | |
| 2929 | try f.object.indent_writer.insertNewline(); | |
| 2911 | try genBody(f, body); | |
| 2912 | try f.object.indent_writer.insertNewline(); | |
| 2913 | } | |
| 2930 | 2914 | |
| 2931 | 2915 | if (!payload_has_bits) { |
| 2932 | 2916 | if (!operand_is_ptr) { |
| ... | ... | @@ -3466,7 +3450,7 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3466 | 3450 | |
| 3467 | 3451 | if (operand_ty.zigTypeTag() == .Pointer) { |
| 3468 | 3452 | const err_union_ty = operand_ty.childType(); |
| 3469 | if (err_union_ty.errorUnionSet().errorSetCardinality() == .zero) { | |
| 3453 | if (err_union_ty.errorUnionSet().errorSetIsEmpty()) { | |
| 3470 | 3454 | return CValue{ .bytes = "0" }; |
| 3471 | 3455 | } |
| 3472 | 3456 | if (!err_union_ty.errorUnionPayload().hasRuntimeBits()) { |
| ... | ... | @@ -3478,7 +3462,7 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3478 | 3462 | try writer.writeAll(";\n"); |
| 3479 | 3463 | return local; |
| 3480 | 3464 | } |
| 3481 | if (operand_ty.errorUnionSet().errorSetCardinality() == .zero) { | |
| 3465 | if (operand_ty.errorUnionSet().errorSetIsEmpty()) { | |
| 3482 | 3466 | return CValue{ .bytes = "0" }; |
| 3483 | 3467 | } |
| 3484 | 3468 | if (!operand_ty.errorUnionPayload().hasRuntimeBits()) { |
| ... | ... | @@ -3507,10 +3491,6 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, maybe_addrof: [*:0]c |
| 3507 | 3491 | const operand_is_ptr = operand_ty.zigTypeTag() == .Pointer; |
| 3508 | 3492 | const error_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty; |
| 3509 | 3493 | |
| 3510 | if (error_union_ty.errorUnionSet().errorSetCardinality() == .zero) { | |
| 3511 | return operand; | |
| 3512 | } | |
| 3513 | ||
| 3514 | 3494 | if (!error_union_ty.errorUnionPayload().hasRuntimeBits()) { |
| 3515 | 3495 | return CValue.none; |
| 3516 | 3496 | } |
| ... | ... | @@ -3575,11 +3555,6 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3575 | 3555 | const error_ty = error_union_ty.errorUnionSet(); |
| 3576 | 3556 | const payload_ty = error_union_ty.errorUnionPayload(); |
| 3577 | 3557 | |
| 3578 | if (error_ty.errorSetCardinality() == .zero) { | |
| 3579 | // TODO: write undefined bytes through the pointer here | |
| 3580 | return operand; | |
| 3581 | } | |
| 3582 | ||
| 3583 | 3558 | // First, set the non-error value. |
| 3584 | 3559 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { |
| 3585 | 3560 | try f.writeCValueDeref(writer, operand); |
| ... | ... | @@ -3623,9 +3598,6 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3623 | 3598 | const operand = try f.resolveInst(ty_op.operand); |
| 3624 | 3599 | |
| 3625 | 3600 | const inst_ty = f.air.typeOfIndex(inst); |
| 3626 | if (inst_ty.errorUnionSet().errorSetCardinality() == .zero) { | |
| 3627 | return operand; | |
| 3628 | } | |
| 3629 | 3601 | const local = try f.allocLocal(inst_ty, .Const); |
| 3630 | 3602 | try writer.writeAll(" = { .error = 0, .payload = "); |
| 3631 | 3603 | try f.writeCValue(writer, operand); |
| ... | ... | @@ -3652,7 +3624,7 @@ fn airIsErr( |
| 3652 | 3624 | |
| 3653 | 3625 | try writer.writeAll(" = "); |
| 3654 | 3626 | |
| 3655 | if (error_ty.errorSetCardinality() == .zero) { | |
| 3627 | if (error_ty.errorSetIsEmpty()) { | |
| 3656 | 3628 | try writer.print("0 {s} 0;\n", .{op_str}); |
| 3657 | 3629 | } else { |
| 3658 | 3630 | if (is_ptr) { |
src/codegen/llvm.zig+38-79| ... | ... | @@ -599,6 +599,13 @@ pub const Object = struct { |
| 599 | 599 | self.llvm_module.dump(); |
| 600 | 600 | } |
| 601 | 601 | |
| 602 | var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa); | |
| 603 | defer arena_allocator.deinit(); | |
| 604 | const arena = arena_allocator.allocator(); | |
| 605 | ||
| 606 | const mod = comp.bin_file.options.module.?; | |
| 607 | const cache_dir = mod.zig_cache_artifact_directory; | |
| 608 | ||
| 602 | 609 | if (std.debug.runtime_safety) { |
| 603 | 610 | var error_message: [*:0]const u8 = undefined; |
| 604 | 611 | // verifyModule always allocs the error_message even if there is no error |
| ... | ... | @@ -606,17 +613,15 @@ pub const Object = struct { |
| 606 | 613 | |
| 607 | 614 | if (self.llvm_module.verify(.ReturnStatus, &error_message).toBool()) { |
| 608 | 615 | std.debug.print("\n{s}\n", .{error_message}); |
| 616 | ||
| 617 | if (try locPath(arena, comp.emit_llvm_ir, cache_dir)) |emit_llvm_ir_path| { | |
| 618 | _ = self.llvm_module.printModuleToFile(emit_llvm_ir_path, &error_message); | |
| 619 | } | |
| 620 | ||
| 609 | 621 | @panic("LLVM module verification failed"); |
| 610 | 622 | } |
| 611 | 623 | } |
| 612 | 624 | |
| 613 | var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa); | |
| 614 | defer arena_allocator.deinit(); | |
| 615 | const arena = arena_allocator.allocator(); | |
| 616 | ||
| 617 | const mod = comp.bin_file.options.module.?; | |
| 618 | const cache_dir = mod.zig_cache_artifact_directory; | |
| 619 | ||
| 620 | 625 | var emit_bin_path: ?[*:0]const u8 = if (comp.bin_file.options.emit) |emit| |
| 621 | 626 | try emit.basenamePath(arena, try arena.dupeZ(u8, comp.bin_file.intermediary_basename.?)) |
| 622 | 627 | else |
| ... | ... | @@ -1566,22 +1571,6 @@ pub const Object = struct { |
| 1566 | 1571 | }, |
| 1567 | 1572 | .ErrorUnion => { |
| 1568 | 1573 | const payload_ty = ty.errorUnionPayload(); |
| 1569 | switch (ty.errorUnionSet().errorSetCardinality()) { | |
| 1570 | .zero => { | |
| 1571 | const payload_di_ty = try o.lowerDebugType(payload_ty, .full); | |
| 1572 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. | |
| 1573 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(payload_di_ty), .{ .mod = o.module }); | |
| 1574 | return payload_di_ty; | |
| 1575 | }, | |
| 1576 | .one => { | |
| 1577 | if (payload_ty.isNoReturn()) { | |
| 1578 | const di_type = dib.createBasicType("void", 0, DW.ATE.signed); | |
| 1579 | gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_type); | |
| 1580 | return di_type; | |
| 1581 | } | |
| 1582 | }, | |
| 1583 | .many => {}, | |
| 1584 | } | |
| 1585 | 1574 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { |
| 1586 | 1575 | const err_set_di_ty = try o.lowerDebugType(Type.anyerror, .full); |
| 1587 | 1576 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| ... | ... | @@ -2549,15 +2538,6 @@ pub const DeclGen = struct { |
| 2549 | 2538 | }, |
| 2550 | 2539 | .ErrorUnion => { |
| 2551 | 2540 | const payload_ty = t.errorUnionPayload(); |
| 2552 | switch (t.errorUnionSet().errorSetCardinality()) { | |
| 2553 | .zero => return dg.lowerType(payload_ty), | |
| 2554 | .one => { | |
| 2555 | if (payload_ty.isNoReturn()) { | |
| 2556 | return dg.context.voidType(); | |
| 2557 | } | |
| 2558 | }, | |
| 2559 | .many => {}, | |
| 2560 | } | |
| 2561 | 2541 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { |
| 2562 | 2542 | return try dg.lowerType(Type.anyerror); |
| 2563 | 2543 | } |
| ... | ... | @@ -3217,10 +3197,6 @@ pub const DeclGen = struct { |
| 3217 | 3197 | }, |
| 3218 | 3198 | .ErrorUnion => { |
| 3219 | 3199 | const payload_type = tv.ty.errorUnionPayload(); |
| 3220 | if (tv.ty.errorUnionSet().errorSetCardinality() == .zero) { | |
| 3221 | const payload_val = tv.val.castTag(.eu_payload).?.data; | |
| 3222 | return dg.lowerValue(.{ .ty = payload_type, .val = payload_val }); | |
| 3223 | } | |
| 3224 | 3200 | const is_pl = tv.val.errorUnionIsPayload(); |
| 3225 | 3201 | |
| 3226 | 3202 | if (!payload_type.hasRuntimeBitsIgnoreComptime()) { |
| ... | ... | @@ -4790,40 +4766,37 @@ pub const FuncGen = struct { |
| 4790 | 4766 | } |
| 4791 | 4767 | |
| 4792 | 4768 | fn lowerTry(fg: *FuncGen, err_union: *const llvm.Value, body: []const Air.Inst.Index, err_union_ty: Type, operand_is_ptr: bool, result_ty: Type) !?*const llvm.Value { |
| 4793 | if (err_union_ty.errorUnionSet().errorSetCardinality() == .zero) { | |
| 4794 | // If the error set has no fields, then the payload and the error | |
| 4795 | // union are the same value. | |
| 4796 | return err_union; | |
| 4797 | } | |
| 4798 | ||
| 4799 | 4769 | const payload_ty = err_union_ty.errorUnionPayload(); |
| 4800 | 4770 | const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(); |
| 4801 | 4771 | const target = fg.dg.module.getTarget(); |
| 4802 | const is_err = err: { | |
| 4803 | const err_set_ty = try fg.dg.lowerType(Type.anyerror); | |
| 4804 | const zero = err_set_ty.constNull(); | |
| 4805 | if (!payload_has_bits) { | |
| 4806 | const loaded = if (operand_is_ptr) fg.builder.buildLoad(err_union, "") else err_union; | |
| 4807 | break :err fg.builder.buildICmp(.NE, loaded, zero, ""); | |
| 4808 | } | |
| 4809 | const err_field_index = errUnionErrorOffset(payload_ty, target); | |
| 4810 | if (operand_is_ptr or isByRef(err_union_ty)) { | |
| 4811 | const err_field_ptr = fg.builder.buildStructGEP(err_union, err_field_index, ""); | |
| 4812 | const loaded = fg.builder.buildLoad(err_field_ptr, ""); | |
| 4772 | ||
| 4773 | if (!err_union_ty.errorUnionSet().errorSetIsEmpty()) { | |
| 4774 | const is_err = err: { | |
| 4775 | const err_set_ty = try fg.dg.lowerType(Type.anyerror); | |
| 4776 | const zero = err_set_ty.constNull(); | |
| 4777 | if (!payload_has_bits) { | |
| 4778 | const loaded = if (operand_is_ptr) fg.builder.buildLoad(err_union, "") else err_union; | |
| 4779 | break :err fg.builder.buildICmp(.NE, loaded, zero, ""); | |
| 4780 | } | |
| 4781 | const err_field_index = errUnionErrorOffset(payload_ty, target); | |
| 4782 | if (operand_is_ptr or isByRef(err_union_ty)) { | |
| 4783 | const err_field_ptr = fg.builder.buildStructGEP(err_union, err_field_index, ""); | |
| 4784 | const loaded = fg.builder.buildLoad(err_field_ptr, ""); | |
| 4785 | break :err fg.builder.buildICmp(.NE, loaded, zero, ""); | |
| 4786 | } | |
| 4787 | const loaded = fg.builder.buildExtractValue(err_union, err_field_index, ""); | |
| 4813 | 4788 | break :err fg.builder.buildICmp(.NE, loaded, zero, ""); |
| 4814 | } | |
| 4815 | const loaded = fg.builder.buildExtractValue(err_union, err_field_index, ""); | |
| 4816 | break :err fg.builder.buildICmp(.NE, loaded, zero, ""); | |
| 4817 | }; | |
| 4789 | }; | |
| 4818 | 4790 | |
| 4819 | const return_block = fg.context.appendBasicBlock(fg.llvm_func, "TryRet"); | |
| 4820 | const continue_block = fg.context.appendBasicBlock(fg.llvm_func, "TryCont"); | |
| 4821 | _ = fg.builder.buildCondBr(is_err, return_block, continue_block); | |
| 4791 | const return_block = fg.context.appendBasicBlock(fg.llvm_func, "TryRet"); | |
| 4792 | const continue_block = fg.context.appendBasicBlock(fg.llvm_func, "TryCont"); | |
| 4793 | _ = fg.builder.buildCondBr(is_err, return_block, continue_block); | |
| 4822 | 4794 | |
| 4823 | fg.builder.positionBuilderAtEnd(return_block); | |
| 4824 | try fg.genBody(body); | |
| 4795 | fg.builder.positionBuilderAtEnd(return_block); | |
| 4796 | try fg.genBody(body); | |
| 4825 | 4797 | |
| 4826 | fg.builder.positionBuilderAtEnd(continue_block); | |
| 4798 | fg.builder.positionBuilderAtEnd(continue_block); | |
| 4799 | } | |
| 4827 | 4800 | if (!payload_has_bits) { |
| 4828 | 4801 | if (!operand_is_ptr) return null; |
| 4829 | 4802 | |
| ... | ... | @@ -5660,7 +5633,7 @@ pub const FuncGen = struct { |
| 5660 | 5633 | const err_set_ty = try self.dg.lowerType(Type.initTag(.anyerror)); |
| 5661 | 5634 | const zero = err_set_ty.constNull(); |
| 5662 | 5635 | |
| 5663 | if (err_union_ty.errorUnionSet().errorSetCardinality() == .zero) { | |
| 5636 | if (err_union_ty.errorUnionSet().errorSetIsEmpty()) { | |
| 5664 | 5637 | const llvm_i1 = self.context.intType(1); |
| 5665 | 5638 | switch (op) { |
| 5666 | 5639 | .EQ => return llvm_i1.constInt(1, .False), // 0 == 0 |
| ... | ... | @@ -5783,13 +5756,6 @@ pub const FuncGen = struct { |
| 5783 | 5756 | |
| 5784 | 5757 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 5785 | 5758 | const operand = try self.resolveInst(ty_op.operand); |
| 5786 | const operand_ty = self.air.typeOf(ty_op.operand); | |
| 5787 | const error_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty; | |
| 5788 | if (error_union_ty.errorUnionSet().errorSetCardinality() == .zero) { | |
| 5789 | // If the error set has no fields, then the payload and the error | |
| 5790 | // union are the same value. | |
| 5791 | return operand; | |
| 5792 | } | |
| 5793 | 5759 | const result_ty = self.air.typeOfIndex(inst); |
| 5794 | 5760 | const payload_ty = if (operand_is_ptr) result_ty.childType() else result_ty; |
| 5795 | 5761 | const target = self.dg.module.getTarget(); |
| ... | ... | @@ -5820,7 +5786,7 @@ pub const FuncGen = struct { |
| 5820 | 5786 | const operand = try self.resolveInst(ty_op.operand); |
| 5821 | 5787 | const operand_ty = self.air.typeOf(ty_op.operand); |
| 5822 | 5788 | const err_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty; |
| 5823 | if (err_union_ty.errorUnionSet().errorSetCardinality() == .zero) { | |
| 5789 | if (err_union_ty.errorUnionSet().errorSetIsEmpty()) { | |
| 5824 | 5790 | const err_llvm_ty = try self.dg.lowerType(Type.anyerror); |
| 5825 | 5791 | if (operand_is_ptr) { |
| 5826 | 5792 | return self.builder.buildBitCast(operand, err_llvm_ty.pointerType(0), ""); |
| ... | ... | @@ -5851,10 +5817,6 @@ pub const FuncGen = struct { |
| 5851 | 5817 | const operand = try self.resolveInst(ty_op.operand); |
| 5852 | 5818 | const error_union_ty = self.air.typeOf(ty_op.operand).childType(); |
| 5853 | 5819 | |
| 5854 | if (error_union_ty.errorUnionSet().errorSetCardinality() == .zero) { | |
| 5855 | // TODO: write undefined bytes through the pointer here | |
| 5856 | return operand; | |
| 5857 | } | |
| 5858 | 5820 | const payload_ty = error_union_ty.errorUnionPayload(); |
| 5859 | 5821 | const non_error_val = try self.dg.lowerValue(.{ .ty = Type.anyerror, .val = Value.zero }); |
| 5860 | 5822 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { |
| ... | ... | @@ -5933,9 +5895,6 @@ pub const FuncGen = struct { |
| 5933 | 5895 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 5934 | 5896 | const inst_ty = self.air.typeOfIndex(inst); |
| 5935 | 5897 | const operand = try self.resolveInst(ty_op.operand); |
| 5936 | if (inst_ty.errorUnionSet().errorSetCardinality() == .zero) { | |
| 5937 | return operand; | |
| 5938 | } | |
| 5939 | 5898 | const payload_ty = self.air.typeOf(ty_op.operand); |
| 5940 | 5899 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { |
| 5941 | 5900 | return operand; |
src/codegen/llvm/bindings.zig+3| ... | ... | @@ -390,6 +390,9 @@ pub const Module = opaque { |
| 390 | 390 | |
| 391 | 391 | pub const setModuleInlineAsm2 = LLVMSetModuleInlineAsm2; |
| 392 | 392 | extern fn LLVMSetModuleInlineAsm2(M: *const Module, Asm: [*]const u8, Len: usize) void; |
| 393 | ||
| 394 | pub const printModuleToFile = LLVMPrintModuleToFile; | |
| 395 | extern fn LLVMPrintModuleToFile(M: *const Module, Filename: [*:0]const u8, ErrorMessage: *[*:0]const u8) Bool; | |
| 393 | 396 | }; |
| 394 | 397 | |
| 395 | 398 | pub const lookupIntrinsicID = LLVMLookupIntrinsicID; |
src/print_air.zig+30-8| ... | ... | @@ -4,6 +4,7 @@ const fmtIntSizeBin = std.fmt.fmtIntSizeBin; |
| 4 | 4 | |
| 5 | 5 | const Module = @import("Module.zig"); |
| 6 | 6 | const Value = @import("value.zig").Value; |
| 7 | const Type = @import("type.zig").Type; | |
| 7 | 8 | const Air = @import("Air.zig"); |
| 8 | 9 | const Liveness = @import("Liveness.zig"); |
| 9 | 10 | |
| ... | ... | @@ -304,14 +305,27 @@ const Writer = struct { |
| 304 | 305 | // no-op, no argument to write |
| 305 | 306 | } |
| 306 | 307 | |
| 308 | fn writeType(w: *Writer, s: anytype, ty: Type) !void { | |
| 309 | const t = ty.tag(); | |
| 310 | switch (t) { | |
| 311 | .inferred_alloc_const => try s.writeAll("(inferred_alloc_const)"), | |
| 312 | .inferred_alloc_mut => try s.writeAll("(inferred_alloc_mut)"), | |
| 313 | .generic_poison => try s.writeAll("(generic_poison)"), | |
| 314 | .var_args_param => try s.writeAll("(var_args_param)"), | |
| 315 | .bound_fn => try s.writeAll("(bound_fn)"), | |
| 316 | else => try ty.print(s, w.module), | |
| 317 | } | |
| 318 | } | |
| 319 | ||
| 307 | 320 | fn writeTy(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { |
| 308 | 321 | const ty = w.air.instructions.items(.data)[inst].ty; |
| 309 | try s.print("{}", .{ty.fmtDebug()}); | |
| 322 | try w.writeType(s, ty); | |
| 310 | 323 | } |
| 311 | 324 | |
| 312 | 325 | fn writeTyOp(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { |
| 313 | 326 | const ty_op = w.air.instructions.items(.data)[inst].ty_op; |
| 314 | try s.print("{}, ", .{w.air.getRefType(ty_op.ty).fmtDebug()}); | |
| 327 | try w.writeType(s, w.air.getRefType(ty_op.ty)); | |
| 328 | try s.writeAll(", "); | |
| 315 | 329 | try w.writeOperand(s, inst, 0, ty_op.operand); |
| 316 | 330 | } |
| 317 | 331 | |
| ... | ... | @@ -320,7 +334,8 @@ const Writer = struct { |
| 320 | 334 | const extra = w.air.extraData(Air.Block, ty_pl.payload); |
| 321 | 335 | const body = w.air.extra[extra.end..][0..extra.data.body_len]; |
| 322 | 336 | |
| 323 | try s.print("{}, {{\n", .{w.air.getRefType(ty_pl.ty).fmtDebug()}); | |
| 337 | try w.writeType(s, w.air.getRefType(ty_pl.ty)); | |
| 338 | try s.writeAll(", {\n"); | |
| 324 | 339 | const old_indent = w.indent; |
| 325 | 340 | w.indent += 2; |
| 326 | 341 | try w.writeBody(s, body); |
| ... | ... | @@ -335,7 +350,8 @@ const Writer = struct { |
| 335 | 350 | const len = @intCast(usize, vector_ty.arrayLen()); |
| 336 | 351 | const elements = @ptrCast([]const Air.Inst.Ref, w.air.extra[ty_pl.payload..][0..len]); |
| 337 | 352 | |
| 338 | try s.print("{}, [", .{vector_ty.fmtDebug()}); | |
| 353 | try w.writeType(s, vector_ty); | |
| 354 | try s.writeAll(", ["); | |
| 339 | 355 | for (elements) |elem, i| { |
| 340 | 356 | if (i != 0) try s.writeAll(", "); |
| 341 | 357 | try w.writeOperand(s, inst, i, elem); |
| ... | ... | @@ -408,7 +424,8 @@ const Writer = struct { |
| 408 | 424 | const extra = w.air.extraData(Air.Bin, pl_op.payload).data; |
| 409 | 425 | |
| 410 | 426 | const elem_ty = w.air.typeOfIndex(inst).childType(); |
| 411 | try s.print("{}, ", .{elem_ty.fmtDebug()}); | |
| 427 | try w.writeType(s, elem_ty); | |
| 428 | try s.writeAll(", "); | |
| 412 | 429 | try w.writeOperand(s, inst, 0, pl_op.operand); |
| 413 | 430 | try s.writeAll(", "); |
| 414 | 431 | try w.writeOperand(s, inst, 1, extra.lhs); |
| ... | ... | @@ -511,7 +528,9 @@ const Writer = struct { |
| 511 | 528 | fn writeConstant(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { |
| 512 | 529 | const ty_pl = w.air.instructions.items(.data)[inst].ty_pl; |
| 513 | 530 | const val = w.air.values[ty_pl.payload]; |
| 514 | try s.print("{}, {}", .{ w.air.getRefType(ty_pl.ty).fmtDebug(), val.fmtDebug() }); | |
| 531 | const ty = w.air.getRefType(ty_pl.ty); | |
| 532 | try w.writeType(s, ty); | |
| 533 | try s.print(", {}", .{val.fmtValue(ty, w.module)}); | |
| 515 | 534 | } |
| 516 | 535 | |
| 517 | 536 | fn writeAssembly(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { |
| ... | ... | @@ -523,7 +542,7 @@ const Writer = struct { |
| 523 | 542 | var op_index: usize = 0; |
| 524 | 543 | |
| 525 | 544 | const ret_ty = w.air.typeOfIndex(inst); |
| 526 | try s.print("{}", .{ret_ty.fmtDebug()}); | |
| 545 | try w.writeType(s, ret_ty); | |
| 527 | 546 | |
| 528 | 547 | if (is_volatile) { |
| 529 | 548 | try s.writeAll(", volatile"); |
| ... | ... | @@ -647,7 +666,10 @@ const Writer = struct { |
| 647 | 666 | const body = w.air.extra[extra.end..][0..extra.data.body_len]; |
| 648 | 667 | |
| 649 | 668 | try w.writeOperand(s, inst, 0, extra.data.ptr); |
| 650 | try s.print(", {}, {{\n", .{w.air.getRefType(ty_pl.ty).fmtDebug()}); | |
| 669 | ||
| 670 | try s.writeAll(", "); | |
| 671 | try w.writeType(s, w.air.getRefType(ty_pl.ty)); | |
| 672 | try s.writeAll(", {\n"); | |
| 651 | 673 | const old_indent = w.indent; |
| 652 | 674 | w.indent += 2; |
| 653 | 675 | try w.writeBody(s, body); |
src/type.zig+29-163| ... | ... | @@ -2366,6 +2366,10 @@ pub const Type = extern union { |
| 2366 | 2366 | .anyopaque, |
| 2367 | 2367 | .@"opaque", |
| 2368 | 2368 | .type_info, |
| 2369 | .error_set_single, | |
| 2370 | .error_union, | |
| 2371 | .error_set, | |
| 2372 | .error_set_merged, | |
| 2369 | 2373 | => return true, |
| 2370 | 2374 | |
| 2371 | 2375 | // These are false because they are comptime-only types. |
| ... | ... | @@ -2389,20 +2393,8 @@ pub const Type = extern union { |
| 2389 | 2393 | .fn_void_no_args, |
| 2390 | 2394 | .fn_naked_noreturn_no_args, |
| 2391 | 2395 | .fn_ccc_void_no_args, |
| 2392 | .error_set_single, | |
| 2393 | 2396 | => return false, |
| 2394 | 2397 | |
| 2395 | .error_set => { | |
| 2396 | const err_set_obj = ty.castTag(.error_set).?.data; | |
| 2397 | const names = err_set_obj.names.keys(); | |
| 2398 | return names.len > 1; | |
| 2399 | }, | |
| 2400 | .error_set_merged => { | |
| 2401 | const name_map = ty.castTag(.error_set_merged).?.data; | |
| 2402 | const names = name_map.keys(); | |
| 2403 | return names.len > 1; | |
| 2404 | }, | |
| 2405 | ||
| 2406 | 2398 | // These types have more than one possible value, so the result is the same as |
| 2407 | 2399 | // asking whether they are comptime-only types. |
| 2408 | 2400 | .anyframe_T, |
| ... | ... | @@ -2443,25 +2435,6 @@ pub const Type = extern union { |
| 2443 | 2435 | } |
| 2444 | 2436 | }, |
| 2445 | 2437 | |
| 2446 | .error_union => { | |
| 2447 | // This code needs to be kept in sync with the equivalent switch prong | |
| 2448 | // in abiSizeAdvanced. | |
| 2449 | const data = ty.castTag(.error_union).?.data; | |
| 2450 | switch (data.error_set.errorSetCardinality()) { | |
| 2451 | .zero => return hasRuntimeBitsAdvanced(data.payload, ignore_comptime_only, sema_kit), | |
| 2452 | .one => return !data.payload.isNoReturn(), | |
| 2453 | .many => { | |
| 2454 | if (ignore_comptime_only) { | |
| 2455 | return true; | |
| 2456 | } else if (sema_kit) |sk| { | |
| 2457 | return !(try sk.sema.typeRequiresComptime(sk.block, sk.src, ty)); | |
| 2458 | } else { | |
| 2459 | return !comptimeOnly(ty); | |
| 2460 | } | |
| 2461 | }, | |
| 2462 | } | |
| 2463 | }, | |
| 2464 | ||
| 2465 | 2438 | .@"struct" => { |
| 2466 | 2439 | const struct_obj = ty.castTag(.@"struct").?.data; |
| 2467 | 2440 | if (struct_obj.status == .field_types_wip) { |
| ... | ... | @@ -2926,27 +2899,11 @@ pub const Type = extern union { |
| 2926 | 2899 | .anyerror_void_error_union, |
| 2927 | 2900 | .anyerror, |
| 2928 | 2901 | .error_set_inferred, |
| 2902 | .error_set_single, | |
| 2903 | .error_set, | |
| 2904 | .error_set_merged, | |
| 2929 | 2905 | => return AbiAlignmentAdvanced{ .scalar = 2 }, |
| 2930 | 2906 | |
| 2931 | .error_set => { | |
| 2932 | const err_set_obj = ty.castTag(.error_set).?.data; | |
| 2933 | const names = err_set_obj.names.keys(); | |
| 2934 | if (names.len <= 1) { | |
| 2935 | return AbiAlignmentAdvanced{ .scalar = 0 }; | |
| 2936 | } else { | |
| 2937 | return AbiAlignmentAdvanced{ .scalar = 2 }; | |
| 2938 | } | |
| 2939 | }, | |
| 2940 | .error_set_merged => { | |
| 2941 | const name_map = ty.castTag(.error_set_merged).?.data; | |
| 2942 | const names = name_map.keys(); | |
| 2943 | if (names.len <= 1) { | |
| 2944 | return AbiAlignmentAdvanced{ .scalar = 0 }; | |
| 2945 | } else { | |
| 2946 | return AbiAlignmentAdvanced{ .scalar = 2 }; | |
| 2947 | } | |
| 2948 | }, | |
| 2949 | ||
| 2950 | 2907 | .array, .array_sentinel => return ty.elemType().abiAlignmentAdvanced(target, strat), |
| 2951 | 2908 | |
| 2952 | 2909 | // TODO audit this - is there any more complicated logic to determine |
| ... | ... | @@ -2971,12 +2928,7 @@ pub const Type = extern union { |
| 2971 | 2928 | |
| 2972 | 2929 | switch (child_type.zigTypeTag()) { |
| 2973 | 2930 | .Pointer => return AbiAlignmentAdvanced{ .scalar = @divExact(target.cpu.arch.ptrBitWidth(), 8) }, |
| 2974 | .ErrorSet => switch (child_type.errorSetCardinality()) { | |
| 2975 | // `?error{}` is comptime-known to be null. | |
| 2976 | .zero => return AbiAlignmentAdvanced{ .scalar = 0 }, | |
| 2977 | .one => return AbiAlignmentAdvanced{ .scalar = 1 }, | |
| 2978 | .many => return abiAlignmentAdvanced(Type.anyerror, target, strat), | |
| 2979 | }, | |
| 2931 | .ErrorSet => return abiAlignmentAdvanced(Type.anyerror, target, strat), | |
| 2980 | 2932 | .NoReturn => return AbiAlignmentAdvanced{ .scalar = 0 }, |
| 2981 | 2933 | else => {}, |
| 2982 | 2934 | } |
| ... | ... | @@ -2999,15 +2951,6 @@ pub const Type = extern union { |
| 2999 | 2951 | // This code needs to be kept in sync with the equivalent switch prong |
| 3000 | 2952 | // in abiSizeAdvanced. |
| 3001 | 2953 | const data = ty.castTag(.error_union).?.data; |
| 3002 | switch (data.error_set.errorSetCardinality()) { | |
| 3003 | .zero => return abiAlignmentAdvanced(data.payload, target, strat), | |
| 3004 | .one => { | |
| 3005 | if (data.payload.isNoReturn()) { | |
| 3006 | return AbiAlignmentAdvanced{ .scalar = 0 }; | |
| 3007 | } | |
| 3008 | }, | |
| 3009 | .many => {}, | |
| 3010 | } | |
| 3011 | 2954 | const code_align = abiAlignment(Type.anyerror, target); |
| 3012 | 2955 | switch (strat) { |
| 3013 | 2956 | .eager, .sema_kit => { |
| ... | ... | @@ -3118,7 +3061,6 @@ pub const Type = extern union { |
| 3118 | 3061 | .@"undefined", |
| 3119 | 3062 | .enum_literal, |
| 3120 | 3063 | .type_info, |
| 3121 | .error_set_single, | |
| 3122 | 3064 | => return AbiAlignmentAdvanced{ .scalar = 0 }, |
| 3123 | 3065 | |
| 3124 | 3066 | .noreturn, |
| ... | ... | @@ -3237,7 +3179,6 @@ pub const Type = extern union { |
| 3237 | 3179 | .empty_struct_literal, |
| 3238 | 3180 | .empty_struct, |
| 3239 | 3181 | .void, |
| 3240 | .error_set_single, | |
| 3241 | 3182 | => return AbiSizeAdvanced{ .scalar = 0 }, |
| 3242 | 3183 | |
| 3243 | 3184 | .@"struct", .tuple, .anon_struct => switch (ty.containerLayout()) { |
| ... | ... | @@ -3396,27 +3337,11 @@ pub const Type = extern union { |
| 3396 | 3337 | .anyerror_void_error_union, |
| 3397 | 3338 | .anyerror, |
| 3398 | 3339 | .error_set_inferred, |
| 3340 | .error_set, | |
| 3341 | .error_set_merged, | |
| 3342 | .error_set_single, | |
| 3399 | 3343 | => return AbiSizeAdvanced{ .scalar = 2 }, |
| 3400 | 3344 | |
| 3401 | .error_set => { | |
| 3402 | const err_set_obj = ty.castTag(.error_set).?.data; | |
| 3403 | const names = err_set_obj.names.keys(); | |
| 3404 | if (names.len <= 1) { | |
| 3405 | return AbiSizeAdvanced{ .scalar = 0 }; | |
| 3406 | } else { | |
| 3407 | return AbiSizeAdvanced{ .scalar = 2 }; | |
| 3408 | } | |
| 3409 | }, | |
| 3410 | .error_set_merged => { | |
| 3411 | const name_map = ty.castTag(.error_set_merged).?.data; | |
| 3412 | const names = name_map.keys(); | |
| 3413 | if (names.len <= 1) { | |
| 3414 | return AbiSizeAdvanced{ .scalar = 0 }; | |
| 3415 | } else { | |
| 3416 | return AbiSizeAdvanced{ .scalar = 2 }; | |
| 3417 | } | |
| 3418 | }, | |
| 3419 | ||
| 3420 | 3345 | .i16, .u16 => return AbiSizeAdvanced{ .scalar = intAbiSize(16, target) }, |
| 3421 | 3346 | .u29 => return AbiSizeAdvanced{ .scalar = intAbiSize(29, target) }, |
| 3422 | 3347 | .i32, .u32 => return AbiSizeAdvanced{ .scalar = intAbiSize(32, target) }, |
| ... | ... | @@ -3467,24 +3392,6 @@ pub const Type = extern union { |
| 3467 | 3392 | // This code needs to be kept in sync with the equivalent switch prong |
| 3468 | 3393 | // in abiAlignmentAdvanced. |
| 3469 | 3394 | const data = ty.castTag(.error_union).?.data; |
| 3470 | // Here we need to care whether or not the error set is *empty* or whether | |
| 3471 | // it only has *one possible value*. In the former case, it means there | |
| 3472 | // cannot possibly be an error, meaning the ABI size is equivalent to the | |
| 3473 | // payload ABI size. In the latter case, we need to account for the "tag" | |
| 3474 | // because even if both the payload type and the error set type of an | |
| 3475 | // error union have no runtime bits, an error union still has | |
| 3476 | // 1 bit of data which is whether or not the value is an error. | |
| 3477 | // Zig still uses the error code encoding at runtime, even when only 1 bit | |
| 3478 | // would suffice. This prevents coercions from needing to branch. | |
| 3479 | switch (data.error_set.errorSetCardinality()) { | |
| 3480 | .zero => return abiSizeAdvanced(data.payload, target, strat), | |
| 3481 | .one => { | |
| 3482 | if (data.payload.isNoReturn()) { | |
| 3483 | return AbiSizeAdvanced{ .scalar = 0 }; | |
| 3484 | } | |
| 3485 | }, | |
| 3486 | .many => {}, | |
| 3487 | } | |
| 3488 | 3395 | const code_size = abiSize(Type.anyerror, target); |
| 3489 | 3396 | if (!data.payload.hasRuntimeBits()) { |
| 3490 | 3397 | // Same as anyerror. |
| ... | ... | @@ -3727,11 +3634,7 @@ pub const Type = extern union { |
| 3727 | 3634 | |
| 3728 | 3635 | .error_union => { |
| 3729 | 3636 | const payload = ty.castTag(.error_union).?.data; |
| 3730 | if (!payload.error_set.hasRuntimeBits() and !payload.payload.hasRuntimeBits()) { | |
| 3731 | return 0; | |
| 3732 | } else if (!payload.error_set.hasRuntimeBits()) { | |
| 3733 | return payload.payload.bitSizeAdvanced(target, sema_kit); | |
| 3734 | } else if (!payload.payload.hasRuntimeBits()) { | |
| 3637 | if (!payload.payload.hasRuntimeBits()) { | |
| 3735 | 3638 | return payload.error_set.bitSizeAdvanced(target, sema_kit); |
| 3736 | 3639 | } |
| 3737 | 3640 | @panic("TODO bitSize error union"); |
| ... | ... | @@ -4351,30 +4254,25 @@ pub const Type = extern union { |
| 4351 | 4254 | }; |
| 4352 | 4255 | } |
| 4353 | 4256 | |
| 4354 | const ErrorSetCardinality = enum { zero, one, many }; | |
| 4355 | ||
| 4356 | pub fn errorSetCardinality(ty: Type) ErrorSetCardinality { | |
| 4257 | /// Returns false for unresolved inferred error sets. | |
| 4258 | pub fn errorSetIsEmpty(ty: Type) bool { | |
| 4357 | 4259 | switch (ty.tag()) { |
| 4358 | .anyerror => return .many, | |
| 4359 | .error_set_inferred => return .many, | |
| 4360 | .error_set_single => return .one, | |
| 4260 | .anyerror => return false, | |
| 4261 | .error_set_inferred => { | |
| 4262 | const inferred_error_set = ty.castTag(.error_set_inferred).?.data; | |
| 4263 | // Can't know for sure. | |
| 4264 | if (!inferred_error_set.is_resolved) return false; | |
| 4265 | if (inferred_error_set.is_anyerror) return false; | |
| 4266 | return inferred_error_set.errors.count() == 0; | |
| 4267 | }, | |
| 4268 | .error_set_single => return false, | |
| 4361 | 4269 | .error_set => { |
| 4362 | 4270 | const err_set_obj = ty.castTag(.error_set).?.data; |
| 4363 | const names = err_set_obj.names.keys(); | |
| 4364 | switch (names.len) { | |
| 4365 | 0 => return .zero, | |
| 4366 | 1 => return .one, | |
| 4367 | else => return .many, | |
| 4368 | } | |
| 4271 | return err_set_obj.names.count() == 0; | |
| 4369 | 4272 | }, |
| 4370 | 4273 | .error_set_merged => { |
| 4371 | 4274 | const name_map = ty.castTag(.error_set_merged).?.data; |
| 4372 | const names = name_map.keys(); | |
| 4373 | switch (names.len) { | |
| 4374 | 0 => return .zero, | |
| 4375 | 1 => return .one, | |
| 4376 | else => return .many, | |
| 4377 | } | |
| 4275 | return name_map.count() == 0; | |
| 4378 | 4276 | }, |
| 4379 | 4277 | else => unreachable, |
| 4380 | 4278 | } |
| ... | ... | @@ -4883,6 +4781,10 @@ pub const Type = extern union { |
| 4883 | 4781 | .bool, |
| 4884 | 4782 | .type, |
| 4885 | 4783 | .anyerror, |
| 4784 | .error_union, | |
| 4785 | .error_set_single, | |
| 4786 | .error_set, | |
| 4787 | .error_set_merged, | |
| 4886 | 4788 | .fn_noreturn_no_args, |
| 4887 | 4789 | .fn_void_no_args, |
| 4888 | 4790 | .fn_naked_noreturn_no_args, |
| ... | ... | @@ -4939,42 +4841,6 @@ pub const Type = extern union { |
| 4939 | 4841 | } |
| 4940 | 4842 | }, |
| 4941 | 4843 | |
| 4942 | .error_union => { | |
| 4943 | const error_ty = ty.errorUnionSet(); | |
| 4944 | switch (error_ty.errorSetCardinality()) { | |
| 4945 | .zero => { | |
| 4946 | const payload_ty = ty.errorUnionPayload(); | |
| 4947 | if (onePossibleValue(payload_ty)) |payload_val| { | |
| 4948 | _ = payload_val; | |
| 4949 | return Value.initTag(.the_only_possible_value); | |
| 4950 | } else { | |
| 4951 | return null; | |
| 4952 | } | |
| 4953 | }, | |
| 4954 | .one => { | |
| 4955 | if (ty.errorUnionPayload().isNoReturn()) { | |
| 4956 | const error_val = onePossibleValue(error_ty).?; | |
| 4957 | return error_val; | |
| 4958 | } else { | |
| 4959 | return null; | |
| 4960 | } | |
| 4961 | }, | |
| 4962 | .many => return null, | |
| 4963 | } | |
| 4964 | }, | |
| 4965 | ||
| 4966 | .error_set_single => return Value.initTag(.the_only_possible_value), | |
| 4967 | .error_set => { | |
| 4968 | const err_set_obj = ty.castTag(.error_set).?.data; | |
| 4969 | if (err_set_obj.names.count() > 1) return null; | |
| 4970 | return Value.initTag(.the_only_possible_value); | |
| 4971 | }, | |
| 4972 | .error_set_merged => { | |
| 4973 | const name_map = ty.castTag(.error_set_merged).?.data; | |
| 4974 | if (name_map.count() > 1) return null; | |
| 4975 | return Value.initTag(.the_only_possible_value); | |
| 4976 | }, | |
| 4977 | ||
| 4978 | 4844 | .@"struct" => { |
| 4979 | 4845 | const s = ty.castTag(.@"struct").?.data; |
| 4980 | 4846 | assert(s.haveFieldTypes()); |
src/value.zig+1| ... | ... | @@ -1062,6 +1062,7 @@ pub const Value = extern union { |
| 1062 | 1062 | sema_kit: ?Module.WipAnalysis, |
| 1063 | 1063 | ) Module.CompileError!BigIntConst { |
| 1064 | 1064 | switch (val.tag()) { |
| 1065 | .null_value, | |
| 1065 | 1066 | .zero, |
| 1066 | 1067 | .bool_false, |
| 1067 | 1068 | .the_only_possible_value, // i0, u0 |
test/behavior/basic.zig+23| ... | ... | @@ -1086,3 +1086,26 @@ test "inline call of function with a switch inside the return statement" { |
| 1086 | 1086 | }; |
| 1087 | 1087 | try expect(S.foo(1) == 1); |
| 1088 | 1088 | } |
| 1089 | ||
| 1090 | test "namespace lookup ignores decl causing the lookup" { | |
| 1091 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; | |
| 1092 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | |
| 1093 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 1094 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 1095 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 1096 | ||
| 1097 | const S = struct { | |
| 1098 | fn Mixin(comptime T: type) type { | |
| 1099 | return struct { | |
| 1100 | fn foo() void { | |
| 1101 | const set = std.EnumSet(T.E).init(undefined); | |
| 1102 | _ = set; | |
| 1103 | } | |
| 1104 | }; | |
| 1105 | } | |
| 1106 | ||
| 1107 | const E = enum { a, b }; | |
| 1108 | usingnamespace Mixin(@This()); | |
| 1109 | }; | |
| 1110 | _ = S.foo(); | |
| 1111 | } |
test/behavior/cast.zig+1| ... | ... | @@ -1426,6 +1426,7 @@ test "coerce undefined single-item pointer of array to error union of slice" { |
| 1426 | 1426 | } |
| 1427 | 1427 | |
| 1428 | 1428 | test "pointer to empty struct literal to mutable slice" { |
| 1429 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 1429 | 1430 | var x: []i32 = &.{}; |
| 1430 | 1431 | try expect(x.len == 0); |
| 1431 | 1432 | } |
test/behavior/error.zig-59| ... | ... | @@ -453,65 +453,6 @@ test "optional error set is the same size as error set" { |
| 453 | 453 | comptime try expect(S.returnsOptErrSet() == null); |
| 454 | 454 | } |
| 455 | 455 | |
| 456 | test "optional error set with only one error is the same size as bool" { | |
| 457 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; | |
| 458 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 459 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 460 | ||
| 461 | const E = error{only}; | |
| 462 | comptime try expect(@sizeOf(?E) == @sizeOf(bool)); | |
| 463 | comptime try expect(@alignOf(?E) == @alignOf(bool)); | |
| 464 | const S = struct { | |
| 465 | fn gimmeNull() ?E { | |
| 466 | return null; | |
| 467 | } | |
| 468 | fn gimmeErr() ?E { | |
| 469 | return error.only; | |
| 470 | } | |
| 471 | }; | |
| 472 | try expect(S.gimmeNull() == null); | |
| 473 | try expect(error.only == S.gimmeErr().?); | |
| 474 | comptime try expect(S.gimmeNull() == null); | |
| 475 | comptime try expect(error.only == S.gimmeErr().?); | |
| 476 | } | |
| 477 | ||
| 478 | test "optional empty error set" { | |
| 479 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; | |
| 480 | ||
| 481 | comptime try expect(@sizeOf(error{}!void) == @sizeOf(void)); | |
| 482 | comptime try expect(@alignOf(error{}!void) == @alignOf(void)); | |
| 483 | ||
| 484 | var x: ?error{} = undefined; | |
| 485 | if (x != null) { | |
| 486 | @compileError("test failed"); | |
| 487 | } | |
| 488 | } | |
| 489 | ||
| 490 | test "empty error set plus zero-bit payload" { | |
| 491 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; | |
| 492 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 493 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 494 | ||
| 495 | comptime try expect(@sizeOf(error{}!void) == @sizeOf(void)); | |
| 496 | comptime try expect(@alignOf(error{}!void) == @alignOf(void)); | |
| 497 | ||
| 498 | var x: error{}!void = undefined; | |
| 499 | if (x) |payload| { | |
| 500 | if (payload != {}) { | |
| 501 | @compileError("test failed"); | |
| 502 | } | |
| 503 | } else |_| { | |
| 504 | @compileError("test failed"); | |
| 505 | } | |
| 506 | const S = struct { | |
| 507 | fn empty() error{}!void {} | |
| 508 | fn inferred() !void { | |
| 509 | return empty(); | |
| 510 | } | |
| 511 | }; | |
| 512 | try S.inferred(); | |
| 513 | } | |
| 514 | ||
| 515 | 456 | test "nested catch" { |
| 516 | 457 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 517 | 458 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
test/behavior/typename.zig+25-36| ... | ... | @@ -137,43 +137,8 @@ const A_Enum = enum { |
| 137 | 137 | |
| 138 | 138 | fn regular() void {} |
| 139 | 139 | |
| 140 | test "fn body decl" { | |
| 141 | if (builtin.zig_backend == .stage1) { | |
| 142 | // stage1 fails to return fully qualified namespaces. | |
| 143 | return error.SkipZigTest; | |
| 144 | } | |
| 145 | ||
| 146 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 147 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 148 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 149 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 150 | ||
| 151 | try B.doTest(); | |
| 152 | } | |
| 153 | ||
| 154 | 140 | const B = struct { |
| 155 | fn doTest() !void { | |
| 156 | const B_Struct = struct {}; | |
| 157 | const B_Union = union { | |
| 158 | unused: u8, | |
| 159 | }; | |
| 160 | const B_Enum = enum { | |
| 161 | unused, | |
| 162 | }; | |
| 163 | ||
| 164 | try expectEqualStringsIgnoreDigits( | |
| 165 | "behavior.typename.B.doTest__struct_0", | |
| 166 | @typeName(B_Struct), | |
| 167 | ); | |
| 168 | try expectEqualStringsIgnoreDigits( | |
| 169 | "behavior.typename.B.doTest__union_0", | |
| 170 | @typeName(B_Union), | |
| 171 | ); | |
| 172 | try expectEqualStringsIgnoreDigits( | |
| 173 | "behavior.typename.B.doTest__enum_0", | |
| 174 | @typeName(B_Enum), | |
| 175 | ); | |
| 176 | } | |
| 141 | fn doTest() !void {} | |
| 177 | 142 | }; |
| 178 | 143 | |
| 179 | 144 | test "fn param" { |
| ... | ... | @@ -246,3 +211,27 @@ pub fn expectEqualStringsIgnoreDigits(expected: []const u8, actual: []const u8) |
| 246 | 211 | } |
| 247 | 212 | return expectEqualStrings(expected, actual_buf[0..actual_i]); |
| 248 | 213 | } |
| 214 | ||
| 215 | test "local variable" { | |
| 216 | if (builtin.zig_backend == .stage1) { | |
| 217 | // stage1 fails to return fully qualified namespaces. | |
| 218 | return error.SkipZigTest; | |
| 219 | } | |
| 220 | ||
| 221 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 222 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 223 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 224 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 225 | ||
| 226 | const Foo = struct { a: u32 }; | |
| 227 | const Bar = union { a: u32 }; | |
| 228 | const Baz = enum { a, b }; | |
| 229 | const Qux = enum { a, b }; | |
| 230 | const Quux = enum { a, b }; | |
| 231 | ||
| 232 | try expectEqualStrings("behavior.typename.test.local variable.Foo", @typeName(Foo)); | |
| 233 | try expectEqualStrings("behavior.typename.test.local variable.Bar", @typeName(Bar)); | |
| 234 | try expectEqualStrings("behavior.typename.test.local variable.Baz", @typeName(Baz)); | |
| 235 | try expectEqualStrings("behavior.typename.test.local variable.Qux", @typeName(Qux)); | |
| 236 | try expectEqualStrings("behavior.typename.test.local variable.Quux", @typeName(Quux)); | |
| 237 | } |
test/behavior/union.zig+18| ... | ... | @@ -1183,3 +1183,21 @@ test "comptime equality of extern unions with same tag" { |
| 1183 | 1183 | const b = S.U{ .a = 1234 }; |
| 1184 | 1184 | try expect(S.foo(a) == S.foo(b)); |
| 1185 | 1185 | } |
| 1186 | ||
| 1187 | test "union tag is set when initiated as a temporary value at runtime" { | |
| 1188 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 1189 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 1190 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 1191 | ||
| 1192 | const U = union(enum) { | |
| 1193 | a, | |
| 1194 | b: u32, | |
| 1195 | c, | |
| 1196 | ||
| 1197 | fn doTheTest(u: @This()) !void { | |
| 1198 | try expect(u == .b); | |
| 1199 | } | |
| 1200 | }; | |
| 1201 | var b: u32 = 1; | |
| 1202 | try (U{ .b = b }).doTheTest(); | |
| 1203 | } |