Commit 5834ff0cc5
Changed files (3)
test
cases
src/all_types.hpp
@@ -1174,13 +1174,6 @@ struct TypeTableEntry {
bool is_copyable;
bool gen_h_loop_flag;
- // This is denormalized data. The simplest type that has this
- // flag set to true is a mutable pointer. A const pointer has
- // the same value for this flag as the child type.
- // If a struct has any fields that have this flag true, then
- // the flag is true for the struct.
- bool can_mutate_state_through_it;
-
union {
TypeTableEntryPointer pointer;
TypeTableEntryInt integral;
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;
test/cases/eval.zig
@@ -486,3 +486,20 @@ test "comptime slice of pointer preserves comptime var" {
assert(buff[0..][0..][0] == 1);
}
}
+
+const SingleFieldStruct = struct {
+ x: i32,
+
+ fn read_x(self: &const SingleFieldStruct) i32 {
+ return self.x;
+ }
+};
+test "const ptr to comptime mutable data is not memoized" {
+
+ comptime {
+ var foo = SingleFieldStruct {.x = 1};
+ assert(foo.read_x() == 1);
+ foo.x = 2;
+ assert(foo.read_x() == 2);
+ }
+}