| author | |
| committer | |
| log | 7fa88cc0a678a3690b61054030f5597b623964a4 |
| tree | a1cdaabfbbe0fe8b240691a9b1921245973f5107 |
| parent | b5dba702fff35c2d9aa86c9d5dd93a4a38d3b75b |
| signature |
std lib tests are passing now8 files changed, 47 insertions(+), 64 deletions(-)
lib/std/fmt.zig+2-1| ... | @@ -1223,7 +1223,8 @@ test "slice" { | ... | @@ -1223,7 +1223,8 @@ test "slice" { |
| 1223 | try testFmt("slice: abc\n", "slice: {}\n", .{value}); | 1223 | try testFmt("slice: abc\n", "slice: {}\n", .{value}); |
| 1224 | } | 1224 | } |
| 1225 | { | 1225 | { |
| 1226 | const value = @intToPtr([*]align(1) const []const u8, 0xdeadbeef)[0..0]; | 1226 | var runtime_zero: usize = 0; |
| 1227 | const value = @intToPtr([*]align(1) const []const u8, 0xdeadbeef)[runtime_zero..runtime_zero]; | ||
| 1227 | try testFmt("slice: []const u8@deadbeef\n", "slice: {}\n", .{value}); | 1228 | try testFmt("slice: []const u8@deadbeef\n", "slice: {}\n", .{value}); |
| 1228 | } | 1229 | } |
| 1229 | 1230 |
lib/std/fs.zig+1-1| ... | @@ -360,7 +360,7 @@ pub const Dir = struct { | ... | @@ -360,7 +360,7 @@ pub const Dir = struct { |
| 360 | if (self.index >= self.end_index) { | 360 | if (self.index >= self.end_index) { |
| 361 | const rc = os.system.getdirentries( | 361 | const rc = os.system.getdirentries( |
| 362 | self.dir.fd, | 362 | self.dir.fd, |
| 363 | self.buf[0..].ptr, | 363 | &self.buf, |
| 364 | self.buf.len, | 364 | self.buf.len, |
| 365 | &self.seek, | 365 | &self.seek, |
| 366 | ); | 366 | ); |
lib/std/hash/auto_hash.zig+8-4| ... | @@ -40,7 +40,9 @@ pub fn hashPointer(hasher: var, key: var, comptime strat: HashStrategy) void { | ... | @@ -40,7 +40,9 @@ pub fn hashPointer(hasher: var, key: var, comptime strat: HashStrategy) void { |
| 40 | .DeepRecursive => hashArray(hasher, key, .DeepRecursive), | 40 | .DeepRecursive => hashArray(hasher, key, .DeepRecursive), |
| 41 | }, | 41 | }, |
| 42 | 42 | ||
| 43 | .Many, .C, => switch (strat) { | 43 | .Many, |
| 44 | .C, | ||
| 45 | => switch (strat) { | ||
| 44 | .Shallow => hash(hasher, @ptrToInt(key), .Shallow), | 46 | .Shallow => hash(hasher, @ptrToInt(key), .Shallow), |
| 45 | else => @compileError( | 47 | else => @compileError( |
| 46 | \\ unknown-length pointers and C pointers cannot be hashed deeply. | 48 | \\ unknown-length pointers and C pointers cannot be hashed deeply. |
| ... | @@ -236,9 +238,11 @@ test "hash slice shallow" { | ... | @@ -236,9 +238,11 @@ test "hash slice shallow" { |
| 236 | defer std.testing.allocator.destroy(array1); | 238 | defer std.testing.allocator.destroy(array1); |
| 237 | array1.* = [_]u32{ 1, 2, 3, 4, 5, 6 }; | 239 | array1.* = [_]u32{ 1, 2, 3, 4, 5, 6 }; |
| 238 | const array2 = [_]u32{ 1, 2, 3, 4, 5, 6 }; | 240 | const array2 = [_]u32{ 1, 2, 3, 4, 5, 6 }; |
| 239 | const a = array1[0..]; | 241 | // TODO audit deep/shallow - maybe it has the wrong behavior with respect to array pointers and slices |
| 240 | const b = array2[0..]; | 242 | var runtime_zero: usize = 0; |
| 241 | const c = array1[0..3]; | 243 | const a = array1[runtime_zero..]; |
| 244 | const b = array2[runtime_zero..]; | ||
| 245 | const c = array1[runtime_zero..3]; | ||
| 242 | testing.expect(testHashShallow(a) == testHashShallow(a)); | 246 | testing.expect(testHashShallow(a) == testHashShallow(a)); |
| 243 | testing.expect(testHashShallow(a) != testHashShallow(array1)); | 247 | testing.expect(testHashShallow(a) != testHashShallow(array1)); |
| 244 | testing.expect(testHashShallow(a) != testHashShallow(b)); | 248 | testing.expect(testHashShallow(a) != testHashShallow(b)); |
lib/std/json.zig+16-7| ... | @@ -2249,11 +2249,16 @@ pub const StringifyOptions = struct { | ... | @@ -2249,11 +2249,16 @@ pub const StringifyOptions = struct { |
| 2249 | // TODO: allow picking if []u8 is string or array? | 2249 | // TODO: allow picking if []u8 is string or array? |
| 2250 | }; | 2250 | }; |
| 2251 | 2251 | ||
| 2252 | pub const StringifyError = error{ | ||
| 2253 | TooMuchData, | ||
| 2254 | DifferentData, | ||
| 2255 | }; | ||
| 2256 | |||
| 2252 | pub fn stringify( | 2257 | pub fn stringify( |
| 2253 | value: var, | 2258 | value: var, |
| 2254 | options: StringifyOptions, | 2259 | options: StringifyOptions, |
| 2255 | out_stream: var, | 2260 | out_stream: var, |
| 2256 | ) !void { | 2261 | ) StringifyError!void { |
| 2257 | const T = @TypeOf(value); | 2262 | const T = @TypeOf(value); |
| 2258 | switch (@typeInfo(T)) { | 2263 | switch (@typeInfo(T)) { |
| 2259 | .Float, .ComptimeFloat => { | 2264 | .Float, .ComptimeFloat => { |
| ... | @@ -2320,9 +2325,15 @@ pub fn stringify( | ... | @@ -2320,9 +2325,15 @@ pub fn stringify( |
| 2320 | return; | 2325 | return; |
| 2321 | }, | 2326 | }, |
| 2322 | .Pointer => |ptr_info| switch (ptr_info.size) { | 2327 | .Pointer => |ptr_info| switch (ptr_info.size) { |
| 2323 | .One => { | 2328 | .One => switch (@typeInfo(ptr_info.child)) { |
| 2324 | // TODO: avoid loops? | 2329 | .Array => { |
| 2325 | return try stringify(value.*, options, out_stream); | 2330 | const Slice = []const std.meta.Elem(ptr_info.child); |
| 2331 | return stringify(@as(Slice, value), options, out_stream); | ||
| 2332 | }, | ||
| 2333 | else => { | ||
| 2334 | // TODO: avoid loops? | ||
| 2335 | return stringify(value.*, options, out_stream); | ||
| 2336 | }, | ||
| 2326 | }, | 2337 | }, |
| 2327 | // TODO: .Many when there is a sentinel (waiting for https://github.com/ziglang/zig/pull/3972) | 2338 | // TODO: .Many when there is a sentinel (waiting for https://github.com/ziglang/zig/pull/3972) |
| 2328 | .Slice => { | 2339 | .Slice => { |
| ... | @@ -2381,9 +2392,7 @@ pub fn stringify( | ... | @@ -2381,9 +2392,7 @@ pub fn stringify( |
| 2381 | }, | 2392 | }, |
| 2382 | else => @compileError("Unable to stringify type '" ++ @typeName(T) ++ "'"), | 2393 | else => @compileError("Unable to stringify type '" ++ @typeName(T) ++ "'"), |
| 2383 | }, | 2394 | }, |
| 2384 | .Array => |info| { | 2395 | .Array => return stringify(&value, options, out_stream), |
| 2385 | return try stringify(value[0..], options, out_stream); | ||
| 2386 | }, | ||
| 2387 | else => @compileError("Unable to stringify type '" ++ @typeName(T) ++ "'"), | 2396 | else => @compileError("Unable to stringify type '" ++ @typeName(T) ++ "'"), |
| 2388 | } | 2397 | } |
| 2389 | unreachable; | 2398 | unreachable; |
lib/std/mem.zig+7-40| ... | @@ -1586,24 +1586,24 @@ pub fn nativeToBig(comptime T: type, x: T) T { | ... | @@ -1586,24 +1586,24 @@ pub fn nativeToBig(comptime T: type, x: T) T { |
| 1586 | } | 1586 | } |
| 1587 | 1587 | ||
| 1588 | fn AsBytesReturnType(comptime P: type) type { | 1588 | fn AsBytesReturnType(comptime P: type) type { |
| 1589 | if (comptime !trait.isSingleItemPtr(P)) | 1589 | if (!trait.isSingleItemPtr(P)) |
| 1590 | @compileError("expected single item pointer, passed " ++ @typeName(P)); | 1590 | @compileError("expected single item pointer, passed " ++ @typeName(P)); |
| 1591 | 1591 | ||
| 1592 | const size = @as(usize, @sizeOf(meta.Child(P))); | 1592 | const size = @sizeOf(meta.Child(P)); |
| 1593 | const alignment = comptime meta.alignment(P); | 1593 | const alignment = meta.alignment(P); |
| 1594 | 1594 | ||
| 1595 | if (alignment == 0) { | 1595 | if (alignment == 0) { |
| 1596 | if (comptime trait.isConstPtr(P)) | 1596 | if (trait.isConstPtr(P)) |
| 1597 | return *const [size]u8; | 1597 | return *const [size]u8; |
| 1598 | return *[size]u8; | 1598 | return *[size]u8; |
| 1599 | } | 1599 | } |
| 1600 | 1600 | ||
| 1601 | if (comptime trait.isConstPtr(P)) | 1601 | if (trait.isConstPtr(P)) |
| 1602 | return *align(alignment) const [size]u8; | 1602 | return *align(alignment) const [size]u8; |
| 1603 | return *align(alignment) [size]u8; | 1603 | return *align(alignment) [size]u8; |
| 1604 | } | 1604 | } |
| 1605 | 1605 | ||
| 1606 | ///Given a pointer to a single item, returns a slice of the underlying bytes, preserving constness. | 1606 | /// Given a pointer to a single item, returns a slice of the underlying bytes, preserving constness. |
| 1607 | pub fn asBytes(ptr: var) AsBytesReturnType(@TypeOf(ptr)) { | 1607 | pub fn asBytes(ptr: var) AsBytesReturnType(@TypeOf(ptr)) { |
| 1608 | const P = @TypeOf(ptr); | 1608 | const P = @TypeOf(ptr); |
| 1609 | return @ptrCast(AsBytesReturnType(P), ptr); | 1609 | return @ptrCast(AsBytesReturnType(P), ptr); |
| ... | @@ -1841,7 +1841,7 @@ pub fn sliceAsBytes(slice: var) SliceAsBytesReturnType(@TypeOf(slice)) { | ... | @@ -1841,7 +1841,7 @@ pub fn sliceAsBytes(slice: var) SliceAsBytesReturnType(@TypeOf(slice)) { |
| 1841 | 1841 | ||
| 1842 | const cast_target = if (comptime trait.isConstPtr(Slice)) [*]align(alignment) const u8 else [*]align(alignment) u8; | 1842 | const cast_target = if (comptime trait.isConstPtr(Slice)) [*]align(alignment) const u8 else [*]align(alignment) u8; |
| 1843 | 1843 | ||
| 1844 | return @ptrCast(cast_target, slice)[0 .. slice.len * @sizeOf(meta.Child(Slice))]; | 1844 | return @ptrCast(cast_target, slice)[0 .. slice.len * @sizeOf(meta.Elem(Slice))]; |
| 1845 | } | 1845 | } |
| 1846 | 1846 | ||
| 1847 | test "sliceAsBytes" { | 1847 | test "sliceAsBytes" { |
| ... | @@ -1911,39 +1911,6 @@ test "sliceAsBytes and bytesAsSlice back" { | ... | @@ -1911,39 +1911,6 @@ test "sliceAsBytes and bytesAsSlice back" { |
| 1911 | testing.expect(bytes[11] == math.maxInt(u8)); | 1911 | testing.expect(bytes[11] == math.maxInt(u8)); |
| 1912 | } | 1912 | } |
| 1913 | 1913 | ||
| 1914 | fn SubArrayPtrReturnType(comptime T: type, comptime length: usize) type { | ||
| 1915 | if (trait.isConstPtr(T)) | ||
| 1916 | return *const [length]meta.Child(meta.Child(T)); | ||
| 1917 | return *[length]meta.Child(meta.Child(T)); | ||
| 1918 | } | ||
| 1919 | |||
| 1920 | /// Given a pointer to an array, returns a pointer to a portion of that array, preserving constness. | ||
| 1921 | /// TODO this will be obsoleted by https://github.com/ziglang/zig/issues/863 | ||
| 1922 | pub fn subArrayPtr( | ||
| 1923 | ptr: var, | ||
| 1924 | comptime start: usize, | ||
| 1925 | comptime length: usize, | ||
| 1926 | ) SubArrayPtrReturnType(@TypeOf(ptr), length) { | ||
| 1927 | assert(start + length <= ptr.*.len); | ||
| 1928 | |||
| 1929 | const ReturnType = SubArrayPtrReturnType(@TypeOf(ptr), length); | ||
| 1930 | const T = meta.Child(meta.Child(@TypeOf(ptr))); | ||
| 1931 | return @ptrCast(ReturnType, &ptr[start]); | ||
| 1932 | } | ||
| 1933 | |||
| 1934 | test "subArrayPtr" { | ||
| 1935 | const a1: [6]u8 = "abcdef".*; | ||
| 1936 | const sub1 = subArrayPtr(&a1, 2, 3); | ||
| 1937 | testing.expect(eql(u8, sub1, "cde")); | ||
| 1938 | |||
| 1939 | var a2: [6]u8 = "abcdef".*; | ||
| 1940 | var sub2 = subArrayPtr(&a2, 2, 3); | ||
| 1941 | |||
| 1942 | testing.expect(eql(u8, sub2, "cde")); | ||
| 1943 | sub2[1] = 'X'; | ||
| 1944 | testing.expect(eql(u8, &a2, "abcXef")); | ||
| 1945 | } | ||
| 1946 | |||
| 1947 | /// Round an address up to the nearest aligned address | 1914 | /// Round an address up to the nearest aligned address |
| 1948 | /// The alignment must be a power of 2 and greater than 0. | 1915 | /// The alignment must be a power of 2 and greater than 0. |
| 1949 | pub fn alignForward(addr: usize, alignment: usize) usize { | 1916 | pub fn alignForward(addr: usize, alignment: usize) usize { |
lib/std/meta/trait.zig+7-5| ... | @@ -230,9 +230,10 @@ pub fn isSingleItemPtr(comptime T: type) bool { | ... | @@ -230,9 +230,10 @@ pub fn isSingleItemPtr(comptime T: type) bool { |
| 230 | 230 | ||
| 231 | test "std.meta.trait.isSingleItemPtr" { | 231 | test "std.meta.trait.isSingleItemPtr" { |
| 232 | const array = [_]u8{0} ** 10; | 232 | const array = [_]u8{0} ** 10; |
| 233 | testing.expect(isSingleItemPtr(@TypeOf(&array[0]))); | 233 | comptime testing.expect(isSingleItemPtr(@TypeOf(&array[0]))); |
| 234 | testing.expect(!isSingleItemPtr(@TypeOf(array))); | 234 | comptime testing.expect(!isSingleItemPtr(@TypeOf(array))); |
| 235 | testing.expect(!isSingleItemPtr(@TypeOf(array[0..1]))); | 235 | var runtime_zero: usize = 0; |
| 236 | testing.expect(!isSingleItemPtr(@TypeOf(array[runtime_zero..1]))); | ||
| 236 | } | 237 | } |
| 237 | 238 | ||
| 238 | pub fn isManyItemPtr(comptime T: type) bool { | 239 | pub fn isManyItemPtr(comptime T: type) bool { |
| ... | @@ -259,7 +260,8 @@ pub fn isSlice(comptime T: type) bool { | ... | @@ -259,7 +260,8 @@ pub fn isSlice(comptime T: type) bool { |
| 259 | 260 | ||
| 260 | test "std.meta.trait.isSlice" { | 261 | test "std.meta.trait.isSlice" { |
| 261 | const array = [_]u8{0} ** 10; | 262 | const array = [_]u8{0} ** 10; |
| 262 | testing.expect(isSlice(@TypeOf(array[0..]))); | 263 | var runtime_zero: usize = 0; |
| 264 | testing.expect(isSlice(@TypeOf(array[runtime_zero..]))); | ||
| 263 | testing.expect(!isSlice(@TypeOf(array))); | 265 | testing.expect(!isSlice(@TypeOf(array))); |
| 264 | testing.expect(!isSlice(@TypeOf(&array[0]))); | 266 | testing.expect(!isSlice(@TypeOf(&array[0]))); |
| 265 | } | 267 | } |
| ... | @@ -276,7 +278,7 @@ pub fn isIndexable(comptime T: type) bool { | ... | @@ -276,7 +278,7 @@ pub fn isIndexable(comptime T: type) bool { |
| 276 | 278 | ||
| 277 | test "std.meta.trait.isIndexable" { | 279 | test "std.meta.trait.isIndexable" { |
| 278 | const array = [_]u8{0} ** 10; | 280 | const array = [_]u8{0} ** 10; |
| 279 | const slice = array[0..]; | 281 | const slice = @as([]const u8, &array); |
| 280 | 282 | ||
| 281 | testing.expect(isIndexable(@TypeOf(array))); | 283 | testing.expect(isIndexable(@TypeOf(array))); |
| 282 | testing.expect(isIndexable(@TypeOf(&array))); | 284 | testing.expect(isIndexable(@TypeOf(&array))); |
lib/std/net.zig+5-5| ... | @@ -612,8 +612,7 @@ fn linuxLookupName( | ... | @@ -612,8 +612,7 @@ fn linuxLookupName( |
| 612 | } else { | 612 | } else { |
| 613 | mem.copy(u8, &sa6.addr, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff"); | 613 | mem.copy(u8, &sa6.addr, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff"); |
| 614 | mem.copy(u8, &da6.addr, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff"); | 614 | mem.copy(u8, &da6.addr, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff"); |
| 615 | // TODO https://github.com/ziglang/zig/issues/863 | 615 | mem.writeIntNative(u32, da6.addr[12..], addr.addr.in.addr); |
| 616 | mem.writeIntNative(u32, @ptrCast(*[4]u8, da6.addr[12..].ptr), addr.addr.in.addr); | ||
| 617 | da4.addr = addr.addr.in.addr; | 616 | da4.addr = addr.addr.in.addr; |
| 618 | da = @ptrCast(*os.sockaddr, &da4); | 617 | da = @ptrCast(*os.sockaddr, &da4); |
| 619 | dalen = @sizeOf(os.sockaddr_in); | 618 | dalen = @sizeOf(os.sockaddr_in); |
| ... | @@ -821,7 +820,7 @@ fn linuxLookupNameFromHosts( | ... | @@ -821,7 +820,7 @@ fn linuxLookupNameFromHosts( |
| 821 | // Skip to the delimiter in the stream, to fix parsing | 820 | // Skip to the delimiter in the stream, to fix parsing |
| 822 | try stream.skipUntilDelimiterOrEof('\n'); | 821 | try stream.skipUntilDelimiterOrEof('\n'); |
| 823 | // Use the truncated line. A truncated comment or hostname will be handled correctly. | 822 | // Use the truncated line. A truncated comment or hostname will be handled correctly. |
| 824 | break :blk line_buf[0..]; | 823 | break :blk @as([]u8, &line_buf); // TODO the cast should not be necessary |
| 825 | }, | 824 | }, |
| 826 | else => |e| return e, | 825 | else => |e| return e, |
| 827 | }) |line| { | 826 | }) |line| { |
| ... | @@ -958,7 +957,8 @@ fn linuxLookupNameFromDns( | ... | @@ -958,7 +957,8 @@ fn linuxLookupNameFromDns( |
| 958 | } | 957 | } |
| 959 | } | 958 | } |
| 960 | 959 | ||
| 961 | var ap = [2][]u8{ apbuf[0][0..0], apbuf[1][0..0] }; | 960 | var hack: usize = 0; // TODO remove this hack |
| 961 | var ap = [2][]u8{ apbuf[0][0..hack], apbuf[1][0..hack] }; | ||
| 962 | try resMSendRc(qp[0..nq], ap[0..nq], apbuf[0..nq], rc); | 962 | try resMSendRc(qp[0..nq], ap[0..nq], apbuf[0..nq], rc); |
| 963 | 963 | ||
| 964 | var i: usize = 0; | 964 | var i: usize = 0; |
| ... | @@ -1015,7 +1015,7 @@ fn getResolvConf(allocator: *mem.Allocator, rc: *ResolvConf) !void { | ... | @@ -1015,7 +1015,7 @@ fn getResolvConf(allocator: *mem.Allocator, rc: *ResolvConf) !void { |
| 1015 | // Skip to the delimiter in the stream, to fix parsing | 1015 | // Skip to the delimiter in the stream, to fix parsing |
| 1016 | try stream.skipUntilDelimiterOrEof('\n'); | 1016 | try stream.skipUntilDelimiterOrEof('\n'); |
| 1017 | // Give an empty line to the while loop, which will be skipped. | 1017 | // Give an empty line to the while loop, which will be skipped. |
| 1018 | break :blk line_buf[0..0]; | 1018 | break :blk @as([]u8, line_buf[0..0]); // TODO the cast should not be necessary |
| 1019 | }, | 1019 | }, |
| 1020 | else => |e| return e, | 1020 | else => |e| return e, |
| 1021 | }) |line| { | 1021 | }) |line| { |
src/ir.cpp+1-1| ... | @@ -14633,7 +14633,7 @@ static IrInstGen *ir_analyze_cast(IrAnalyze *ira, IrInst *source_instr, | ... | @@ -14633,7 +14633,7 @@ static IrInstGen *ir_analyze_cast(IrAnalyze *ira, IrInst *source_instr, |
| 14633 | return ir_analyze_widen_or_shorten(ira, source_instr, value, wanted_type); | 14633 | return ir_analyze_widen_or_shorten(ira, source_instr, value, wanted_type); |
| 14634 | } | 14634 | } |
| 14635 | 14635 | ||
| 14636 | // *[N]T to ?[]const T | 14636 | // *[N]T to ?[]T |
| 14637 | if (wanted_type->id == ZigTypeIdOptional && | 14637 | if (wanted_type->id == ZigTypeIdOptional && |
| 14638 | is_slice(wanted_type->data.maybe.child_type) && | 14638 | is_slice(wanted_type->data.maybe.child_type) && |
| 14639 | actual_type->id == ZigTypeIdPointer && | 14639 | actual_type->id == ZigTypeIdPointer && |