diff options
Diffstat (limited to 'src/analyze.cpp')
| -rw-r--r-- | src/analyze.cpp | 79 |
1 files changed, 67 insertions, 12 deletions
diff --git a/src/analyze.cpp b/src/analyze.cpp index bb30f53967..c7ba8ccc74 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -398,7 +398,6 @@ TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdPointer); entry->is_copyable = true; - entry->can_mutate_state_through_it = is_const ? child_type->can_mutate_state_through_it : true; const char *const_str = is_const ? "const " : ""; const char *volatile_str = is_volatile ? "volatile " : ""; @@ -483,7 +482,6 @@ TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) { assert(child_type->type_ref || child_type->zero_bits); assert(child_type->di_type); entry->is_copyable = type_is_copyable(g, child_type); - entry->can_mutate_state_through_it = child_type->can_mutate_state_through_it; buf_resize(&entry->name, 0); 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 entry->is_copyable = true; assert(payload_type->di_type); ensure_complete_type(g, payload_type); - entry->can_mutate_state_through_it = payload_type->can_mutate_state_through_it; buf_resize(&entry->name, 0); 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) { TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdStruct); entry->is_copyable = true; - entry->can_mutate_state_through_it = ptr_type->can_mutate_state_through_it; // replace the & with [] to go from a ptr type name to a slice type name buf_resize(&entry->name, 0); @@ -1739,8 +1735,6 @@ TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *f struct_type->data.structure.gen_field_count += 1; } else { field->gen_index = SIZE_MAX; - struct_type->can_mutate_state_through_it = struct_type->can_mutate_state_through_it || - field->type_entry->can_mutate_state_through_it; } 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) { if (!type_has_bits(field_type)) continue; - struct_type->can_mutate_state_through_it = struct_type->can_mutate_state_through_it || - field_type->can_mutate_state_through_it; - if (gen_field_index == 0) { if (struct_type->data.structure.layout == ContainerLayoutPacked) { struct_type->data.structure.abi_alignment = 1; @@ -2671,8 +2662,6 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { } } union_field->type_entry = field_type; - union_type->can_mutate_state_through_it = union_type->can_mutate_state_through_it || - field_type->can_mutate_state_through_it; if (field_node->data.struct_field.value != nullptr && !decl_node->data.container_decl.auto_enum) { 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) { return true; } +static bool can_mutate_comptime_var_state(ConstExprValue *value) { + assert(value != nullptr); + switch (value->type->id) { + case TypeTableEntryIdInvalid: + zig_unreachable(); + case TypeTableEntryIdMetaType: + case TypeTableEntryIdVoid: + case TypeTableEntryIdBool: + case TypeTableEntryIdUnreachable: + case TypeTableEntryIdInt: + case TypeTableEntryIdFloat: + case TypeTableEntryIdNumLitFloat: + case TypeTableEntryIdNumLitInt: + case TypeTableEntryIdUndefLit: + case TypeTableEntryIdNullLit: + case TypeTableEntryIdNamespace: + case TypeTableEntryIdBoundFn: + case TypeTableEntryIdFn: + case TypeTableEntryIdBlock: + case TypeTableEntryIdOpaque: + case TypeTableEntryIdPromise: + case TypeTableEntryIdErrorSet: + case TypeTableEntryIdEnum: + return false; + + case TypeTableEntryIdPointer: + return value->data.x_ptr.mut == ConstPtrMutComptimeVar; + + case TypeTableEntryIdArray: + if (value->type->data.array.len == 0) + return false; + if (value->data.x_array.special == ConstArraySpecialUndef) + return false; + for (uint32_t i = 0; i < value->type->data.array.len; i += 1) { + if (can_mutate_comptime_var_state(&value->data.x_array.s_none.elements[i])) + return true; + } + return false; + + case TypeTableEntryIdStruct: + 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])) + return true; + } + return false; + + case TypeTableEntryIdMaybe: + if (value->data.x_maybe == nullptr) + return false; + return can_mutate_comptime_var_state(value->data.x_maybe); + + case TypeTableEntryIdErrorUnion: + if (value->data.x_err_union.err != nullptr) + return false; + assert(value->data.x_err_union.payload != nullptr); + return can_mutate_comptime_var_state(value->data.x_err_union.payload); + + case TypeTableEntryIdUnion: + return can_mutate_comptime_var_state(value->data.x_union.payload); + + case TypeTableEntryIdArgTuple: + zig_panic("TODO var args at comptime is currently not supported"); + } + zig_unreachable(); +} + bool fn_eval_cacheable(Scope *scope) { while (scope) { if (scope->id == ScopeIdVarDecl) { ScopeVarDecl *var_scope = (ScopeVarDecl *)scope; - if (var_scope->var->value->type->can_mutate_state_through_it) + if (can_mutate_comptime_var_state(var_scope->var->value)) return false; } else if (scope->id == ScopeIdFnDef) { return true; |
