| ... | @@ -1163,7 +1163,6 @@ fn zirValidateStructInitPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Ind | ... | @@ -1163,7 +1163,6 @@ fn zirValidateStructInitPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Ind |
| 1163 | // Maps field index to field_ptr index of where it was already initialized. | 1163 | // Maps field index to field_ptr index of where it was already initialized. |
| 1164 | const found_fields = try gpa.alloc(Zir.Inst.Index, struct_obj.fields.entries.items.len); | 1164 | const found_fields = try gpa.alloc(Zir.Inst.Index, struct_obj.fields.entries.items.len); |
| 1165 | defer gpa.free(found_fields); | 1165 | defer gpa.free(found_fields); |
| 1166 | | | |
| 1167 | mem.set(Zir.Inst.Index, found_fields, 0); | 1166 | mem.set(Zir.Inst.Index, found_fields, 0); |
| 1168 | | 1167 | |
| 1169 | for (instrs) |field_ptr| { | 1168 | for (instrs) |field_ptr| { |
| ... | @@ -1190,11 +1189,12 @@ fn zirValidateStructInitPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Ind | ... | @@ -1190,11 +1189,12 @@ fn zirValidateStructInitPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Ind |
| 1190 | | 1189 | |
| 1191 | var root_msg: ?*Module.ErrorMsg = null; | 1190 | var root_msg: ?*Module.ErrorMsg = null; |
| 1192 | | 1191 | |
| | 1192 | // TODO handle default struct field values |
| 1193 | for (found_fields) |field_ptr, i| { | 1193 | for (found_fields) |field_ptr, i| { |
| 1194 | if (field_ptr != 0) continue; | 1194 | if (field_ptr != 0) continue; |
| 1195 | | 1195 | |
| 1196 | const field_name = struct_obj.fields.entries.items[i].key; | 1196 | const field_name = struct_obj.fields.entries.items[i].key; |
| 1197 | const template = "mising struct field: {s}"; | 1197 | const template = "missing struct field: {s}"; |
| 1198 | const args = .{field_name}; | 1198 | const args = .{field_name}; |
| 1199 | if (root_msg) |msg| { | 1199 | if (root_msg) |msg| { |
| 1200 | try mod.errNote(&block.base, struct_init_src, msg, template, args); | 1200 | try mod.errNote(&block.base, struct_init_src, msg, template, args); |
| ... | @@ -4614,7 +4614,7 @@ fn zirTypeInfo(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErro | ... | @@ -4614,7 +4614,7 @@ fn zirTypeInfo(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErro |
| 4614 | } | 4614 | } |
| 4615 | | 4615 | |
| 4616 | fn zirTypeof(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst { | 4616 | fn zirTypeof(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst { |
| 4617 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 4617 | const inst_data = sema.code.instructions.items(.data)[inst].un_tok; |
| 4618 | const src = inst_data.src(); | 4618 | const src = inst_data.src(); |
| 4619 | const operand = try sema.resolveInst(inst_data.operand); | 4619 | const operand = try sema.resolveInst(inst_data.operand); |
| 4620 | return sema.mod.constType(sema.arena, src, operand.ty); | 4620 | return sema.mod.constType(sema.arena, src, operand.ty); |
| ... | @@ -5052,9 +5052,112 @@ fn zirUnionInitPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Inner | ... | @@ -5052,9 +5052,112 @@ fn zirUnionInitPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Inner |
| 5052 | } | 5052 | } |
| 5053 | | 5053 | |
| 5054 | fn zirStructInit(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index, is_ref: bool) InnerError!*Inst { | 5054 | fn zirStructInit(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index, is_ref: bool) InnerError!*Inst { |
| 5055 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 5055 | const mod = sema.mod; |
| | 5056 | const gpa = sema.gpa; |
| | 5057 | const zir_datas = sema.code.instructions.items(.data); |
| | 5058 | const inst_data = zir_datas[inst].pl_node; |
| | 5059 | const extra = sema.code.extraData(Zir.Inst.StructInit, inst_data.payload_index); |
| 5056 | const src = inst_data.src(); | 5060 | const src = inst_data.src(); |
| 5057 | return sema.mod.fail(&block.base, src, "TODO: Sema.zirStructInit", .{}); | 5061 | |
| | 5062 | const first_item = sema.code.extraData(Zir.Inst.StructInit.Item, extra.end).data; |
| | 5063 | const first_field_type_data = zir_datas[first_item.field_type].pl_node; |
| | 5064 | const first_field_type_extra = sema.code.extraData(Zir.Inst.FieldType, first_field_type_data.payload_index).data; |
| | 5065 | const unresolved_struct_type = try sema.resolveType(block, src, first_field_type_extra.container_type); |
| | 5066 | const struct_ty = try sema.resolveTypeFields(block, src, unresolved_struct_type); |
| | 5067 | const struct_obj = struct_ty.castTag(.@"struct").?.data; |
| | 5068 | |
| | 5069 | // Maps field index to field_type index of where it was already initialized. |
| | 5070 | // For making sure all fields are accounted for and no fields are duplicated. |
| | 5071 | const found_fields = try gpa.alloc(Zir.Inst.Index, struct_obj.fields.entries.items.len); |
| | 5072 | defer gpa.free(found_fields); |
| | 5073 | mem.set(Zir.Inst.Index, found_fields, 0); |
| | 5074 | |
| | 5075 | // The init values to use for the struct instance. |
| | 5076 | const field_inits = try gpa.alloc(*ir.Inst, struct_obj.fields.entries.items.len); |
| | 5077 | defer gpa.free(field_inits); |
| | 5078 | |
| | 5079 | var field_i: u32 = 0; |
| | 5080 | var extra_index = extra.end; |
| | 5081 | |
| | 5082 | while (field_i < extra.data.fields_len) : (field_i += 1) { |
| | 5083 | const item = sema.code.extraData(Zir.Inst.StructInit.Item, extra_index); |
| | 5084 | extra_index = item.end; |
| | 5085 | |
| | 5086 | const field_type_data = zir_datas[item.data.field_type].pl_node; |
| | 5087 | const field_src: LazySrcLoc = .{ .node_offset_back2tok = field_type_data.src_node }; |
| | 5088 | const field_type_extra = sema.code.extraData(Zir.Inst.FieldType, field_type_data.payload_index).data; |
| | 5089 | const field_name = sema.code.nullTerminatedString(field_type_extra.name_start); |
| | 5090 | const field_index = struct_obj.fields.getIndex(field_name) orelse |
| | 5091 | return sema.failWithBadFieldAccess(block, struct_obj, field_src, field_name); |
| | 5092 | if (found_fields[field_index] != 0) { |
| | 5093 | const other_field_type = found_fields[field_index]; |
| | 5094 | const other_field_type_data = zir_datas[other_field_type].pl_node; |
| | 5095 | const other_field_src: LazySrcLoc = .{ .node_offset_back2tok = other_field_type_data.src_node }; |
| | 5096 | const msg = msg: { |
| | 5097 | const msg = try mod.errMsg(&block.base, field_src, "duplicate field", .{}); |
| | 5098 | errdefer msg.destroy(gpa); |
| | 5099 | try mod.errNote(&block.base, other_field_src, msg, "other field here", .{}); |
| | 5100 | break :msg msg; |
| | 5101 | }; |
| | 5102 | return mod.failWithOwnedErrorMsg(&block.base, msg); |
| | 5103 | } |
| | 5104 | found_fields[field_index] = item.data.field_type; |
| | 5105 | field_inits[field_index] = try sema.resolveInst(item.data.init); |
| | 5106 | } |
| | 5107 | |
| | 5108 | var root_msg: ?*Module.ErrorMsg = null; |
| | 5109 | |
| | 5110 | for (found_fields) |field_type_inst, i| { |
| | 5111 | if (field_type_inst != 0) continue; |
| | 5112 | |
| | 5113 | // Check if the field has a default init. |
| | 5114 | const field = struct_obj.fields.entries.items[i].value; |
| | 5115 | if (field.default_val.tag() == .unreachable_value) { |
| | 5116 | const field_name = struct_obj.fields.entries.items[i].key; |
| | 5117 | const template = "missing struct field: {s}"; |
| | 5118 | const args = .{field_name}; |
| | 5119 | if (root_msg) |msg| { |
| | 5120 | try mod.errNote(&block.base, src, msg, template, args); |
| | 5121 | } else { |
| | 5122 | root_msg = try mod.errMsg(&block.base, src, template, args); |
| | 5123 | } |
| | 5124 | } else { |
| | 5125 | field_inits[i] = try mod.constInst(sema.arena, src, .{ |
| | 5126 | .ty = field.ty, |
| | 5127 | .val = field.default_val, |
| | 5128 | }); |
| | 5129 | } |
| | 5130 | } |
| | 5131 | if (root_msg) |msg| { |
| | 5132 | const fqn = try struct_obj.getFullyQualifiedName(gpa); |
| | 5133 | defer gpa.free(fqn); |
| | 5134 | try mod.errNoteNonLazy( |
| | 5135 | struct_obj.srcLoc(), |
| | 5136 | msg, |
| | 5137 | "struct '{s}' declared here", |
| | 5138 | .{fqn}, |
| | 5139 | ); |
| | 5140 | return mod.failWithOwnedErrorMsg(&block.base, msg); |
| | 5141 | } |
| | 5142 | |
| | 5143 | const is_comptime = for (field_inits) |field_init| { |
| | 5144 | if (field_init.value() == null) { |
| | 5145 | break false; |
| | 5146 | } |
| | 5147 | } else true; |
| | 5148 | |
| | 5149 | if (is_comptime) { |
| | 5150 | const values = try sema.arena.alloc(Value, field_inits.len); |
| | 5151 | for (field_inits) |field_init, i| { |
| | 5152 | values[i] = field_init.value().?; |
| | 5153 | } |
| | 5154 | return mod.constInst(sema.arena, src, .{ |
| | 5155 | .ty = struct_ty, |
| | 5156 | .val = try Value.Tag.@"struct".create(sema.arena, values.ptr), |
| | 5157 | }); |
| | 5158 | } |
| | 5159 | |
| | 5160 | return mod.fail(&block.base, src, "TODO: Sema.zirStructInit for runtime-known struct values", .{}); |
| 5058 | } | 5161 | } |
| 5059 | | 5162 | |
| 5060 | fn zirStructInitAnon(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index, is_ref: bool) InnerError!*Inst { | 5163 | fn zirStructInitAnon(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index, is_ref: bool) InnerError!*Inst { |
| ... | @@ -6043,17 +6146,18 @@ fn coerce( | ... | @@ -6043,17 +6146,18 @@ fn coerce( |
| 6043 | if (inst.ty.zigTypeTag() == .EnumLiteral) { | 6146 | if (inst.ty.zigTypeTag() == .EnumLiteral) { |
| 6044 | const val = try sema.resolveConstValue(block, inst_src, inst); | 6147 | const val = try sema.resolveConstValue(block, inst_src, inst); |
| 6045 | const bytes = val.castTag(.enum_literal).?.data; | 6148 | const bytes = val.castTag(.enum_literal).?.data; |
| 6046 | const field_index = dest_type.enumFieldIndex(bytes) orelse { | 6149 | const resolved_dest_type = try sema.resolveTypeFields(block, inst_src, dest_type); |
| | 6150 | const field_index = resolved_dest_type.enumFieldIndex(bytes) orelse { |
| 6047 | const msg = msg: { | 6151 | const msg = msg: { |
| 6048 | const msg = try mod.errMsg( | 6152 | const msg = try mod.errMsg( |
| 6049 | &block.base, | 6153 | &block.base, |
| 6050 | inst_src, | 6154 | inst_src, |
| 6051 | "enum '{}' has no field named '{s}'", | 6155 | "enum '{}' has no field named '{s}'", |
| 6052 | .{ dest_type, bytes }, | 6156 | .{ resolved_dest_type, bytes }, |
| 6053 | ); | 6157 | ); |
| 6054 | errdefer msg.destroy(sema.gpa); | 6158 | errdefer msg.destroy(sema.gpa); |
| 6055 | try mod.errNoteNonLazy( | 6159 | try mod.errNoteNonLazy( |
| 6056 | dest_type.declSrcLoc(), | 6160 | resolved_dest_type.declSrcLoc(), |
| 6057 | msg, | 6161 | msg, |
| 6058 | "enum declared here", | 6162 | "enum declared here", |
| 6059 | .{}, | 6163 | .{}, |
| ... | @@ -6063,7 +6167,7 @@ fn coerce( | ... | @@ -6063,7 +6167,7 @@ fn coerce( |
| 6063 | return mod.failWithOwnedErrorMsg(&block.base, msg); | 6167 | return mod.failWithOwnedErrorMsg(&block.base, msg); |
| 6064 | }; | 6168 | }; |
| 6065 | return mod.constInst(arena, inst_src, .{ | 6169 | return mod.constInst(arena, inst_src, .{ |
| 6066 | .ty = dest_type, | 6170 | .ty = resolved_dest_type, |
| 6067 | .val = try Value.Tag.enum_field_index.create(arena, @intCast(u32, field_index)), | 6171 | .val = try Value.Tag.enum_field_index.create(arena, @intCast(u32, field_index)), |
| 6068 | }); | 6172 | }); |
| 6069 | } | 6173 | } |
| ... | @@ -6698,23 +6802,41 @@ fn resolveTypeFields(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, ty: Type | ... | @@ -6698,23 +6802,41 @@ fn resolveTypeFields(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, ty: Type |
| 6698 | const struct_obj = ty.castTag(.@"struct").?.data; | 6802 | const struct_obj = ty.castTag(.@"struct").?.data; |
| 6699 | switch (struct_obj.status) { | 6803 | switch (struct_obj.status) { |
| 6700 | .none => {}, | 6804 | .none => {}, |
| 6701 | .have_field_types, .have_layout => return ty, | 6805 | .field_types_wip => { |
| | 6806 | return sema.mod.fail(&block.base, src, "struct {} depends on itself", .{ |
| | 6807 | ty, |
| | 6808 | }); |
| | 6809 | }, |
| | 6810 | .have_field_types, .have_layout, .layout_wip => return ty, |
| 6702 | } | 6811 | } |
| | 6812 | struct_obj.status = .field_types_wip; |
| 6703 | try sema.mod.analyzeStructFields(struct_obj); | 6813 | try sema.mod.analyzeStructFields(struct_obj); |
| | 6814 | struct_obj.status = .have_field_types; |
| 6704 | return ty; | 6815 | return ty; |
| 6705 | }, | 6816 | }, |
| 6706 | .extern_options => { | 6817 | .extern_options => return sema.resolveBuiltinTypeFields(block, src, ty, "ExternOptions"), |
| 6707 | const extern_options_ty = try sema.getBuiltinType(block, src, "ExternOptions"); | 6818 | .export_options => return sema.resolveBuiltinTypeFields(block, src, ty, "ExportOptions"), |
| 6708 | return sema.resolveTypeFields(block, src, extern_options_ty); | 6819 | .atomic_ordering => return sema.resolveBuiltinTypeFields(block, src, ty, "AtomicOrdering"), |
| 6709 | }, | 6820 | .atomic_rmw_op => return sema.resolveBuiltinTypeFields(block, src, ty, "AtomicRmwOp"), |
| 6710 | .export_options => { | 6821 | .calling_convention => return sema.resolveBuiltinTypeFields(block, src, ty, "CallingConvention"), |
| 6711 | const export_options_ty = try sema.getBuiltinType(block, src, "ExportOptions"); | 6822 | .float_mode => return sema.resolveBuiltinTypeFields(block, src, ty, "FloatMode"), |
| 6712 | return sema.resolveTypeFields(block, src, export_options_ty); | 6823 | .reduce_op => return sema.resolveBuiltinTypeFields(block, src, ty, "ReduceOp"), |
| 6713 | }, | 6824 | .call_options => return sema.resolveBuiltinTypeFields(block, src, ty, "CallOptions"), |
| 6714 | else => return ty, | 6825 | else => return ty, |
| 6715 | } | 6826 | } |
| 6716 | } | 6827 | } |
| 6717 | | 6828 | |
| | 6829 | fn resolveBuiltinTypeFields( |
| | 6830 | sema: *Sema, |
| | 6831 | block: *Scope.Block, |
| | 6832 | src: LazySrcLoc, |
| | 6833 | ty: Type, |
| | 6834 | name: []const u8, |
| | 6835 | ) InnerError!Type { |
| | 6836 | const resolved_ty = try sema.getBuiltinType(block, src, name); |
| | 6837 | return sema.resolveTypeFields(block, src, resolved_ty); |
| | 6838 | } |
| | 6839 | |
| 6718 | fn getBuiltinType( | 6840 | fn getBuiltinType( |
| 6719 | sema: *Sema, | 6841 | sema: *Sema, |
| 6720 | block: *Scope.Block, | 6842 | block: *Scope.Block, |