| ... | @@ -398,6 +398,7 @@ TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type | ... | @@ -398,6 +398,7 @@ 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; |
| 401 | | 402 | |
| 402 | const char *const_str = is_const ? "const " : ""; | 403 | const char *const_str = is_const ? "const " : ""; |
| 403 | const char *volatile_str = is_volatile ? "volatile " : ""; | 404 | const char *volatile_str = is_volatile ? "volatile " : ""; |
| ... | @@ -482,6 +483,7 @@ TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) { | ... | @@ -482,6 +483,7 @@ TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) { |
| 482 | assert(child_type->type_ref || child_type->zero_bits); | 483 | assert(child_type->type_ref || child_type->zero_bits); |
| 483 | assert(child_type->di_type); | 484 | assert(child_type->di_type); |
| 484 | entry->is_copyable = type_is_copyable(g, child_type); | 485 | entry->is_copyable = type_is_copyable(g, child_type); |
| | 486 | entry->can_mutate_state_through_it = child_type->can_mutate_state_through_it; |
| 485 | | 487 | |
| 486 | buf_resize(&entry->name, 0); | 488 | buf_resize(&entry->name, 0); |
| 487 | buf_appendf(&entry->name, "?%s", buf_ptr(&child_type->name)); | 489 | buf_appendf(&entry->name, "?%s", buf_ptr(&child_type->name)); |
| ... | @@ -572,6 +574,7 @@ TypeTableEntry *get_error_union_type(CodeGen *g, TypeTableEntry *err_set_type, T | ... | @@ -572,6 +574,7 @@ TypeTableEntry *get_error_union_type(CodeGen *g, TypeTableEntry *err_set_type, T |
| 572 | entry->is_copyable = true; | 574 | entry->is_copyable = true; |
| 573 | assert(payload_type->di_type); | 575 | assert(payload_type->di_type); |
| 574 | ensure_complete_type(g, payload_type); | 576 | ensure_complete_type(g, payload_type); |
| | 577 | entry->can_mutate_state_through_it = payload_type->can_mutate_state_through_it; |
| 575 | | 578 | |
| 576 | buf_resize(&entry->name, 0); | 579 | buf_resize(&entry->name, 0); |
| 577 | buf_appendf(&entry->name, "%s!%s", buf_ptr(&err_set_type->name), buf_ptr(&payload_type->name)); | 580 | buf_appendf(&entry->name, "%s!%s", buf_ptr(&err_set_type->name), buf_ptr(&payload_type->name)); |
| ... | @@ -730,6 +733,7 @@ TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *ptr_type) { | ... | @@ -730,6 +733,7 @@ TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *ptr_type) { |
| 730 | | 733 | |
| 731 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdStruct); | 734 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdStruct); |
| 732 | entry->is_copyable = true; | 735 | entry->is_copyable = true; |
| | 736 | entry->can_mutate_state_through_it = ptr_type->can_mutate_state_through_it; |
| 733 | | 737 | |
| 734 | // replace the & with [] to go from a ptr type name to a slice type name | 738 | // replace the & with [] to go from a ptr type name to a slice type name |
| 735 | buf_resize(&entry->name, 0); | 739 | buf_resize(&entry->name, 0); |
| ... | @@ -1735,6 +1739,8 @@ TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *f | ... | @@ -1735,6 +1739,8 @@ TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *f |
| 1735 | struct_type->data.structure.gen_field_count += 1; | 1739 | struct_type->data.structure.gen_field_count += 1; |
| 1736 | } else { | 1740 | } else { |
| 1737 | field->gen_index = SIZE_MAX; | 1741 | 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; |
| 1738 | } | 1744 | } |
| 1739 | | 1745 | |
| 1740 | auto prev_entry = struct_type->data.structure.fields_by_name.put_unique(field->name, field); | 1746 | auto prev_entry = struct_type->data.structure.fields_by_name.put_unique(field->name, field); |
| ... | @@ -2475,6 +2481,9 @@ static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) { | ... | @@ -2475,6 +2481,9 @@ static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) { |
| 2475 | if (!type_has_bits(field_type)) | 2481 | if (!type_has_bits(field_type)) |
| 2476 | continue; | 2482 | continue; |
| 2477 | | 2483 | |
| | 2484 | struct_type->can_mutate_state_through_it = struct_type->can_mutate_state_through_it || |
| | 2485 | field_type->can_mutate_state_through_it; |
| | 2486 | |
| 2478 | if (gen_field_index == 0) { | 2487 | if (gen_field_index == 0) { |
| 2479 | if (struct_type->data.structure.layout == ContainerLayoutPacked) { | 2488 | if (struct_type->data.structure.layout == ContainerLayoutPacked) { |
| 2480 | struct_type->data.structure.abi_alignment = 1; | 2489 | struct_type->data.structure.abi_alignment = 1; |
| ... | @@ -2662,6 +2671,8 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { | ... | @@ -2662,6 +2671,8 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { |
| 2662 | } | 2671 | } |
| 2663 | } | 2672 | } |
| 2664 | union_field->type_entry = field_type; | 2673 | 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; |
| 2665 | | 2676 | |
| 2666 | if (field_node->data.struct_field.value != nullptr && !decl_node->data.container_decl.auto_enum) { | 2677 | if (field_node->data.struct_field.value != nullptr && !decl_node->data.container_decl.auto_enum) { |
| 2667 | ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.value, | 2678 | ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.value, |
| ... | @@ -4565,6 +4576,23 @@ bool generic_fn_type_id_eql(GenericFnTypeId *a, GenericFnTypeId *b) { | ... | @@ -4565,6 +4576,23 @@ bool generic_fn_type_id_eql(GenericFnTypeId *a, GenericFnTypeId *b) { |
| 4565 | return true; | 4576 | return true; |
| 4566 | } | 4577 | } |
| 4567 | | 4578 | |
| | 4579 | bool fn_eval_cacheable(Scope *scope) { |
| | 4580 | while (scope) { |
| | 4581 | if (scope->id == ScopeIdVarDecl) { |
| | 4582 | ScopeVarDecl *var_scope = (ScopeVarDecl *)scope; |
| | 4583 | if (var_scope->var->value->type->can_mutate_state_through_it) |
| | 4584 | return false; |
| | 4585 | } else if (scope->id == ScopeIdFnDef) { |
| | 4586 | return true; |
| | 4587 | } else { |
| | 4588 | zig_unreachable(); |
| | 4589 | } |
| | 4590 | |
| | 4591 | scope = scope->parent; |
| | 4592 | } |
| | 4593 | zig_unreachable(); |
| | 4594 | } |
| | 4595 | |
| 4568 | uint32_t fn_eval_hash(Scope* scope) { | 4596 | uint32_t fn_eval_hash(Scope* scope) { |
| 4569 | uint32_t result = 0; | 4597 | uint32_t result = 0; |
| 4570 | while (scope) { | 4598 | while (scope) { |