Commit 101440c199

Andrew Kelley <andrew@ziglang.org>
2019-08-23 23:14:51
add lazy value support for optional types
this case works now: ```zig const Node = struct { node: ?*Node, }; ```
1 parent f003449
Changed files (3)
src/all_types.hpp
@@ -302,6 +302,7 @@ enum LazyValueId {
     LazyValueIdInvalid,
     LazyValueIdAlignOf,
     LazyValueIdPtrType,
+    LazyValueIdOptType,
     LazyValueIdSliceType,
     LazyValueIdFnType,
 };
@@ -340,6 +341,13 @@ struct LazyValuePtrType {
     uint32_t host_int_bytes;
 };
 
+struct LazyValueOptType {
+    LazyValue base;
+
+    ConstExprValue *payload_type_val;
+    AstNode *payload_type_src_node;
+};
+
 struct LazyValueFnType {
     LazyValue base;
     bool is_generic;
src/analyze.cpp
@@ -992,6 +992,7 @@ static Error type_val_resolve_zero_bits(CodeGen *g, ConstExprValue *type_val, Zi
                         parent_type_val, is_zero_bits);
             }
         }
+        case LazyValueIdOptType:
         case LazyValueIdSliceType:
             *is_zero_bits = false;
             return ErrorNone;
@@ -1017,6 +1018,7 @@ Error type_val_resolve_is_opaque_type(CodeGen *g, ConstExprValue *type_val, bool
         case LazyValueIdSliceType:
         case LazyValueIdPtrType:
         case LazyValueIdFnType:
+        case LazyValueIdOptType:
             *is_opaque_type = false;
             return ErrorNone;
     }
@@ -1041,6 +1043,10 @@ static ReqCompTime type_val_resolve_requires_comptime(CodeGen *g, ConstExprValue
             LazyValuePtrType *lazy_ptr_type = reinterpret_cast<LazyValuePtrType *>(type_val->data.x_lazy);
             return type_val_resolve_requires_comptime(g, lazy_ptr_type->elem_type_val);
         }
+        case LazyValueIdOptType: {
+            LazyValueOptType *lazy_opt_type = reinterpret_cast<LazyValueOptType *>(type_val->data.x_lazy);
+            return type_val_resolve_requires_comptime(g, lazy_opt_type->payload_type_val);
+        }
         case LazyValueIdFnType: {
             LazyValueFnType *lazy_fn_type = reinterpret_cast<LazyValueFnType *>(type_val->data.x_lazy);
             if (lazy_fn_type->is_generic)
@@ -1091,6 +1097,10 @@ static Error type_val_resolve_abi_align(CodeGen *g, ConstExprValue *type_val, si
         case LazyValueIdFnType:
             *abi_align = g->builtin_types.entry_usize->abi_align;
             return ErrorNone;
+        case LazyValueIdOptType: {
+            LazyValueOptType *lazy_opt_type = reinterpret_cast<LazyValueOptType *>(type_val->data.x_lazy);
+            return type_val_resolve_abi_align(g, lazy_opt_type->payload_type_val, abi_align);
+        }
     }
     zig_unreachable();
 }
