From 7fa88cc0a678a3690b61054030f5597b623964a4 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 18 Mar 2020 20:35:19 -0400 Subject: [PATCH] std lib fixups for new semantics std lib tests are passing now --- lib/std/fmt.zig | 3 ++- lib/std/fs.zig | 2 +- lib/std/hash/auto_hash.zig | 12 ++++++---- lib/std/json.zig | 23 +++++++++++++------ lib/std/mem.zig | 47 ++++++-------------------------------- lib/std/meta/trait.zig | 12 ++++++---- lib/std/net.zig | 10 ++++---- src/ir.cpp | 2 +- 8 files changed, 47 insertions(+), 64 deletions(-) diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig index 592fe9bb4e..7fc9961938 100644 --- a/lib/std/fmt.zig +++ b/lib/std/fmt.zig @@ -1223,7 +1223,8 @@ test "slice" { try testFmt("slice: abc\n", "slice: {}\n", .{value}); } { - const value = @intToPtr([*]align(1) const []const u8, 0xdeadbeef)[0..0]; + var runtime_zero: usize = 0; + const value = @intToPtr([*]align(1) const []const u8, 0xdeadbeef)[runtime_zero..runtime_zero]; try testFmt("slice: []const u8@deadbeef\n", "slice: {}\n", .{value}); } diff --git a/lib/std/fs.zig b/lib/std/fs.zig index bc02fd0c91..01ed80c742 100644 --- a/lib/std/fs.zig +++ b/lib/std/fs.zig @@ -360,7 +360,7 @@ pub const Dir = struct { if (self.index >= self.end_index) { const rc = os.system.getdirentries( self.dir.fd, - self.buf[0..].ptr, + &self.buf, self.buf.len, &self.seek, ); diff --git a/lib/std/hash/auto_hash.zig b/lib/std/hash/auto_hash.zig index 2c6b37e3db..b5d6c528a5 100644 --- a/lib/std/hash/auto_hash.zig +++ b/lib/std/hash/auto_hash.zig @@ -40,7 +40,9 @@ pub fn hashPointer(hasher: var, key: var, comptime strat: HashStrategy) void { .DeepRecursive => hashArray(hasher, key, .DeepRecursive), }, - .Many, .C, => switch (strat) { + .Many, + .C, + => switch (strat) { .Shallow => hash(hasher, @ptrToInt(key), .Shallow), else => @compileError( \\ unknown-length pointers and C pointers cannot be hashed deeply. @@ -236,9 +238,11 @@ test "hash slice shallow" { defer std.testing.allocator.destroy(array1); array1.* = [_]u32{ 1, 2, 3, 4, 5, 6 }; const array2 = [_]u32{ 1, 2, 3, 4, 5, 6 }; - const a = array1[0..]; - const b = array2[0..]; - const c = array1[0..3]; + // TODO audit deep/shallow - maybe it has the wrong behavior with respect to array pointers and slices + var runtime_zero: usize = 0; + const a = array1[runtime_zero..]; + const b = array2[runtime_zero..]; + const c = array1[runtime_zero..3]; testing.expect(testHashShallow(a) == testHashShallow(a)); testing.expect(testHashShallow(a) != testHashShallow(array1)); testing.expect(testHashShallow(a) != testHashShallow(b)); diff --git a/lib/std/json.zig b/lib/std/json.zig index f5a72d86da..3dd8088785 100644 --- a/lib/std/json.zig +++ b/lib/std/json.zig @@ -2249,11 +2249,16 @@ pub const StringifyOptions = struct { // TODO: allow picking if []u8 is string or array? }; +pub const StringifyError = error{ + TooMuchData, + DifferentData, +}; + pub fn stringify( value: var, options: StringifyOptions, out_stream: var, -) !void { +) StringifyError!void { const T = @TypeOf(value); switch (@typeInfo(T)) { .Float, .ComptimeFloat => { @@ -2320,9 +2325,15 @@ pub fn stringify( return; }, .Pointer => |ptr_info| switch (ptr_info.size) { - .One => { - // TODO: avoid loops? - return try stringify(value.*, options, out_stream); + .One => switch (@typeInfo(ptr_info.child)) { + .Array => { + const Slice = []const std.meta.Elem(ptr_info.child); + return stringify(@as(Slice, value), options, out_stream); + }, + else => { + // TODO: avoid loops? + return stringify(value.*, options, out_stream); + }, }, // TODO: .Many when there is a sentinel (waiting for https://github.com/ziglang/zig/pull/3972) .Slice => { @@ -2381,9 +2392,7 @@ pub fn stringify( }, else => @compileError("Unable to stringify type '" ++ @typeName(T) ++ "'"), }, - .Array => |info| { - return try stringify(value[0..], options, out_stream); - }, + .Array => return stringify(&value, options, out_stream), else => @compileError("Unable to stringify type '" ++ @typeName(T) ++ "'"), } unreachable; diff --git a/lib/std/mem.zig b/lib/std/mem.zig index dcdf76e195..951f40ef19 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -1586,24 +1586,24 @@ pub fn nativeToBig(comptime T: type, x: T) T { } fn AsBytesReturnType(comptime P: type) type { - if (comptime !trait.isSingleItemPtr(P)) + if (!trait.isSingleItemPtr(P)) @compileError("expected single item pointer, passed " ++ @typeName(P)); - const size = @as(usize, @sizeOf(meta.Child(P))); - const alignment = comptime meta.alignment(P); + const size = @sizeOf(meta.Child(P)); + const alignment = meta.alignment(P); if (alignment == 0) { - if (comptime trait.isConstPtr(P)) + if (trait.isConstPtr(P)) return *const [size]u8; return *[size]u8; } - if (comptime trait.isConstPtr(P)) + if (trait.isConstPtr(P)) return *align(alignment) const [size]u8; return *align(alignment) [size]u8; } -///Given a pointer to a single item, returns a slice of the underlying bytes, preserving constness. +/// Given a pointer to a single item, returns a slice of the underlying bytes, preserving constness. pub fn asBytes(ptr: var) AsBytesReturnType(@TypeOf(ptr)) { const P = @TypeOf(ptr); return @ptrCast(AsBytesReturnType(P), ptr); @@ -1841,7 +1841,7 @@ pub fn sliceAsBytes(slice: var) SliceAsBytesReturnType(@TypeOf(slice)) { const cast_target = if (comptime trait.isConstPtr(Slice)) [*]align(alignment) const u8 else [*]align(alignment) u8; - return @ptrCast(cast_target, slice)[0 .. slice.len * @sizeOf(meta.Child(Slice))]; + return @ptrCast(cast_target, slice)[0 .. slice.len * @sizeOf(meta.Elem(Slice))]; } test "sliceAsBytes" { @@ -1911,39 +1911,6 @@ test "sliceAsBytes and bytesAsSlice back" { testing.expect(bytes[11] == math.maxInt(u8)); } -fn SubArrayPtrReturnType(comptime T: type, comptime length: usize) type { - if (trait.isConstPtr(T)) - return *const [length]meta.Child(meta.Child(T)); - return *[length]meta.Child(meta.Child(T)); -} - -/// Given a pointer to an array, returns a pointer to a portion of that array, preserving constness. -/// TODO this will be obsoleted by https://github.com/ziglang/zig/issues/863 -pub fn subArrayPtr( - ptr: var, - comptime start: usize, - comptime length: usize, -) SubArrayPtrReturnType(@TypeOf(ptr), length) { - assert(start + length <= ptr.*.len); - - const ReturnType = SubArrayPtrReturnType(@TypeOf(ptr), length); - const T = meta.Child(meta.Child(@TypeOf(ptr))); - return @ptrCast(ReturnType, &ptr[start]); -} - -test "subArrayPtr" { - const a1: [6]u8 = "abcdef".*; - const sub1 = subArrayPtr(&a1, 2, 3); - testing.expect(eql(u8, sub1, "cde")); - - var a2: [6]u8 = "abcdef".*; - var sub2 = subArrayPtr(&a2, 2, 3); - - testing.expect(eql(u8, sub2, "cde")); - sub2[1] = 'X'; - testing.expect(eql(u8, &a2, "abcXef")); -} - /// Round an address up to the nearest aligned address /// The alignment must be a power of 2 and greater than 0. pub fn alignForward(addr: usize, alignment: usize) usize { diff --git a/lib/std/meta/trait.zig b/lib/std/meta/trait.zig index c0fb8c5025..c99e1389f4 100644 --- a/lib/std/meta/trait.zig +++ b/lib/std/meta/trait.zig @@ -230,9 +230,10 @@ pub fn isSingleItemPtr(comptime T: type) bool { test "std.meta.trait.isSingleItemPtr" { const array = [_]u8{0} ** 10; - testing.expect(isSingleItemPtr(@TypeOf(&array[0]))); - testing.expect(!isSingleItemPtr(@TypeOf(array))); - testing.expect(!isSingleItemPtr(@TypeOf(array[0..1]))); + comptime testing.expect(isSingleItemPtr(@TypeOf(&array[0]))); + comptime testing.expect(!isSingleItemPtr(@TypeOf(array))); + var runtime_zero: usize = 0; + testing.expect(!isSingleItemPtr(@TypeOf(array[runtime_zero..1]))); } pub fn isManyItemPtr(comptime T: type) bool { @@ -259,7 +260,8 @@ pub fn isSlice(comptime T: type) bool { test "std.meta.trait.isSlice" { const array = [_]u8{0} ** 10; - testing.expect(isSlice(@TypeOf(array[0..]))); + var runtime_zero: usize = 0; + testing.expect(isSlice(@TypeOf(array[runtime_zero..]))); testing.expect(!isSlice(@TypeOf(array))); testing.expect(!isSlice(@TypeOf(&array[0]))); } @@ -276,7 +278,7 @@ pub fn isIndexable(comptime T: type) bool { test "std.meta.trait.isIndexable" { const array = [_]u8{0} ** 10; - const slice = array[0..]; + const slice = @as([]const u8, &array); testing.expect(isIndexable(@TypeOf(array))); testing.expect(isIndexable(@TypeOf(&array))); diff --git a/lib/std/net.zig b/lib/std/net.zig index c2328b9bd0..44efc4644a 100644 --- a/lib/std/net.zig +++ b/lib/std/net.zig @@ -612,8 +612,7 @@ fn linuxLookupName( } else { mem.copy(u8, &sa6.addr, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff"); mem.copy(u8, &da6.addr, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff"); - // TODO https://github.com/ziglang/zig/issues/863 - mem.writeIntNative(u32, @ptrCast(*[4]u8, da6.addr[12..].ptr), addr.addr.in.addr); + mem.writeIntNative(u32, da6.addr[12..], addr.addr.in.addr); da4.addr = addr.addr.in.addr; da = @ptrCast(*os.sockaddr, &da4); dalen = @sizeOf(os.sockaddr_in); @@ -821,7 +820,7 @@ fn linuxLookupNameFromHosts( // Skip to the delimiter in the stream, to fix parsing try stream.skipUntilDelimiterOrEof('\n'); // Use the truncated line. A truncated comment or hostname will be handled correctly. - break :blk line_buf[0..]; + break :blk @as([]u8, &line_buf); // TODO the cast should not be necessary }, else => |e| return e, }) |line| { @@ -958,7 +957,8 @@ fn linuxLookupNameFromDns( } } - var ap = [2][]u8{ apbuf[0][0..0], apbuf[1][0..0] }; + var hack: usize = 0; // TODO remove this hack + var ap = [2][]u8{ apbuf[0][0..hack], apbuf[1][0..hack] }; try resMSendRc(qp[0..nq], ap[0..nq], apbuf[0..nq], rc); var i: usize = 0; @@ -1015,7 +1015,7 @@ fn getResolvConf(allocator: *mem.Allocator, rc: *ResolvConf) !void { // Skip to the delimiter in the stream, to fix parsing try stream.skipUntilDelimiterOrEof('\n'); // Give an empty line to the while loop, which will be skipped. - break :blk line_buf[0..0]; + break :blk @as([]u8, line_buf[0..0]); // TODO the cast should not be necessary }, else => |e| return e, }) |line| { diff --git a/src/ir.cpp b/src/ir.cpp index 93f265a2d5..4800dd9109 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -14633,7 +14633,7 @@ static IrInstGen *ir_analyze_cast(IrAnalyze *ira, IrInst *source_instr, return ir_analyze_widen_or_shorten(ira, source_instr, value, wanted_type); } - // *[N]T to ?[]const T + // *[N]T to ?[]T if (wanted_type->id == ZigTypeIdOptional && is_slice(wanted_type->data.maybe.child_type) && actual_type->id == ZigTypeIdPointer &&