| ... | @@ -398,7 +398,6 @@ TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type | ... | @@ -398,7 +398,6 @@ TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type |
| 398 | | 398 | |
| 399 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdPointer); | 399 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdPointer); |
| 400 | entry->is_copyable = true; | 400 | entry->is_copyable = true; |
| 401 | entry->can_mutate_state_through_it = is_const ? child_type->can_mutate_state_through_it : true; | | |
| 402 | | 401 | |
| 403 | const char *const_str = is_const ? "const " : ""; | 402 | const char *const_str = is_const ? "const " : ""; |
| 404 | const char *volatile_str = is_volatile ? "volatile " : ""; | 403 | const char *volatile_str = is_volatile ? "volatile " : ""; |
| ... | @@ -483,7 +482,6 @@ TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) { | ... | @@ -483,7 +482,6 @@ TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) { |
| 483 | assert(child_type->type_ref || child_type->zero_bits); | 482 | assert(child_type->type_ref || child_type->zero_bits); |
| 484 | assert(child_type->di_type); | 483 | assert(child_type->di_type); |
| 485 | entry->is_copyable = type_is_copyable(g, child_type); | 484 | entry->is_copyable = type_is_copyable(g, child_type); |
| 486 | entry->can_mutate_state_through_it = child_type->can_mutate_state_through_it; | | |
| 487 | | 485 | |
| 488 | buf_resize(&entry->name, 0); | 486 | buf_resize(&entry->name, 0); |
| 489 | buf_appendf(&entry->name, "?%s", buf_ptr(&child_type->name)); | 487 | buf_appendf(&entry->name, "?%s", buf_ptr(&child_type->name)); |
| ... | @@ -574,7 +572,6 @@ TypeTableEntry *get_error_union_type(CodeGen *g, TypeTableEntry *err_set_type, T | ... | @@ -574,7 +572,6 @@ TypeTableEntry *get_error_union_type(CodeGen *g, TypeTableEntry *err_set_type, T |
| 574 | entry->is_copyable = true; | 572 | entry->is_copyable = true; |
| 575 | assert(payload_type->di_type); | 573 | assert(payload_type->di_type); |
| 576 | ensure_complete_type(g, payload_type); | 574 | ensure_complete_type(g, payload_type); |
| 577 | entry->can_mutate_state_through_it = payload_type->can_mutate_state_through_it; | | |
| 578 | | 575 | |
| 579 | buf_resize(&entry->name, 0); | 576 | buf_resize(&entry->name, 0); |
| 580 | buf_appendf(&entry->name, "%s!%s", buf_ptr(&err_set_type->name), buf_ptr(&payload_type->name)); | 577 | buf_appendf(&entry->name, "%s!%s", buf_ptr(&err_set_type->name), buf_ptr(&payload_type->name)); |
| ... | @@ -733,7 +730,6 @@ TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *ptr_type) { | ... | @@ -733,7 +730,6 @@ TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *ptr_type) { |
| 733 | | 730 | |
| 734 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdStruct); | 731 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdStruct); |
| 735 | entry->is_copyable = true; | 732 | entry->is_copyable = true; |
| 736 | entry->can_mutate_state_through_it = ptr_type->can_mutate_state_through_it; | | |
| 737 | | 733 | |
| 738 | // replace the & with [] to go from a ptr type name to a slice type name | 734 | // replace the & with [] to go from a ptr type name to a slice type name |
| 739 | buf_resize(&entry->name, 0); | 735 | buf_resize(&entry->name, 0); |
| ... | @@ -1739,8 +1735,6 @@ TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *f | ... | @@ -1739,8 +1735,6 @@ TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *f |
| 1739 | struct_type->data.structure.gen_field_count += 1; | 1735 | struct_type->data.structure.gen_field_count += 1; |
| 1740 | } else { | 1736 | } else { |
| 1741 | field->gen_index = SIZE_MAX; | 1737 | field->gen_index = SIZE_MAX; |
| 1742 | struct_type->can_mutate_state_through_it = struct_type->can_mutate_state_through_it || | | |
| 1743 | field->type_entry->can_mutate_state_through_it; | | |
| 1744 | } | 1738 | } |
| 1745 | | 1739 | |
| 1746 | auto prev_entry = struct_type->data.structure.fields_by_name.put_unique(field->name, field); | 1740 | auto prev_entry = struct_type->data.structure.fields_by_name.put_unique(field->name, field); |
| ... | @@ -2481,9 +2475,6 @@ static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) { | ... | @@ -2481,9 +2475,6 @@ static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) { |
| 2481 | if (!type_has_bits(field_type)) | 2475 | if (!type_has_bits(field_type)) |
| 2482 | continue; | 2476 | continue; |
| 2483 | | 2477 | |
| 2484 | struct_type->can_mutate_state_through_it = struct_type->can_mutate_state_through_it || | | |
| 2485 | field_type->can_mutate_state_through_it; | | |
| 2486 | | | |
| 2487 | if (gen_field_index == 0) { | 2478 | if (gen_field_index == 0) { |
| 2488 | if (struct_type->data.structure.layout == ContainerLayoutPacked) { | 2479 | if (struct_type->data.structure.layout == ContainerLayoutPacked) { |
| 2489 | struct_type->data.structure.abi_alignment = 1; | 2480 | struct_type->data.structure.abi_alignment = 1; |
| ... | @@ -2671,8 +2662,6 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { | ... | @@ -2671,8 +2662,6 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { |
| 2671 | } | 2662 | } |
| 2672 | } | 2663 | } |
| 2673 | union_field->type_entry = field_type; | 2664 | union_field->type_entry = field_type; |
| 2674 | union_type->can_mutate_state_through_it = union_type->can_mutate_state_through_it || | | |
| 2675 | field_type->can_mutate_state_through_it; | | |
| 2676 | | 2665 | |
| 2677 | if (field_node->data.struct_field.value != nullptr && !decl_node->data.container_decl.auto_enum) { | 2666 | if (field_node->data.struct_field.value != nullptr && !decl_node->data.container_decl.auto_enum) { |
| 2678 | ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.value, | 2667 | ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.value, |
| ... | @@ -4576,11 +4565,77 @@ bool generic_fn_type_id_eql(GenericFnTypeId *a, GenericFnTypeId *b) { | ... | @@ -4576,11 +4565,77 @@ bool generic_fn_type_id_eql(GenericFnTypeId *a, GenericFnTypeId *b) { |
| 4576 | return true; | 4565 | return true; |
| 4577 | } | 4566 | } |
| 4578 | | 4567 | |
| | 4568 | static bool can_mutate_comptime_var_state(ConstExprValue *value) { |
| | 4569 | assert(value != nullptr); |
| | 4570 | switch (value->type->id) { |
| | 4571 | case TypeTableEntryIdInvalid: |
| | 4572 | zig_unreachable(); |
| | 4573 | case TypeTableEntryIdMetaType: |
| | 4574 | case TypeTableEntryIdVoid: |
| | 4575 | case TypeTableEntryIdBool: |
| | 4576 | case TypeTableEntryIdUnreachable: |
| | 4577 | case TypeTableEntryIdInt: |
| | 4578 | case TypeTableEntryIdFloat: |
| | 4579 | case TypeTableEntryIdNumLitFloat: |
| | 4580 | case TypeTableEntryIdNumLitInt: |
| | 4581 | case TypeTableEntryIdUndefLit: |
| | 4582 | case TypeTableEntryIdNullLit: |
| | 4583 | case TypeTableEntryIdNamespace: |
| | 4584 | case TypeTableEntryIdBoundFn: |
| | 4585 | case TypeTableEntryIdFn: |
| | 4586 | case TypeTableEntryIdBlock: |
| | 4587 | case TypeTableEntryIdOpaque: |
| | 4588 | case TypeTableEntryIdPromise: |
| | 4589 | case TypeTableEntryIdErrorSet: |
| | 4590 | case TypeTableEntryIdEnum: |
| | 4591 | return false; |
| | 4592 | |
| | 4593 | case TypeTableEntryIdPointer: |
| | 4594 | return value->data.x_ptr.mut == ConstPtrMutComptimeVar; |
| | 4595 | |
| | 4596 | case TypeTableEntryIdArray: |
| | 4597 | if (value->type->data.array.len == 0) |
| | 4598 | return false; |
| | 4599 | if (value->data.x_array.special == ConstArraySpecialUndef) |
| | 4600 | return false; |
| | 4601 | for (uint32_t i = 0; i < value->type->data.array.len; i += 1) { |
| | 4602 | if (can_mutate_comptime_var_state(&value->data.x_array.s_none.elements[i])) |
| | 4603 | return true; |
| | 4604 | } |
| | 4605 | return false; |
| | 4606 | |
| | 4607 | case TypeTableEntryIdStruct: |
| | 4608 | for (uint32_t i = 0; i < value->type->data.structure.src_field_count; i += 1) { |
| | 4609 | if (can_mutate_comptime_var_state(&value->data.x_struct.fields[i])) |
| | 4610 | return true; |
| | 4611 | } |
| | 4612 | return false; |
| | 4613 | |
| | 4614 | case TypeTableEntryIdMaybe: |
| | 4615 | if (value->data.x_maybe == nullptr) |
| | 4616 | return false; |
| | 4617 | return can_mutate_comptime_var_state(value->data.x_maybe); |
| | 4618 | |
| | 4619 | case TypeTableEntryIdErrorUnion: |
| | 4620 | if (value->data.x_err_union.err != nullptr) |
| | 4621 | return false; |
| | 4622 | assert(value->data.x_err_union.payload != nullptr); |
| | 4623 | return can_mutate_comptime_var_state(value->data.x_err_union.payload); |
| | 4624 | |
| | 4625 | case TypeTableEntryIdUnion: |
| | 4626 | return can_mutate_comptime_var_state(value->data.x_union.payload); |
| | 4627 | |
| | 4628 | case TypeTableEntryIdArgTuple: |
| | 4629 | zig_panic("TODO var args at comptime is currently not supported"); |
| | 4630 | } |
| | 4631 | zig_unreachable(); |
| | 4632 | } |
| | 4633 | |
| 4579 | bool fn_eval_cacheable(Scope *scope) { | 4634 | bool fn_eval_cacheable(Scope *scope) { |
| 4580 | while (scope) { | 4635 | while (scope) { |
| 4581 | if (scope->id == ScopeIdVarDecl) { | 4636 | if (scope->id == ScopeIdVarDecl) { |
| 4582 | ScopeVarDecl *var_scope = (ScopeVarDecl *)scope; | 4637 | ScopeVarDecl *var_scope = (ScopeVarDecl *)scope; |
| 4583 | if (var_scope->var->value->type->can_mutate_state_through_it) | 4638 | if (can_mutate_comptime_var_state(var_scope->var->value)) |
| 4584 | return false; | 4639 | return false; |
| 4585 | } else if (scope->id == ScopeIdFnDef) { | 4640 | } else if (scope->id == ScopeIdFnDef) { |
| 4586 | return true; | 4641 | return true; |