authorgravatar for alex_naskos@hotmail.comAlexandros Naskos <alex_naskos@hotmail.com> 2020-09-29 20:28:56+03:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-09-29 20:28:56+03:00
log3b478631fb658f96227652f71dc7785d0c3324be
tree4aea123e0325d8ce3569305d886f2a3fb1355b08
parent3342e28784b9ef7bf8356004a7b2698edcb70b40
parentd27a34f05c8c78aa9a9a6f2a30d4db1468b50999
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #6415 from MasterQ32/args-tuple

Implements std.meta.ArgsTuple.

1 files changed, 71 insertions(+), 24 deletions(-)

lib/std/meta.zig+71-24
......@@ -827,6 +827,46 @@ test "sizeof" {
827827 testing.expect(sizeof(S) == 4);
828828}
829829
830/// For a given function type, returns a tuple type which fields will
831/// correspond to the argument types.
832///
833/// Examples:
834/// - `ArgsTuple(fn() void)` ⇒ `tuple { }`
835/// - `ArgsTuple(fn(a: u32) u32)` ⇒ `tuple { u32 }`
836/// - `ArgsTuple(fn(a: u32, b: f16) noreturn)` ⇒ `tuple { u32, f16 }`
837pub fn ArgsTuple(comptime Function: type) type {
838 const info = @typeInfo(Function);
839 if (info != .Fn)
840 @compileError("ArgsTuple expects a function type");
841
842 const function_info = info.Fn;
843 if (function_info.is_generic)
844 @compileError("Cannot create ArgsTuple for generic function");
845 if (function_info.is_var_args)
846 @compileError("Cannot create ArgsTuple for variadic function");
847
848 var argument_field_list: [function_info.args.len]std.builtin.TypeInfo.StructField = undefined;
849 inline for (function_info.args) |arg, i| {
850 @setEvalBranchQuota(10_000);
851 var num_buf: [128]u8 = undefined;
852 argument_field_list[i] = std.builtin.TypeInfo.StructField{
853 .name = std.fmt.bufPrint(&num_buf, "{d}", .{i}) catch unreachable,
854 .field_type = arg.arg_type.?,
855 .default_value = @as(?(arg.arg_type.?), null),
856 .is_comptime = false,
857 };
858 }
859
860 return @Type(std.builtin.TypeInfo{
861 .Struct = std.builtin.TypeInfo.Struct{
862 .is_tuple = true,
863 .layout = .Auto,
864 .decls = &[_]std.builtin.TypeInfo.Declaration{},
865 .fields = &argument_field_list,
866 },
867 });
868}
869
830870/// For a given anonymous list of types, returns a new tuple type
831871/// with those types as fields.
832872///
......@@ -857,34 +897,41 @@ pub fn Tuple(comptime types: []const type) type {
857897 });
858898}
859899
860test "Tuple" {
861 const T = struct {
862 fn assertTypeEqual(comptime Expected: type, comptime Actual: type) void {
863 if (Expected != Actual)
864 @compileError("Expected type " ++ @typeName(Expected) ++ ", but got type " ++ @typeName(Actual));
865 }
900const TupleTester = struct {
901 fn assertTypeEqual(comptime Expected: type, comptime Actual: type) void {
902 if (Expected != Actual)
903 @compileError("Expected type " ++ @typeName(Expected) ++ ", but got type " ++ @typeName(Actual));
904 }
866905
867 fn assertTuple(comptime expected: anytype, comptime Actual: type) void {
868 const info = @typeInfo(Actual);
869 if (info != .Struct)
870 @compileError("Expected struct type");
871 if (!info.Struct.is_tuple)
872 @compileError("Struct type must be a tuple type");
906 fn assertTuple(comptime expected: anytype, comptime Actual: type) void {
907 const info = @typeInfo(Actual);
908 if (info != .Struct)
909 @compileError("Expected struct type");
910 if (!info.Struct.is_tuple)
911 @compileError("Struct type must be a tuple type");
873912
874 const fields_list = std.meta.fields(Actual);
875 if (expected.len != fields_list.len)
876 @compileError("Argument count mismatch");
913 const fields_list = std.meta.fields(Actual);
914 if (expected.len != fields_list.len)
915 @compileError("Argument count mismatch");
877916
878 inline for (fields_list) |fld, i| {
879 if (expected[i] != fld.field_type) {
880 @compileError("Field " ++ fld.name ++ " expected to be type " ++ @typeName(expected[i]) ++ ", but was type " ++ @typeName(fld.field_type));
881 }
917 inline for (fields_list) |fld, i| {
918 if (expected[i] != fld.field_type) {
919 @compileError("Field " ++ fld.name ++ " expected to be type " ++ @typeName(expected[i]) ++ ", but was type " ++ @typeName(fld.field_type));
882920 }
883921 }
884 };
922 }
923};
885924
886 T.assertTuple(.{}, Tuple(&[_]type{}));
887 T.assertTuple(.{u32}, Tuple(&[_]type{u32}));
888 T.assertTuple(.{ u32, f16 }, Tuple(&[_]type{ u32, f16 }));
889 T.assertTuple(.{ u32, f16, []const u8 }, Tuple(&[_]type{ u32, f16, []const u8 }));
925test "ArgsTuple" {
926 TupleTester.assertTuple(.{}, ArgsTuple(fn () void));
927 TupleTester.assertTuple(.{u32}, ArgsTuple(fn (a: u32) []const u8));
928 TupleTester.assertTuple(.{ u32, f16 }, ArgsTuple(fn (a: u32, b: f16) noreturn));
929 TupleTester.assertTuple(.{ u32, f16, []const u8 }, ArgsTuple(fn (a: u32, b: f16, c: []const u8) noreturn));
930}
931
932test "Tuple" {
933 TupleTester.assertTuple(.{}, Tuple(&[_]type{}));
934 TupleTester.assertTuple(.{u32}, Tuple(&[_]type{u32}));
935 TupleTester.assertTuple(.{ u32, f16 }, Tuple(&[_]type{ u32, f16 }));
936 TupleTester.assertTuple(.{ u32, f16, []const u8 }, Tuple(&[_]type{ u32, f16, []const u8 }));
890937}