diff options
Diffstat (limited to 'lib/std')
| -rw-r--r-- | lib/std/meta.zig | 114 | ||||
| -rw-r--r-- | lib/std/meta/trait.zig | 107 |
2 files changed, 95 insertions, 126 deletions
diff --git a/lib/std/meta.zig b/lib/std/meta.zig index f090e1e8e4..9c83b8304d 100644 --- a/lib/std/meta.zig +++ b/lib/std/meta.zig @@ -7,13 +7,12 @@ const testing = std.testing; pub const trait = @import("meta/trait.zig"); -const TypeId = builtin.TypeId; const TypeInfo = builtin.TypeInfo; pub fn tagName(v: var) []const u8 { const T = @TypeOf(v); switch (@typeInfo(T)) { - TypeId.ErrorSet => return @errorName(v), + .ErrorSet => return @errorName(v), else => return @tagName(v), } } @@ -55,7 +54,7 @@ test "std.meta.tagName" { pub fn stringToEnum(comptime T: type, str: []const u8) ?T { inline for (@typeInfo(T).Enum.fields) |enumField| { - if (std.mem.eql(u8, str, enumField.name)) { + if (mem.eql(u8, str, enumField.name)) { return @field(T, enumField.name); } } @@ -74,9 +73,9 @@ test "std.meta.stringToEnum" { pub fn bitCount(comptime T: type) comptime_int { return switch (@typeInfo(T)) { - TypeId.Bool => 1, - TypeId.Int => |info| info.bits, - TypeId.Float => |info| info.bits, + .Bool => 1, + .Int => |info| info.bits, + .Float => |info| info.bits, else => @compileError("Expected bool, int or float type, found '" ++ @typeName(T) ++ "'"), }; } @@ -88,7 +87,7 @@ test "std.meta.bitCount" { pub fn alignment(comptime T: type) comptime_int { //@alignOf works on non-pointer types - const P = if (comptime trait.is(TypeId.Pointer)(T)) T else *T; + const P = if (comptime trait.is(.Pointer)(T)) T else *T; return @typeInfo(P).Pointer.alignment; } @@ -102,9 +101,9 @@ test "std.meta.alignment" { pub fn Child(comptime T: type) type { return switch (@typeInfo(T)) { - TypeId.Array => |info| info.child, - TypeId.Pointer => |info| info.child, - TypeId.Optional => |info| info.child, + .Array => |info| info.child, + .Pointer => |info| info.child, + .Optional => |info| info.child, else => @compileError("Expected pointer, optional, or array type, " ++ "found '" ++ @typeName(T) ++ "'"), }; } @@ -118,9 +117,9 @@ test "std.meta.Child" { pub fn containerLayout(comptime T: type) TypeInfo.ContainerLayout { return switch (@typeInfo(T)) { - TypeId.Struct => |info| info.layout, - TypeId.Enum => |info| info.layout, - TypeId.Union => |info| info.layout, + .Struct => |info| info.layout, + .Enum => |info| info.layout, + .Union => |info| info.layout, else => @compileError("Expected struct, enum or union type, found '" ++ @typeName(T) ++ "'"), }; } @@ -148,22 +147,22 @@ test "std.meta.containerLayout" { a: u8, }; - testing.expect(containerLayout(E1) == TypeInfo.ContainerLayout.Auto); - testing.expect(containerLayout(E2) == TypeInfo.ContainerLayout.Packed); - testing.expect(containerLayout(E3) == TypeInfo.ContainerLayout.Extern); - testing.expect(containerLayout(S1) == TypeInfo.ContainerLayout.Auto); - testing.expect(containerLayout(S2) == TypeInfo.ContainerLayout.Packed); - testing.expect(containerLayout(S3) == TypeInfo.ContainerLayout.Extern); - testing.expect(containerLayout(U1) == TypeInfo.ContainerLayout.Auto); - testing.expect(containerLayout(U2) == TypeInfo.ContainerLayout.Packed); - testing.expect(containerLayout(U3) == TypeInfo.ContainerLayout.Extern); + testing.expect(containerLayout(E1) == .Auto); + testing.expect(containerLayout(E2) == .Packed); + testing.expect(containerLayout(E3) == .Extern); + testing.expect(containerLayout(S1) == .Auto); + testing.expect(containerLayout(S2) == .Packed); + testing.expect(containerLayout(S3) == .Extern); + testing.expect(containerLayout(U1) == .Auto); + testing.expect(containerLayout(U2) == .Packed); + testing.expect(containerLayout(U3) == .Extern); } pub fn declarations(comptime T: type) []TypeInfo.Declaration { return switch (@typeInfo(T)) { - TypeId.Struct => |info| info.decls, - TypeId.Enum => |info| info.decls, - TypeId.Union => |info| info.decls, + .Struct => |info| info.decls, + .Enum => |info| info.decls, + .Union => |info| info.decls, else => @compileError("Expected struct, enum or union type, found '" ++ @typeName(T) ++ "'"), }; } @@ -232,17 +231,17 @@ test "std.meta.declarationInfo" { } pub fn fields(comptime T: type) switch (@typeInfo(T)) { - TypeId.Struct => []TypeInfo.StructField, - TypeId.Union => []TypeInfo.UnionField, - TypeId.ErrorSet => []TypeInfo.Error, - TypeId.Enum => []TypeInfo.EnumField, + .Struct => []TypeInfo.StructField, + .Union => []TypeInfo.UnionField, + .ErrorSet => []TypeInfo.Error, + .Enum => []TypeInfo.EnumField, else => @compileError("Expected struct, union, error set or enum type, found '" ++ @typeName(T) ++ "'"), } { return switch (@typeInfo(T)) { - TypeId.Struct => |info| info.fields, - TypeId.Union => |info| info.fields, - TypeId.Enum => |info| info.fields, - TypeId.ErrorSet => |errors| errors.?, // must be non global error set + .Struct => |info| info.fields, + .Union => |info| info.fields, + .Enum => |info| info.fields, + .ErrorSet => |errors| errors.?, // must be non global error set else => @compileError("Expected struct, union, error set or enum type, found '" ++ @typeName(T) ++ "'"), }; } @@ -277,10 +276,10 @@ test "std.meta.fields" { } pub fn fieldInfo(comptime T: type, comptime field_name: []const u8) switch (@typeInfo(T)) { - TypeId.Struct => TypeInfo.StructField, - TypeId.Union => TypeInfo.UnionField, - TypeId.ErrorSet => TypeInfo.Error, - TypeId.Enum => TypeInfo.EnumField, + .Struct => TypeInfo.StructField, + .Union => TypeInfo.UnionField, + .ErrorSet => TypeInfo.Error, + .Enum => TypeInfo.EnumField, else => @compileError("Expected struct, union, error set or enum type, found '" ++ @typeName(T) ++ "'"), } { inline for (comptime fields(T)) |field| { @@ -318,8 +317,8 @@ test "std.meta.fieldInfo" { pub fn TagType(comptime T: type) type { return switch (@typeInfo(T)) { - TypeId.Enum => |info| info.tag_type, - TypeId.Union => |info| if (info.tag_type) |Tag| Tag else null, + .Enum => |info| info.tag_type, + .Union => |info| if (info.tag_type) |Tag| Tag else null, else => @compileError("expected enum or union type, found '" ++ @typeName(T) ++ "'"), }; } @@ -365,7 +364,7 @@ test "std.meta.activeTag" { ///Given a tagged union type, and an enum, return the type of the union /// field corresponding to the enum tag. pub fn TagPayloadType(comptime U: type, tag: @TagType(U)) type { - testing.expect(trait.is(builtin.TypeId.Union)(U)); + testing.expect(trait.is(.Union)(U)); const info = @typeInfo(U).Union; @@ -387,30 +386,26 @@ test "std.meta.TagPayloadType" { testing.expect(MovedEvent == @TypeOf(e.Moved)); } -///Compares two of any type for equality. Containers are compared on a field-by-field basis, +/// Compares two of any type for equality. Containers are compared on a field-by-field basis, /// where possible. Pointers are not followed. pub fn eql(a: var, b: @TypeOf(a)) bool { const T = @TypeOf(a); - switch (@typeId(T)) { - builtin.TypeId.Struct => { - const info = @typeInfo(T).Struct; - + switch (@typeInfo(T)) { + .Struct => |info| { inline for (info.fields) |field_info| { if (!eql(@field(a, field_info.name), @field(b, field_info.name))) return false; } return true; }, - builtin.TypeId.ErrorUnion => { + .ErrorUnion => { if (a) |a_p| { if (b) |b_p| return eql(a_p, b_p) else |_| return false; } else |a_e| { if (b) |_| return false else |b_e| return a_e == b_e; } }, - builtin.TypeId.Union => { - const info = @typeInfo(T).Union; - + .Union => |info| { if (info.tag_type) |_| { const tag_a = activeTag(a); const tag_b = activeTag(b); @@ -427,31 +422,26 @@ pub fn eql(a: var, b: @TypeOf(a)) bool { @compileError("cannot compare untagged union type " ++ @typeName(T)); }, - builtin.TypeId.Array => { + .Array => { if (a.len != b.len) return false; for (a) |e, i| if (!eql(e, b[i])) return false; return true; }, - builtin.TypeId.Vector => { - const info = @typeInfo(T).Vector; + .Vector => |info| { var i: usize = 0; while (i < info.len) : (i += 1) { if (!eql(a[i], b[i])) return false; } return true; }, - builtin.TypeId.Pointer => { - const info = @typeInfo(T).Pointer; - switch (info.size) { - builtin.TypeInfo.Pointer.Size.One, - builtin.TypeInfo.Pointer.Size.Many, - builtin.TypeInfo.Pointer.Size.C, - => return a == b, - builtin.TypeInfo.Pointer.Size.Slice => return a.ptr == b.ptr and a.len == b.len, - } + .Pointer => |info| { + return switch (info.size) { + .One, .Many, .C, => a == b, + .Slice => a.ptr == b.ptr and a.len == b.len, + }; }, - builtin.TypeId.Optional => { + .Optional => { if (a == null and b == null) return true; if (a == null or b == null) return false; return eql(a.?, b.?); diff --git a/lib/std/meta/trait.zig b/lib/std/meta/trait.zig index d17f2dedaf..b1fd233ff2 100644 --- a/lib/std/meta/trait.zig +++ b/lib/std/meta/trait.zig @@ -7,17 +7,11 @@ const warn = debug.warn; const meta = @import("../meta.zig"); -//This is necessary if we want to return generic functions directly because of how the -// the type erasure works. see: #1375 -fn traitFnWorkaround(comptime T: type) bool { - return false; -} - -pub const TraitFn = @TypeOf(traitFnWorkaround); +pub const TraitFn = fn (type) bool; //////Trait generators -//Need TraitList because compiler can't do varargs at comptime yet +// TODO convert to tuples when #4335 is done pub const TraitList = []const TraitFn; pub fn multiTrait(comptime traits: TraitList) TraitFn { const Closure = struct { @@ -60,8 +54,7 @@ pub fn hasFn(comptime name: []const u8) TraitFn { if (!comptime isContainer(T)) return false; if (!comptime @hasDecl(T, name)) return false; const DeclType = @TypeOf(@field(T, name)); - const decl_type_id = @typeId(DeclType); - return decl_type_id == builtin.TypeId.Fn; + return @typeId(DeclType) == .Fn; } }; return Closure.trait; @@ -80,11 +73,10 @@ test "std.meta.trait.hasFn" { pub fn hasField(comptime name: []const u8) TraitFn { const Closure = struct { pub fn trait(comptime T: type) bool { - const info = @typeInfo(T); - const fields = switch (info) { - builtin.TypeId.Struct => |s| s.fields, - builtin.TypeId.Union => |u| u.fields, - builtin.TypeId.Enum => |e| e.fields, + const fields = switch (@typeInfo(T)) { + .Struct => |s| s.fields, + .Union => |u| u.fields, + .Enum => |e| e.fields, else => return false, }; @@ -120,11 +112,11 @@ pub fn is(comptime id: builtin.TypeId) TraitFn { } test "std.meta.trait.is" { - testing.expect(is(builtin.TypeId.Int)(u8)); - testing.expect(!is(builtin.TypeId.Int)(f32)); - testing.expect(is(builtin.TypeId.Pointer)(*u8)); - testing.expect(is(builtin.TypeId.Void)(void)); - testing.expect(!is(builtin.TypeId.Optional)(anyerror)); + testing.expect(is(.Int)(u8)); + testing.expect(!is(.Int)(f32)); + testing.expect(is(.Pointer)(*u8)); + testing.expect(is(.Void)(void)); + testing.expect(!is(.Optional)(anyerror)); } pub fn isPtrTo(comptime id: builtin.TypeId) TraitFn { @@ -138,9 +130,9 @@ pub fn isPtrTo(comptime id: builtin.TypeId) TraitFn { } test "std.meta.trait.isPtrTo" { - testing.expect(!isPtrTo(builtin.TypeId.Struct)(struct {})); - testing.expect(isPtrTo(builtin.TypeId.Struct)(*struct {})); - testing.expect(!isPtrTo(builtin.TypeId.Struct)(**struct {})); + testing.expect(!isPtrTo(.Struct)(struct {})); + testing.expect(isPtrTo(.Struct)(*struct {})); + testing.expect(!isPtrTo(.Struct)(**struct {})); } ///////////Strait trait Fns @@ -149,12 +141,10 @@ test "std.meta.trait.isPtrTo" { // Somewhat limited since we can't apply this logic to normal variables, fields, or // Fns yet. Should be isExternType? pub fn isExtern(comptime T: type) bool { - const Extern = builtin.TypeInfo.ContainerLayout.Extern; - const info = @typeInfo(T); - return switch (info) { - builtin.TypeId.Struct => |s| s.layout == Extern, - builtin.TypeId.Union => |u| u.layout == Extern, - builtin.TypeId.Enum => |e| e.layout == Extern, + return switch (@typeInfo(T)) { + .Struct => |s| s.layout == .Extern, + .Union => |u| u.layout == .Extern, + .Enum => |e| e.layout == .Extern, else => false, }; } @@ -169,12 +159,10 @@ test "std.meta.trait.isExtern" { } pub fn isPacked(comptime T: type) bool { - const Packed = builtin.TypeInfo.ContainerLayout.Packed; - const info = @typeInfo(T); - return switch (info) { - builtin.TypeId.Struct => |s| s.layout == Packed, - builtin.TypeId.Union => |u| u.layout == Packed, - builtin.TypeId.Enum => |e| e.layout == Packed, + return switch (@typeInfo(T)) { + .Struct => |s| s.layout == .Packed, + .Union => |u| u.layout == .Packed, + .Enum => |e| e.layout == .Packed, else => false, }; } @@ -189,8 +177,8 @@ test "std.meta.trait.isPacked" { } pub fn isUnsignedInt(comptime T: type) bool { - return switch (@typeId(T)) { - builtin.TypeId.Int => !@typeInfo(T).Int.is_signed, + return switch (@typeInfo(T)) { + .Int => |i| !i.is_signed, else => false, }; } @@ -203,9 +191,9 @@ test "isUnsignedInt" { } pub fn isSignedInt(comptime T: type) bool { - return switch (@typeId(T)) { - builtin.TypeId.ComptimeInt => true, - builtin.TypeId.Int => @typeInfo(T).Int.is_signed, + return switch (@typeInfo(T)) { + .ComptimeInt => true, + .Int => |i| i.is_signed, else => false, }; } @@ -218,9 +206,8 @@ test "isSignedInt" { } pub fn isSingleItemPtr(comptime T: type) bool { - if (comptime is(builtin.TypeId.Pointer)(T)) { - const info = @typeInfo(T); - return info.Pointer.size == builtin.TypeInfo.Pointer.Size.One; + if (comptime is(.Pointer)(T)) { + return @typeInfo(T).Pointer.size == .One; } return false; } @@ -233,9 +220,8 @@ test "std.meta.trait.isSingleItemPtr" { } pub fn isManyItemPtr(comptime T: type) bool { - if (comptime is(builtin.TypeId.Pointer)(T)) { - const info = @typeInfo(T); - return info.Pointer.size == builtin.TypeInfo.Pointer.Size.Many; + if (comptime is(.Pointer)(T)) { + return @typeInfo(T).Pointer.size == .Many; } return false; } @@ -249,9 +235,8 @@ test "std.meta.trait.isManyItemPtr" { } pub fn isSlice(comptime T: type) bool { - if (comptime is(builtin.TypeId.Pointer)(T)) { - const info = @typeInfo(T); - return info.Pointer.size == builtin.TypeInfo.Pointer.Size.Slice; + if (comptime is(.Pointer)(T)) { + return @typeInfo(T).Pointer.size == .Slice; } return false; } @@ -264,15 +249,13 @@ test "std.meta.trait.isSlice" { } pub fn isIndexable(comptime T: type) bool { - if (comptime is(builtin.TypeId.Pointer)(T)) { - const info = @typeInfo(T); - if (info.Pointer.size == builtin.TypeInfo.Pointer.Size.One) { - if (comptime is(builtin.TypeId.Array)(meta.Child(T))) return true; - return false; + if (comptime is(.Pointer)(T)) { + if (@typeInfo(T).Pointer.size == .One) { + return (comptime is(.Array)(meta.Child(T))); } return true; } - return comptime is(builtin.TypeId.Array)(T); + return comptime is(.Array)(T); } test "std.meta.trait.isIndexable" { @@ -287,7 +270,7 @@ test "std.meta.trait.isIndexable" { pub fn isNumber(comptime T: type) bool { return switch (@typeId(T)) { - builtin.TypeId.Int, builtin.TypeId.Float, builtin.TypeId.ComptimeInt, builtin.TypeId.ComptimeFloat => true, + .Int, .Float, .ComptimeInt, .ComptimeFloat => true, else => false, }; } @@ -307,9 +290,8 @@ test "std.meta.trait.isNumber" { } pub fn isConstPtr(comptime T: type) bool { - if (!comptime is(builtin.TypeId.Pointer)(T)) return false; - const info = @typeInfo(T); - return info.Pointer.is_const; + if (!comptime is(.Pointer)(T)) return false; + return @typeInfo(T).Pointer.is_const; } test "std.meta.trait.isConstPtr" { @@ -322,11 +304,8 @@ test "std.meta.trait.isConstPtr" { } pub fn isContainer(comptime T: type) bool { - const info = @typeInfo(T); - return switch (info) { - builtin.TypeId.Struct => true, - builtin.TypeId.Union => true, - builtin.TypeId.Enum => true, + return switch (@typeId(T)) { + .Struct, .Union, .Enum => true, else => false, }; } |
