@@ -286,6 +286,7 @@ static IrInstGen *ir_analyze_struct_value_field_value(IrAnalyze *ira, IrInst* so
286
286
IrInstGen *struct_operand, TypeStructField *field);
287
287
static bool value_cmp_numeric_val_any(ZigValue *left, Cmp predicate, ZigValue *right);
288
288
static bool value_cmp_numeric_val_all(ZigValue *left, Cmp predicate, ZigValue *right);
289
+ static void memoize_field_init_val(CodeGen *codegen, ZigType *container_type, TypeStructField *field);
289
290
290
291
#define ir_assert(OK, SOURCE_INSTRUCTION) ir_assert_impl((OK), (SOURCE_INSTRUCTION), __FILE__, __LINE__)
291
292
#define ir_assert_gen(OK, SOURCE_INSTRUCTION) ir_assert_gen_impl((OK), (SOURCE_INSTRUCTION), __FILE__, __LINE__)
@@ -14703,10 +14704,139 @@ static IrInstGen *ir_analyze_struct_literal_to_array(IrAnalyze *ira, IrInst* sou
14703
14704
}
14704
14705
14705
14706
static IrInstGen *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, IrInst* source_instr,
14706
- IrInstGen *value , ZigType *wanted_type)
14707
+ IrInstGen *struct_operand , ZigType *wanted_type)
14707
14708
{
14708
- ir_add_error(ira, source_instr, buf_sprintf("TODO: type coercion of anon struct literal to struct"));
14709
- return ira->codegen->invalid_inst_gen;
14709
+ Error err;
14710
+
14711
+ IrInstGen *struct_ptr = ir_get_ref(ira, source_instr, struct_operand, true, false);
14712
+ if (type_is_invalid(struct_ptr->value->type))
14713
+ return ira->codegen->invalid_inst_gen;
14714
+
14715
+ if (wanted_type->data.structure.resolve_status == ResolveStatusBeingInferred) {
14716
+ ir_add_error(ira, source_instr, buf_sprintf("type coercion of anon struct literal to inferred struct"));
14717
+ return ira->codegen->invalid_inst_gen;
14718
+ }
14719
+
14720
+ if ((err = type_resolve(ira->codegen, wanted_type, ResolveStatusSizeKnown)))
14721
+ return ira->codegen->invalid_inst_gen;
14722
+
14723
+ size_t actual_field_count = wanted_type->data.structure.src_field_count;
14724
+ size_t instr_field_count = struct_operand->value->type->data.structure.src_field_count;
14725
+
14726
+ bool need_comptime = ir_should_inline(ira->old_irb.exec, source_instr->scope)
14727
+ || type_requires_comptime(ira->codegen, wanted_type) == ReqCompTimeYes;
14728
+ bool is_comptime = true;
14729
+
14730
+ // Determine if the struct_operand will be comptime.
14731
+ // Also emit compile errors for missing fields and duplicate fields.
14732
+ AstNode **field_assign_nodes = heap::c_allocator.allocate<AstNode *>(actual_field_count);
14733
+ ZigValue **field_values = heap::c_allocator.allocate<ZigValue *>(actual_field_count);
14734
+ IrInstGen **casted_fields = heap::c_allocator.allocate<IrInstGen *>(actual_field_count);
14735
+ IrInstGen *const_result = ir_const(ira, source_instr, wanted_type);
14736
+
14737
+ for (size_t i = 0; i < instr_field_count; i += 1) {
14738
+ TypeStructField *src_field = struct_operand->value->type->data.structure.fields[i];
14739
+ TypeStructField *dst_field = find_struct_type_field(wanted_type, src_field->name);
14740
+ if (dst_field == nullptr) {
14741
+ ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("no field named '%s' in struct '%s'",
14742
+ buf_ptr(src_field->name), buf_ptr(&wanted_type->name)));
14743
+ if (wanted_type->data.structure.decl_node) {
14744
+ add_error_note(ira->codegen, msg, wanted_type->data.structure.decl_node,
14745
+ buf_sprintf("struct '%s' declared here", buf_ptr(&wanted_type->name)));
14746
+ }
14747
+ add_error_note(ira->codegen, msg, src_field->decl_node,
14748
+ buf_sprintf("field '%s' declared here", buf_ptr(src_field->name)));
14749
+ return ira->codegen->invalid_inst_gen;
14750
+ }
14751
+
14752
+ ir_assert(src_field->decl_node != nullptr, source_instr);
14753
+ AstNode *existing_assign_node = field_assign_nodes[dst_field->src_index];
14754
+ if (existing_assign_node != nullptr) {
14755
+ ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("duplicate field"));
14756
+ add_error_note(ira->codegen, msg, existing_assign_node, buf_sprintf("other field here"));
14757
+ return ira->codegen->invalid_inst_gen;
14758
+ }
14759
+ field_assign_nodes[dst_field->src_index] = src_field->decl_node;
14760
+
14761
+ IrInstGen *field_ptr = ir_analyze_struct_field_ptr(ira, source_instr, src_field, struct_ptr,
14762
+ struct_operand->value->type, false);
14763
+ if (type_is_invalid(field_ptr->value->type))
14764
+ return ira->codegen->invalid_inst_gen;
14765
+ IrInstGen *field_value = ir_get_deref(ira, source_instr, field_ptr, nullptr);
14766
+ if (type_is_invalid(field_value->value->type))
14767
+ return ira->codegen->invalid_inst_gen;
14768
+ IrInstGen *casted_value = ir_implicit_cast(ira, field_value, dst_field->type_entry);
14769
+ if (type_is_invalid(casted_value->value->type))
14770
+ return ira->codegen->invalid_inst_gen;
14771
+
14772
+ casted_fields[dst_field->src_index] = casted_value;
14773
+ if (need_comptime || instr_is_comptime(casted_value)) {
14774
+ ZigValue *field_val = ir_resolve_const(ira, casted_value, UndefOk);
14775
+ if (field_val == nullptr)
14776
+ return ira->codegen->invalid_inst_gen;
14777
+ field_val->parent.id = ConstParentIdStruct;
14778
+ field_val->parent.data.p_struct.struct_val = const_result->value;
14779
+ field_val->parent.data.p_struct.field_index = dst_field->src_index;
14780
+ field_values[dst_field->src_index] = field_val;
14781
+ } else {
14782
+ is_comptime = false;
14783
+ }
14784
+ }
14785
+
14786
+ bool any_missing = false;
14787
+ for (size_t i = 0; i < actual_field_count; i += 1) {
14788
+ if (field_assign_nodes[i] != nullptr) continue;
14789
+
14790
+ // look for a default field value
14791
+ TypeStructField *field = wanted_type->data.structure.fields[i];
14792
+ memoize_field_init_val(ira->codegen, wanted_type, field);
14793
+ if (field->init_val == nullptr) {
14794
+ ir_add_error(ira, source_instr,
14795
+ buf_sprintf("missing field: '%s'", buf_ptr(field->name)));
14796
+ any_missing = true;
14797
+ continue;
14798
+ }
14799
+ if (type_is_invalid(field->init_val->type))
14800
+ return ira->codegen->invalid_inst_gen;
14801
+ ZigValue *init_val_copy = ira->codegen->pass1_arena->create<ZigValue>();
14802
+ copy_const_val(ira->codegen, init_val_copy, field->init_val);
14803
+ init_val_copy->parent.id = ConstParentIdStruct;
14804
+ init_val_copy->parent.data.p_struct.struct_val = const_result->value;
14805
+ init_val_copy->parent.data.p_struct.field_index = i;
14806
+ field_values[i] = init_val_copy;
14807
+ casted_fields[i] = ir_const_move(ira, source_instr, init_val_copy);
14808
+ }
14809
+ if (any_missing)
14810
+ return ira->codegen->invalid_inst_gen;
14811
+
14812
+ if (is_comptime) {
14813
+ heap::c_allocator.deallocate(field_assign_nodes, actual_field_count);
14814
+ IrInstGen *const_result = ir_const(ira, source_instr, wanted_type);
14815
+ const_result->value->data.x_struct.fields = field_values;
14816
+ return const_result;
14817
+ }
14818
+
14819
+ IrInstGen *result_loc_inst = ir_resolve_result(ira, source_instr, no_result_loc(),
14820
+ wanted_type, nullptr, true, true);
14821
+ if (type_is_invalid(result_loc_inst->value->type) || result_loc_inst->value->type->id == ZigTypeIdUnreachable) {
14822
+ return ira->codegen->invalid_inst_gen;
14823
+ }
14824
+
14825
+ for (size_t i = 0; i < actual_field_count; i += 1) {
14826
+ TypeStructField *field = wanted_type->data.structure.fields[i];
14827
+ IrInstGen *field_ptr = ir_analyze_struct_field_ptr(ira, source_instr, field, result_loc_inst, wanted_type, true);
14828
+ if (type_is_invalid(field_ptr->value->type))
14829
+ return ira->codegen->invalid_inst_gen;
14830
+ IrInstGen *store_ptr_inst = ir_analyze_store_ptr(ira, source_instr, field_ptr, casted_fields[i], true);
14831
+ if (type_is_invalid(store_ptr_inst->value->type))
14832
+ return ira->codegen->invalid_inst_gen;
14833
+ }
14834
+
14835
+ heap::c_allocator.deallocate(field_assign_nodes, actual_field_count);
14836
+ heap::c_allocator.deallocate(field_values, actual_field_count);
14837
+ heap::c_allocator.deallocate(casted_fields, actual_field_count);
14838
+
14839
+ return ir_get_deref(ira, source_instr, result_loc_inst, nullptr);
14710
14840
}
14711
14841
14712
14842
static IrInstGen *ir_analyze_struct_literal_to_union(IrAnalyze *ira, IrInst* source_instr,
@@ -14727,7 +14857,7 @@ static IrInstGen *ir_analyze_struct_literal_to_union(IrAnalyze *ira, IrInst* sou
14727
14857
TypeUnionField *union_field = find_union_type_field(union_type, only_field->name);
14728
14858
if (union_field == nullptr) {
14729
14859
ir_add_error_node(ira, only_field->decl_node,
14730
- buf_sprintf("no member named '%s' in union '%s'",
14860
+ buf_sprintf("no field named '%s' in union '%s'",
14731
14861
buf_ptr(only_field->name), buf_ptr(&union_type->name)));
14732
14862
return ira->codegen->invalid_inst_gen;
14733
14863
}
@@ -22407,7 +22537,7 @@ static IrInstGen *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstSrcFiel
22407
22537
usize, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
22408
22538
} else {
22409
22539
ir_add_error_node(ira, source_node,
22410
- buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name),
22540
+ buf_sprintf("no field named '%s' in '%s'", buf_ptr(field_name),
22411
22541
buf_ptr(&container_type->name)));
22412
22542
return ira->codegen->invalid_inst_gen;
22413
22543
}
@@ -23834,7 +23964,7 @@ static IrInstGen *ir_analyze_union_init(IrAnalyze *ira, IrInst* source_instructi
23834
23964
TypeUnionField *type_field = find_union_type_field(union_type, field_name);
23835
23965
if (type_field == nullptr) {
23836
23966
ir_add_error_node(ira, field_source_node,
23837
- buf_sprintf("no member named '%s' in union '%s'",
23967
+ buf_sprintf("no field named '%s' in union '%s'",
23838
23968
buf_ptr(field_name), buf_ptr(&union_type->name)));
23839
23969
return ira->codegen->invalid_inst_gen;
23840
23970
}
@@ -23930,7 +24060,7 @@ static IrInstGen *ir_analyze_container_init_fields(IrAnalyze *ira, IrInst *sourc
23930
24060
TypeStructField *type_field = find_struct_type_field(container_type, field->name);
23931
24061
if (!type_field) {
23932
24062
ir_add_error_node(ira, field->source_node,
23933
- buf_sprintf("no member named '%s' in struct '%s'",
24063
+ buf_sprintf("no field named '%s' in struct '%s'",
23934
24064
buf_ptr(field->name), buf_ptr(&container_type->name)));
23935
24065
return ira->codegen->invalid_inst_gen;
23936
24066
}
@@ -23965,7 +24095,7 @@ static IrInstGen *ir_analyze_container_init_fields(IrAnalyze *ira, IrInst *sourc
23965
24095
memoize_field_init_val(ira->codegen, container_type, field);
23966
24096
if (field->init_val == nullptr) {
23967
24097
ir_add_error(ira, source_instr,
23968
- buf_sprintf("missing field: '%s'", buf_ptr(container_type->data.structure.fields[i] ->name)));
24098
+ buf_sprintf("missing field: '%s'", buf_ptr(field ->name)));
23969
24099
any_missing = true;
23970
24100
continue;
23971
24101
}
0 commit comments