| ... | @@ -30053,8 +30053,8 @@ fn coerceExtra( | ... | @@ -30053,8 +30053,8 @@ fn coerceExtra( |
| 30053 | else => {}, | 30053 | else => {}, |
| 30054 | }, | 30054 | }, |
| 30055 | .@"struct" => blk: { | 30055 | .@"struct" => blk: { |
| 30056 | if (inst_ty.isTuple(zcu)) { | 30056 | if (dest_ty.isTuple(zcu) and inst_ty.isTuple(zcu)) { |
| 30057 | return sema.coerceTupleToStruct(block, dest_ty, inst, inst_src) catch |err| switch (err) { | 30057 | return sema.coerceTupleToTuple(block, dest_ty, inst, inst_src) catch |err| switch (err) { |
| 30058 | error.NotCoercible => break :blk, | 30058 | error.NotCoercible => break :blk, |
| 30059 | else => |e| return e, | 30059 | else => |e| return e, |
| 30060 | }; | 30060 | }; |
| ... | @@ -32135,114 +32135,6 @@ fn coerceTupleToArrayPtrs( | ... | @@ -32135,114 +32135,6 @@ fn coerceTupleToArrayPtrs( |
| 32135 | return ptr_array; | 32135 | return ptr_array; |
| 32136 | } | 32136 | } |
| 32137 | | 32137 | |
| 32138 | /// Handles both tuples and anon struct literals. Coerces field-wise. Reports | | |
| 32139 | /// errors for both extra fields and missing fields. | | |
| 32140 | fn coerceTupleToStruct( | | |
| 32141 | sema: *Sema, | | |
| 32142 | block: *Block, | | |
| 32143 | struct_ty: Type, | | |
| 32144 | inst: Air.Inst.Ref, | | |
| 32145 | inst_src: LazySrcLoc, | | |
| 32146 | ) !Air.Inst.Ref { | | |
| 32147 | const pt = sema.pt; | | |
| 32148 | const zcu = pt.zcu; | | |
| 32149 | const ip = &zcu.intern_pool; | | |
| 32150 | try struct_ty.resolveFields(pt); | | |
| 32151 | try struct_ty.resolveStructFieldInits(pt); | | |
| 32152 | | | |
| 32153 | if (struct_ty.isTuple(zcu)) { | | |
| 32154 | return sema.coerceTupleToTuple(block, struct_ty, inst, inst_src); | | |
| 32155 | } | | |
| 32156 | | | |
| 32157 | const struct_type = zcu.typeToStruct(struct_ty).?; | | |
| 32158 | const field_vals = try sema.arena.alloc(InternPool.Index, struct_type.field_types.len); | | |
| 32159 | const field_refs = try sema.arena.alloc(Air.Inst.Ref, field_vals.len); | | |
| 32160 | @memset(field_refs, .none); | | |
| 32161 | | | |
| 32162 | const inst_ty = sema.typeOf(inst); | | |
| 32163 | var runtime_src: ?LazySrcLoc = null; | | |
| 32164 | const field_count = switch (ip.indexToKey(inst_ty.toIntern())) { | | |
| 32165 | .tuple_type => |tuple| tuple.types.len, | | |
| 32166 | .struct_type => ip.loadStructType(inst_ty.toIntern()).field_types.len, | | |
| 32167 | else => unreachable, | | |
| 32168 | }; | | |
| 32169 | for (0..field_count) |tuple_field_index| { | | |
| 32170 | const field_src = inst_src; // TODO better source location | | |
| 32171 | const field_name = inst_ty.structFieldName(tuple_field_index, zcu).unwrap() orelse | | |
| 32172 | try ip.getOrPutStringFmt(sema.gpa, pt.tid, "{d}", .{tuple_field_index}, .no_embedded_nulls); | | |
| 32173 | | | |
| 32174 | const struct_field_index = try sema.structFieldIndex(block, struct_ty, field_name, field_src); | | |
| 32175 | const struct_field_ty = Type.fromInterned(struct_type.field_types.get(ip)[struct_field_index]); | | |
| 32176 | const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, @intCast(tuple_field_index)); | | |
| 32177 | const coerced = try sema.coerce(block, struct_field_ty, elem_ref, field_src); | | |
| 32178 | field_refs[struct_field_index] = coerced; | | |
| 32179 | if (struct_type.fieldIsComptime(ip, struct_field_index)) { | | |
| 32180 | const init_val = try sema.resolveValue(coerced) orelse { | | |
| 32181 | return sema.failWithNeededComptime(block, field_src, .{ .simple = .stored_to_comptime_field }); | | |
| 32182 | }; | | |
| 32183 | | | |
| 32184 | const field_init = Value.fromInterned(struct_type.field_inits.get(ip)[struct_field_index]); | | |
| 32185 | if (!init_val.eql(field_init, struct_field_ty, pt.zcu)) { | | |
| 32186 | return sema.failWithInvalidComptimeFieldStore(block, field_src, inst_ty, tuple_field_index); | | |
| 32187 | } | | |
| 32188 | } | | |
| 32189 | if (runtime_src == null) { | | |
| 32190 | if (try sema.resolveValue(coerced)) |field_val| { | | |
| 32191 | field_vals[struct_field_index] = field_val.toIntern(); | | |
| 32192 | } else { | | |
| 32193 | runtime_src = field_src; | | |
| 32194 | } | | |
| 32195 | } | | |
| 32196 | } | | |
| 32197 | | | |
| 32198 | // Populate default field values and report errors for missing fields. | | |
| 32199 | var root_msg: ?*Zcu.ErrorMsg = null; | | |
| 32200 | errdefer if (root_msg) |msg| msg.destroy(sema.gpa); | | |
| 32201 | | | |
| 32202 | for (field_refs, 0..) |*field_ref, i| { | | |
| 32203 | if (field_ref.* != .none) continue; | | |
| 32204 | | | |
| 32205 | const field_name = struct_type.field_names.get(ip)[i]; | | |
| 32206 | const field_default_val = struct_type.fieldInit(ip, i); | | |
| 32207 | const field_src = inst_src; // TODO better source location | | |
| 32208 | if (field_default_val == .none) { | | |
| 32209 | const template = "missing struct field: {}"; | | |
| 32210 | const args = .{field_name.fmt(ip)}; | | |
| 32211 | if (root_msg) |msg| { | | |
| 32212 | try sema.errNote(field_src, msg, template, args); | | |
| 32213 | } else { | | |
| 32214 | root_msg = try sema.errMsg(field_src, template, args); | | |
| 32215 | } | | |
| 32216 | continue; | | |
| 32217 | } | | |
| 32218 | if (runtime_src == null) { | | |
| 32219 | field_vals[i] = field_default_val; | | |
| 32220 | } else { | | |
| 32221 | field_ref.* = Air.internedToRef(field_default_val); | | |
| 32222 | } | | |
| 32223 | } | | |
| 32224 | | | |
| 32225 | if (root_msg) |msg| { | | |
| 32226 | try sema.addDeclaredHereNote(msg, struct_ty); | | |
| 32227 | root_msg = null; | | |
| 32228 | return sema.failWithOwnedErrorMsg(block, msg); | | |
| 32229 | } | | |
| 32230 | | | |
| 32231 | if (runtime_src) |rs| { | | |
| 32232 | try sema.requireRuntimeBlock(block, inst_src, rs); | | |
| 32233 | return block.addAggregateInit(struct_ty, field_refs); | | |
| 32234 | } | | |
| 32235 | | | |
| 32236 | const struct_val = try pt.intern(.{ .aggregate = .{ | | |
| 32237 | .ty = struct_ty.toIntern(), | | |
| 32238 | .storage = .{ .elems = field_vals }, | | |
| 32239 | } }); | | |
| 32240 | // TODO: figure out InternPool removals for incremental compilation | | |
| 32241 | //errdefer ip.remove(struct_val); | | |
| 32242 | | | |
| 32243 | return Air.internedToRef(struct_val); | | |
| 32244 | } | | |
| 32245 | | | |
| 32246 | fn coerceTupleToTuple( | 32138 | fn coerceTupleToTuple( |
| 32247 | sema: *Sema, | 32139 | sema: *Sema, |
| 32248 | block: *Block, | 32140 | block: *Block, |