From ac4dd9d665ba195a6b21b3b033f27c865015ccac Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 23 Aug 2019 15:54:51 -0400 Subject: [PATCH] better handling of lazy structs this case works now: ```zig const A = struct { b_list_pointer: *const []B, }; const B = struct { a_pointer: *const A, }; const b_list: []B = [_]B{}; const a = A{ .b_list_pointer = &b_list }; const obj = B{ .a_pointer = &a }; ``` --- src/all_types.hpp | 3 ++- src/analyze.cpp | 57 ++++++++++++++++++++++++----------------------- src/analyze.hpp | 2 +- src/codegen.cpp | 4 ++-- src/ir.cpp | 20 ++++++++--------- 5 files changed, 44 insertions(+), 42 deletions(-) diff --git a/src/all_types.hpp b/src/all_types.hpp index d23020593d..2a20d3c860 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1190,7 +1190,8 @@ struct ZigTypeStruct { // whether any of the fields require comptime // known after ResolveStatusZeroBitsKnown bool requires_comptime; - bool resolve_loop_flag; + bool resolve_loop_flag_zero_bits; + bool resolve_loop_flag_other; }; struct ZigTypeOptional { diff --git a/src/analyze.cpp b/src/analyze.cpp index f140489ab3..f6e8a77770 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -685,7 +685,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) { entry->data.structure.fields_by_name.put(ptr_field_name, &entry->data.structure.fields[slice_ptr_index]); entry->data.structure.fields_by_name.put(len_field_name, &entry->data.structure.fields[slice_len_index]); - switch (type_requires_comptime(g, ptr_type, entry)) { + switch (type_requires_comptime(g, ptr_type)) { case ReqCompTimeInvalid: zig_unreachable(); case ReqCompTimeNo: @@ -1016,9 +1016,9 @@ Error type_val_resolve_is_opaque_type(CodeGen *g, ConstExprValue *type_val, bool zig_unreachable(); } -static ReqCompTime type_val_resolve_requires_comptime(CodeGen *g, ConstExprValue *type_val, ZigType *parent_type) { +static ReqCompTime type_val_resolve_requires_comptime(CodeGen *g, ConstExprValue *type_val) { if (type_val->special != ConstValSpecialLazy) { - return type_requires_comptime(g, type_val->data.x_type, parent_type); + return type_requires_comptime(g, type_val->data.x_type); } switch (type_val->data.x_lazy->id) { case LazyValueIdInvalid: @@ -1028,17 +1028,17 @@ static ReqCompTime type_val_resolve_requires_comptime(CodeGen *g, ConstExprValue LazyValueSliceType *lazy_slice_type = reinterpret_cast(type_val->data.x_lazy); if (type_is_invalid(lazy_slice_type->elem_type)) return ReqCompTimeInvalid; - return type_requires_comptime(g, lazy_slice_type->elem_type, parent_type); + return type_requires_comptime(g, lazy_slice_type->elem_type); } case LazyValueIdPtrType: { LazyValuePtrType *lazy_ptr_type = reinterpret_cast(type_val->data.x_lazy); - return type_val_resolve_requires_comptime(g, lazy_ptr_type->elem_type_val, parent_type); + return type_val_resolve_requires_comptime(g, lazy_ptr_type->elem_type_val); } case LazyValueIdFnType: { LazyValueFnType *lazy_fn_type = reinterpret_cast(type_val->data.x_lazy); if (lazy_fn_type->is_generic) return ReqCompTimeYes; - switch (type_val_resolve_requires_comptime(g, lazy_fn_type->return_type, parent_type)) { + switch (type_val_resolve_requires_comptime(g, lazy_fn_type->return_type)) { case ReqCompTimeInvalid: return ReqCompTimeInvalid; case ReqCompTimeYes: @@ -1051,7 +1051,7 @@ static ReqCompTime type_val_resolve_requires_comptime(CodeGen *g, ConstExprValue AstNode *param_node = lazy_fn_type->proto_node->data.fn_proto.params.at(i); bool param_is_var_args = param_node->data.param_decl.is_var_args; if (param_is_var_args) break; - switch (type_val_resolve_requires_comptime(g, lazy_fn_type->param_types[i], parent_type)) { + switch (type_val_resolve_requires_comptime(g, lazy_fn_type->param_types[i])) { case ReqCompTimeInvalid: return ReqCompTimeInvalid; case ReqCompTimeYes: @@ -1517,7 +1517,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc case ZigTypeIdVector: case ZigTypeIdFnFrame: case ZigTypeIdAnyFrame: - switch (type_requires_comptime(g, type_entry, fn_entry->type_entry)) { + switch (type_requires_comptime(g, type_entry)) { case ReqCompTimeNo: break; case ReqCompTimeYes: @@ -1613,7 +1613,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc case ZigTypeIdVector: case ZigTypeIdFnFrame: case ZigTypeIdAnyFrame: - switch (type_requires_comptime(g, fn_type_id.return_type, fn_entry->type_entry)) { + switch (type_requires_comptime(g, fn_type_id.return_type)) { case ReqCompTimeInvalid: return g->builtin_types.entry_invalid; case ReqCompTimeYes: @@ -1745,7 +1745,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { AstNode *decl_node = struct_type->data.structure.decl_node; - if (struct_type->data.structure.resolve_loop_flag) { + if (struct_type->data.structure.resolve_loop_flag_other) { if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) { struct_type->data.structure.resolve_status = ResolveStatusInvalid; g->trace_err = add_node_error(g, decl_node, @@ -1760,7 +1760,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { size_t field_count = struct_type->data.structure.src_field_count; bool packed = (struct_type->data.structure.layout == ContainerLayoutPacked); - struct_type->data.structure.resolve_loop_flag = true; + struct_type->data.structure.resolve_loop_flag_other = true; uint32_t *host_int_bytes = packed ? allocate(struct_type->data.structure.gen_field_count) : nullptr; @@ -1877,7 +1877,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { struct_type->size_in_bits = size_in_bits; struct_type->data.structure.resolve_status = ResolveStatusSizeKnown; struct_type->data.structure.gen_field_count = (uint32_t)gen_field_index; - struct_type->data.structure.resolve_loop_flag = false; + struct_type->data.structure.resolve_loop_flag_other = false; struct_type->data.structure.host_int_bytes = host_int_bytes; return ErrorNone; @@ -2275,7 +2275,7 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { AstNode *decl_node = struct_type->data.structure.decl_node; assert(decl_node->type == NodeTypeContainerDecl); - if (struct_type->data.structure.resolve_loop_flag) { + if (struct_type->data.structure.resolve_loop_flag_zero_bits) { if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) { struct_type->data.structure.resolve_status = ResolveStatusInvalid; g->trace_err = add_node_error(g, decl_node, @@ -2285,7 +2285,7 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { return ErrorSemanticAnalyzeFail; } - struct_type->data.structure.resolve_loop_flag = true; + struct_type->data.structure.resolve_loop_flag_zero_bits = true; assert(!struct_type->data.structure.fields); size_t field_count = decl_node->data.container_decl.fields.length; @@ -2343,7 +2343,7 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { type_struct_field->src_index = i; type_struct_field->gen_index = SIZE_MAX; - switch (type_val_resolve_requires_comptime(g, field_type_val, struct_type)) { + switch (type_val_resolve_requires_comptime(g, field_type_val)) { case ReqCompTimeYes: struct_type->data.structure.requires_comptime = true; break; @@ -2370,7 +2370,7 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { gen_field_index += 1; } - struct_type->data.structure.resolve_loop_flag = false; + struct_type->data.structure.resolve_loop_flag_zero_bits = false; struct_type->data.structure.gen_field_count = (uint32_t)gen_field_index; if (gen_field_index != 0) { struct_type->abi_size = SIZE_MAX; @@ -2400,7 +2400,7 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { AstNode *decl_node = struct_type->data.structure.decl_node; - if (struct_type->data.structure.resolve_loop_flag) { + if (struct_type->data.structure.resolve_loop_flag_other) { if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) { struct_type->data.structure.resolve_status = ResolveStatusInvalid; g->trace_err = add_node_error(g, decl_node, @@ -2409,7 +2409,7 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { return ErrorSemanticAnalyzeFail; } - struct_type->data.structure.resolve_loop_flag = true; + struct_type->data.structure.resolve_loop_flag_other = true; assert(decl_node->type == NodeTypeContainerDecl); size_t field_count = struct_type->data.structure.src_field_count; @@ -2444,7 +2444,7 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { } } - struct_type->data.structure.resolve_loop_flag = false; + struct_type->data.structure.resolve_loop_flag_other = false; if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) { return ErrorSemanticAnalyzeFail; @@ -2614,7 +2614,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { return ErrorSemanticAnalyzeFail; } - switch (type_requires_comptime(g, field_type, union_type)) { + switch (type_requires_comptime(g, field_type)) { case ReqCompTimeInvalid: union_type->data.unionation.resolve_status = ResolveStatusInvalid; return ErrorSemanticAnalyzeFail; @@ -4959,11 +4959,8 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) { zig_unreachable(); } -ReqCompTime type_requires_comptime(CodeGen *g, ZigType *ty, ZigType *parent_type) { +ReqCompTime type_requires_comptime(CodeGen *g, ZigType *ty) { Error err; - if (ty == parent_type) { - return ReqCompTimeNo; - } switch (ty->id) { case ZigTypeIdInvalid: zig_unreachable(); @@ -4977,8 +4974,12 @@ ReqCompTime type_requires_comptime(CodeGen *g, ZigType *ty, ZigType *parent_type case ZigTypeIdArgTuple: return ReqCompTimeYes; case ZigTypeIdArray: - return type_requires_comptime(g, ty->data.array.child_type, parent_type); + return type_requires_comptime(g, ty->data.array.child_type); case ZigTypeIdStruct: + if (ty->data.structure.resolve_loop_flag_zero_bits) { + // Does a struct which contains a pointer field to itself require comptime? No. + return ReqCompTimeNo; + } if ((err = type_resolve(g, ty, ResolveStatusZeroBitsKnown))) return ReqCompTimeInvalid; return ty->data.structure.requires_comptime ? ReqCompTimeYes : ReqCompTimeNo; @@ -4987,14 +4988,14 @@ ReqCompTime type_requires_comptime(CodeGen *g, ZigType *ty, ZigType *parent_type return ReqCompTimeInvalid; return ty->data.unionation.requires_comptime ? ReqCompTimeYes : ReqCompTimeNo; case ZigTypeIdOptional: - return type_requires_comptime(g, ty->data.maybe.child_type, parent_type); + return type_requires_comptime(g, ty->data.maybe.child_type); case ZigTypeIdErrorUnion: - return type_requires_comptime(g, ty->data.error_union.payload_type, parent_type); + return type_requires_comptime(g, ty->data.error_union.payload_type); case ZigTypeIdPointer: if (ty->data.pointer.child_type->id == ZigTypeIdOpaque) { return ReqCompTimeNo; } else { - return type_requires_comptime(g, ty->data.pointer.child_type, parent_type); + return type_requires_comptime(g, ty->data.pointer.child_type); } case ZigTypeIdFn: return ty->data.fn.is_generic ? ReqCompTimeYes : ReqCompTimeNo; diff --git a/src/analyze.hpp b/src/analyze.hpp index cd855522f3..0da9ec09af 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -221,7 +221,7 @@ enum ReqCompTime { ReqCompTimeNo, ReqCompTimeYes, }; -ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry, ZigType *parent_type); +ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry); OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry); diff --git a/src/codegen.cpp b/src/codegen.cpp index 29c3a30158..930818ab42 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -3688,7 +3688,7 @@ static void render_async_spills(CodeGen *g) { } if (ir_get_var_is_comptime(var)) continue; - switch (type_requires_comptime(g, var->var_type, nullptr)) { + switch (type_requires_comptime(g, var->var_type)) { case ReqCompTimeInvalid: zig_unreachable(); case ReqCompTimeYes: @@ -7049,7 +7049,7 @@ static void do_code_gen(CodeGen *g) { } if (ir_get_var_is_comptime(var)) continue; - switch (type_requires_comptime(g, var->var_type, nullptr)) { + switch (type_requires_comptime(g, var->var_type)) { case ReqCompTimeInvalid: zig_unreachable(); case ReqCompTimeYes: diff --git a/src/ir.cpp b/src/ir.cpp index 13ae0715a4..70dc894f86 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -14234,7 +14234,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, } } - switch (type_requires_comptime(ira->codegen, result_type, nullptr)) { + switch (type_requires_comptime(ira->codegen, result_type)) { case ReqCompTimeInvalid: result_type = ira->codegen->builtin_types.entry_invalid; break; @@ -15200,7 +15200,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod } if (!comptime_arg) { - switch (type_requires_comptime(ira->codegen, casted_arg->value.type, nullptr)) { + switch (type_requires_comptime(ira->codegen, casted_arg->value.type)) { case ReqCompTimeYes: ir_add_error(ira, casted_arg, buf_sprintf("parameter of type '%s' requires comptime", buf_ptr(&casted_arg->value.type->name))); @@ -15401,7 +15401,7 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source } } - switch (type_requires_comptime(ira->codegen, child_type, nullptr)) { + switch (type_requires_comptime(ira->codegen, child_type)) { case ReqCompTimeInvalid: return ira->codegen->invalid_instruction; case ReqCompTimeYes: @@ -15794,7 +15794,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c inst_fn_type_id.return_type = specified_return_type; } - switch (type_requires_comptime(ira->codegen, specified_return_type, nullptr)) { + switch (type_requires_comptime(ira->codegen, specified_return_type)) { case ReqCompTimeYes: // Throw out our work and call the function as if it were comptime. return ir_analyze_fn_call(ira, call_instruction, fn_entry, fn_type, fn_ref, first_arg_ptr, @@ -16601,7 +16601,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh break; } - switch (type_requires_comptime(ira->codegen, resolved_type, nullptr)) { + switch (type_requires_comptime(ira->codegen, resolved_type)) { case ReqCompTimeInvalid: return ira->codegen->invalid_instruction; case ReqCompTimeYes: @@ -17049,7 +17049,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct } } else { // runtime known element index - switch (type_requires_comptime(ira->codegen, return_type, nullptr)) { + switch (type_requires_comptime(ira->codegen, return_type)) { case ReqCompTimeYes: ir_add_error(ira, elem_index, buf_sprintf("values of type '%s' must be comptime known, but index value is runtime known", @@ -19034,7 +19034,7 @@ static IrInstruction *ir_analyze_union_init(IrAnalyze *ira, IrInstruction *sourc } bool is_comptime = ir_should_inline(ira->new_irb.exec, source_instruction->scope) - || type_requires_comptime(ira->codegen, union_type, nullptr) == ReqCompTimeYes; + || type_requires_comptime(ira->codegen, union_type) == ReqCompTimeYes; IrInstruction *result = ir_get_deref(ira, source_instruction, result_loc, nullptr); if (is_comptime && !instr_is_comptime(result)) { @@ -19082,7 +19082,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc ZigList const_ptrs = {}; bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope) - || type_requires_comptime(ira->codegen, container_type, nullptr) == ReqCompTimeYes; + || type_requires_comptime(ira->codegen, container_type) == ReqCompTimeYes; // Here we iterate over the fields that have been initialized, and emit @@ -19260,7 +19260,7 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira, } bool is_comptime; - switch (type_requires_comptime(ira->codegen, container_type, nullptr)) { + switch (type_requires_comptime(ira->codegen, container_type)) { case ReqCompTimeInvalid: return ira->codegen->invalid_instruction; case ReqCompTimeNo: @@ -25502,7 +25502,7 @@ static ZigType *ir_resolve_lazy_fn_type(CodeGen *codegen, IrExecutable *exec, As lazy_fn_type->param_types[fn_type_id.next_param_index]); if (type_is_invalid(param_type)) return nullptr; - switch (type_requires_comptime(codegen, param_type, nullptr)) { + switch (type_requires_comptime(codegen, param_type)) { case ReqCompTimeYes: if (!calling_convention_allows_zig_types(fn_type_id.cc)) { exec_add_error_node(codegen, exec, source_node,