| ... | @@ -807,7 +807,7 @@ pub fn sizeof(target: anytype) usize { | ... | @@ -807,7 +807,7 @@ pub fn sizeof(target: anytype) usize { |
| 807 | // TODO to get the correct result we have to translate | 807 | // TODO to get the correct result we have to translate |
| 808 | // `1073741824 * 4` as `int(1073741824) *% int(4)` since | 808 | // `1073741824 * 4` as `int(1073741824) *% int(4)` since |
| 809 | // sizeof(1073741824 * 4) != sizeof(4294967296). | 809 | // sizeof(1073741824 * 4) != sizeof(4294967296). |
| 810 | | 810 | |
| 811 | // TODO test if target fits in int, long or long long | 811 | // TODO test if target fits in int, long or long long |
| 812 | return @sizeOf(c_int); | 812 | return @sizeOf(c_int); |
| 813 | }, | 813 | }, |
| ... | @@ -826,3 +826,65 @@ test "sizeof" { | ... | @@ -826,3 +826,65 @@ test "sizeof" { |
| 826 | testing.expect(sizeof(E.One) == @sizeOf(c_int)); | 826 | testing.expect(sizeof(E.One) == @sizeOf(c_int)); |
| 827 | testing.expect(sizeof(S) == 4); | 827 | testing.expect(sizeof(S) == 4); |
| 828 | } | 828 | } |
| | 829 | |
| | 830 | /// For a given anonymous list of types, returns a new tuple type |
| | 831 | /// with those types as fields. |
| | 832 | /// |
| | 833 | /// Examples: |
| | 834 | /// - `Tuple(.{})` ⇒ `tuple { }` |
| | 835 | /// - `Tuple(.{f32})` ⇒ `tuple { f32 }` |
| | 836 | /// - `Tuple(.{f32,u32})` ⇒ `tuple { f32, u32 }` |
| | 837 | pub fn Tuple(comptime types: anytype) type { |
| | 838 | var tuple_fields: [types.len]std.builtin.TypeInfo.StructField = undefined; |
| | 839 | inline for (types) |T, i| { |
| | 840 | @setEvalBranchQuota(10_000); |
| | 841 | var num_buf: [128]u8 = undefined; |
| | 842 | tuple_fields[i] = std.builtin.TypeInfo.StructField{ |
| | 843 | .name = std.fmt.bufPrint(&num_buf, "{d}", .{i}) catch unreachable, |
| | 844 | .field_type = T, |
| | 845 | .default_value = @as(?T, null), |
| | 846 | .is_comptime = false, |
| | 847 | }; |
| | 848 | } |
| | 849 | |
| | 850 | return @Type(std.builtin.TypeInfo{ |
| | 851 | .Struct = std.builtin.TypeInfo.Struct{ |
| | 852 | .is_tuple = true, |
| | 853 | .layout = .Auto, |
| | 854 | .decls = &[_]std.builtin.TypeInfo.Declaration{}, |
| | 855 | .fields = &tuple_fields, |
| | 856 | }, |
| | 857 | }); |
| | 858 | } |
| | 859 | |
| | 860 | comptime { |
| | 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 | } |
| | 866 | |
| | 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"); |
| | 873 | |
| | 874 | const fields_list = std.meta.fields(Actual); |
| | 875 | if (expected.len != fields_list.len) |
| | 876 | @compileError("Argument count mismatch"); |
| | 877 | |
| | 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 | } |
| | 882 | } |
| | 883 | } |
| | 884 | }; |
| | 885 | |
| | 886 | T.assertTuple(.{}, Tuple(.{})); |
| | 887 | T.assertTuple(.{u32}, Tuple(.{u32})); |
| | 888 | T.assertTuple(.{ u32, f16 }, Tuple(.{ u32, f16 })); |
| | 889 | T.assertTuple(.{ u32, f16, []const u8 }, Tuple(.{ u32, f16, []const u8 })); |
| | 890 | } |