| ... | @@ -12178,17 +12178,21 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -12178,17 +12178,21 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12178 | const rhs_ty = sema.typeOf(rhs); | 12178 | const rhs_ty = sema.typeOf(rhs); |
| 12179 | const src = inst_data.src(); | 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 | return sema.analyzeTupleCat(block, inst_data.src_node, lhs, rhs); | 12184 | return sema.analyzeTupleCat(block, inst_data.src_node, lhs, rhs); |
| 12183 | } | 12185 | } |
| 12184 | | 12186 | |
| 12185 | const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; | 12187 | const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; |
| 12186 | const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; | 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 | return sema.fail(block, lhs_src, "expected indexable; found '{}'", .{lhs_ty.fmt(sema.mod)}); | 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 | return sema.fail(block, rhs_src, "expected indexable; found '{}'", .{rhs_ty.fmt(sema.mod)}); | 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,18 +12278,24 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12274 | const element_vals = try sema.arena.alloc(Value, final_len_including_sent); | 12278 | const element_vals = try sema.arena.alloc(Value, final_len_including_sent); |
| 12275 | var elem_i: usize = 0; | 12279 | var elem_i: usize = 0; |
| 12276 | while (elem_i < lhs_len) : (elem_i += 1) { | 12280 | while (elem_i < lhs_len) : (elem_i += 1) { |
| 12277 | const elem_val = try lhs_sub_val.elemValue(sema.mod, sema.arena, elem_i); | 12281 | const lhs_elem_i = elem_i; |
| 12278 | const elem_val_inst = try sema.addConstant(lhs_info.elem_type, elem_val); | 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 | const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, .unneeded); | 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, ""); | 12287 | const coerced_elem_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, coerced_elem_val_inst, ""); |
| 12281 | element_vals[elem_i] = coereced_elem_val; | 12288 | element_vals[elem_i] = coerced_elem_val; |
| 12282 | } | 12289 | } |
| 12283 | while (elem_i < result_len) : (elem_i += 1) { | 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); | 12291 | const rhs_elem_i = elem_i - lhs_len; |
| 12285 | const elem_val_inst = try sema.addConstant(lhs_info.elem_type, elem_val); | 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 | const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, .unneeded); | 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, ""); | 12297 | const coerced_elem_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, coerced_elem_val_inst, ""); |
| 12288 | element_vals[elem_i] = coereced_elem_val; | 12298 | element_vals[elem_i] = coerced_elem_val; |
| 12289 | } | 12299 | } |
| 12290 | if (res_sent_val) |sent_val| { | 12300 | if (res_sent_val) |sent_val| { |
| 12291 | element_vals[result_len] = sent_val; | 12301 | element_vals[result_len] = sent_val; |
| ... | @@ -12350,7 +12360,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -12350,7 +12360,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12350 | return block.addAggregateInit(result_ty, element_refs); | 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 | const operand_ty = sema.typeOf(operand); | 12364 | const operand_ty = sema.typeOf(operand); |
| 12355 | switch (operand_ty.zigTypeTag()) { | 12365 | switch (operand_ty.zigTypeTag()) { |
| 12356 | .Array => return operand_ty.arrayInfo(), | 12366 | .Array => return operand_ty.arrayInfo(), |
| ... | @@ -12376,6 +12386,16 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Ins | ... | @@ -12376,6 +12386,16 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Ins |
| 12376 | .C => {}, | 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 | else => {}, | 12399 | else => {}, |
| 12380 | } | 12400 | } |
| 12381 | return null; | 12401 | return null; |
| ... | @@ -12470,7 +12490,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -12470,7 +12490,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12470 | } | 12490 | } |
| 12471 | | 12491 | |
| 12472 | // Analyze the lhs first, to catch the case that someone tried to do exponentiation | 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 | const msg = msg: { | 12494 | const msg = msg: { |
| 12475 | const msg = try sema.errMsg(block, lhs_src, "expected indexable; found '{}'", .{lhs_ty.fmt(sema.mod)}); | 12495 | const msg = try sema.errMsg(block, lhs_src, "expected indexable; found '{}'", .{lhs_ty.fmt(sema.mod)}); |
| 12476 | errdefer msg.destroy(sema.gpa); | 12496 | errdefer msg.destroy(sema.gpa); |