| ... | ... | @@ -30053,8 +30053,8 @@ fn coerceExtra( |
| 30053 | 30053 | else => {}, |
| 30054 | 30054 | }, |
| 30055 | 30055 | .@"struct" => blk: { |
| 30056 | | if (inst_ty.isTuple(zcu)) { |
| 30057 | | return sema.coerceTupleToStruct(block, dest_ty, inst, inst_src) catch |err| switch (err) { |
| 30056 | if (dest_ty.isTuple(zcu) and inst_ty.isTuple(zcu)) { |
| 30057 | return sema.coerceTupleToTuple(block, dest_ty, inst, inst_src) catch |err| switch (err) { |
| 30058 | 30058 | error.NotCoercible => break :blk, |
| 30059 | 30059 | else => |e| return e, |
| 30060 | 30060 | }; |
| ... | ... | @@ -32135,114 +32135,6 @@ fn coerceTupleToArrayPtrs( |
| 32135 | 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 | 32138 | fn coerceTupleToTuple( |
| 32247 | 32139 | sema: *Sema, |
| 32248 | 32140 | block: *Block, |