From 6d2f103bfb8931e2e65ca7f79d62389b69781492 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sun, 25 Oct 2020 11:25:02 +0100 Subject: [PATCH] stage1: Fix crash in comptime struct value copy Comptime fields are never materialized in the ZigValue so pay attention when iterating over the fields array. Fixes #6800 --- src/stage1/analyze.cpp | 13 ++++++++++++- test/stage1/behavior/tuple.zig | 18 ++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/stage1/analyze.cpp b/src/stage1/analyze.cpp index fd0de8e90..0da3ec58d 100644 --- a/src/stage1/analyze.cpp +++ b/src/stage1/analyze.cpp @@ -5686,7 +5686,13 @@ static bool can_mutate_comptime_var_state(ZigValue *value) { zig_unreachable(); case ZigTypeIdStruct: for (uint32_t i = 0; i < value->type->data.structure.src_field_count; i += 1) { - if (can_mutate_comptime_var_state(value->data.x_struct.fields[i])) + TypeStructField *type_struct_field = value->type->data.structure.fields[i]; + + ZigValue *field_value = type_struct_field->is_comptime ? + type_struct_field->init_val : + value->data.x_struct.fields[i]; + + if (can_mutate_comptime_var_state(field_value)) return true; } return false; @@ -9690,6 +9696,11 @@ void copy_const_val(CodeGen *g, ZigValue *dest, ZigValue *src) { if (dest->type->id == ZigTypeIdStruct) { dest->data.x_struct.fields = alloc_const_vals_ptrs(g, dest->type->data.structure.src_field_count); for (size_t i = 0; i < dest->type->data.structure.src_field_count; i += 1) { + TypeStructField *type_struct_field = dest->type->data.structure.fields[i]; + // comptime-known values are stored in the field init_val inside + // the struct type. + if (type_struct_field->is_comptime) + continue; copy_const_val(g, dest->data.x_struct.fields[i], src->data.x_struct.fields[i]); dest->data.x_struct.fields[i]->parent.id = ConstParentIdStruct; dest->data.x_struct.fields[i]->parent.data.p_struct.struct_val = dest; diff --git a/test/stage1/behavior/tuple.zig b/test/stage1/behavior/tuple.zig index 299abec3c..4eb5b73ab 100644 --- a/test/stage1/behavior/tuple.zig +++ b/test/stage1/behavior/tuple.zig @@ -93,3 +93,21 @@ test "pass tuple to comptime var parameter" { S.doTheTest(); comptime S.doTheTest(); } + +test "tuple initializer for var" { + const S = struct { + fn doTheTest() void { + const Bytes = struct { + id: usize, + }; + + var tmp = .{ + .id = @as(usize, 2), + .name = Bytes{ .id = 20 }, + }; + } + }; + + S.doTheTest(); + comptime S.doTheTest(); +}