Commit d3693dca73

Andrew Kelley <superjoe30@gmail.com>
2018-06-06 06:39:39
Pointer Reform: update @typeInfo
* add assertion for trying to do @typeInfo on global error set * remove TypeInfo.Slice * add TypeInfo.Pointer.Size with possible values - One - Many - Slice See #770
1 parent 76c8efd
Changed files (5)
src/analyze.cpp
@@ -5981,7 +5981,7 @@ size_t type_id_index(TypeTableEntry *entry) {
             return 7;
         case TypeTableEntryIdStruct:
             if (entry->data.structure.is_slice)
-                return 25;
+                return 6;
             return 8;
         case TypeTableEntryIdComptimeFloat:
             return 9;
src/codegen.cpp
@@ -6481,7 +6481,6 @@ static void define_builtin_compile_vars(CodeGen *g) {
             const TypeTableEntryId id = type_id_at_index(i);
             buf_appendf(contents, "    %s,\n", type_id_name(id));
         }
-        buf_appendf(contents, "    Slice,\n");
         buf_appendf(contents, "};\n\n");
     }
     {
@@ -6494,7 +6493,6 @@ static void define_builtin_compile_vars(CodeGen *g) {
             "    Int: Int,\n"
             "    Float: Float,\n"
             "    Pointer: Pointer,\n"
-            "    Slice: Slice,\n"
             "    Array: Array,\n"
             "    Struct: Struct,\n"
             "    ComptimeFloat: void,\n"
@@ -6524,13 +6522,18 @@ static void define_builtin_compile_vars(CodeGen *g) {
             "    };\n"
             "\n"
             "    pub const Pointer = struct {\n"
+            "        size: Size,\n"
             "        is_const: bool,\n"
             "        is_volatile: bool,\n"
             "        alignment: u32,\n"
             "        child: type,\n"
-            "    };\n"
             "\n"
-            "    pub const Slice = Pointer;\n"
+            "        pub const Size = enum {\n"
+            "            One,\n"
+            "            Many,\n"
+            "            Slice,\n"
+            "        };\n"
+            "    };\n"
             "\n"
             "    pub const Array = struct {\n"
             "        len: usize,\n"
src/ir.cpp
@@ -16222,8 +16222,7 @@ static bool ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Scop
     return true;
 }
 
-static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *type_entry)
-{
+static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *type_entry) {
     assert(type_entry != nullptr);
     assert(!type_is_invalid(type_entry));
 
@@ -16248,38 +16247,67 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t
         enum_field_val->data.x_struct.fields = inner_fields;
     };
 
-    const auto create_ptr_like_type_info = [ira](const char *name, TypeTableEntry *ptr_type_entry) {
+    const auto create_ptr_like_type_info = [ira](TypeTableEntry *ptr_type_entry) {
+        TypeTableEntry *attrs_type;
+        uint32_t size_enum_index;
+        if (is_slice(ptr_type_entry)) {
+            attrs_type = ptr_type_entry->data.structure.fields[slice_ptr_index].type_entry;
+            size_enum_index = 2;
+        } else if (ptr_type_entry->id == TypeTableEntryIdPointer) {
+            attrs_type = ptr_type_entry;
+            size_enum_index = (ptr_type_entry->data.pointer.ptr_len == PtrLenSingle) ? 0 : 1;
+        } else {
+            zig_unreachable();
+        }
+
+        TypeTableEntry *type_info_pointer_type = ir_type_info_get_type(ira, "Pointer");
+        ensure_complete_type(ira->codegen, type_info_pointer_type);
+        assert(!type_is_invalid(type_info_pointer_type));
+
         ConstExprValue *result = create_const_vals(1);
         result->special = ConstValSpecialStatic;
-        result->type = ir_type_info_get_type(ira, name);
+        result->type = type_info_pointer_type;
 
-        ConstExprValue *fields = create_const_vals(4);
+        ConstExprValue *fields = create_const_vals(5);
         result->data.x_struct.fields = fields;
 
-        // is_const: bool
-        ensure_field_index(result->type, "is_const", 0);
+        // size: Size
+        ensure_field_index(result->type, "size", 0);
+        TypeTableEntry *type_info_pointer_size_type = ir_type_info_get_type(ira, "Size", type_info_pointer_type);
+        ensure_complete_type(ira->codegen, type_info_pointer_size_type);
+        assert(!type_is_invalid(type_info_pointer_size_type));
         fields[0].special = ConstValSpecialStatic;
-        fields[0].type = ira->codegen->builtin_types.entry_bool;
-        fields[0].data.x_bool = ptr_type_entry->data.pointer.is_const;
-        // is_volatile: bool
-        ensure_field_index(result->type, "is_volatile", 1);
+        fields[0].type = type_info_pointer_size_type;
+        bigint_init_unsigned(&fields[0].data.x_enum_tag, size_enum_index);
+
+        // is_const: bool
+        ensure_field_index(result->type, "is_const", 1);
         fields[1].special = ConstValSpecialStatic;
         fields[1].type = ira->codegen->builtin_types.entry_bool;
-        fields[1].data.x_bool = ptr_type_entry->data.pointer.is_volatile;
-        // alignment: u32
-        ensure_field_index(result->type, "alignment", 2);
+        fields[1].data.x_bool = attrs_type->data.pointer.is_const;
+        // is_volatile: bool
+        ensure_field_index(result->type, "is_volatile", 2);
         fields[2].special = ConstValSpecialStatic;
-        fields[2].type = ira->codegen->builtin_types.entry_u32;
-        bigint_init_unsigned(&fields[2].data.x_bigint, ptr_type_entry->data.pointer.alignment);
-        // child: type
-        ensure_field_index(result->type, "child", 3);
+        fields[2].type = ira->codegen->builtin_types.entry_bool;
+        fields[2].data.x_bool = attrs_type->data.pointer.is_volatile;
+        // alignment: u32
+        ensure_field_index(result->type, "alignment", 3);
         fields[3].special = ConstValSpecialStatic;
-        fields[3].type = ira->codegen->builtin_types.entry_type;
-        fields[3].data.x_type = ptr_type_entry->data.pointer.child_type;
+        fields[3].type = ira->codegen->builtin_types.entry_u32;
+        bigint_init_unsigned(&fields[3].data.x_bigint, attrs_type->data.pointer.alignment);
+        // child: type
+        ensure_field_index(result->type, "child", 4);
+        fields[4].special = ConstValSpecialStatic;
+        fields[4].type = ira->codegen->builtin_types.entry_type;
+        fields[4].data.x_type = attrs_type->data.pointer.child_type;
 
         return result;
     };
 
+    if (type_entry == ira->codegen->builtin_types.entry_global_error_set) {
+        zig_panic("TODO implement @typeInfo for global error set");
+    }
+
     ConstExprValue *result = nullptr;
     switch (type_entry->id)
     {
@@ -16348,7 +16376,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t
             }
         case TypeTableEntryIdPointer:
             {
-                result = create_ptr_like_type_info("Pointer", type_entry);
+                result = create_ptr_like_type_info(type_entry);
                 break;
             }
         case TypeTableEntryIdArray:
@@ -16621,15 +16649,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t
         case TypeTableEntryIdStruct:
             {
                 if (type_entry->data.structure.is_slice) {
-                    Buf ptr_field_name = BUF_INIT;
-                    buf_init_from_str(&ptr_field_name, "ptr");
-                    TypeTableEntry *ptr_type = type_entry->data.structure.fields_by_name.get(&ptr_field_name)->type_entry;
-                    ensure_complete_type(ira->codegen, ptr_type);
-                    if (type_is_invalid(ptr_type))
-                        return nullptr;
-                    buf_deinit(&ptr_field_name);
-
-                    result = create_ptr_like_type_info("Slice", ptr_type);
+                    result = create_ptr_like_type_info(type_entry);
                     break;
                 }
 
std/fmt/index.zig
@@ -97,7 +97,11 @@ pub fn formatType(
     output: fn (@typeOf(context), []const u8) Errors!void,
 ) Errors!void {
     const T = @typeOf(value);
-    switch (@typeId(T)) {
+    if (T == error) {
+        try output(context, "error.");
+        return output(context, @errorName(value));
+    }
+    switch (@typeInfo(T)) {
         builtin.TypeId.Int, builtin.TypeId.Float => {
             return formatValue(value, fmt, context, Errors, output);
         },
@@ -125,12 +129,13 @@ pub fn formatType(
             try output(context, "error.");
             return output(context, @errorName(value));
         },
-        builtin.TypeId.Pointer => {
-            switch (@typeId(T.Child)) {
-                builtin.TypeId.Array => {
-                    if (T.Child.Child == u8) {
+        builtin.TypeId.Pointer => |ptr_info| switch (ptr_info.size) {
+            builtin.TypeInfo.Pointer.Size.One => switch (@typeInfo(ptr_info.child)) {
+                builtin.TypeId.Array => |info| {
+                    if (info.child == u8) {
                         return formatText(value, fmt, context, Errors, output);
                     }
+                    return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value));
                 },
                 builtin.TypeId.Enum, builtin.TypeId.Union, builtin.TypeId.Struct => {
                     const has_cust_fmt = comptime cf: {
@@ -154,14 +159,16 @@ pub fn formatType(
                     return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value));
                 },
                 else => return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value)),
-            }
-        },
-        else => if (@canImplicitCast([]const u8, value)) {
-            const casted_value = ([]const u8)(value);
-            return output(context, casted_value);
-        } else {
-            @compileError("Unable to format type '" ++ @typeName(T) ++ "'");
+            },
+            builtin.TypeInfo.Pointer.Size.Many => {
+                return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value));
+            },
+            builtin.TypeInfo.Pointer.Size.Slice => {
+                const casted_value = ([]const u8)(value);
+                return output(context, casted_value);
+            },
         },
+        else => @compileError("Unable to format type '" ++ @typeName(T) ++ "'"),
     }
 }
 
test/cases/type_info.zig
@@ -39,12 +39,28 @@ test "type info: pointer type info" {
 fn testPointer() void {
     const u32_ptr_info = @typeInfo(*u32);
     assert(TypeId(u32_ptr_info) == TypeId.Pointer);
+    assert(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.One);
     assert(u32_ptr_info.Pointer.is_const == false);
     assert(u32_ptr_info.Pointer.is_volatile == false);
-    assert(u32_ptr_info.Pointer.alignment == 4);
+    assert(u32_ptr_info.Pointer.alignment == @alignOf(u32));
     assert(u32_ptr_info.Pointer.child == u32);
 }
 
+test "type info: unknown length pointer type info" {
+    testUnknownLenPtr();
+    comptime testUnknownLenPtr();
+}
+
+fn testUnknownLenPtr() void {
+    const u32_ptr_info = @typeInfo([*]const volatile f64);
+    assert(TypeId(u32_ptr_info) == TypeId.Pointer);
+    assert(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many);
+    assert(u32_ptr_info.Pointer.is_const == true);
+    assert(u32_ptr_info.Pointer.is_volatile == true);
+    assert(u32_ptr_info.Pointer.alignment == @alignOf(f64));
+    assert(u32_ptr_info.Pointer.child == f64);
+}
+
 test "type info: slice type info" {
     testSlice();
     comptime testSlice();
@@ -52,11 +68,12 @@ test "type info: slice type info" {
 
 fn testSlice() void {
     const u32_slice_info = @typeInfo([]u32);
-    assert(TypeId(u32_slice_info) == TypeId.Slice);
-    assert(u32_slice_info.Slice.is_const == false);
-    assert(u32_slice_info.Slice.is_volatile == false);
-    assert(u32_slice_info.Slice.alignment == 4);
-    assert(u32_slice_info.Slice.child == u32);
+    assert(TypeId(u32_slice_info) == TypeId.Pointer);
+    assert(u32_slice_info.Pointer.size == TypeInfo.Pointer.Size.Slice);
+    assert(u32_slice_info.Pointer.is_const == false);
+    assert(u32_slice_info.Pointer.is_volatile == false);
+    assert(u32_slice_info.Pointer.alignment == 4);
+    assert(u32_slice_info.Pointer.child == u32);
 }
 
 test "type info: array type info" {
@@ -149,11 +166,11 @@ fn testUnion() void {
     assert(TypeId(typeinfo_info) == TypeId.Union);
     assert(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto);
     assert(typeinfo_info.Union.tag_type == TypeId);
-    assert(typeinfo_info.Union.fields.len == 26);
+    assert(typeinfo_info.Union.fields.len == 25);
     assert(typeinfo_info.Union.fields[4].enum_field != null);
     assert((??typeinfo_info.Union.fields[4].enum_field).value == 4);
     assert(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int));
-    assert(typeinfo_info.Union.defs.len == 21);
+    assert(typeinfo_info.Union.defs.len == 20);
 
     const TestNoTagUnion = union {
         Foo: void,