Commit 1392313236

Alexandros Naskos <alex_naskos@hotmail.com>
2018-06-19 16:45:19
@typeInfo now uses optional types instead of @typeOf(undefined)
1 parent 1ca90b5
Changed files (4)
doc/langref.html.in
@@ -5684,20 +5684,20 @@ pub const TypeInfo = union(TypeId) {
     pub const FnArg = struct {
         is_generic: bool,
         is_noalias: bool,
-        arg_type: type,
+        arg_type: ?type,
     };
 
     pub const Fn = struct {
         calling_convention: CallingConvention,
         is_generic: bool,
         is_var_args: bool,
-        return_type: type,
-        async_allocator_type: type,
+        return_type: ?type,
+        async_allocator_type: ?type,
         args: []FnArg,
     };
 
     pub const Promise = struct {
-        child: type,
+        child: ?type,
     };
 
     pub const Definition = struct {
src/codegen.cpp
@@ -6627,7 +6627,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
             "\n"
             "    pub const Union = struct {\n"
             "        layout: ContainerLayout,\n"
-            "        tag_type: type,\n"
+            "        tag_type: ?type,\n"
             "        fields: []UnionField,\n"
             "        defs: []Definition,\n"
             "    };\n"
@@ -6644,20 +6644,20 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
             "    pub const FnArg = struct {\n"
             "        is_generic: bool,\n"
             "        is_noalias: bool,\n"
-            "        arg_type: type,\n"
+            "        arg_type: ?type,\n"
             "    };\n"
             "\n"
             "    pub const Fn = struct {\n"
             "        calling_convention: CallingConvention,\n"
             "        is_generic: bool,\n"
             "        is_var_args: bool,\n"
-            "        return_type: type,\n"
-            "        async_allocator_type: type,\n"
+            "        return_type: ?type,\n"
+            "        async_allocator_type: ?type,\n"
             "        args: []FnArg,\n"
             "    };\n"
             "\n"
             "    pub const Promise = struct {\n"
-            "        child: type,\n"
+            "        child: ?type,\n"
             "    };\n"
             "\n"
             "    pub const Definition = struct {\n"
src/ir.cpp
@@ -16722,16 +16722,20 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t
                 ConstExprValue *fields = create_const_vals(1);
                 result->data.x_struct.fields = fields;
 
-                // @TODO ?type instead of using @typeOf(undefined) when we have no type.
-                // child: type
+                // child: ?type
                 ensure_field_index(result->type, "child", 0);
                 fields[0].special = ConstValSpecialStatic;
-                fields[0].type = ira->codegen->builtin_types.entry_type;
+                fields[0].type = get_maybe_type(ira->codegen, ira->codegen->builtin_types.entry_type);
 
                 if (type_entry->data.promise.result_type == nullptr)
-                    fields[0].data.x_type = ira->codegen->builtin_types.entry_undef;
-                else
-                    fields[0].data.x_type = type_entry->data.promise.result_type;
+                    fields[0].data.x_optional = nullptr;
+                else {
+                    ConstExprValue *child_type = create_const_vals(1);
+                    child_type->special = ConstValSpecialStatic;
+                    child_type->type = ira->codegen->builtin_types.entry_type;
+                    child_type->data.x_type = type_entry->data.promise.result_type;
+                    fields[0].data.x_optional = child_type;
+                }
 
                 break;
             }
@@ -16872,19 +16876,23 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t
                 fields[0].special = ConstValSpecialStatic;
                 fields[0].type = ir_type_info_get_type(ira, "ContainerLayout");
                 bigint_init_unsigned(&fields[0].data.x_enum_tag, type_entry->data.unionation.layout);
-                // tag_type: type
+                // tag_type: ?type
                 ensure_field_index(result->type, "tag_type", 1);
                 fields[1].special = ConstValSpecialStatic;
-                fields[1].type = ira->codegen->builtin_types.entry_type;
-                // @TODO ?type instead of using @typeOf(undefined) when we have no type.
+                fields[1].type = get_maybe_type(ira->codegen, ira->codegen->builtin_types.entry_type);
+
                 AstNode *union_decl_node = type_entry->data.unionation.decl_node;
                 if (union_decl_node->data.container_decl.auto_enum ||
                     union_decl_node->data.container_decl.init_arg_expr != nullptr)
                 {
-                    fields[1].data.x_type = type_entry->data.unionation.tag_type;
+                    ConstExprValue *tag_type = create_const_vals(1);
+                    tag_type->special = ConstValSpecialStatic;
+                    tag_type->type = ira->codegen->builtin_types.entry_type;
+                    tag_type->data.x_type = type_entry->data.unionation.tag_type;
+                    fields[1].data.x_optional = tag_type;
                 }
                 else
-                    fields[1].data.x_type = ira->codegen->builtin_types.entry_undef;
+                    fields[1].data.x_optional = nullptr;
                 // fields: []TypeInfo.UnionField
                 ensure_field_index(result->type, "fields", 2);
 
@@ -16913,7 +16921,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t
                     inner_fields[1].special = ConstValSpecialStatic;
                     inner_fields[1].type = get_maybe_type(ira->codegen, type_info_enum_field_type);
 
-                    if (fields[1].data.x_type == ira->codegen->builtin_types.entry_undef) {
+                    if (fields[1].data.x_optional == nullptr) {
                         inner_fields[1].data.x_optional = nullptr;
                     } else {
                         inner_fields[1].data.x_optional = create_const_vals(1);
@@ -17022,8 +17030,6 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t
                 ConstExprValue *fields = create_const_vals(6);
                 result->data.x_struct.fields = fields;
 
-                // @TODO Fix type = undefined with ?type
-
                 // calling_convention: TypeInfo.CallingConvention
                 ensure_field_index(result->type, "calling_convention", 0);
                 fields[0].special = ConstValSpecialStatic;
@@ -17041,22 +17047,32 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t
                 fields[2].special = ConstValSpecialStatic;
                 fields[2].type = ira->codegen->builtin_types.entry_bool;
                 fields[2].data.x_bool = type_entry->data.fn.fn_type_id.is_var_args;
-                // return_type: type
+                // return_type: ?type
                 ensure_field_index(result->type, "return_type", 3);
                 fields[3].special = ConstValSpecialStatic;
-                fields[3].type = ira->codegen->builtin_types.entry_type;
+                fields[3].type = get_maybe_type(ira->codegen, ira->codegen->builtin_types.entry_type);
                 if (type_entry->data.fn.fn_type_id.return_type == nullptr)
-                    fields[3].data.x_type = ira->codegen->builtin_types.entry_undef;
-                else
-                    fields[3].data.x_type = type_entry->data.fn.fn_type_id.return_type;
+                    fields[3].data.x_optional = nullptr;
+                else {
+                    ConstExprValue *return_type = create_const_vals(1);
+                    return_type->special = ConstValSpecialStatic;
+                    return_type->type = ira->codegen->builtin_types.entry_type;
+                    return_type->data.x_type = type_entry->data.fn.fn_type_id.return_type;
+                    fields[3].data.x_optional = return_type;
+                }
                 // async_allocator_type: type
                 ensure_field_index(result->type, "async_allocator_type", 4);
                 fields[4].special = ConstValSpecialStatic;
-                fields[4].type = ira->codegen->builtin_types.entry_type;
+                fields[4].type = get_maybe_type(ira->codegen, ira->codegen->builtin_types.entry_type);
                 if (type_entry->data.fn.fn_type_id.async_allocator_type == nullptr)
-                    fields[4].data.x_type = ira->codegen->builtin_types.entry_undef;
-                else
-                    fields[4].data.x_type = type_entry->data.fn.fn_type_id.async_allocator_type;
+                    fields[4].data.x_optional = nullptr;
+                else {
+                    ConstExprValue *async_alloc_type = create_const_vals(1);
+                    async_alloc_type->special = ConstValSpecialStatic;
+                    async_alloc_type->type = ira->codegen->builtin_types.entry_type;
+                    async_alloc_type->data.x_type = type_entry->data.fn.fn_type_id.async_allocator_type;
+                    fields[4].data.x_optional = async_alloc_type;
+                }
                 // args: []TypeInfo.FnArg
                 TypeTableEntry *type_info_fn_arg_type = ir_type_info_get_type(ira, "FnArg");
                 size_t fn_arg_count = type_entry->data.fn.fn_type_id.param_count -
@@ -17090,12 +17106,17 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t
                     inner_fields[1].type = ira->codegen->builtin_types.entry_bool;
                     inner_fields[1].data.x_bool = fn_param_info->is_noalias;
                     inner_fields[2].special = ConstValSpecialStatic;
-                    inner_fields[2].type = ira->codegen->builtin_types.entry_type;
+                    inner_fields[2].type = get_maybe_type(ira->codegen, ira->codegen->builtin_types.entry_type);
 
                     if (arg_is_generic)
-                        inner_fields[2].data.x_type = ira->codegen->builtin_types.entry_undef;
-                    else
-                        inner_fields[2].data.x_type = fn_param_info->type;
+                        inner_fields[2].data.x_optional = nullptr;
+                    else {
+                        ConstExprValue *arg_type = create_const_vals(1);
+                        arg_type->special = ConstValSpecialStatic;
+                        arg_type->type = ira->codegen->builtin_types.entry_type;
+                        arg_type->data.x_type = fn_param_info->type;
+                        inner_fields[2].data.x_optional = arg_type;
+                    }
 
                     fn_arg_val->data.x_struct.fields = inner_fields;
                     fn_arg_val->data.x_struct.parent.id = ConstParentIdArray;
test/cases/type_info.zig
@@ -107,11 +107,11 @@ test "type info: promise info" {
 fn testPromise() void {
     const null_promise_info = @typeInfo(promise);
     assert(TypeId(null_promise_info) == TypeId.Promise);
-    assert(null_promise_info.Promise.child == @typeOf(undefined));
+    assert(null_promise_info.Promise.child == null);
 
     const promise_info = @typeInfo(promise->usize);
     assert(TypeId(promise_info) == TypeId.Promise);
-    assert(promise_info.Promise.child == usize);
+    assert(promise_info.Promise.child.? == usize);
 }
 
 test "type info: error set, error union info" {
@@ -165,7 +165,7 @@ fn testUnion() void {
     const typeinfo_info = @typeInfo(TypeInfo);
     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.tag_type.? == TypeId);
     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);
@@ -179,7 +179,7 @@ fn testUnion() void {
 
     const notag_union_info = @typeInfo(TestNoTagUnion);
     assert(TypeId(notag_union_info) == TypeId.Union);
-    assert(notag_union_info.Union.tag_type == @typeOf(undefined));
+    assert(notag_union_info.Union.tag_type == null);
     assert(notag_union_info.Union.layout == TypeInfo.ContainerLayout.Auto);
     assert(notag_union_info.Union.fields.len == 2);
     assert(notag_union_info.Union.fields[0].enum_field == null);
@@ -191,7 +191,7 @@ fn testUnion() void {
 
     const extern_union_info = @typeInfo(TestExternUnion);
     assert(extern_union_info.Union.layout == TypeInfo.ContainerLayout.Extern);
-    assert(extern_union_info.Union.tag_type == @typeOf(undefined));
+    assert(extern_union_info.Union.tag_type == null);
     assert(extern_union_info.Union.fields[0].enum_field == null);
     assert(extern_union_info.Union.fields[0].field_type == *c_void);
 }
@@ -238,13 +238,13 @@ fn testFunction() void {
     assert(fn_info.Fn.is_generic);
     assert(fn_info.Fn.args.len == 2);
     assert(fn_info.Fn.is_var_args);
-    assert(fn_info.Fn.return_type == @typeOf(undefined));
-    assert(fn_info.Fn.async_allocator_type == @typeOf(undefined));
+    assert(fn_info.Fn.return_type == null);
+    assert(fn_info.Fn.async_allocator_type == null);
 
     const test_instance: TestStruct = undefined;
     const bound_fn_info = @typeInfo(@typeOf(test_instance.foo));
     assert(TypeId(bound_fn_info) == TypeId.BoundFn);
-    assert(bound_fn_info.BoundFn.args[0].arg_type == *const TestStruct);
+    assert(bound_fn_info.BoundFn.args[0].arg_type.? == *const TestStruct);
 }
 
 fn foo(comptime a: usize, b: bool, args: ...) usize {