From b5dba702fff35c2d9aa86c9d5dd93a4a38d3b75b Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 18 Mar 2020 19:29:24 -0400 Subject: [PATCH] fixes to std.meta behavior tests are passing now --- lib/std/meta.zig | 34 ++++++++++++++++++++++++++++--- test/stage1/behavior/pointers.zig | 9 ++++---- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/lib/std/meta.zig b/lib/std/meta.zig index e8b9f16895..7343cfc51a 100644 --- a/lib/std/meta.zig +++ b/lib/std/meta.zig @@ -104,7 +104,7 @@ pub fn Child(comptime T: type) type { .Array => |info| info.child, .Pointer => |info| info.child, .Optional => |info| info.child, - else => @compileError("Expected pointer, optional, or array type, " ++ "found '" ++ @typeName(T) ++ "'"), + else => @compileError("Expected pointer, optional, or array type, found '" ++ @typeName(T) ++ "'"), }; } @@ -115,16 +115,39 @@ test "std.meta.Child" { testing.expect(Child(?u8) == u8); } +/// Given a "memory span" type, returns the "element type". +pub fn Elem(comptime T: type) type { + switch (@typeInfo(T)) { + .Array => |info| return info.child, + .Pointer => |info| switch (info.size) { + .One => switch (@typeInfo(info.child)) { + .Array => |array_info| return array_info.child, + else => {}, + }, + .Many, .C, .Slice => return info.child, + }, + else => {}, + } + @compileError("Expected pointer, slice, or array, found '" ++ @typeName(T) ++ "'"); +} + +test "std.meta.Elem" { + testing.expect(Elem([1]u8) == u8); + testing.expect(Elem([*]u8) == u8); + testing.expect(Elem([]u8) == u8); + testing.expect(Elem(*[10]u8) == u8); +} + /// Given a type which can have a sentinel e.g. `[:0]u8`, returns the sentinel value, /// or `null` if there is not one. /// Types which cannot possibly have a sentinel will be a compile error. -pub fn sentinel(comptime T: type) ?Child(T) { +pub fn sentinel(comptime T: type) ?Elem(T) { switch (@typeInfo(T)) { .Array => |info| return info.sentinel, .Pointer => |info| { switch (info.size) { .Many, .Slice => return info.sentinel, - .One => switch (info.child) { + .One => switch (@typeInfo(info.child)) { .Array => |array_info| return array_info.sentinel, else => {}, }, @@ -137,6 +160,11 @@ pub fn sentinel(comptime T: type) ?Child(T) { } test "std.meta.sentinel" { + testSentinel(); + comptime testSentinel(); +} + +fn testSentinel() void { testing.expectEqual(@as(u8, 0), sentinel([:0]u8).?); testing.expectEqual(@as(u8, 0), sentinel([*:0]u8).?); testing.expectEqual(@as(u8, 0), sentinel([5:0]u8).?); diff --git a/test/stage1/behavior/pointers.zig b/test/stage1/behavior/pointers.zig index bcc1d62df3..fbce9731f0 100644 --- a/test/stage1/behavior/pointers.zig +++ b/test/stage1/behavior/pointers.zig @@ -159,12 +159,13 @@ test "allowzero pointer and slice" { var opt_ptr: ?[*]allowzero i32 = ptr; expect(opt_ptr != null); expect(@ptrToInt(ptr) == 0); - var slice = ptr[0..10]; - expect(@TypeOf(slice) == []allowzero i32); + var runtime_zero: usize = 0; + var slice = ptr[runtime_zero..10]; + comptime expect(@TypeOf(slice) == []allowzero i32); expect(@ptrToInt(&slice[5]) == 20); - expect(@typeInfo(@TypeOf(ptr)).Pointer.is_allowzero); - expect(@typeInfo(@TypeOf(slice)).Pointer.is_allowzero); + comptime expect(@typeInfo(@TypeOf(ptr)).Pointer.is_allowzero); + comptime expect(@typeInfo(@TypeOf(slice)).Pointer.is_allowzero); } test "assign null directly to C pointer and test null equality" {