authorgravatar for john.schmidt.h@gmail.comJohn Schmidt <john.schmidt.h@gmail.com> 2023-02-25 20:44:53+01:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-03-21 15:09:42+02:00
logec445fb6b8bb3f3d423cafa4f3a7860da65ca233
treed9e9a35edb8bd62431fa5a0e9f0945ad62e10a48
parent8642770eff4f1770aa5de88907946c60fe5ff0d8

Improve error messages for break type coercion


9 files changed, 199 insertions(+), 67 deletions(-)

src/AstGen.zig+133-36
......@@ -1280,7 +1280,7 @@ fn fnProtoExpr(
12801280 defer param_gz.unstack();
12811281 const param_type = try expr(&param_gz, scope, coerced_type_ri, param_type_node);
12821282 const param_inst_expected = @intCast(u32, astgen.instructions.len + 1);
1283 _ = try param_gz.addBreak(.break_inline, param_inst_expected, param_type);
1283 _ = try param_gz.addBreakWithSrcNode(.break_inline, param_inst_expected, param_type, param_type_node);
12841284 const main_tokens = tree.nodes.items(.main_token);
12851285 const name_token = param.name_token orelse main_tokens[param_type_node];
12861286 const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param;
......@@ -1991,7 +1991,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
19911991
19921992 switch (block_gz.break_result_info.rl) {
19931993 .block_ptr => {
1994 const br = try parent_gz.addBreak(break_tag, block_inst, operand);
1994 const br = try parent_gz.addBreakWithSrcNode(break_tag, block_inst, operand, rhs);
19951995 try block_gz.labeled_breaks.append(astgen.gpa, .{ .br = br, .search = search_index });
19961996 },
19971997 .ptr => {
......@@ -2003,7 +2003,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
20032003 _ = try parent_gz.addBreak(break_tag, block_inst, .void_value);
20042004 },
20052005 else => {
2006 _ = try parent_gz.addBreak(break_tag, block_inst, operand);
2006 _ = try parent_gz.addBreakWithSrcNode(break_tag, block_inst, operand, rhs);
20072007 },
20082008 }
20092009 return Zir.Inst.Ref.unreachable_value;
......@@ -3754,7 +3754,7 @@ fn fnDecl(
37543754 defer param_gz.unstack();
37553755 const param_type = try expr(&param_gz, params_scope, coerced_type_ri, param_type_node);
37563756 const param_inst_expected = @intCast(u32, astgen.instructions.len + 1);
3757 _ = try param_gz.addBreak(.break_inline, param_inst_expected, param_type);
3757 _ = try param_gz.addBreakWithSrcNode(.break_inline, param_inst_expected, param_type, param_type_node);
37583758
37593759 const main_tokens = tree.nodes.items(.main_token);
37603760 const name_token = param.name_token orelse main_tokens[param_type_node];
......@@ -4114,7 +4114,7 @@ fn globalVarDecl(
41144114 };
41154115 // We do this at the end so that the instruction index marks the end
41164116 // range of a top level declaration.
4117 _ = try block_scope.addBreak(.break_inline, block_inst, var_inst);
4117 _ = try block_scope.addBreakWithSrcNode(.break_inline, block_inst, var_inst, node);
41184118 try block_scope.setBlockBody(block_inst);
41194119
41204120 {
......@@ -5456,7 +5456,9 @@ fn orelseCatchExpr(
54565456 condbr,
54575457 cond,
54585458 then_result,
5459 node,
54595460 else_result,
5461 rhs,
54605462 block,
54615463 block,
54625464 break_tag,
......@@ -5475,7 +5477,9 @@ fn finishThenElseBlock(
54755477 condbr: Zir.Inst.Index,
54765478 cond: Zir.Inst.Ref,
54775479 then_result: Zir.Inst.Ref,
5480 then_src_node: Ast.Node.Index,
54785481 else_result: Zir.Inst.Ref,
5482 else_src_node: Ast.Node.Index,
54795483 main_block: Zir.Inst.Index,
54805484 then_break_block: Zir.Inst.Index,
54815485 break_tag: Zir.Inst.Tag,
......@@ -5498,11 +5502,11 @@ fn finishThenElseBlock(
54985502 return indexToRef(main_block);
54995503 },
55005504 .break_operand => {
5501 const then_break = if (!then_no_return) try then_scope.makeBreak(break_tag, then_break_block, then_result) else 0;
5505 const then_break = if (!then_no_return) try then_scope.makeBreakWithSrcNode(break_tag, then_break_block, then_result, then_src_node) else 0;
55025506 const else_break = if (else_result == .none)
55035507 try else_scope.makeBreak(break_tag, main_block, .void_value)
55045508 else if (!else_no_return)
5505 try else_scope.makeBreak(break_tag, main_block, else_result)
5509 try else_scope.makeBreakWithSrcNode(break_tag, main_block, else_result, else_src_node)
55065510 else
55075511 0;
55085512
......@@ -5683,7 +5687,7 @@ fn boolBinOp(
56835687 defer rhs_scope.unstack();
56845688 const rhs = try expr(&rhs_scope, &rhs_scope.base, bool_ri, node_datas[node].rhs);
56855689 if (!gz.refIsNoReturn(rhs)) {
5686 _ = try rhs_scope.addBreak(.break_inline, bool_br, rhs);
5690 _ = try rhs_scope.addBreakWithSrcNode(.break_inline, bool_br, rhs, node_datas[node].rhs);
56875691 }
56885692 try rhs_scope.setBoolBrBody(bool_br);
56895693
......@@ -5758,6 +5762,7 @@ fn ifExpr(
57585762 var payload_val_scope: Scope.LocalVal = undefined;
57595763
57605764 try then_scope.addDbgBlockBegin();
5765 const then_node = if_full.ast.then_expr;
57615766 const then_sub_scope = s: {
57625767 if (if_full.error_token != null) {
57635768 if (if_full.payload_token) |payload_token| {
......@@ -5765,7 +5770,7 @@ fn ifExpr(
57655770 .err_union_payload_unsafe_ptr
57665771 else
57675772 .err_union_payload_unsafe;
5768 const payload_inst = try then_scope.addUnNode(tag, cond.inst, if_full.ast.then_expr);
5773 const payload_inst = try then_scope.addUnNode(tag, cond.inst, then_node);
57695774 const token_name_index = payload_token + @boolToInt(payload_is_ref);
57705775 const ident_name = try astgen.identAsString(token_name_index);
57715776 const token_name_str = tree.tokenSlice(token_name_index);
......@@ -5795,7 +5800,7 @@ fn ifExpr(
57955800 const ident_bytes = tree.tokenSlice(ident_token);
57965801 if (mem.eql(u8, "_", ident_bytes))
57975802 break :s &then_scope.base;
5798 const payload_inst = try then_scope.addUnNode(tag, cond.inst, if_full.ast.then_expr);
5803 const payload_inst = try then_scope.addUnNode(tag, cond.inst, then_node);
57995804 const ident_name = try astgen.identAsString(ident_token);
58005805 try astgen.detectLocalShadowing(&then_scope.base, ident_name, ident_token, ident_bytes, .capture);
58015806 payload_val_scope = .{
......@@ -5813,7 +5818,7 @@ fn ifExpr(
58135818 }
58145819 };
58155820
5816 const then_result = try expr(&then_scope, then_sub_scope, block_scope.break_result_info, if_full.ast.then_expr);
5821 const then_result = try expr(&then_scope, then_sub_scope, block_scope.break_result_info, then_node);
58175822 if (!then_scope.endsWithNoReturn()) {
58185823 block_scope.break_count += 1;
58195824 }
......@@ -5878,7 +5883,7 @@ fn ifExpr(
58785883 .result = e,
58795884 };
58805885 } else .{
5881 .src = if_full.ast.then_expr,
5886 .src = then_node,
58825887 .result = switch (ri.rl) {
58835888 // Explicitly store void to ptr result loc if there is no else branch
58845889 .ptr, .block_ptr => try rvalue(&else_scope, ri, .void_value, node),
......@@ -5897,7 +5902,9 @@ fn ifExpr(
58975902 condbr,
58985903 cond.bool_bit,
58995904 then_result,
5905 then_node,
59005906 else_info.result,
5907 else_info.src,
59015908 block,
59025909 block,
59035910 break_tag,
......@@ -6185,6 +6192,7 @@ fn whileExpr(
61856192 then_scope.instructions_top = then_scope.instructions.items.len;
61866193
61876194 try then_scope.addDbgBlockBegin();
6195 const then_node = while_full.ast.then_expr;
61886196 if (payload_inst != 0) try then_scope.instructions.append(astgen.gpa, payload_inst);
61896197 if (dbg_var_name) |name| try then_scope.addDbgVar(.dbg_var_val, name, dbg_var_inst);
61906198 try then_scope.instructions.append(astgen.gpa, continue_block);
......@@ -6198,7 +6206,7 @@ fn whileExpr(
61986206 try then_scope.addDbgBlockEnd();
61996207
62006208 continue_scope.instructions_top = continue_scope.instructions.items.len;
6201 _ = try unusedResultExpr(&continue_scope, &continue_scope.base, while_full.ast.then_expr);
6209 _ = try unusedResultExpr(&continue_scope, &continue_scope.base, then_node);
62026210 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);
62036211 const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break";
62046212 if (!continue_scope.endsWithNoReturn()) {
......@@ -6261,7 +6269,7 @@ fn whileExpr(
62616269 .result = else_result,
62626270 };
62636271 } else .{
6264 .src = while_full.ast.then_expr,
6272 .src = then_node,
62656273 .result = .none,
62666274 };
62676275
......@@ -6280,7 +6288,9 @@ fn whileExpr(
62806288 condbr,
62816289 cond.bool_bit,
62826290 .void_value,
6291 then_node,
62836292 else_info.result,
6293 else_info.src,
62846294 loop_block,
62856295 cond_block,
62866296 break_tag,
......@@ -6468,6 +6478,7 @@ fn forExpr(
64686478 });
64696479 }
64706480
6481 var then_node = for_full.ast.then_expr;
64716482 var then_scope = parent_gz.makeSubBlock(&cond_scope.base);
64726483 defer then_scope.unstack();
64736484
......@@ -6535,8 +6546,8 @@ fn forExpr(
65356546 break :blk capture_sub_scope;
65366547 };
65376548
6538 const then_result = try expr(&then_scope, then_sub_scope, .{ .rl = .none }, for_full.ast.then_expr);
6539 _ = try addEnsureResult(&then_scope, then_result, for_full.ast.then_expr);
6549 const then_result = try expr(&then_scope, then_sub_scope, .{ .rl = .none }, then_node);
6550 _ = try addEnsureResult(&then_scope, then_result, then_node);
65406551
65416552 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);
65426553 try then_scope.addDbgBlockEnd();
......@@ -6567,7 +6578,7 @@ fn forExpr(
65676578 .result = else_result,
65686579 };
65696580 } else .{
6570 .src = for_full.ast.then_expr,
6581 .src = then_node,
65716582 .result = .none,
65726583 };
65736584
......@@ -6587,7 +6598,9 @@ fn forExpr(
65876598 condbr,
65886599 cond,
65896600 then_result,
6601 then_node,
65906602 else_info.result,
6603 else_info.src,
65916604 loop_block,
65926605 cond_block,
65936606 break_tag,
......@@ -6949,12 +6962,13 @@ fn switchExpr(
69496962 if (dbg_var_tag_name) |some| {
69506963 try case_scope.addDbgVar(.dbg_var_val, some, dbg_var_tag_inst);
69516964 }
6952 const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_info, case.ast.target_expr);
6965 const target_expr_node = case.ast.target_expr;
6966 const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_info, target_expr_node);
69536967 try checkUsed(parent_gz, &case_scope.base, sub_scope);
69546968 try case_scope.addDbgBlockEnd();
69556969 if (!parent_gz.refIsNoReturn(case_result)) {
69566970 block_scope.break_count += 1;
6957 _ = try case_scope.addBreak(.@"break", switch_block, case_result);
6971 _ = try case_scope.addBreakWithSrcNode(.@"break", switch_block, case_result, target_expr_node);
69586972 }
69596973
69606974 const case_slice = case_scope.instructionsSlice();
......@@ -7057,10 +7071,12 @@ fn switchExpr(
70577071 .break_void => {
70587072 assert(!strat.elide_store_to_block_ptr_instructions);
70597073 const last_inst = payloads.items[end_index - 1];
7060 if (zir_tags[last_inst] == .@"break" and
7061 zir_datas[last_inst].@"break".block_inst == switch_block)
7062 {
7063 zir_datas[last_inst].@"break".operand = .void_value;
7074 if (zir_tags[last_inst] == .@"break") {
7075 const inst_data = zir_datas[last_inst].@"break";
7076 const block_inst = astgen.extra.items[inst_data.payload_index];
7077 if (block_inst == switch_block) {
7078 zir_datas[last_inst].@"break".operand = .void_value;
7079 }
70647080 }
70657081 },
70667082 }
......@@ -8856,7 +8872,7 @@ fn callExpr(
88568872 // `call_inst` is reused to provide the param type.
88578873 arg_block.rl_ty_inst = call_inst;
88588874 const arg_ref = try expr(&arg_block, &arg_block.base, .{ .rl = .{ .coerced_ty = call_inst }, .ctx = .fn_arg }, param_node);
8859 _ = try arg_block.addBreak(.break_inline, call_index, arg_ref);
8875 _ = try arg_block.addBreakWithSrcNode(.break_inline, call_index, arg_ref, param_node);
88608876
88618877 const body = arg_block.instructionsSlice();
88628878 try astgen.scratch.ensureUnusedCapacity(astgen.gpa, countBodyLenAfterFixups(astgen, body));
......@@ -11262,35 +11278,40 @@ const GenZir = struct {
1126211278 if (align_body.len != 0) {
1126311279 astgen.extra.appendAssumeCapacity(countBodyLenAfterFixups(astgen, align_body));
1126411280 astgen.appendBodyWithFixups(align_body);
11265 zir_datas[align_body[align_body.len - 1]].@"break".block_inst = new_index;
11281 const inst_data = zir_datas[align_body[align_body.len - 1]].@"break";
11282 astgen.extra.items[inst_data.payload_index] = new_index;
1126611283 } else if (args.align_ref != .none) {
1126711284 astgen.extra.appendAssumeCapacity(@enumToInt(args.align_ref));
1126811285 }
1126911286 if (addrspace_body.len != 0) {
1127011287 astgen.extra.appendAssumeCapacity(countBodyLenAfterFixups(astgen, addrspace_body));
1127111288 astgen.appendBodyWithFixups(addrspace_body);
11272 zir_datas[addrspace_body[addrspace_body.len - 1]].@"break".block_inst = new_index;
11289 const inst_data = zir_datas[addrspace_body[addrspace_body.len - 1]].@"break";
11290 astgen.extra.items[inst_data.payload_index] = new_index;
1127311291 } else if (args.addrspace_ref != .none) {
1127411292 astgen.extra.appendAssumeCapacity(@enumToInt(args.addrspace_ref));
1127511293 }
1127611294 if (section_body.len != 0) {
1127711295 astgen.extra.appendAssumeCapacity(countBodyLenAfterFixups(astgen, section_body));
1127811296 astgen.appendBodyWithFixups(section_body);
11279 zir_datas[section_body[section_body.len - 1]].@"break".block_inst = new_index;
11297 const inst_data = zir_datas[section_body[section_body.len - 1]].@"break";
11298 astgen.extra.items[inst_data.payload_index] = new_index;
1128011299 } else if (args.section_ref != .none) {
1128111300 astgen.extra.appendAssumeCapacity(@enumToInt(args.section_ref));
1128211301 }
1128311302 if (cc_body.len != 0) {
1128411303 astgen.extra.appendAssumeCapacity(countBodyLenAfterFixups(astgen, cc_body));
1128511304 astgen.appendBodyWithFixups(cc_body);
11286 zir_datas[cc_body[cc_body.len - 1]].@"break".block_inst = new_index;
11305 const inst_data = zir_datas[cc_body[cc_body.len - 1]].@"break";
11306 astgen.extra.items[inst_data.payload_index] = new_index;
1128711307 } else if (args.cc_ref != .none) {
1128811308 astgen.extra.appendAssumeCapacity(@enumToInt(args.cc_ref));
1128911309 }
1129011310 if (ret_body.len != 0) {
1129111311 astgen.extra.appendAssumeCapacity(countBodyLenAfterFixups(astgen, ret_body));
1129211312 astgen.appendBodyWithFixups(ret_body);
11293 zir_datas[ret_body[ret_body.len - 1]].@"break".block_inst = new_index;
11313 const inst_data = zir_datas[ret_body[ret_body.len - 1]].@"break";
11314 astgen.extra.items[inst_data.payload_index] = new_index;
1129411315 } else if (ret_ref != .none) {
1129511316 astgen.extra.appendAssumeCapacity(@enumToInt(ret_ref));
1129611317 }
......@@ -11344,7 +11365,9 @@ const GenZir = struct {
1134411365 const zir_datas = astgen.instructions.items(.data);
1134511366 if (ret_body.len != 0) {
1134611367 astgen.appendBodyWithFixups(ret_body);
11347 zir_datas[ret_body[ret_body.len - 1]].@"break".block_inst = new_index;
11368
11369 const inst_data = zir_datas[ret_body[ret_body.len - 1]].@"break";
11370 astgen.extra.items[inst_data.payload_index] = new_index;
1134811371 } else if (ret_ref != .none) {
1134911372 astgen.extra.appendAssumeCapacity(@enumToInt(ret_ref));
1135011373 }
......@@ -11790,30 +11813,104 @@ const GenZir = struct {
1179011813 fn addBreak(
1179111814 gz: *GenZir,
1179211815 tag: Zir.Inst.Tag,
11793 break_block: Zir.Inst.Index,
11816 block_inst: Zir.Inst.Index,
1179411817 operand: Zir.Inst.Ref,
1179511818 ) !Zir.Inst.Index {
11796 return gz.addAsIndex(.{
11819 const gpa = gz.astgen.gpa;
11820 try gz.instructions.ensureUnusedCapacity(gpa, 1);
11821 try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1);
11822
11823 const extra: Zir.Inst.Break = .{
11824 .block_inst = block_inst,
11825 .operand_src_node = Zir.Inst.Break.no_src_node,
11826 };
11827 const payload_index = try gz.astgen.addExtra(extra);
11828 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
11829 gz.astgen.instructions.appendAssumeCapacity(.{
1179711830 .tag = tag,
1179811831 .data = .{ .@"break" = .{
11799 .block_inst = break_block,
1180011832 .operand = operand,
11833 .payload_index = payload_index,
1180111834 } },
1180211835 });
11836 gz.instructions.appendAssumeCapacity(new_index);
11837 return new_index;
1180311838 }
1180411839
1180511840 fn makeBreak(
1180611841 gz: *GenZir,
1180711842 tag: Zir.Inst.Tag,
11808 break_block: Zir.Inst.Index,
11843 block_inst: Zir.Inst.Index,
1180911844 operand: Zir.Inst.Ref,
1181011845 ) !Zir.Inst.Index {
11846 const gpa = gz.astgen.gpa;
11847 try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1);
11848
11849 const extra: Zir.Inst.Break = .{
11850 .block_inst = block_inst,
11851 .operand_src_node = Zir.Inst.Break.no_src_node,
11852 };
11853 const payload_index = try gz.astgen.addExtra(extra);
1181111854 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
11812 try gz.astgen.instructions.append(gz.astgen.gpa, .{
11855 gz.astgen.instructions.appendAssumeCapacity(.{
1181311856 .tag = tag,
1181411857 .data = .{ .@"break" = .{
11815 .block_inst = break_block,
1181611858 .operand = operand,
11859 .payload_index = payload_index,
11860 } },
11861 });
11862 return new_index;
11863 }
11864
11865 fn addBreakWithSrcNode(
11866 gz: *GenZir,
11867 tag: Zir.Inst.Tag,
11868 block_inst: Zir.Inst.Index,
11869 operand: Zir.Inst.Ref,
11870 operand_src_node: Ast.Node.Index,
11871 ) !Zir.Inst.Index {
11872 const gpa = gz.astgen.gpa;
11873 try gz.instructions.ensureUnusedCapacity(gpa, 1);
11874 try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1);
11875
11876 const extra: Zir.Inst.Break = .{
11877 .block_inst = block_inst,
11878 .operand_src_node = gz.nodeIndexToRelative(operand_src_node),
11879 };
11880 const payload_index = try gz.astgen.addExtra(extra);
11881 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
11882 gz.astgen.instructions.appendAssumeCapacity(.{
11883 .tag = tag,
11884 .data = .{ .@"break" = .{
11885 .operand = operand,
11886 .payload_index = payload_index,
11887 } },
11888 });
11889 gz.instructions.appendAssumeCapacity(new_index);
11890 return new_index;
11891 }
11892
11893 fn makeBreakWithSrcNode(
11894 gz: *GenZir,
11895 tag: Zir.Inst.Tag,
11896 block_inst: Zir.Inst.Index,
11897 operand: Zir.Inst.Ref,
11898 operand_src_node: Ast.Node.Index,
11899 ) !Zir.Inst.Index {
11900 const gpa = gz.astgen.gpa;
11901 try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1);
11902
11903 const extra: Zir.Inst.Break = .{
11904 .block_inst = block_inst,
11905 .operand_src_node = gz.nodeIndexToRelative(operand_src_node),
11906 };
11907 const payload_index = try gz.astgen.addExtra(extra);
11908 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
11909 gz.astgen.instructions.appendAssumeCapacity(.{
11910 .tag = tag,
11911 .data = .{ .@"break" = .{
11912 .operand = operand,
11913 .payload_index = payload_index,
1181711914 } },
1181811915 });
1181911916 return new_index;
src/Module.zig+1-1
......@@ -5949,7 +5949,7 @@ pub const PeerTypeCandidateSrc = union(enum) {
59495949 none: void,
59505950 /// When we want to know the the src of candidate i, look up at
59515951 /// index i in this slice
5952 override: []LazySrcLoc,
5952 override: []?LazySrcLoc,
59535953 /// resolvePeerTypes originates from a @TypeOf(...) call
59545954 typeof_builtin_call_node_offset: i32,
59555955
src/Sema.zig+47-28
......@@ -349,6 +349,16 @@ pub const Block = struct {
349349 /// if we need to add type coercion at the end of block analysis.
350350 /// Same indexes, capacity, length as `results`.
351351 br_list: std.ArrayListUnmanaged(Air.Inst.Index),
352 /// Keeps the source location of the rhs operand of the break instruction,
353 /// to enable more precise compile errors.
354 /// Same indexes, capacity, length as `results`.
355 src_locs: std.ArrayListUnmanaged(?LazySrcLoc),
356
357 pub fn deinit(merges: *@This(), allocator: mem.Allocator) void {
358 merges.results.deinit(allocator);
359 merges.br_list.deinit(allocator);
360 merges.src_locs.deinit(allocator);
361 }
352362 };
353363
354364 /// For debugging purposes.
......@@ -722,8 +732,7 @@ const LabeledBlock = struct {
722732
723733 fn destroy(lb: *LabeledBlock, gpa: Allocator) void {
724734 lb.block.instructions.deinit(gpa);
725 lb.label.merges.results.deinit(gpa);
726 lb.label.merges.br_list.deinit(gpa);
735 lb.label.merges.deinit(gpa);
727736 gpa.destroy(lb);
728737 }
729738};
......@@ -777,8 +786,9 @@ fn analyzeBodyRuntimeBreak(sema: *Sema, block: *Block, body: []const Zir.Inst.In
777786 error.ComptimeBreak => {
778787 const zir_datas = sema.code.instructions.items(.data);
779788 const break_data = zir_datas[sema.comptime_break_inst].@"break";
789 const extra = sema.code.extraData(Zir.Inst.Break, break_data.payload_index).data;
780790 try sema.addRuntimeBreak(block, .{
781 .block_inst = break_data.block_inst,
791 .block_inst = extra.block_inst,
782792 .operand = break_data.operand,
783793 .inst = sema.comptime_break_inst,
784794 });
......@@ -817,8 +827,9 @@ pub fn analyzeBodyBreak(
817827 sema.typeOf(Air.indexToRef(block.instructions.items[block.instructions.items.len - 1])).isNoReturn())
818828 return null;
819829 const break_data = sema.code.instructions.items(.data)[break_inst].@"break";
830 const extra = sema.code.extraData(Zir.Inst.Break, break_data.payload_index).data;
820831 return BreakData{
821 .block_inst = break_data.block_inst,
832 .block_inst = extra.block_inst,
822833 .operand = break_data.operand,
823834 .inst = break_inst,
824835 };
......@@ -5238,6 +5249,7 @@ fn zirLoop(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError
52385249 var label: Block.Label = .{
52395250 .zir_block = inst,
52405251 .merges = .{
5252 .src_locs = .{},
52415253 .results = .{},
52425254 .br_list = .{},
52435255 .block_inst = block_inst,
......@@ -5251,8 +5263,7 @@ fn zirLoop(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError
52515263 const merges = &child_block.label.?.merges;
52525264
52535265 defer child_block.instructions.deinit(gpa);
5254 defer merges.results.deinit(gpa);
5255 defer merges.br_list.deinit(gpa);
5266 defer merges.deinit(gpa);
52565267
52575268 var loop_block = child_block.makeSubBlock();
52585269 defer loop_block.instructions.deinit(gpa);
......@@ -5422,6 +5433,7 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErro
54225433 var label: Block.Label = .{
54235434 .zir_block = inst,
54245435 .merges = .{
5436 .src_locs = .{},
54255437 .results = .{},
54265438 .br_list = .{},
54275439 .block_inst = block_inst,
......@@ -5450,8 +5462,7 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErro
54505462 };
54515463
54525464 defer child_block.instructions.deinit(gpa);
5453 defer label.merges.results.deinit(gpa);
5454 defer label.merges.br_list.deinit(gpa);
5465 defer label.merges.deinit(gpa);
54555466
54565467 return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
54575468}
......@@ -5480,7 +5491,8 @@ fn resolveBlockBody(
54805491
54815492 const break_inst = sema.comptime_break_inst;
54825493 const break_data = sema.code.instructions.items(.data)[break_inst].@"break";
5483 if (break_data.block_inst == body_inst) {
5494 const extra = sema.code.extraData(Zir.Inst.Break, break_data.payload_index).data;
5495 if (extra.block_inst == body_inst) {
54845496 return try sema.resolveInst(break_data.operand);
54855497 } else {
54865498 return error.ComptimeBreak;
......@@ -5533,7 +5545,7 @@ fn analyzeBlockBody(
55335545 // Need to set the type and emit the Block instruction. This allows machine code generation
55345546 // to emit a jump instruction to after the block when it encounters the break.
55355547 try parent_block.instructions.append(gpa, merges.block_inst);
5536 const resolved_ty = try sema.resolvePeerTypes(parent_block, src, merges.results.items, .none);
5548 const resolved_ty = try sema.resolvePeerTypes(parent_block, src, merges.results.items, .{ .override = merges.src_locs.items });
55375549 // TODO add note "missing else causes void value"
55385550
55395551 const type_src = src; // TODO: better source location
......@@ -5842,14 +5854,20 @@ fn zirBreak(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) CompileError
58425854 defer tracy.end();
58435855
58445856 const inst_data = sema.code.instructions.items(.data)[inst].@"break";
5857 const extra = sema.code.extraData(Zir.Inst.Break, inst_data.payload_index).data;
58455858 const operand = try sema.resolveInst(inst_data.operand);
5846 const zir_block = inst_data.block_inst;
5859 const zir_block = extra.block_inst;
58475860
58485861 var block = start_block;
58495862 while (true) {
58505863 if (block.label) |label| {
58515864 if (label.zir_block == zir_block) {
58525865 const br_ref = try start_block.addBr(label.merges.block_inst, operand);
5866 const src_loc = if (extra.operand_src_node != Zir.Inst.Break.no_src_node)
5867 LazySrcLoc.nodeOffset(extra.operand_src_node)
5868 else
5869 null;
5870 try label.merges.src_locs.append(sema.gpa, src_loc);
58535871 try label.merges.results.append(sema.gpa, operand);
58545872 try label.merges.br_list.append(sema.gpa, Air.refToIndex(br_ref).?);
58555873 block.runtime_index.increment();
......@@ -6643,6 +6661,7 @@ fn analyzeCall(
66436661 .func = null,
66446662 .comptime_result = undefined,
66456663 .merges = .{
6664 .src_locs = .{},
66466665 .results = .{},
66476666 .br_list = .{},
66486667 .block_inst = block_inst,
......@@ -6692,8 +6711,7 @@ fn analyzeCall(
66926711 const merges = &child_block.inlining.?.merges;
66936712
66946713 defer child_block.instructions.deinit(gpa);
6695 defer merges.results.deinit(gpa);
6696 defer merges.br_list.deinit(gpa);
6714 defer merges.deinit(gpa);
66976715
66986716 // If it's a comptime function call, we need to memoize it as long as no external
66996717 // comptime memory is mutated.
......@@ -10780,6 +10798,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1078010798 var label: Block.Label = .{
1078110799 .zir_block = inst,
1078210800 .merges = .{
10801 .src_locs = .{},
1078310802 .results = .{},
1078410803 .br_list = .{},
1078510804 .block_inst = block_inst,
......@@ -10807,8 +10826,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1080710826 };
1080810827 const merges = &child_block.label.?.merges;
1080910828 defer child_block.instructions.deinit(gpa);
10810 defer merges.results.deinit(gpa);
10811 defer merges.br_list.deinit(gpa);
10829 defer merges.deinit(gpa);
1081210830
1081310831 if (try sema.resolveDefinedValue(&child_block, src, operand)) |operand_val| {
1081410832 var extra_index: usize = special.end;
......@@ -12298,7 +12316,7 @@ fn zirBitwise(
1229812316 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
1229912317
1230012318 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
12301 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]LazySrcLoc{ lhs_src, rhs_src } });
12319 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]?LazySrcLoc{ lhs_src, rhs_src } });
1230212320 const scalar_type = resolved_type.scalarType();
1230312321 const scalar_tag = scalar_type.zigTypeTag();
1230412322
......@@ -12502,7 +12520,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1250212520 try trash_block.addBitCast(rhs_info.elem_type, .void_value),
1250312521 };
1250412522 break :t try sema.resolvePeerTypes(block, src, &instructions, .{
12505 .override = &[_]LazySrcLoc{ lhs_src, rhs_src },
12523 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
1250612524 });
1250712525 };
1250812526
......@@ -13002,7 +13020,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1300213020
1300313021 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
1300413022 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{
13005 .override = &[_]LazySrcLoc{ lhs_src, rhs_src },
13023 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
1300613024 });
1300713025
1300813026 const is_vector = resolved_type.zigTypeTag() == .Vector;
......@@ -13162,7 +13180,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1316213180
1316313181 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
1316413182 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{
13165 .override = &[_]LazySrcLoc{ lhs_src, rhs_src },
13183 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
1316613184 });
1316713185
1316813186 const is_vector = resolved_type.zigTypeTag() == .Vector;
......@@ -13325,7 +13343,7 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1332513343
1332613344 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
1332713345 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{
13328 .override = &[_]LazySrcLoc{ lhs_src, rhs_src },
13346 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
1332913347 });
1333013348
1333113349 const is_vector = resolved_type.zigTypeTag() == .Vector;
......@@ -13441,7 +13459,7 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1344113459
1344213460 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
1344313461 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{
13444 .override = &[_]LazySrcLoc{ lhs_src, rhs_src },
13462 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
1344513463 });
1344613464
1344713465 const is_vector = resolved_type.zigTypeTag() == .Vector;
......@@ -13683,7 +13701,7 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
1368313701
1368413702 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
1368513703 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{
13686 .override = &[_]LazySrcLoc{ lhs_src, rhs_src },
13704 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
1368713705 });
1368813706
1368913707 const is_vector = resolved_type.zigTypeTag() == .Vector;
......@@ -13866,7 +13884,7 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1386613884
1386713885 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
1386813886 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{
13869 .override = &[_]LazySrcLoc{ lhs_src, rhs_src },
13887 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
1387013888 });
1387113889
1387213890 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
......@@ -13968,7 +13986,7 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1396813986
1396913987 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
1397013988 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{
13971 .override = &[_]LazySrcLoc{ lhs_src, rhs_src },
13989 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
1397213990 });
1397313991
1397413992 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
......@@ -14081,7 +14099,7 @@ fn zirOverflowArithmetic(
1408114099 lhs_ty
1408214100 else
1408314101 try sema.resolvePeerTypes(block, src, instructions, .{
14084 .override = &[_]LazySrcLoc{ lhs_src, rhs_src },
14102 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
1408514103 });
1408614104
1408714105 const rhs_dest_ty = if (zir_tag == .shl_with_overflow)
......@@ -14312,7 +14330,7 @@ fn analyzeArithmetic(
1431214330
1431314331 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
1431414332 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{
14315 .override = &[_]LazySrcLoc{ lhs_src, rhs_src },
14333 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
1431614334 });
1431714335
1431814336 const is_vector = resolved_type.zigTypeTag() == .Vector;
......@@ -15200,7 +15218,7 @@ fn analyzeCmp(
1520015218 return sema.cmpSelf(block, src, lhs, casted_rhs, op, lhs_src, rhs_src);
1520115219 }
1520215220 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
15203 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]LazySrcLoc{ lhs_src, rhs_src } });
15221 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]?LazySrcLoc{ lhs_src, rhs_src } });
1520415222 if (!resolved_type.isSelfComparable(is_equality_cmp)) {
1520515223 return sema.fail(block, src, "operator {s} not allowed for type '{}'", .{
1520615224 compareOperatorName(op), resolved_type.fmt(sema.mod),
......@@ -17024,6 +17042,7 @@ fn addRuntimeBreak(sema: *Sema, child_block: *Block, break_data: BreakData) !voi
1702417042 .label = .{
1702517043 .zir_block = break_data.block_inst,
1702617044 .merges = .{
17045 .src_locs = .{},
1702717046 .results = .{},
1702817047 .br_list = .{},
1702917048 .block_inst = new_block_inst,
......@@ -20605,7 +20624,7 @@ fn checkSimdBinOp(
2060520624 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
2060620625 var vec_len: ?usize = if (lhs_ty.zigTypeTag() == .Vector) lhs_ty.vectorLen() else null;
2060720626 const result_ty = try sema.resolvePeerTypes(block, src, &.{ uncasted_lhs, uncasted_rhs }, .{
20608 .override = &[_]LazySrcLoc{ lhs_src, rhs_src },
20627 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
2060920628 });
2061020629 const lhs = try sema.coerce(block, result_ty, uncasted_lhs, lhs_src);
2061120630 const rhs = try sema.coerce(block, result_ty, uncasted_rhs, rhs_src);
src/Zir.zig+8-1
......@@ -2603,8 +2603,8 @@ pub const Inst = struct {
26032603 }
26042604 },
26052605 @"break": struct {
2606 block_inst: Index,
26072606 operand: Ref,
2607 payload_index: u32,
26082608 },
26092609 switch_capture: struct {
26102610 switch_inst: Index,
......@@ -2690,6 +2690,13 @@ pub const Inst = struct {
26902690 };
26912691 };
26922692
2693 pub const Break = struct {
2694 pub const no_src_node = std.math.maxInt(i32);
2695
2696 block_inst: Index,
2697 operand_src_node: i32,
2698 };
2699
26932700 /// Trailing:
26942701 /// 0. Output for every outputs_len
26952702 /// 1. Input for every inputs_len
src/print_zir.zig+2-1
......@@ -2321,8 +2321,9 @@ const Writer = struct {
23212321
23222322 fn writeBreak(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
23232323 const inst_data = self.code.instructions.items(.data)[inst].@"break";
2324 const extra = self.code.extraData(Zir.Inst.Break, inst_data.payload_index).data;
23242325
2325 try self.writeInstIndex(stream, inst_data.block_inst);
2326 try self.writeInstIndex(stream, extra.block_inst);
23262327 try stream.writeAll(", ");
23272328 try self.writeInstRef(stream, inst_data.operand);
23282329 try stream.writeAll(")");
test/cases/compile_errors/incompatible sub-byte fields.zig +2
......@@ -25,3 +25,5 @@ export fn entry() void {
2525// target=native
2626//
2727// :14:17: error: incompatible types: '*align(1:0:1) u2' and '*align(2:8:2) u2'
28// :15:14: note: type '*align(1:0:1) u2' here
29// :16:14: note: type '*align(2:8:2) u2' here
test/cases/compile_errors/missing_else_clause.zig+2
......@@ -31,7 +31,9 @@ export fn entry() void {
3131// target=native
3232//
3333// :2:21: error: incompatible types: 'i32' and 'void'
34// :6:25: note: type 'i32' here
3435// :6:15: error: incompatible types: 'i32' and 'void'
36// :2:31: note: type 'i32' here
3537// :12:16: error: expected type 'tmp.h.T', found 'void'
3638// :11:15: note: struct declared here
3739// :18:9: error: incompatible types: 'void' and 'tmp.k.T'
test/cases/compile_errors/missing_result_type_for_phi_node.zig+2
......@@ -10,3 +10,5 @@ export fn entry() void {
1010// target=native
1111//
1212// :5:11: error: incompatible types: 'void' and 'comptime_int'
13// :5:11: note: type 'void' here
14// :5:17: note: type 'comptime_int' here
test/cases/compile_errors/unused_value_in_switch_in_loop.zig+2
......@@ -12,3 +12,5 @@ export fn entry() void {
1212// target=native
1313//
1414// :3:18: error: incompatible types: 'comptime_int' and 'void'
15// :4:14: note: type 'comptime_int' here
16// :5:16: note: type 'void' here