@@ -1104,6 +1114,7 @@ static OnePossibleValue type_val_resolve_has_one_possible_value(CodeGen *g, Cons
         case LazyValueIdAlignOf:
             zig_unreachable();
         case LazyValueIdSliceType: // it has the len field
+        case LazyValueIdOptType: // it has the optional bit
         case LazyValueIdFnType:
             return OnePossibleValueNo;
         case LazyValueIdPtrType: {
src/ir.cpp
@@ -8212,6 +8212,7 @@ static Error eval_comptime_ptr_reinterpret(IrAnalyze *ira, CodeGen *codegen, Ast
 {
     Error err;
     assert(ptr_val->type->id == ZigTypeIdPointer);
+    assert(ptr_val->special == ConstValSpecialStatic);
     ConstExprValue tmp = {};
     tmp.special = ConstValSpecialStatic;
     tmp.type = ptr_val->type->data.pointer.child_type;
@@ -16150,51 +16151,21 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
     zig_unreachable();
 }
 
-static IrInstruction *ir_analyze_optional_type(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
-    Error err;
-    IrInstruction *value = un_op_instruction->value->child;
-    ZigType *type_entry = ir_resolve_type(ira, value);
-    if (type_is_invalid(type_entry))
-        return ira->codegen->invalid_instruction;
-    if ((err = type_resolve(ira->codegen, type_entry, ResolveStatusSizeKnown)))
-        return ira->codegen->invalid_instruction;
+static IrInstruction *ir_analyze_optional_type(IrAnalyze *ira, IrInstructionUnOp *instruction) {
+    IrInstruction *result = ir_const(ira, &instruction->base, ira->codegen->builtin_types.entry_type);
+    result->value.special = ConstValSpecialLazy;
 
-    switch (type_entry->id) {
-        case ZigTypeIdInvalid:
-            zig_unreachable();
-        case ZigTypeIdMetaType:
-        case ZigTypeIdVoid:
-        case ZigTypeIdBool:
-        case ZigTypeIdInt:
-        case ZigTypeIdVector:
-        case ZigTypeIdFloat:
-        case ZigTypeIdPointer:
-        case ZigTypeIdArray:
-        case ZigTypeIdStruct:
-        case ZigTypeIdComptimeFloat:
-        case ZigTypeIdComptimeInt:
-        case ZigTypeIdEnumLiteral:
-        case ZigTypeIdUndefined:
-        case ZigTypeIdNull:
-        case ZigTypeIdOptional:
-        case ZigTypeIdErrorUnion:
-        case ZigTypeIdErrorSet:
-        case ZigTypeIdEnum:
-        case ZigTypeIdUnion:
-        case ZigTypeIdFn:
-        case ZigTypeIdBoundFn:
-        case ZigTypeIdArgTuple:
-        case ZigTypeIdFnFrame:
-        case ZigTypeIdAnyFrame:
-            return ir_const_type(ira, &un_op_instruction->base, get_optional_type(ira->codegen, type_entry));
+    LazyValueOptType *lazy_opt_type = allocate<LazyValueOptType>(1);
+    result->value.data.x_lazy = &lazy_opt_type->base;
+    lazy_opt_type->base.id = LazyValueIdOptType;
+    lazy_opt_type->base.exec = ira->new_irb.exec;
 
-        case ZigTypeIdUnreachable:
-        case ZigTypeIdOpaque:
-            ir_add_error_node(ira, un_op_instruction->base.source_node,
-                    buf_sprintf("type '%s' not optional", buf_ptr(&type_entry->name)));
-            return ira->codegen->invalid_instruction;
-    }
-    zig_unreachable();
+    lazy_opt_type->payload_type_val = ir_resolve_type_lazy(ira, instruction->value->child);
+    if (lazy_opt_type->payload_type_val == nullptr)
+        return ira->codegen->invalid_instruction;
+    lazy_opt_type->payload_type_src_node = instruction->value->source_node;
+
+    return result;
 }
 
 static ErrorMsg *ir_eval_negation_scalar(IrAnalyze *ira, IrInstruction *source_instr, ZigType *scalar_type,
@@ -19658,11 +19629,9 @@ static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, Zig
 
     ZigVar *var = tld->var;
 
-    if ((err = type_resolve(ira->codegen, var->const_value->type, ResolveStatusSizeKnown)))
-        return ira->codegen->builtin_types.entry_invalid;
-
     assert(var->const_value->type->id == ZigTypeIdMetaType);
-    return var->const_value->data.x_type;
+
+    return ir_resolve_const_type(ira->codegen, ira->new_irb.exec, nullptr, var->const_value);
 }
 
 static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr, ConstExprValue *out_val,
@@ -25633,6 +25602,28 @@ static Error ir_resolve_lazy_raw(CodeGen *codegen, AstNode *source_node, ConstEx
             val->special = ConstValSpecialStatic;
             return ErrorNone;
         }
+        case LazyValueIdOptType: {
+            LazyValueOptType *lazy_opt_type = reinterpret_cast<LazyValueOptType *>(val->data.x_lazy);
+
+            ZigType *payload_type = ir_resolve_const_type(codegen, exec, lazy_opt_type->payload_type_src_node,
+                    lazy_opt_type->payload_type_val);
+            if (type_is_invalid(payload_type))
+                return ErrorSemanticAnalyzeFail;
+
+            if (payload_type->id == ZigTypeIdOpaque || payload_type->id == ZigTypeIdUnreachable) {
+                exec_add_error_node(codegen, exec, lazy_opt_type->payload_type_src_node,
+                        buf_sprintf("type '%s' cannot be optional", buf_ptr(&payload_type->name)));
+                return ErrorSemanticAnalyzeFail;
+            }
+
+            if ((err = type_resolve(codegen, payload_type, ResolveStatusSizeKnown)))
+                return err;
+
+            assert(val->type->id == ZigTypeIdMetaType);
+            val->data.x_type = get_optional_type(codegen, payload_type);
+            val->special = ConstValSpecialStatic;
+            return ErrorNone;
+        }
         case LazyValueIdFnType: {
             ZigType *fn_type = ir_resolve_lazy_fn_type(codegen, exec, source_node,
                     reinterpret_cast<LazyValueFnType *>(val->data.x_lazy));