| ... | ... | @@ -12178,17 +12178,21 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12178 | 12178 | const rhs_ty = sema.typeOf(rhs); |
| 12179 | 12179 | const src = inst_data.src(); |
| 12180 | 12180 | |
| 12181 | | if (lhs_ty.isTuple() and rhs_ty.isTuple()) { |
| 12181 | const lhs_is_tuple = lhs_ty.isTuple(); |
| 12182 | const rhs_is_tuple = rhs_ty.isTuple(); |
| 12183 | if (lhs_is_tuple and rhs_is_tuple) { |
| 12182 | 12184 | return sema.analyzeTupleCat(block, inst_data.src_node, lhs, rhs); |
| 12183 | 12185 | } |
| 12184 | 12186 | |
| 12185 | 12187 | const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; |
| 12186 | 12188 | const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; |
| 12187 | 12189 | |
| 12188 | | const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs) orelse { |
| 12190 | const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs, rhs_ty) orelse lhs_info: { |
| 12191 | if (lhs_is_tuple) break :lhs_info @as(Type.ArrayInfo, undefined); |
| 12189 | 12192 | return sema.fail(block, lhs_src, "expected indexable; found '{}'", .{lhs_ty.fmt(sema.mod)}); |
| 12190 | 12193 | }; |
| 12191 | | const rhs_info = try sema.getArrayCatInfo(block, rhs_src, rhs) orelse { |
| 12194 | const rhs_info = try sema.getArrayCatInfo(block, rhs_src, rhs, lhs_ty) orelse { |
| 12195 | assert(!rhs_is_tuple); |
| 12192 | 12196 | return sema.fail(block, rhs_src, "expected indexable; found '{}'", .{rhs_ty.fmt(sema.mod)}); |
| 12193 | 12197 | }; |
| 12194 | 12198 | |
| ... | ... | @@ -12274,18 +12278,24 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12274 | 12278 | const element_vals = try sema.arena.alloc(Value, final_len_including_sent); |
| 12275 | 12279 | var elem_i: usize = 0; |
| 12276 | 12280 | while (elem_i < lhs_len) : (elem_i += 1) { |
| 12277 | | const elem_val = try lhs_sub_val.elemValue(sema.mod, sema.arena, elem_i); |
| 12278 | | const elem_val_inst = try sema.addConstant(lhs_info.elem_type, elem_val); |
| 12281 | const lhs_elem_i = elem_i; |
| 12282 | const elem_ty = if (lhs_is_tuple) lhs_ty.structFieldType(lhs_elem_i) else lhs_info.elem_type; |
| 12283 | const elem_default_val = if (lhs_is_tuple) lhs_ty.structFieldDefaultValue(lhs_elem_i) else Value.initTag(.unreachable_value); |
| 12284 | const elem_val = if (elem_default_val.tag() == .unreachable_value) try lhs_sub_val.elemValue(sema.mod, sema.arena, lhs_elem_i) else elem_default_val; |
| 12285 | const elem_val_inst = try sema.addConstant(elem_ty, elem_val); |
| 12279 | 12286 | const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, .unneeded); |
| 12280 | | const coereced_elem_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, coerced_elem_val_inst, ""); |
| 12281 | | element_vals[elem_i] = coereced_elem_val; |
| 12287 | const coerced_elem_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, coerced_elem_val_inst, ""); |
| 12288 | element_vals[elem_i] = coerced_elem_val; |
| 12282 | 12289 | } |
| 12283 | 12290 | while (elem_i < result_len) : (elem_i += 1) { |
| 12284 | | const elem_val = try rhs_sub_val.elemValue(sema.mod, sema.arena, elem_i - lhs_len); |
| 12285 | | const elem_val_inst = try sema.addConstant(lhs_info.elem_type, elem_val); |
| 12291 | const rhs_elem_i = elem_i - lhs_len; |
| 12292 | const elem_ty = if (rhs_is_tuple) rhs_ty.structFieldType(rhs_elem_i) else rhs_info.elem_type; |
| 12293 | const elem_default_val = if (rhs_is_tuple) rhs_ty.structFieldDefaultValue(rhs_elem_i) else Value.initTag(.unreachable_value); |
| 12294 | const elem_val = if (elem_default_val.tag() == .unreachable_value) try rhs_sub_val.elemValue(sema.mod, sema.arena, rhs_elem_i) else elem_default_val; |
| 12295 | const elem_val_inst = try sema.addConstant(elem_ty, elem_val); |
| 12286 | 12296 | const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, .unneeded); |
| 12287 | | const coereced_elem_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, coerced_elem_val_inst, ""); |
| 12288 | | element_vals[elem_i] = coereced_elem_val; |
| 12297 | const coerced_elem_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, coerced_elem_val_inst, ""); |
| 12298 | element_vals[elem_i] = coerced_elem_val; |
| 12289 | 12299 | } |
| 12290 | 12300 | if (res_sent_val) |sent_val| { |
| 12291 | 12301 | element_vals[result_len] = sent_val; |
| ... | ... | @@ -12350,7 +12360,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12350 | 12360 | return block.addAggregateInit(result_ty, element_refs); |
| 12351 | 12361 | } |
| 12352 | 12362 | |
| 12353 | | fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Inst.Ref) !?Type.ArrayInfo { |
| 12363 | fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Inst.Ref, peer_ty: Type) !?Type.ArrayInfo { |
| 12354 | 12364 | const operand_ty = sema.typeOf(operand); |
| 12355 | 12365 | switch (operand_ty.zigTypeTag()) { |
| 12356 | 12366 | .Array => return operand_ty.arrayInfo(), |
| ... | ... | @@ -12376,6 +12386,16 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Ins |
| 12376 | 12386 | .C => {}, |
| 12377 | 12387 | } |
| 12378 | 12388 | }, |
| 12389 | .Struct => { |
| 12390 | if (operand_ty.isTuple() and peer_ty.isIndexable()) { |
| 12391 | assert(!peer_ty.isTuple()); |
| 12392 | return .{ |
| 12393 | .elem_type = peer_ty.elemType2(), |
| 12394 | .sentinel = null, |
| 12395 | .len = operand_ty.arrayLen(), |
| 12396 | }; |
| 12397 | } |
| 12398 | }, |
| 12379 | 12399 | else => {}, |
| 12380 | 12400 | } |
| 12381 | 12401 | return null; |
| ... | ... | @@ -12470,7 +12490,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12470 | 12490 | } |
| 12471 | 12491 | |
| 12472 | 12492 | // Analyze the lhs first, to catch the case that someone tried to do exponentiation |
| 12473 | | const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs) orelse { |
| 12493 | const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs, lhs_ty) orelse { |
| 12474 | 12494 | const msg = msg: { |
| 12475 | 12495 | const msg = try sema.errMsg(block, lhs_src, "expected indexable; found '{}'", .{lhs_ty.fmt(sema.mod)}); |
| 12476 | 12496 | errdefer msg.destroy(sema.gpa); |