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...@@ -3963,7 +3963,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
3963 const bin_op = sema.air_instructions.items(.data)[@backingInt(store_inst)].bin_op;3963 const bin_op = sema.air_instructions.items(.data)[@backingInt(store_inst)].bin_op;
3964 peer_val.* = bin_op.rhs;3964 peer_val.* = bin_op.rhs;
3965 }3965 }
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);
3967 // The layout of the peers is already resolved, so the layout of `final_elem_ty` is too.3967 // The layout of the peers is already resolved, so the layout of `final_elem_ty` is too.
3968 final_elem_ty.assertHasLayout(zcu);3968 final_elem_ty.assertHasLayout(zcu);
39693969
...@@ -5496,7 +5496,12 @@ fn resolveAnalyzedBlock(...@@ -5496,7 +5496,12 @@ fn resolveAnalyzedBlock(
5496 // Need to set the type and emit the Block instruction. This allows machine code generation5496 // Need to set the type and emit the Block instruction. This allows machine code generation
5497 // to emit a jump instruction to after the block when it encounters the break.5497 // to emit a jump instruction to after the block when it encounters the break.
5498 try parent_block.instructions.append(gpa, merges.block_inst);5498 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 );
5500 resolved_ty.assertHasLayout(zcu);5505 resolved_ty.assertHasLayout(zcu);
5501 // TODO add note "missing else causes void value"5506 // TODO add note "missing else causes void value"
55025507
...@@ -12299,11 +12304,10 @@ fn analyzeSwitchPayloadCaptureTaggedUnion(...@@ -12299,11 +12304,10 @@ fn analyzeSwitchPayloadCaptureTaggedUnion(
1229912304
12300 const capture_ty: Type = capture_ty: {12305 const capture_ty: Type = capture_ty: {
12301 if (same_types) break :capture_ty first_field_ty;12306 if (same_types) break :capture_ty first_field_ty;
12302 // We need values to run PTR on, so make a bunch of undef constants.12307
12303 const dummy_captures = try sema.arena.alloc(Air.Inst.Ref, item_refs.len);12308 const item_types = try sema.arena.alloc(Type, item_refs.len);
12304 for (dummy_captures, field_indices) |*dummy, field_idx| {12309 for (item_types, field_indices) |*field_ty, field_idx| {
12305 const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_idx]);12310 field_ty.* = .fromInterned(union_obj.field_types.get(ip)[field_idx]);
12306 dummy.* = try pt.undefRef(field_ty);
12307 }12311 }
1230812312
12309 const item_srcs = try sema.arena.alloc(?LazySrcLoc, item_refs.len);12313 const item_srcs = try sema.arena.alloc(?LazySrcLoc, item_refs.len);
...@@ -12321,7 +12325,7 @@ fn analyzeSwitchPayloadCaptureTaggedUnion(...@@ -12321,7 +12325,7 @@ fn analyzeSwitchPayloadCaptureTaggedUnion(
12321 break :capture_ty sema.resolvePeerTypes(12325 break :capture_ty sema.resolvePeerTypes(
12322 case_block,12326 case_block,
12323 capture_src,12327 capture_src,
12324 dummy_captures,12328 .{ .types = item_types },
12325 .{ .override = item_srcs },12329 .{ .override = item_srcs },
12326 ) catch |err| switch (err) {12330 ) catch |err| switch (err) {
12327 error.AlreadyReported => |e| {12331 error.AlreadyReported => |e| {
...@@ -12340,12 +12344,11 @@ fn analyzeSwitchPayloadCaptureTaggedUnion(...@@ -12340,12 +12344,11 @@ fn analyzeSwitchPayloadCaptureTaggedUnion(
12340 const capture_ptr_ty = resolve: {12344 const capture_ptr_ty = resolve: {
12341 // By-ref captures of hetereogeneous types are only allowed if all field12345 // By-ref captures of hetereogeneous types are only allowed if all field
12342 // pointer types are peer resolvable to each other.12346 // pointer types are peer resolvable to each other.
12343 // We need values to run PTR on, so make a bunch of undef constants.12347 const item_types = try sema.arena.alloc(Type, item_refs.len);
12344 const dummy_captures = try sema.arena.alloc(Air.Inst.Ref, item_refs.len);12348 for (item_types, field_indices) |*field_ptr_ty, field_index| {
12345 for (field_indices, dummy_captures) |field_index, *dummy| {12349 field_ptr_ty.* = try operand_ptr_ty.fieldPtrType(field_index, pt);
12346 const field_ptr_ty = try operand_ptr_ty.fieldPtrType(field_index, pt);
12347 dummy.* = try pt.undefRef(field_ptr_ty);
12348 }12350 }
12351
12349 const item_srcs = try sema.arena.alloc(?LazySrcLoc, item_refs.len);12352 const item_srcs = try sema.arena.alloc(?LazySrcLoc, item_refs.len);
12350 for (item_srcs, 0..) |*item_src, item_i| {12353 for (item_srcs, 0..) |*item_src, item_i| {
12351 item_src.* = .{12354 item_src.* = .{
...@@ -12361,7 +12364,7 @@ fn analyzeSwitchPayloadCaptureTaggedUnion(...@@ -12361,7 +12364,7 @@ fn analyzeSwitchPayloadCaptureTaggedUnion(
12361 break :resolve sema.resolvePeerTypes(12364 break :resolve sema.resolvePeerTypes(
12362 case_block,12365 case_block,
12363 capture_src,12366 capture_src,
12364 dummy_captures,12367 .{ .types = item_types },
12365 .{ .override = item_srcs },12368 .{ .override = item_srcs },
12366 ) catch |err| switch (err) {12369 ) catch |err| switch (err) {
12367 error.AlreadyReported => |e| {12370 error.AlreadyReported => |e| {
...@@ -13315,8 +13318,12 @@ fn zirBitwise(...@@ -13315,8 +13318,12 @@ fn zirBitwise(
13315 const rhs_ty = sema.typeOf(rhs);13318 const rhs_ty = sema.typeOf(rhs);
13316 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);13319 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
1331713320
13318 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };13321 const resolved_type = try sema.resolvePeerTypes(
13319 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]?LazySrcLoc{ lhs_src, rhs_src } });13322 block,
13323 src,
13324 .{ .insts = &.{ lhs, rhs } },
13325 .{ .override = &.{ lhs_src, rhs_src } },
13326 );
13320 const scalar_type = resolved_type.scalarType(zcu);13327 const scalar_type = resolved_type.scalarType(zcu);
13321 const scalar_tag = scalar_type.zigTypeTag(zcu);13328 const scalar_tag = scalar_type.zigTypeTag(zcu);
1332213329
...@@ -13510,19 +13517,12 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13510,19 +13517,12 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13510 return sema.fail(block, rhs_src, "expected indexable; found '{f}'", .{rhs_ty.fmt(zcu)});13517 return sema.fail(block, rhs_src, "expected indexable; found '{f}'", .{rhs_ty.fmt(zcu)});
13511 };13518 };
1351213519
13513 const resolved_elem_ty = t: {13520 const resolved_elem_ty = try sema.resolvePeerTypes(
13514 var trash_block = block.makeSubBlock();13521 block,
13515 trash_block.comptime_reason = null;13522 src,
13516 defer trash_block.instructions.deinit(sema.gpa);13523 .{ .types = &.{ lhs_info.elem_type, rhs_info.elem_type } },
1351713524 .{ .override = &.{ lhs_src, rhs_src } },
13518 const instructions = [_]Air.Inst.Ref{13525 );
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 };
1352613526
13527 // When there is a sentinel mismatch, no sentinel on the result.13527 // When there is a sentinel mismatch, no sentinel on the result.
13528 // Otherwise, use the sentinel value provided by either operand,13528 // 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...@@ -14004,9 +14004,12 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
14004 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);14004 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
14005 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);14005 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);
1400614006
14007 const resolved_type = try sema.resolvePeerTypes(block, src, &.{ lhs, rhs }, .{14007 const resolved_type = try sema.resolvePeerTypes(
14008 .override = &.{ lhs_src, rhs_src },14008 block,
14009 });14009 src,
14010 .{ .insts = &.{ lhs, rhs } },
14011 .{ .override = &.{ lhs_src, rhs_src } },
14012 );
1401014013
14011 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);14014 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
14012 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);14015 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...@@ -14113,9 +14116,12 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
14113 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);14116 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
14114 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);14117 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);
1411514118
14116 const resolved_type = try sema.resolvePeerTypes(block, src, &.{ lhs, rhs }, .{14119 const resolved_type = try sema.resolvePeerTypes(
14117 .override = &.{ lhs_src, rhs_src },14120 block,
14118 });14121 src,
14122 .{ .insts = &.{ lhs, rhs } },
14123 .{ .override = &.{ lhs_src, rhs_src } },
14124 );
1411914125
14120 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);14126 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
14121 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);14127 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...@@ -14209,9 +14215,12 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
14209 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);14215 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
14210 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);14216 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);
1421114217
14212 const resolved_type = try sema.resolvePeerTypes(block, src, &.{ lhs, rhs }, .{14218 const resolved_type = try sema.resolvePeerTypes(
14213 .override = &.{ lhs_src, rhs_src },14219 block,
14214 });14220 src,
14221 .{ .insts = &.{ lhs, rhs } },
14222 .{ .override = &.{ lhs_src, rhs_src } },
14223 );
1421514224
14216 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);14225 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
14217 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);14226 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...@@ -14274,9 +14283,12 @@ fn zirDivCeil(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
14274 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);14283 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
14275 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);14284 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);
1427614285
14277 const resolved_type = try sema.resolvePeerTypes(block, src, &.{ lhs, rhs }, .{14286 const resolved_type = try sema.resolvePeerTypes(
14278 .override = &.{ lhs_src, rhs_src },14287 block,
14279 });14288 src,
14289 .{ .insts = &.{ lhs, rhs } },
14290 .{ .override = &.{ lhs_src, rhs_src } },
14291 );
1428014292
14281 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);14293 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
14282 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);14294 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...@@ -14339,9 +14351,12 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
14339 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);14351 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
14340 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);14352 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);
1434114353
14342 const resolved_type = try sema.resolvePeerTypes(block, src, &.{ lhs, rhs }, .{14354 const resolved_type = try sema.resolvePeerTypes(
14343 .override = &.{ lhs_src, rhs_src },14355 block,
14344 });14356 src,
14357 .{ .insts = &.{ lhs, rhs } },
14358 .{ .override = &.{ lhs_src, rhs_src } },
14359 );
1434514360
14346 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);14361 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
14347 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);14362 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....@@ -14550,9 +14565,12 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
14550 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);14565 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
14551 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);14566 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);
1455214567
14553 const resolved_type = try sema.resolvePeerTypes(block, src, &.{ lhs, rhs }, .{14568 const resolved_type = try sema.resolvePeerTypes(
14554 .override = &.{ lhs_src, rhs_src },14569 block,
14555 });14570 src,
14571 .{ .insts = &.{ lhs, rhs } },
14572 .{ .override = &.{ lhs_src, rhs_src } },
14573 );
1455614574
14557 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);14575 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
14558 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);14576 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...@@ -14651,9 +14669,12 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
14651 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);14669 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
14652 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);14670 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);
1465314671
14654 const resolved_type = try sema.resolvePeerTypes(block, src, &.{ lhs, rhs }, .{14672 const resolved_type = try sema.resolvePeerTypes(
14655 .override = &.{ lhs_src, rhs_src },14673 block,
14656 });14674 src,
14675 .{ .insts = &.{ lhs, rhs } },
14676 .{ .override = &.{ lhs_src, rhs_src } },
14677 );
1465714678
14658 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);14679 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
14659 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);14680 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...@@ -14715,9 +14736,12 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
14715 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);14736 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
14716 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);14737 try sema.checkInvalidPtrIntArithmetic(block, src, lhs_ty);
1471714738
14718 const resolved_type = try sema.resolvePeerTypes(block, src, &.{ lhs, rhs }, .{14739 const resolved_type = try sema.resolvePeerTypes(
14719 .override = &.{ lhs_src, rhs_src },14740 block,
14720 });14741 src,
14742 .{ .insts = &.{ lhs, rhs } },
14743 .{ .override = &.{ lhs_src, rhs_src } },
14744 );
1472114745
14722 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);14746 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
14723 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);14747 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
...@@ -14785,13 +14809,15 @@ fn zirOverflowArithmetic(...@@ -14785,13 +14809,15 @@ fn zirOverflowArithmetic(
1478514809
14786 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);14810 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
1478714811
14788 const instructions = &[_]Air.Inst.Ref{ uncasted_lhs, uncasted_rhs };
14789 const dest_ty = if (zir_tag == .shl_with_overflow)14812 const dest_ty = if (zir_tag == .shl_with_overflow)
14790 lhs_ty14813 lhs_ty
14791 else14814 else
14792 try sema.resolvePeerTypes(block, src, instructions, .{14815 try sema.resolvePeerTypes(
14793 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },14816 block,
14794 });14817 src,
14818 .{ .insts = &.{ uncasted_lhs, uncasted_rhs } },
14819 .{ .override = &.{ lhs_src, rhs_src } },
14820 );
1479514821
14796 const rhs_dest_ty = if (zir_tag == .shl_with_overflow)14822 const rhs_dest_ty = if (zir_tag == .shl_with_overflow)
14797 try sema.log2IntType(block, lhs_ty, src)14823 try sema.log2IntType(block, lhs_ty, src)
...@@ -15126,9 +15152,12 @@ fn analyzeArithmetic(...@@ -15126,9 +15152,12 @@ fn analyzeArithmetic(
15126 }15152 }
15127 }15153 }
1512815154
15129 const resolved_type = try sema.resolvePeerTypes(block, src, &.{ lhs, rhs }, .{15155 const resolved_type = try sema.resolvePeerTypes(
15130 .override = &.{ lhs_src, rhs_src },15156 block,
15131 });15157 src,
15158 .{ .insts = &.{ lhs, rhs } },
15159 .{ .override = &.{ lhs_src, rhs_src } },
15160 );
1513215161
15133 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);15162 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
15134 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);15163 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
...@@ -15732,8 +15761,12 @@ fn analyzeCmp(...@@ -15732,8 +15761,12 @@ fn analyzeCmp(
15732 const casted_rhs = try sema.analyzeErrUnionCode(block, rhs_src, rhs);15761 const casted_rhs = try sema.analyzeErrUnionCode(block, rhs_src, rhs);
15733 return sema.cmpSelf(block, src, lhs, casted_rhs, op, lhs_src, rhs_src);15762 return sema.cmpSelf(block, src, lhs, casted_rhs, op, lhs_src, rhs_src);
15734 }15763 }
15735 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };15764 const resolved_type = try sema.resolvePeerTypes(
15736 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]?LazySrcLoc{ lhs_src, rhs_src } });15765 block,
15766 src,
15767 .{ .insts = &.{ lhs, rhs } },
15768 .{ .override = &.{ lhs_src, rhs_src } },
15769 );
15737 if (!resolved_type.isSelfComparable(zcu, is_equality_cmp)) {15770 if (!resolved_type.isSelfComparable(zcu, is_equality_cmp)) {
15738 return sema.fail(block, src, "operator {s} not allowed for type '{f}'", .{15771 return sema.fail(block, src, "operator {s} not allowed for type '{f}'", .{
15739 compareOperatorName(op), resolved_type.fmt(zcu),15772 compareOperatorName(op), resolved_type.fmt(zcu),
...@@ -17396,7 +17429,12 @@ fn zirTypeofPeer(...@@ -17396,7 +17429,12 @@ fn zirTypeofPeer(
17396 inst_list[i] = sema.resolveInst(arg_ref);17429 inst_list[i] = sema.resolveInst(arg_ref);
17397 }17430 }
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 );
17400 return Air.internedToRef(result_type.toIntern());17438 return Air.internedToRef(result_type.toIntern());
17401}17439}
1740217440
...@@ -22994,9 +23032,12 @@ fn checkSimdBinOp(...@@ -22994,9 +23032,12 @@ fn checkSimdBinOp(
2299423032
22995 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);23033 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
22996 const vec_len: ?usize = if (lhs_ty.zigTypeTag(zcu) == .vector) lhs_ty.vectorLen(zcu) else null;23034 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 }, .{23035 const result_ty = try sema.resolvePeerTypes(
22998 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },23036 block,
22999 });23037 src,
23038 .{ .insts = &.{ uncasted_lhs, uncasted_rhs } },
23039 .{ .override = &.{ lhs_src, rhs_src } },
23040 );
23000 const lhs = try sema.coerce(block, result_ty, uncasted_lhs, lhs_src);23041 const lhs = try sema.coerce(block, result_ty, uncasted_lhs, lhs_src);
23001 const rhs = try sema.coerce(block, result_ty, uncasted_rhs, rhs_src);23042 const rhs = try sema.coerce(block, result_ty, uncasted_rhs, rhs_src);
2300223043
...@@ -32294,7 +32335,12 @@ fn cmpVector(...@@ -32294,7 +32335,12 @@ fn cmpVector(
32294 assert(rhs_ty.zigTypeTag(zcu) == .vector);32335 assert(rhs_ty.zigTypeTag(zcu) == .vector);
32295 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);32336 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 );
32298 const casted_lhs = try sema.coerce(block, resolved_ty, lhs, lhs_src);32344 const casted_lhs = try sema.coerce(block, resolved_ty, lhs, lhs_src);
32299 const casted_rhs = try sema.coerce(block, resolved_ty, rhs, rhs_src);32345 const casted_rhs = try sema.coerce(block, resolved_ty, rhs, rhs_src);
3230032346
...@@ -32628,7 +32674,7 @@ const PeerResolveResult = union(enum) {...@@ -32628,7 +32674,7 @@ const PeerResolveResult = union(enum) {
32628 sema: *Sema,32674 sema: *Sema,
32629 block: *Block,32675 block: *Block,
32630 src: LazySrcLoc,32676 src: LazySrcLoc,
32631 instructions: []const Air.Inst.Ref,32677 start_peer_tys: []const Type,
32632 candidate_srcs: PeerTypeCandidateSrc,32678 candidate_srcs: PeerTypeCandidateSrc,
32633 ) !*Zcu.ErrorMsg {32679 ) !*Zcu.ErrorMsg {
32634 const zcu = sema.pt.zcu;32680 const zcu = sema.pt.zcu;
...@@ -32636,11 +32682,7 @@ const PeerResolveResult = union(enum) {...@@ -32636,11 +32682,7 @@ const PeerResolveResult = union(enum) {
32636 var opt_msg: ?*Zcu.ErrorMsg = null;32682 var opt_msg: ?*Zcu.ErrorMsg = null;
32637 errdefer if (opt_msg) |msg| msg.destroy(sema.gpa);32683 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 buffer32685 var peer_tys = start_peer_tys;
32640 var peer_tys = try sema.arena.alloc(Type, instructions.len);
32641 for (peer_tys, instructions) |*ty, inst| {
32642 ty.* = sema.typeOf(inst);
32643 }
3264432686
32645 var cur = result;32687 var cur = result;
32646 while (true) {32688 while (true) {
...@@ -32716,38 +32758,70 @@ fn resolvePeerTypes(...@@ -32716,38 +32758,70 @@ fn resolvePeerTypes(
32716 sema: *Sema,32758 sema: *Sema,
32717 block: *Block,32759 block: *Block,
32718 src: LazySrcLoc,32760 src: LazySrcLoc,
32719 instructions: []const Air.Inst.Ref,32761 peers: union(enum) {
32762 insts: []const Air.Inst.Ref,
32763 types: []const Type,
32764 },
32720 candidate_srcs: PeerTypeCandidateSrc,32765 candidate_srcs: PeerTypeCandidateSrc,
32721) !Type {32766) !Type {
32722 switch (instructions.len) {32767 const peer_tys: []?Type, const peer_vals: []?Value = switch (peers) {
32723 0 => return .noreturn,32768 .insts => |insts| peers: {
32724 1 => return sema.typeOf(instructions[0]),32769 if (insts.len == 0) return .noreturn;
32725 else => {},32770
32726 }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.32779 const peer_tys = try sema.arena.alloc(?Type, insts.len);
32729 same_type: {32780 const peer_vals = try sema.arena.alloc(?Value, insts.len);
32730 const ty = sema.typeOf(instructions[0]);32781
32731 for (instructions[1..]) |inst| {32782 for (peer_tys, peer_vals, insts) |*ty, *val, inst| {
32732 if (sema.typeOf(inst).toIntern() != ty.toIntern()) {32783 ty.* = sema.typeOf(inst);
32733 break :same_type;32784 val.* = sema.resolveValue(inst);
32734 }32785 }
32735 }
32736 return ty;
32737 }
3273832786
32739 const peer_tys = try sema.arena.alloc(?Type, instructions.len);32787 break :peers .{ peer_tys, peer_vals };
32740 const peer_vals = try sema.arena.alloc(?Value, instructions.len);32788 },
3274132789
32742 for (instructions, peer_tys, peer_vals) |inst, *ty, *val| {32790 .types => |types| peers: {
32743 ty.* = sema.typeOf(inst);32791 if (types.len == 0) return .noreturn;
32744 val.* = sema.resolveValue(inst);32792
32745 }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
32747 switch (try sema.resolvePeerTypesInner(block, src, peer_tys, peer_vals)) {32812 switch (try sema.resolvePeerTypesInner(block, src, peer_tys, peer_vals)) {
32748 .success => |ty| return ty,32813 .success => |ty| return ty,
32749 else => |result| {32814 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);
32751 return sema.failWithOwnedErrorMsg(block, msg);32825 return sema.failWithOwnedErrorMsg(block, msg);
32752 },32826 },
32753 }32827 }
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