authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-10-16 12:21:11+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-10-17 07:33:43+02:00
logcf12b653f1e9e62e1038f338652ce268f7f8e478
tree28beffd4dff462b9bffd787751c419569283b156
parent156fac4665b8084d54970d4a94b640ef94ec6160

Sema: fix crash resolving peer types in array concatenation


2 files changed, 180 insertions(+), 95 deletions(-)

src/Sema.zig+169-95
......@@ -3963,7 +3963,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
39633963 const bin_op = sema.air_instructions.items(.data)[@backingInt(store_inst)].bin_op;
39643964 peer_val.* = bin_op.rhs;
39653965 }
3966 const final_elem_ty = try sema.resolvePeerTypes(block, ty_src, peer_vals, .none);
3966 const final_elem_ty = try sema.resolvePeerTypes(block, ty_src, .{ .insts = peer_vals }, .none);
39673967 // The layout of the peers is already resolved, so the layout of `final_elem_ty` is too.
39683968 final_elem_ty.assertHasLayout(zcu);
39693969
......@@ -5496,7 +5496,12 @@ fn resolveAnalyzedBlock(
54965496 // Need to set the type and emit the Block instruction. This allows machine code generation
54975497 // to emit a jump instruction to after the block when it encounters the break.
54985498 try parent_block.instructions.append(gpa, merges.block_inst);
5499 const resolved_ty = try sema.resolvePeerTypes(parent_block, src, merges.results.items, .{ .override = merges.src_locs.items });
5499 const resolved_ty = try sema.resolvePeerTypes(
5500 parent_block,
5501 src,
5502 .{ .insts = merges.results.items },
5503 .{ .override = merges.src_locs.items },
5504 );
55005505 resolved_ty.assertHasLayout(zcu);
55015506 // TODO add note "missing else causes void value"
55025507
......@@ -12299,11 +12304,10 @@ fn analyzeSwitchPayloadCaptureTaggedUnion(
1229912304
1230012305 const capture_ty: Type = capture_ty: {
1230112306 if (same_types) break :capture_ty first_field_ty;
12302 // We need values to run PTR on, so make a bunch of undef constants.
12303 const dummy_captures = try sema.arena.alloc(Air.Inst.Ref, item_refs.len);
12304 for (dummy_captures, field_indices) |*dummy, field_idx| {
12305 const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_idx]);
12306 dummy.* = try pt.undefRef(field_ty);
12307
12308 const item_types = try sema.arena.alloc(Type, item_refs.len);
12309 for (item_types, field_indices) |*field_ty, field_idx| {
12310 field_ty.* = .fromInterned(union_obj.field_types.get(ip)[field_idx]);
1230712311 }
1230812312
1230912313 const item_srcs = try sema.arena.alloc(?LazySrcLoc, item_refs.len);
......@@ -12321,7 +12325,7 @@ fn analyzeSwitchPayloadCaptureTaggedUnion(
1232112325 break :capture_ty sema.resolvePeerTypes(
1232212326 case_block,
1232312327 capture_src,
12324 dummy_captures,
12328 .{ .types = item_types },
1232512329 .{ .override = item_srcs },
1232612330 ) catch |err| switch (err) {
1232712331 error.AlreadyReported => |e| {
......@@ -12340,12 +12344,11 @@ fn analyzeSwitchPayloadCaptureTaggedUnion(
1234012344 const capture_ptr_ty = resolve: {
1234112345 // By-ref captures of hetereogeneous types are only allowed if all field
1234212346 // pointer types are peer resolvable to each other.
12343 // We need values to run PTR on, so make a bunch of undef constants.
12344 const dummy_captures = try sema.arena.alloc(Air.Inst.Ref, item_refs.len);
12345 for (field_indices, dummy_captures) |field_index, *dummy| {
12346 const field_ptr_ty = try operand_ptr_ty.fieldPtrType(field_index, pt);
12347 dummy.* = try pt.undefRef(field_ptr_ty);
12347 const item_types = try sema.arena.alloc(Type, item_refs.len);
12348 for (item_types, field_indices) |*field_ptr_ty, field_index| {
12349 field_ptr_ty.* = try operand_ptr_ty.fieldPtrType(field_index, pt);
1234812350 }
12351
1234912352 const item_srcs = try sema.arena.alloc(?LazySrcLoc, item_refs.len);
1235012353 for (item_srcs, 0..) |*item_src, item_i| {
1235112354 item_src.* = .{
......@@ -12361,7 +12364,7 @@ fn analyzeSwitchPayloadCaptureTaggedUnion(
1236112364 break :resolve sema.resolvePeerTypes(
1236212365 case_block,
1236312366 capture_src,
12364 dummy_captures,
12367 .{ .types = item_types },
1236512368 .{ .override = item_srcs },
1236612369 ) catch |err| switch (err) {
1236712370 error.AlreadyReported => |e| {
......@@ -13315,8 +13318,12 @@ fn zirBitwise(
1331513318 const rhs_ty = sema.typeOf(rhs);
1331613319 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
1331713320
13318 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
13319 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]?LazySrcLoc{ lhs_src, rhs_src } });
13321 const resolved_type = try sema.resolvePeerTypes(
13322 block,
13323 src,
13324 .{ .insts = &.{ lhs, rhs } },
13325 .{ .override = &.{ lhs_src, rhs_src } },
13326 );
1332013327 const scalar_type = resolved_type.scalarType(zcu);
1332113328 const scalar_tag = scalar_type.zigTypeTag(zcu);
1332213329
......@@ -13510,19 +13517,12 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1351013517 return sema.fail(block, rhs_src, "expected indexable; found '{f}'", .{rhs_ty.fmt(zcu)});
1351113518 };
1351213519
13513 const resolved_elem_ty = t: {
13514 var trash_block = block.makeSubBlock();
13515 trash_block.comptime_reason = null;
13516 defer trash_block.instructions.deinit(sema.gpa);
13517
13518 const instructions = [_]Air.Inst.Ref{
13519 try trash_block.addTyOp(.bit_cast, lhs_info.elem_type, .void_value),
13520 try trash_block.addTyOp(.bit_cast, rhs_info.elem_type, .void_value),
13521 };
13522 break :t try sema.resolvePeerTypes(block, src, &instructions, .{
13523 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
13524 });
13525 };
13520 const resolved_elem_ty = try sema.resolvePeerTypes(
13521 block,
13522 src,
13523 .{ .types = &.{ lhs_info.elem_type, rhs_info.elem_type } },
13524 .{ .override = &.{ lhs_src, rhs_src } },
13525 );
1352613526
1352713527 // When there is a sentinel mismatch, no sentinel on the result.
1352813528 // Otherwise, use the sentinel value provided by either operand,
......@@ -14004,9 +14004,12 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1400414004 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
1400514005 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);
1400614006
14007 const resolved_type = try sema.resolvePeerTypes(block, src, &.{ lhs, rhs }, .{
14008 .override = &.{ lhs_src, rhs_src },
14009 });
14007 const resolved_type = try sema.resolvePeerTypes(
14008 block,
14009 src,
14010 .{ .insts = &.{ lhs, rhs } },
14011 .{ .override = &.{ lhs_src, rhs_src } },
14012 );
1401014013
1401114014 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
1401214015 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
......@@ -14113,9 +14116,12 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1411314116 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
1411414117 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);
1411514118
14116 const resolved_type = try sema.resolvePeerTypes(block, src, &.{ lhs, rhs }, .{
14117 .override = &.{ lhs_src, rhs_src },
14118 });
14119 const resolved_type = try sema.resolvePeerTypes(
14120 block,
14121 src,
14122 .{ .insts = &.{ lhs, rhs } },
14123 .{ .override = &.{ lhs_src, rhs_src } },
14124 );
1411914125
1412014126 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
1412114127 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
......@@ -14209,9 +14215,12 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1420914215 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
1421014216 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);
1421114217
14212 const resolved_type = try sema.resolvePeerTypes(block, src, &.{ lhs, rhs }, .{
14213 .override = &.{ lhs_src, rhs_src },
14214 });
14218 const resolved_type = try sema.resolvePeerTypes(
14219 block,
14220 src,
14221 .{ .insts = &.{ lhs, rhs } },
14222 .{ .override = &.{ lhs_src, rhs_src } },
14223 );
1421514224
1421614225 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
1421714226 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
......@@ -14274,9 +14283,12 @@ fn zirDivCeil(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1427414283 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
1427514284 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);
1427614285
14277 const resolved_type = try sema.resolvePeerTypes(block, src, &.{ lhs, rhs }, .{
14278 .override = &.{ lhs_src, rhs_src },
14279 });
14286 const resolved_type = try sema.resolvePeerTypes(
14287 block,
14288 src,
14289 .{ .insts = &.{ lhs, rhs } },
14290 .{ .override = &.{ lhs_src, rhs_src } },
14291 );
1428014292
1428114293 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
1428214294 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
......@@ -14339,9 +14351,12 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1433914351 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
1434014352 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);
1434114353
14342 const resolved_type = try sema.resolvePeerTypes(block, src, &.{ lhs, rhs }, .{
14343 .override = &.{ lhs_src, rhs_src },
14344 });
14354 const resolved_type = try sema.resolvePeerTypes(
14355 block,
14356 src,
14357 .{ .insts = &.{ lhs, rhs } },
14358 .{ .override = &.{ lhs_src, rhs_src } },
14359 );
1434514360
1434614361 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
1434714362 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
......@@ -14550,9 +14565,12 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
1455014565 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
1455114566 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);
1455214567
14553 const resolved_type = try sema.resolvePeerTypes(block, src, &.{ lhs, rhs }, .{
14554 .override = &.{ lhs_src, rhs_src },
14555 });
14568 const resolved_type = try sema.resolvePeerTypes(
14569 block,
14570 src,
14571 .{ .insts = &.{ lhs, rhs } },
14572 .{ .override = &.{ lhs_src, rhs_src } },
14573 );
1455614574
1455714575 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
1455814576 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
......@@ -14651,9 +14669,12 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1465114669 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
1465214670 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);
1465314671
14654 const resolved_type = try sema.resolvePeerTypes(block, src, &.{ lhs, rhs }, .{
14655 .override = &.{ lhs_src, rhs_src },
14656 });
14672 const resolved_type = try sema.resolvePeerTypes(
14673 block,
14674 src,
14675 .{ .insts = &.{ lhs, rhs } },
14676 .{ .override = &.{ lhs_src, rhs_src } },
14677 );
1465714678
1465814679 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
1465914680 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
......@@ -14715,9 +14736,12 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1471514736 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
1471614737 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);
1471714738
14718 const resolved_type = try sema.resolvePeerTypes(block, src, &.{ lhs, rhs }, .{
14719 .override = &.{ lhs_src, rhs_src },
14720 });
14739 const resolved_type = try sema.resolvePeerTypes(
14740 block,
14741 src,
14742 .{ .insts = &.{ lhs, rhs } },
14743 .{ .override = &.{ lhs_src, rhs_src } },
14744 );
1472114745
1472214746 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
1472314747 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
......@@ -14785,13 +14809,15 @@ fn zirOverflowArithmetic(
1478514809
1478614810 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
1478714811
14788 const instructions = &[_]Air.Inst.Ref{ uncasted_lhs, uncasted_rhs };
1478914812 const dest_ty = if (zir_tag == .shl_with_overflow)
1479014813 lhs_ty
1479114814 else
14792 try sema.resolvePeerTypes(block, src, instructions, .{
14793 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
14794 });
14815 try sema.resolvePeerTypes(
14816 block,
14817 src,
14818 .{ .insts = &.{ uncasted_lhs, uncasted_rhs } },
14819 .{ .override = &.{ lhs_src, rhs_src } },
14820 );
1479514821
1479614822 const rhs_dest_ty = if (zir_tag == .shl_with_overflow)
1479714823 try sema.log2IntType(block, lhs_ty, src)
......@@ -15126,9 +15152,12 @@ fn analyzeArithmetic(
1512615152 }
1512715153 }
1512815154
15129 const resolved_type = try sema.resolvePeerTypes(block, src, &.{ lhs, rhs }, .{
15130 .override = &.{ lhs_src, rhs_src },
15131 });
15155 const resolved_type = try sema.resolvePeerTypes(
15156 block,
15157 src,
15158 .{ .insts = &.{ lhs, rhs } },
15159 .{ .override = &.{ lhs_src, rhs_src } },
15160 );
1513215161
1513315162 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
1513415163 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
......@@ -15732,8 +15761,12 @@ fn analyzeCmp(
1573215761 const casted_rhs = try sema.analyzeErrUnionCode(block, rhs_src, rhs);
1573315762 return sema.cmpSelf(block, src, lhs, casted_rhs, op, lhs_src, rhs_src);
1573415763 }
15735 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
15736 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]?LazySrcLoc{ lhs_src, rhs_src } });
15764 const resolved_type = try sema.resolvePeerTypes(
15765 block,
15766 src,
15767 .{ .insts = &.{ lhs, rhs } },
15768 .{ .override = &.{ lhs_src, rhs_src } },
15769 );
1573715770 if (!resolved_type.isSelfComparable(zcu, is_equality_cmp)) {
1573815771 return sema.fail(block, src, "operator {s} not allowed for type '{f}'", .{
1573915772 compareOperatorName(op), resolved_type.fmt(zcu),
......@@ -17396,7 +17429,12 @@ fn zirTypeofPeer(
1739617429 inst_list[i] = sema.resolveInst(arg_ref);
1739717430 }
1739817431
17399 const result_type = try sema.resolvePeerTypes(block, src, inst_list, .{ .typeof_builtin_call_node_offset = extra.data.src_node });
17432 const result_type = try sema.resolvePeerTypes(
17433 block,
17434 src,
17435 .{ .insts = inst_list },
17436 .{ .typeof_builtin_call_node_offset = extra.data.src_node },
17437 );
1740017438 return Air.internedToRef(result_type.toIntern());
1740117439}
1740217440
......@@ -22994,9 +23032,12 @@ fn checkSimdBinOp(
2299423032
2299523033 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
2299623034 const vec_len: ?usize = if (lhs_ty.zigTypeTag(zcu) == .vector) lhs_ty.vectorLen(zcu) else null;
22997 const result_ty = try sema.resolvePeerTypes(block, src, &.{ uncasted_lhs, uncasted_rhs }, .{
22998 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
22999 });
23035 const result_ty = try sema.resolvePeerTypes(
23036 block,
23037 src,
23038 .{ .insts = &.{ uncasted_lhs, uncasted_rhs } },
23039 .{ .override = &.{ lhs_src, rhs_src } },
23040 );
2300023041 const lhs = try sema.coerce(block, result_ty, uncasted_lhs, lhs_src);
2300123042 const rhs = try sema.coerce(block, result_ty, uncasted_rhs, rhs_src);
2300223043
......@@ -32294,7 +32335,12 @@ fn cmpVector(
3229432335 assert(rhs_ty.zigTypeTag(zcu) == .vector);
3229532336 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
3229632337
32297 const resolved_ty = try sema.resolvePeerTypes(block, src, &.{ lhs, rhs }, .{ .override = &.{ lhs_src, rhs_src } });
32338 const resolved_ty = try sema.resolvePeerTypes(
32339 block,
32340 src,
32341 .{ .insts = &.{ lhs, rhs } },
32342 .{ .override = &.{ lhs_src, rhs_src } },
32343 );
3229832344 const casted_lhs = try sema.coerce(block, resolved_ty, lhs, lhs_src);
3229932345 const casted_rhs = try sema.coerce(block, resolved_ty, rhs, rhs_src);
3230032346
......@@ -32628,7 +32674,7 @@ const PeerResolveResult = union(enum) {
3262832674 sema: *Sema,
3262932675 block: *Block,
3263032676 src: LazySrcLoc,
32631 instructions: []const Air.Inst.Ref,
32677 start_peer_tys: []const Type,
3263232678 candidate_srcs: PeerTypeCandidateSrc,
3263332679 ) !*Zcu.ErrorMsg {
3263432680 const zcu = sema.pt.zcu;
......@@ -32636,11 +32682,7 @@ const PeerResolveResult = union(enum) {
3263632682 var opt_msg: ?*Zcu.ErrorMsg = null;
3263732683 errdefer if (opt_msg) |msg| msg.destroy(sema.gpa);
3263832684
32639 // If we mention fields we'll want to include field types, so put peer types in a buffer
32640 var peer_tys = try sema.arena.alloc(Type, instructions.len);
32641 for (peer_tys, instructions) |*ty, inst| {
32642 ty.* = sema.typeOf(inst);
32643 }
32685 var peer_tys = start_peer_tys;
3264432686
3264532687 var cur = result;
3264632688 while (true) {
......@@ -32716,38 +32758,70 @@ fn resolvePeerTypes(
3271632758 sema: *Sema,
3271732759 block: *Block,
3271832760 src: LazySrcLoc,
32719 instructions: []const Air.Inst.Ref,
32761 peers: union(enum) {
32762 insts: []const Air.Inst.Ref,
32763 types: []const Type,
32764 },
3272032765 candidate_srcs: PeerTypeCandidateSrc,
3272132766) !Type {
32722 switch (instructions.len) {
32723 0 => return .noreturn,
32724 1 => return sema.typeOf(instructions[0]),
32725 else => {},
32726 }
32767 const peer_tys: []?Type, const peer_vals: []?Value = switch (peers) {
32768 .insts => |insts| peers: {
32769 if (insts.len == 0) return .noreturn;
32770
32771 // If everything is the same type we can bypass the main PTR logic.
32772 const first_ty = sema.typeOf(insts[0]);
32773 for (insts[1..]) |inst| {
32774 if (sema.typeOf(inst).toIntern() != first_ty.toIntern()) {
32775 break;
32776 }
32777 } else return first_ty;
3272732778
32728 // Fast path: check if everything has the same type to bypass the main PTR logic.
32729 same_type: {
32730 const ty = sema.typeOf(instructions[0]);
32731 for (instructions[1..]) |inst| {
32732 if (sema.typeOf(inst).toIntern() != ty.toIntern()) {
32733 break :same_type;
32779 const peer_tys = try sema.arena.alloc(?Type, insts.len);
32780 const peer_vals = try sema.arena.alloc(?Value, insts.len);
32781
32782 for (peer_tys, peer_vals, insts) |*ty, *val, inst| {
32783 ty.* = sema.typeOf(inst);
32784 val.* = sema.resolveValue(inst);
3273432785 }
32735 }
32736 return ty;
32737 }
3273832786
32739 const peer_tys = try sema.arena.alloc(?Type, instructions.len);
32740 const peer_vals = try sema.arena.alloc(?Value, instructions.len);
32787 break :peers .{ peer_tys, peer_vals };
32788 },
3274132789
32742 for (instructions, peer_tys, peer_vals) |inst, *ty, *val| {
32743 ty.* = sema.typeOf(inst);
32744 val.* = sema.resolveValue(inst);
32745 }
32790 .types => |types| peers: {
32791 if (types.len == 0) return .noreturn;
32792
32793 // If everything is the same type we can bypass the main PTR logic.
32794 for (types[1..]) |ty| {
32795 if (ty.toIntern() != types[0].toIntern()) {
32796 break;
32797 }
32798 } else return types[0];
32799
32800 const peer_tys = try sema.arena.alloc(?Type, types.len);
32801 const peer_vals = try sema.arena.alloc(?Value, types.len);
32802
32803 for (peer_tys, peer_vals, types) |*opt_ty, *opt_val, ty| {
32804 opt_ty.* = ty;
32805 opt_val.* = try ty.onePossibleValue(sema.pt);
32806 }
32807
32808 break :peers .{ peer_tys, peer_vals };
32809 },
32810 };
3274632811
3274732812 switch (try sema.resolvePeerTypesInner(block, src, peer_tys, peer_vals)) {
3274832813 .success => |ty| return ty,
3274932814 else => |result| {
32750 const msg = try result.report(sema, block, src, instructions, candidate_srcs);
32815 // We can't pass in `peer_tys` because `resolvePeerTypesInner` may clobber it.
32816 const report_peer_tys: []const Type = switch (peers) {
32817 .insts => |insts| types: {
32818 const types = try sema.arena.alloc(Type, insts.len);
32819 for (types, insts) |*ty, inst| ty.* = sema.typeOf(inst);
32820 break :types types;
32821 },
32822 .types => |types| types,
32823 };
32824 const msg = try result.report(sema, block, src, report_peer_tys, candidate_srcs);
3275132825 return sema.failWithOwnedErrorMsg(block, msg);
3275232826 },
3275332827 }
test/cases/compile_errors/invalid_array_concatenation_peer_resolves_with_comptime_int.zig created+11
......@@ -0,0 +1,11 @@
1comptime {
2 const lhs: [2]void = .{ {}, {} };
3 const rhs: [2]comptime_int = .{ 2, 3 };
4 _ = lhs ++ rhs;
5}
6
7// error
8//
9// :4:13: error: incompatible types: 'void' and 'comptime_int'
10// :4:9: note: type 'void' here
11// :4:16: note: type 'comptime_int' here