mirror of
https://github.com/ziglang/zig.git
synced 2026-02-15 22:09:49 +00:00
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 };
```
This commit is contained in:
parent
be0a9a7277
commit
ac4dd9d665
@ -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 {
|
||||
|
||||
@ -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<LazyValueSliceType *>(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<LazyValuePtrType *>(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<LazyValueFnType *>(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<uint32_t>(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;
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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:
|
||||
|
||||
20
src/ir.cpp
20
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<IrInstruction *> 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,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user