authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-07-05 16:22:40-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-07-05 16:22:40-07:00
logb3225a755a78502245bc9c7d7419ebeb67201320
tree7e1e2d770f57dd563caaebdc66a1edd1690fb515
parent0ff9a4d21c1b65c574659be295446f2dd7591723

stage1: avoid incorrectly reading ZigValue data

Hashing, equality checking, and expanding lazy values were not inspecting the is_comptime field of structs, causing incorrect behavior for tuples. When looking at a comptime value of a struct, if the is_comptime field is true, the value must be learned from the type rather than the value.

2 files changed, 23 insertions(+), 3 deletions(-)

src/stage1/analyze.cpp+18-3
......@@ -5719,6 +5719,12 @@ static uint32_t hash_combine_const_val(uint32_t hash_val, ZigValue *const_val) {
57195719 size_t field_count = const_val->type->data.structure.src_field_count;
57205720 for (size_t i = 0; i < field_count; i += 1) {
57215721 ZigValue *field = const_val->data.x_struct.fields[i];
5722 if (const_val->type->data.structure.fields[i]->is_comptime) {
5723 // The values of comptime struct fields are part of the
5724 // type, not the value, so they do not participate in equality
5725 // or hash of comptime values.
5726 continue;
5727 }
57225728 hash_val = hash_combine_const_val(hash_val, field);
57235729 }
57245730 return hash_val;
......@@ -7321,6 +7327,12 @@ bool const_values_equal(CodeGen *g, ZigValue *a, ZigValue *b) {
73217327 return const_values_equal_array(g, a, b, a->type->data.array.len);
73227328 case ZigTypeIdStruct:
73237329 for (size_t i = 0; i < a->type->data.structure.src_field_count; i += 1) {
7330 if (a->type->data.structure.fields[i]->is_comptime) {
7331 // The values of comptime struct fields are part of the
7332 // type, not the value, so they do not participate in equality
7333 // or hash of comptime values.
7334 continue;
7335 }
73247336 ZigValue *field_a = a->data.x_struct.fields[i];
73257337 ZigValue *field_b = b->data.x_struct.fields[i];
73267338 if (!const_values_equal(g, field_a, field_b))
......@@ -9945,10 +9957,13 @@ void copy_const_val(CodeGen *g, ZigValue *dest, ZigValue *src) {
99459957 dest->data.x_struct.fields = alloc_const_vals_ptrs(g, dest->type->data.structure.src_field_count);
99469958 for (size_t i = 0; i < dest->type->data.structure.src_field_count; i += 1) {
99479959 TypeStructField *type_struct_field = dest->type->data.structure.fields[i];
9948 // comptime-known values are stored in the field init_val inside
9949 // the struct type.
9950 if (type_struct_field->is_comptime)
9960 if (type_struct_field->is_comptime) {
9961 // comptime-known values are stored in the field init_val inside
9962 // the struct type. The data stored here is not supposed to be read
9963 // at all; the code should look at the type system and notice the field
9964 // is comptime and look at the type to learn the value.
99519965 continue;
9966 }
99529967 copy_const_val(g, dest->data.x_struct.fields[i], src->data.x_struct.fields[i]);
99539968 dest->data.x_struct.fields[i]->parent.id = ConstParentIdStruct;
99549969 dest->data.x_struct.fields[i]->parent.data.p_struct.struct_val = dest;
src/stage1/ir.cpp+5
......@@ -25620,6 +25620,11 @@ static Error ir_resolve_lazy_recurse(IrAnalyze *ira, AstNode *source_node, ZigVa
2562025620 case ZigTypeIdStruct:
2562125621 for (size_t i = 0; i < val->type->data.structure.src_field_count; i += 1) {
2562225622 ZigValue *field = val->data.x_struct.fields[i];
25623 if (val->type->data.structure.fields[i]->is_comptime) {
25624 // comptime struct fields do not need to be resolved because
25625 // they are not part of the value.
25626 continue;
25627 }
2562325628 if ((err = ir_resolve_lazy_recurse(ira, source_node, field)))
2562425629 return err;
2562525630 }