authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-02 01:09:06-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-02 01:09:06-05:00
log6d8550a7dfecc3f8fcf2e1ff869921ce48ca1683
tree6b1917e2a9bf25c899044e12b050e2b6fe454b98
parentfecd540826b14275784f10fe429ed147543377b6
signaturelock-open Commit is signed but in an unrecognized format.

fix crash assigning optional struct with anon literal

closes #3827

2 files changed, 40 insertions(+), 16 deletions(-)

src/ir.cpp+25-16
...@@ -16797,6 +16797,7 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s...@@ -16797,6 +16797,7 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s
16797 ResultLoc *result_loc_pass1, ZigType *value_type, IrInstruction *value, bool force_runtime,16797 ResultLoc *result_loc_pass1, ZigType *value_type, IrInstruction *value, bool force_runtime,
16798 bool non_null_comptime, bool allow_discard)16798 bool non_null_comptime, bool allow_discard)
16799{16799{
16800 Error err;
16800 if (!allow_discard && result_loc_pass1->id == ResultLocIdInstruction &&16801 if (!allow_discard && result_loc_pass1->id == ResultLocIdInstruction &&
16801 instr_is_comptime(result_loc_pass1->source_instruction) &&16802 instr_is_comptime(result_loc_pass1->source_instruction) &&
16802 result_loc_pass1->source_instruction->value->type->id == ZigTypeIdPointer &&16803 result_loc_pass1->source_instruction->value->type->id == ZigTypeIdPointer &&
...@@ -16818,24 +16819,32 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s...@@ -16818,24 +16819,32 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s
16818 ir_assert(result_loc->value->type->id == ZigTypeIdPointer, suspend_source_instr);16819 ir_assert(result_loc->value->type->id == ZigTypeIdPointer, suspend_source_instr);
16819 ZigType *actual_elem_type = result_loc->value->type->data.pointer.child_type;16820 ZigType *actual_elem_type = result_loc->value->type->data.pointer.child_type;
16820 if (actual_elem_type->id == ZigTypeIdOptional && value_type->id != ZigTypeIdOptional &&16821 if (actual_elem_type->id == ZigTypeIdOptional && value_type->id != ZigTypeIdOptional &&
16821 value_type->id != ZigTypeIdNull && type_has_bits(value_type))16822 value_type->id != ZigTypeIdNull)
16822 {
16823 result_loc_pass1->written = false;
16824 return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr, result_loc, false, true);
16825 } else if (actual_elem_type->id == ZigTypeIdErrorUnion && value_type->id != ZigTypeIdErrorUnion &&
16826 type_has_bits(value_type))
16827 {16823 {
16828 if (value_type->id == ZigTypeIdErrorSet) {16824 bool has_bits;
16829 return ir_analyze_unwrap_err_code(ira, suspend_source_instr, result_loc, true);16825 if ((err = type_has_bits2(ira->codegen, value_type, &has_bits)))
16830 } else {16826 return ira->codegen->invalid_instruction;
16831 IrInstruction *unwrapped_err_ptr = ir_analyze_unwrap_error_payload(ira, suspend_source_instr,16827 if (has_bits) {
16832 result_loc, false, true);16828 result_loc_pass1->written = false;
16833 ZigType *actual_payload_type = actual_elem_type->data.error_union.payload_type;16829 return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr, result_loc, false, true);
16834 if (actual_payload_type->id == ZigTypeIdOptional && value_type->id != ZigTypeIdOptional &&16830 }
16835 value_type->id != ZigTypeIdNull) {16831 } else if (actual_elem_type->id == ZigTypeIdErrorUnion && value_type->id != ZigTypeIdErrorUnion) {
16836 return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr, unwrapped_err_ptr, false, true);16832 bool has_bits;
16833 if ((err = type_has_bits2(ira->codegen, value_type, &has_bits)))
16834 return ira->codegen->invalid_instruction;
16835 if (has_bits) {
16836 if (value_type->id == ZigTypeIdErrorSet) {
16837 return ir_analyze_unwrap_err_code(ira, suspend_source_instr, result_loc, true);
16837 } else {16838 } else {
16838 return unwrapped_err_ptr;16839 IrInstruction *unwrapped_err_ptr = ir_analyze_unwrap_error_payload(ira, suspend_source_instr,
16840 result_loc, false, true);
16841 ZigType *actual_payload_type = actual_elem_type->data.error_union.payload_type;
16842 if (actual_payload_type->id == ZigTypeIdOptional && value_type->id != ZigTypeIdOptional &&
16843 value_type->id != ZigTypeIdNull) {
16844 return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr, unwrapped_err_ptr, false, true);
16845 } else {
16846 return unwrapped_err_ptr;
16847 }
16839 }16848 }
16840 }16849 }
16841 }16850 }
test/stage1/behavior/optional.zig+15
...@@ -130,3 +130,18 @@ test "assigning to an unwrapped optional field in an inline loop" {...@@ -130,3 +130,18 @@ test "assigning to an unwrapped optional field in an inline loop" {
130 maybe_pos_arg.? = 10;130 maybe_pos_arg.? = 10;
131 }131 }
132}132}
133
134test "coerce an anon struct literal to optional struct" {
135 const S = struct {
136 const Struct = struct {
137 field: u32,
138 };
139 export fn doTheTest() void {
140 var maybe_dims: ?Struct = null;
141 maybe_dims = .{ .field = 1 };
142 expect(maybe_dims.?.field == 1);
143 }
144 };
145 S.doTheTest();
146 comptime S.doTheTest();
147}