authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-01-28 11:39:36-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-01-28 11:39:36-05:00
log287d3c37e1f53b6f0a0b29753b68254001194e62
tree3d9a4db2edfc3d2ec1df5c9856b5d1ddf2d562ac
parent8710fdbf39c793027f332bd00efe70edaa86d91c
signature Commit is signed but in an unrecognized format.

fix 0-bit child type coerced to optional return ptr result location

by un-special-casing 0 bit types in result locations

3 files changed, 55 insertions(+), 32 deletions(-)

src/analyze.cpp+19-1
...@@ -5700,6 +5700,9 @@ ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry) {...@@ -5700,6 +5700,9 @@ ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry) {
5700 assert(field_type != nullptr);5700 assert(field_type != nullptr);
5701 result->data.x_struct.fields[i] = get_the_one_possible_value(g, field_type);5701 result->data.x_struct.fields[i] = get_the_one_possible_value(g, field_type);
5702 }5702 }
5703 } else if (result->type->id == ZigTypeIdPointer) {
5704 result->data.x_ptr.special = ConstPtrSpecialRef;
5705 result->data.x_ptr.data.ref.pointee = get_the_one_possible_value(g, result->type->data.pointer.child_type);
5703 }5706 }
5704 g->one_possible_values.put(type_entry, result);5707 g->one_possible_values.put(type_entry, result);
5705 return result;5708 return result;
...@@ -9471,7 +9474,11 @@ static void dump_value_indent(ZigValue *val, int indent) {...@@ -9471,7 +9474,11 @@ static void dump_value_indent(ZigValue *val, int indent) {
9471 fprintf(stderr, " ");9474 fprintf(stderr, " ");
9472 }9475 }
9473 fprintf(stderr, "%s: ", buf_ptr(val->type->data.structure.fields[i]->name));9476 fprintf(stderr, "%s: ", buf_ptr(val->type->data.structure.fields[i]->name));
9474 dump_value_indent(val->data.x_struct.fields[i], 1);9477 if (val->data.x_struct.fields == nullptr) {
9478 fprintf(stderr, "<null>\n");
9479 } else {
9480 dump_value_indent(val->data.x_struct.fields[i], 1);
9481 }
9475 }9482 }
9476 for (int i = 0; i < indent; i += 1) {9483 for (int i = 0; i < indent; i += 1) {
9477 fprintf(stderr, " ");9484 fprintf(stderr, " ");
...@@ -9505,6 +9512,9 @@ static void dump_value_indent(ZigValue *val, int indent) {...@@ -9505,6 +9512,9 @@ static void dump_value_indent(ZigValue *val, int indent) {
95059512
9506 case ZigTypeIdPointer:9513 case ZigTypeIdPointer:
9507 switch (val->data.x_ptr.special) {9514 switch (val->data.x_ptr.special) {
9515 case ConstPtrSpecialInvalid:
9516 fprintf(stderr, "<!invalid ptr!>\n");
9517 return;
9508 case ConstPtrSpecialRef:9518 case ConstPtrSpecialRef:
9509 fprintf(stderr, "<ref\n");9519 fprintf(stderr, "<ref\n");
9510 dump_value_indent(val->data.x_ptr.data.ref.pointee, indent + 1);9520 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) {...@@ -9526,6 +9536,14 @@ static void dump_value_indent(ZigValue *val, int indent) {
9526 }9536 }
9527 break;9537 break;
9528 }9538 }
9539 case ConstPtrSpecialBaseOptionalPayload: {
9540 ZigValue *optional_val = val->data.x_ptr.data.base_optional_payload.optional_val;
9541 fprintf(stderr, "<optional %p payload\n", optional_val);
9542 if (optional_val != nullptr) {
9543 dump_value_indent(optional_val, indent + 1);
9544 }
9545 break;
9546 }
9529 default:9547 default:
9530 fprintf(stderr, "TODO dump more pointer things\n");9548 fprintf(stderr, "TODO dump more pointer things\n");
9531 }9549 }
src/ir.cpp+14-31
...@@ -18576,7 +18576,6 @@ static IrInstGen *ir_resolve_result(IrAnalyze *ira, IrInst *suspend_source_instr...@@ -18576,7 +18576,6 @@ static IrInstGen *ir_resolve_result(IrAnalyze *ira, IrInst *suspend_source_instr
18576 ResultLoc *result_loc_pass1, ZigType *value_type, IrInstGen *value, bool force_runtime,18576 ResultLoc *result_loc_pass1, ZigType *value_type, IrInstGen *value, bool force_runtime,
18577 bool allow_discard)18577 bool allow_discard)
18578{18578{
18579 Error err;
18580 if (!allow_discard && result_loc_is_discard(result_loc_pass1)) {18579 if (!allow_discard && result_loc_is_discard(result_loc_pass1)) {
18581 result_loc_pass1 = no_result_loc();18580 result_loc_pass1 = no_result_loc();
18582 }18581 }
...@@ -18672,32 +18671,22 @@ static IrInstGen *ir_resolve_result(IrAnalyze *ira, IrInst *suspend_source_instr...@@ -18672,32 +18671,22 @@ static IrInstGen *ir_resolve_result(IrAnalyze *ira, IrInst *suspend_source_instr
18672 {18671 {
18673 bool same_comptime_repr = types_have_same_zig_comptime_repr(ira->codegen, actual_elem_type, value_type);18672 bool same_comptime_repr = types_have_same_zig_comptime_repr(ira->codegen, actual_elem_type, value_type);
18674 if (!same_comptime_repr) {18673 if (!same_comptime_repr) {
18675 bool has_bits;18674 result_loc_pass1->written = false;
18676 if ((err = type_has_bits2(ira->codegen, value_type, &has_bits)))18675 return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr, result_loc, false, true);
18677 return ira->codegen->invalid_inst_gen;
18678 if (has_bits) {
18679 result_loc_pass1->written = false;
18680 return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr, result_loc, false, true);
18681 }
18682 }18676 }
18683 } else if (actual_elem_type->id == ZigTypeIdErrorUnion && value_type->id != ZigTypeIdErrorUnion) {18677 } else if (actual_elem_type->id == ZigTypeIdErrorUnion && value_type->id != ZigTypeIdErrorUnion) {
18684 bool has_bits;18678 if (value_type->id == ZigTypeIdErrorSet) {
18685 if ((err = type_has_bits2(ira->codegen, value_type, &has_bits)))18679 return ir_analyze_unwrap_err_code(ira, suspend_source_instr, result_loc, true);
18686 return ira->codegen->invalid_inst_gen;18680 } else {
18687 if (has_bits) {18681 IrInstGen *unwrapped_err_ptr = ir_analyze_unwrap_error_payload(ira, suspend_source_instr,
18688 if (value_type->id == ZigTypeIdErrorSet) {18682 result_loc, false, true);
18689 return ir_analyze_unwrap_err_code(ira, suspend_source_instr, result_loc, true);18683 ZigType *actual_payload_type = actual_elem_type->data.error_union.payload_type;
18684 if (actual_payload_type->id == ZigTypeIdOptional && value_type->id != ZigTypeIdOptional &&
18685 value_type->id != ZigTypeIdNull)
18686 {
18687 return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr, unwrapped_err_ptr, false, true);
18690 } else {18688 } else {
18691 IrInstGen *unwrapped_err_ptr = ir_analyze_unwrap_error_payload(ira, suspend_source_instr,18689 return unwrapped_err_ptr;
18692 result_loc, false, true);
18693 ZigType *actual_payload_type = actual_elem_type->data.error_union.payload_type;
18694 if (actual_payload_type->id == ZigTypeIdOptional && value_type->id != ZigTypeIdOptional &&
18695 value_type->id != ZigTypeIdNull)
18696 {
18697 return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr, unwrapped_err_ptr, false, true);
18698 } else {
18699 return unwrapped_err_ptr;
18700 }
18701 }18690 }
18702 }18691 }
18703 }18692 }
...@@ -22215,14 +22204,8 @@ static IrInstGen *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInst* sou...@@ -22215,14 +22204,8 @@ static IrInstGen *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInst* sou
22215 }22204 }
22216 break;22205 break;
22217 case OnePossibleValueYes: {22206 case OnePossibleValueYes: {
22218 ZigValue *pointee = create_const_vals(1);
22219 pointee->special = ConstValSpecialStatic;
22220 pointee->type = child_type;
22221 pointee->parent.id = ConstParentIdOptionalPayload;
22222 pointee->parent.data.p_optional_payload.optional_val = optional_val;
22223
22224 optional_val->special = ConstValSpecialStatic;22207 optional_val->special = ConstValSpecialStatic;
22225 optional_val->data.x_optional = pointee;22208 optional_val->data.x_optional = get_the_one_possible_value(ira->codegen, child_type);
22226 break;22209 break;
22227 }22210 }
22228 }22211 }
test/stage1/behavior/optional.zig+22
...@@ -153,3 +153,25 @@ test "optional with void type" {...@@ -153,3 +153,25 @@ test "optional with void type" {
153 var x = Foo{ .x = null };153 var x = Foo{ .x = null };
154 expect(x.x == null);154 expect(x.x == null);
155}155}
156
157test "0-bit child type coerced to optional return ptr result location" {
158 const S = struct {
159 fn doTheTest() void {
160 var y = Foo{};
161 var z = y.thing();
162 expect(z != null);
163 }
164
165 const Foo = struct {
166 pub const Bar = struct {
167 field: *Foo,
168 };
169
170 pub fn thing(self: *Foo) ?Bar {
171 return Bar{ .field = self };
172 }
173 };
174 };
175 S.doTheTest();
176 comptime S.doTheTest();
177}