From 287d3c37e1f53b6f0a0b29753b68254001194e62 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 28 Jan 2020 11:39:36 -0500 Subject: [PATCH] fix 0-bit child type coerced to optional return ptr result location by un-special-casing 0 bit types in result locations --- src/analyze.cpp | 20 +++++++++++++- src/ir.cpp | 45 ++++++++++--------------------- test/stage1/behavior/optional.zig | 22 +++++++++++++++ 3 files changed, 55 insertions(+), 32 deletions(-) diff --git a/src/analyze.cpp b/src/analyze.cpp index a5ab984228..db4200b734 100644 --- a/src/analyze.cpp +++ b/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, "\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, "\n"); + return; case ConstPtrSpecialRef: fprintf(stderr, "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, "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; } } diff --git a/test/stage1/behavior/optional.zig b/test/stage1/behavior/optional.zig index 4d9d8e1e82..fa002b707e 100644 --- a/test/stage1/behavior/optional.zig +++ b/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(); +}