aboutsummaryrefslogtreecommitdiff
path: root/src/analyze.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/analyze.cpp')
-rw-r--r--src/analyze.cpp79
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;