Commit 287d3c37e1

Andrew Kelley <andrew@ziglang.org>
2020-01-28 17:39:36
fix 0-bit child type coerced to optional return ptr result location
by un-special-casing 0 bit types in result locations
1 parent 8710fdb
Changed files (3)
src
test
stage1
behavior
src/analyze.cpp
@@ -5700,6 +5700,9 @@ ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry) {
             assert(field_type != nullptr);
             result->data.x_struct.fields[i] = get_the_one_possible_value(g, field_type);
         }
+    } else if (result->type->id == ZigTypeIdPointer) {
+        result->data.x_ptr.special = ConstPtrSpecialRef;
+        result->data.x_ptr.data.ref.pointee = get_the_one_possible_value(g, result->type->data.pointer.child_type);
     }
     g->one_possible_values.put(type_entry, result);
     return result;
@@ -9471,7 +9474,11 @@ static void dump_value_indent(ZigValue *val, int indent) {
                     fprintf(stderr, " ");
                 }
                 fprintf(stderr, "%s: ", buf_ptr(val->type->data.structure.fields[i]->name));
-                dump_value_indent(val->data.x_struct.fields[i], 1);
+                if (val->data.x_struct.fields == nullptr) {
+                    fprintf(stderr, "<null>\n");
+                } else {
+                    dump_value_indent(val->data.x_struct.fields[i], 1);
+                }
             }
             for (int i = 0; i < indent; i += 1) {
                 fprintf(stderr, " ");
@@ -9505,6 +9512,9 @@ static void dump_value_indent(ZigValue *val, int indent) {
 
         case ZigTypeIdPointer:
             switch (val->data.x_ptr.special) {
+                case ConstPtrSpecialInvalid:
+                    fprintf(stderr, "<!invalid ptr!>\n");
+                    return;
                 case ConstPtrSpecialRef:
                     fprintf(stderr, "<ref\n");
                     dump_value_indent(val->data.x_ptr.data.ref.pointee, indent + 1);
@@ -9526,6 +9536,14 @@ static void dump_value_indent(ZigValue *val, int indent) {
                     }
                     break;
                 }
+                case ConstPtrSpecialBaseOptionalPayload: {
+                    ZigValue *optional_val = val->data.x_ptr.data.base_optional_payload.optional_val;
+                    fprintf(stderr, "<optional %p payload\n", optional_val);
+                    if (optional_val != nullptr) {
+                        dump_value_indent(optional_val, indent + 1);
+                    }
+                    break;
+                }
                 default:
                     fprintf(stderr, "TODO dump more pointer things\n");
             }
src/ir.cpp
@@ -18576,7 +18576,6 @@ static IrInstGen *ir_resolve_result(IrAnalyze *ira, IrInst *suspend_source_instr
         ResultLoc *result_loc_pass1, ZigType *value_type, IrInstGen *value, bool force_runtime,
         bool allow_discard)
 {
-    Error err;
     if (!allow_discard && result_loc_is_discard(result_loc_pass1)) {
         result_loc_pass1 = no_result_loc();
     }
@@ -18672,32 +18671,22 @@ static IrInstGen *ir_resolve_result(IrAnalyze *ira, IrInst *suspend_source_instr
     {
         bool same_comptime_repr = types_have_same_zig_comptime_repr(ira->codegen, actual_elem_type, value_type);
         if (!same_comptime_repr) {
-            bool has_bits;
-            if ((err = type_has_bits2(ira->codegen, value_type, &has_bits)))
-                return ira->codegen->invalid_inst_gen;
-            if (has_bits) {
-                result_loc_pass1->written = false;
-                return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr, result_loc, false, true);
-            }
+            result_loc_pass1->written = false;
+            return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr, result_loc, false, true);
         }
     } else if (actual_elem_type->id == ZigTypeIdErrorUnion && value_type->id != ZigTypeIdErrorUnion) {
-        bool has_bits;
-        if ((err = type_has_bits2(ira->codegen, value_type, &has_bits)))
-            return ira->codegen->invalid_inst_gen;
-        if (has_bits) {
-            if (value_type->id == ZigTypeIdErrorSet) {
-                return ir_analyze_unwrap_err_code(ira, suspend_source_instr, result_loc, true);
+        if (value_type->id == ZigTypeIdErrorSet) {
+            return ir_analyze_unwrap_err_code(ira, suspend_source_instr, result_loc, true);
+        } else {
+            IrInstGen *unwrapped_err_ptr = ir_analyze_unwrap_error_payload(ira, suspend_source_instr,
+                    result_loc, false, true);
+            ZigType *actual_payload_type = actual_elem_type->data.error_union.payload_type;
+            if (actual_payload_type->id == ZigTypeIdOptional && value_type->id != ZigTypeIdOptional &&
+                value_type->id != ZigTypeIdNull)
+            {
+                return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr, unwrapped_err_ptr, false, true);
             } else {
-                IrInstGen *unwrapped_err_ptr = ir_analyze_unwrap_error_payload(ira, suspend_source_instr,
-                        result_loc, false, true);
-                ZigType *actual_payload_type = actual_elem_type->data.error_union.payload_type;
-                if (actual_payload_type->id == ZigTypeIdOptional && value_type->id != ZigTypeIdOptional &&
-                    value_type->id != ZigTypeIdNull)
-                {
-                    return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr, unwrapped_err_ptr, false, true);
-                } else {
-                    return unwrapped_err_ptr;
-                }
+                return unwrapped_err_ptr;
             }
         }
     }
@@ -22215,14 +22204,8 @@ static IrInstGen *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInst* sou
                         }
                         break;
                     case OnePossibleValueYes: {
-                        ZigValue *pointee = create_const_vals(1);
-                        pointee->special = ConstValSpecialStatic;
-                        pointee->type = child_type;
-                        pointee->parent.id = ConstParentIdOptionalPayload;
-                        pointee->parent.data.p_optional_payload.optional_val = optional_val;
-
                         optional_val->special = ConstValSpecialStatic;
-                        optional_val->data.x_optional = pointee;
+                        optional_val->data.x_optional = get_the_one_possible_value(ira->codegen, child_type);
                         break;
                     }
                 }
test/stage1/behavior/optional.zig
@@ -153,3 +153,25 @@ test "optional with void type" {
     var x = Foo{ .x = null };
     expect(x.x == null);
 }
+
+test "0-bit child type coerced to optional return ptr result location" {
+    const S = struct {
+        fn doTheTest() void {
+            var y = Foo{};
+            var z = y.thing();
+            expect(z != null);
+        }
+
+        const Foo = struct {
+            pub const Bar = struct {
+                field: *Foo,
+            };
+
+            pub fn thing(self: *Foo) ?Bar {
+                return Bar{ .field = self };
+            }
+        };
+    };
+    S.doTheTest();
+    comptime S.doTheTest();
+}