diff --git a/src/ir.cpp b/src/ir.cpp index fd488d650bb7c2ad0bb68b51d3bf00372fe67562..6b4628b187cb8a5187358fbc7fc8e2419078a37a 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -11356,10 +11356,24 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT } } +// Returns whether the x_optional field of ZigValue is active. +static bool type_has_optional_repr(ZigType *ty) { + if (ty->id != ZigTypeIdOptional) { + return false; + } else if (get_codegen_ptr_type(ty) != nullptr) { + return false; + } else if (is_opt_err_set(ty)) { + return false; + } else { + return true; + } +} + static void copy_const_val(ZigValue *dest, ZigValue *src) { memcpy(dest, src, sizeof(ZigValue)); if (src->special != ConstValSpecialStatic) return; + dest->parent.id = ConstParentIdNone; if (dest->type->id == ZigTypeIdStruct) { dest->data.x_struct.fields = alloc_const_vals_ptrs(dest->type->data.structure.src_field_count); for (size_t i = 0; i < dest->type->data.structure.src_field_count; i += 1) { @@ -11368,8 +11382,12 @@ static void copy_const_val(ZigValue *dest, ZigValue *src) { dest->data.x_struct.fields[i]->parent.data.p_struct.struct_val = dest; dest->data.x_struct.fields[i]->parent.data.p_struct.field_index = i; } + } else if (type_has_optional_repr(dest->type) && dest->data.x_optional != nullptr) { + dest->data.x_optional = create_const_vals(1); + copy_const_val(dest->data.x_optional, src->data.x_optional); + dest->data.x_optional->parent.id = ConstParentIdOptionalPayload; + dest->data.x_optional->parent.data.p_optional_payload.optional_val = dest; } - dest->parent.id = ConstParentIdNone; } static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_instr, diff --git a/test/stage1/behavior/optional.zig b/test/stage1/behavior/optional.zig index 8cc90d10a4822c4736538ce0cc84c9143fa6b777..f664032fd16f19792a151d53428a783ec497be43 100644 --- a/test/stage1/behavior/optional.zig +++ b/test/stage1/behavior/optional.zig @@ -119,3 +119,14 @@ test "self-referential struct through a slice of optional" { var n = S.Node.new(); expect(n.data == null); } + +test "assigning to an unwrapped optional field in an inline loop" { + comptime var maybe_pos_arg: ?comptime_int = null; + inline for ("ab") |x| { + maybe_pos_arg = 0; + if (maybe_pos_arg.? != 0) { + @compileError("bad"); + } + maybe_pos_arg.? = 10; + } +}