diff --git a/src/AstGen.zig b/src/AstGen.zig index 182a28084f..c91303cdb1 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -1280,7 +1280,7 @@ fn fnProtoExpr( defer param_gz.unstack(); const param_type = try expr(¶m_gz, scope, coerced_type_ri, param_type_node); const param_inst_expected = @intCast(u32, astgen.instructions.len + 1); - _ = try param_gz.addBreak(.break_inline, param_inst_expected, param_type); + _ = try param_gz.addBreakWithSrcNode(.break_inline, param_inst_expected, param_type, param_type_node); const main_tokens = tree.nodes.items(.main_token); const name_token = param.name_token orelse main_tokens[param_type_node]; 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 switch (block_gz.break_result_info.rl) { .block_ptr => { - const br = try parent_gz.addBreak(break_tag, block_inst, operand); + const br = try parent_gz.addBreakWithSrcNode(break_tag, block_inst, operand, rhs); try block_gz.labeled_breaks.append(astgen.gpa, .{ .br = br, .search = search_index }); }, .ptr => { @@ -2003,7 +2003,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn _ = try parent_gz.addBreak(break_tag, block_inst, .void_value); }, else => { - _ = try parent_gz.addBreak(break_tag, block_inst, operand); + _ = try parent_gz.addBreakWithSrcNode(break_tag, block_inst, operand, rhs); }, } return Zir.Inst.Ref.unreachable_value; @@ -3754,7 +3754,7 @@ fn fnDecl( defer param_gz.unstack(); const param_type = try expr(¶m_gz, params_scope, coerced_type_ri, param_type_node); const param_inst_expected = @intCast(u32, astgen.instructions.len + 1); - _ = try param_gz.addBreak(.break_inline, param_inst_expected, param_type); + _ = try param_gz.addBreakWithSrcNode(.break_inline, param_inst_expected, param_type, param_type_node); const main_tokens = tree.nodes.items(.main_token); const name_token = param.name_token orelse main_tokens[param_type_node]; @@ -4114,7 +4114,7 @@ fn globalVarDecl( }; // We do this at the end so that the instruction index marks the end // range of a top level declaration. - _ = try block_scope.addBreak(.break_inline, block_inst, var_inst); + _ = try block_scope.addBreakWithSrcNode(.break_inline, block_inst, var_inst, node); try block_scope.setBlockBody(block_inst); { @@ -5456,7 +5456,9 @@ fn orelseCatchExpr( condbr, cond, then_result, + node, else_result, + rhs, block, block, break_tag, @@ -5475,7 +5477,9 @@ fn finishThenElseBlock( condbr: Zir.Inst.Index, cond: Zir.Inst.Ref, then_result: Zir.Inst.Ref, + then_src_node: Ast.Node.Index, else_result: Zir.Inst.Ref, + else_src_node: Ast.Node.Index, main_block: Zir.Inst.Index, then_break_block: Zir.Inst.Index, break_tag: Zir.Inst.Tag, @@ -5498,11 +5502,11 @@ fn finishThenElseBlock( return indexToRef(main_block); }, .break_operand => { - const then_break = if (!then_no_return) try then_scope.makeBreak(break_tag, then_break_block, then_result) else 0; + const then_break = if (!then_no_return) try then_scope.makeBreakWithSrcNode(break_tag, then_break_block, then_result, then_src_node) else 0; const else_break = if (else_result == .none) try else_scope.makeBreak(break_tag, main_block, .void_value) else if (!else_no_return) - try else_scope.makeBreak(break_tag, main_block, else_result) + try else_scope.makeBreakWithSrcNode(break_tag, main_block, else_result, else_src_node) else 0; @@ -5683,7 +5687,7 @@ fn boolBinOp( defer rhs_scope.unstack(); const rhs = try expr(&rhs_scope, &rhs_scope.base, bool_ri, node_datas[node].rhs); if (!gz.refIsNoReturn(rhs)) { - _ = try rhs_scope.addBreak(.break_inline, bool_br, rhs); + _ = try rhs_scope.addBreakWithSrcNode(.break_inline, bool_br, rhs, node_datas[node].rhs); } try rhs_scope.setBoolBrBody(bool_br); @@ -5758,6 +5762,7 @@ fn ifExpr( var payload_val_scope: Scope.LocalVal = undefined; try then_scope.addDbgBlockBegin(); + const then_node = if_full.ast.then_expr; const then_sub_scope = s: { if (if_full.error_token != null) { if (if_full.payload_token) |payload_token| { @@ -5765,7 +5770,7 @@ fn ifExpr( .err_union_payload_unsafe_ptr else .err_union_payload_unsafe; - const payload_inst = try then_scope.addUnNode(tag, cond.inst, if_full.ast.then_expr); + const payload_inst = try then_scope.addUnNode(tag, cond.inst, then_node); const token_name_index = payload_token + @boolToInt(payload_is_ref); const ident_name = try astgen.identAsString(token_name_index); const token_name_str = tree.tokenSlice(token_name_index); @@ -5795,7 +5800,7 @@ fn ifExpr( const ident_bytes = tree.tokenSlice(ident_token); if (mem.eql(u8, "_", ident_bytes)) break :s &then_scope.base; - const payload_inst = try then_scope.addUnNode(tag, cond.inst, if_full.ast.then_expr); + const payload_inst = try then_scope.addUnNode(tag, cond.inst, then_node); const ident_name = try astgen.identAsString(ident_token); try astgen.detectLocalShadowing(&then_scope.base, ident_name, ident_token, ident_bytes, .capture); payload_val_scope = .{ @@ -5813,7 +5818,7 @@ fn ifExpr( } }; - const then_result = try expr(&then_scope, then_sub_scope, block_scope.break_result_info, if_full.ast.then_expr); + const then_result = try expr(&then_scope, then_sub_scope, block_scope.break_result_info, then_node); if (!then_scope.endsWithNoReturn()) { block_scope.break_count += 1; } @@ -5878,7 +5883,7 @@ fn ifExpr( .result = e, }; } else .{ - .src = if_full.ast.then_expr, + .src = then_node, .result = switch (ri.rl) { // Explicitly store void to ptr result loc if there is no else branch .ptr, .block_ptr => try rvalue(&else_scope, ri, .void_value, node), @@ -5897,7 +5902,9 @@ fn ifExpr( condbr, cond.bool_bit, then_result, + then_node, else_info.result, + else_info.src, block, block, break_tag, @@ -6185,6 +6192,7 @@ fn whileExpr( then_scope.instructions_top = then_scope.instructions.items.len; try then_scope.addDbgBlockBegin(); + const then_node = while_full.ast.then_expr; if (payload_inst != 0) try then_scope.instructions.append(astgen.gpa, payload_inst); if (dbg_var_name) |name| try then_scope.addDbgVar(.dbg_var_val, name, dbg_var_inst); try then_scope.instructions.append(astgen.gpa, continue_block); @@ -6198,7 +6206,7 @@ fn whileExpr( try then_scope.addDbgBlockEnd(); continue_scope.instructions_top = continue_scope.instructions.items.len; - _ = try unusedResultExpr(&continue_scope, &continue_scope.base, while_full.ast.then_expr); + _ = try unusedResultExpr(&continue_scope, &continue_scope.base, then_node); try checkUsed(parent_gz, &then_scope.base, then_sub_scope); const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break"; if (!continue_scope.endsWithNoReturn()) { @@ -6261,7 +6269,7 @@ fn whileExpr( .result = else_result, }; } else .{ - .src = while_full.ast.then_expr, + .src = then_node, .result = .none, }; @@ -6280,7 +6288,9 @@ fn whileExpr( condbr, cond.bool_bit, .void_value, + then_node, else_info.result, + else_info.src, loop_block, cond_block, break_tag, @@ -6468,6 +6478,7 @@ fn forExpr( }); } + var then_node = for_full.ast.then_expr; var then_scope = parent_gz.makeSubBlock(&cond_scope.base); defer then_scope.unstack(); @@ -6535,8 +6546,8 @@ fn forExpr( break :blk capture_sub_scope; }; - const then_result = try expr(&then_scope, then_sub_scope, .{ .rl = .none }, for_full.ast.then_expr); - _ = try addEnsureResult(&then_scope, then_result, for_full.ast.then_expr); + const then_result = try expr(&then_scope, then_sub_scope, .{ .rl = .none }, then_node); + _ = try addEnsureResult(&then_scope, then_result, then_node); try checkUsed(parent_gz, &then_scope.base, then_sub_scope); try then_scope.addDbgBlockEnd(); @@ -6567,7 +6578,7 @@ fn forExpr( .result = else_result, }; } else .{ - .src = for_full.ast.then_expr, + .src = then_node, .result = .none, }; @@ -6587,7 +6598,9 @@ fn forExpr( condbr, cond, then_result, + then_node, else_info.result, + else_info.src, loop_block, cond_block, break_tag, @@ -6949,12 +6962,13 @@ fn switchExpr( if (dbg_var_tag_name) |some| { try case_scope.addDbgVar(.dbg_var_val, some, dbg_var_tag_inst); } - const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_info, case.ast.target_expr); + const target_expr_node = case.ast.target_expr; + const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_info, target_expr_node); try checkUsed(parent_gz, &case_scope.base, sub_scope); try case_scope.addDbgBlockEnd(); if (!parent_gz.refIsNoReturn(case_result)) { block_scope.break_count += 1; - _ = try case_scope.addBreak(.@"break", switch_block, case_result); + _ = try case_scope.addBreakWithSrcNode(.@"break", switch_block, case_result, target_expr_node); } const case_slice = case_scope.instructionsSlice(); @@ -7057,10 +7071,12 @@ fn switchExpr( .break_void => { assert(!strat.elide_store_to_block_ptr_instructions); const last_inst = payloads.items[end_index - 1]; - if (zir_tags[last_inst] == .@"break" and - zir_datas[last_inst].@"break".block_inst == switch_block) - { - zir_datas[last_inst].@"break".operand = .void_value; + if (zir_tags[last_inst] == .@"break") { + const inst_data = zir_datas[last_inst].@"break"; + const block_inst = astgen.extra.items[inst_data.payload_index]; + if (block_inst == switch_block) { + zir_datas[last_inst].@"break".operand = .void_value; + } } }, } @@ -8856,7 +8872,7 @@ fn callExpr( // `call_inst` is reused to provide the param type. arg_block.rl_ty_inst = call_inst; const arg_ref = try expr(&arg_block, &arg_block.base, .{ .rl = .{ .coerced_ty = call_inst }, .ctx = .fn_arg }, param_node); - _ = try arg_block.addBreak(.break_inline, call_index, arg_ref); + _ = try arg_block.addBreakWithSrcNode(.break_inline, call_index, arg_ref, param_node); const body = arg_block.instructionsSlice(); try astgen.scratch.ensureUnusedCapacity(astgen.gpa, countBodyLenAfterFixups(astgen, body)); @@ -11262,35 +11278,40 @@ const GenZir = struct { if (align_body.len != 0) { astgen.extra.appendAssumeCapacity(countBodyLenAfterFixups(astgen, align_body)); astgen.appendBodyWithFixups(align_body); - zir_datas[align_body[align_body.len - 1]].@"break".block_inst = new_index; + const inst_data = zir_datas[align_body[align_body.len - 1]].@"break"; + astgen.extra.items[inst_data.payload_index] = new_index; } else if (args.align_ref != .none) { astgen.extra.appendAssumeCapacity(@enumToInt(args.align_ref)); } if (addrspace_body.len != 0) { astgen.extra.appendAssumeCapacity(countBodyLenAfterFixups(astgen, addrspace_body)); astgen.appendBodyWithFixups(addrspace_body); - zir_datas[addrspace_body[addrspace_body.len - 1]].@"break".block_inst = new_index; + const inst_data = zir_datas[addrspace_body[addrspace_body.len - 1]].@"break"; + astgen.extra.items[inst_data.payload_index] = new_index; } else if (args.addrspace_ref != .none) { astgen.extra.appendAssumeCapacity(@enumToInt(args.addrspace_ref)); } if (section_body.len != 0) { astgen.extra.appendAssumeCapacity(countBodyLenAfterFixups(astgen, section_body)); astgen.appendBodyWithFixups(section_body); - zir_datas[section_body[section_body.len - 1]].@"break".block_inst = new_index; + const inst_data = zir_datas[section_body[section_body.len - 1]].@"break"; + astgen.extra.items[inst_data.payload_index] = new_index; } else if (args.section_ref != .none) { astgen.extra.appendAssumeCapacity(@enumToInt(args.section_ref)); } if (cc_body.len != 0) { astgen.extra.appendAssumeCapacity(countBodyLenAfterFixups(astgen, cc_body)); astgen.appendBodyWithFixups(cc_body); - zir_datas[cc_body[cc_body.len - 1]].@"break".block_inst = new_index; + const inst_data = zir_datas[cc_body[cc_body.len - 1]].@"break"; + astgen.extra.items[inst_data.payload_index] = new_index; } else if (args.cc_ref != .none) { astgen.extra.appendAssumeCapacity(@enumToInt(args.cc_ref)); } if (ret_body.len != 0) { astgen.extra.appendAssumeCapacity(countBodyLenAfterFixups(astgen, ret_body)); astgen.appendBodyWithFixups(ret_body); - zir_datas[ret_body[ret_body.len - 1]].@"break".block_inst = new_index; + const inst_data = zir_datas[ret_body[ret_body.len - 1]].@"break"; + astgen.extra.items[inst_data.payload_index] = new_index; } else if (ret_ref != .none) { astgen.extra.appendAssumeCapacity(@enumToInt(ret_ref)); } @@ -11344,7 +11365,9 @@ const GenZir = struct { const zir_datas = astgen.instructions.items(.data); if (ret_body.len != 0) { astgen.appendBodyWithFixups(ret_body); - zir_datas[ret_body[ret_body.len - 1]].@"break".block_inst = new_index; + + const inst_data = zir_datas[ret_body[ret_body.len - 1]].@"break"; + astgen.extra.items[inst_data.payload_index] = new_index; } else if (ret_ref != .none) { astgen.extra.appendAssumeCapacity(@enumToInt(ret_ref)); } @@ -11790,30 +11813,104 @@ const GenZir = struct { fn addBreak( gz: *GenZir, tag: Zir.Inst.Tag, - break_block: Zir.Inst.Index, + block_inst: Zir.Inst.Index, operand: Zir.Inst.Ref, ) !Zir.Inst.Index { - return gz.addAsIndex(.{ + const gpa = gz.astgen.gpa; + try gz.instructions.ensureUnusedCapacity(gpa, 1); + try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1); + + const extra: Zir.Inst.Break = .{ + .block_inst = block_inst, + .operand_src_node = Zir.Inst.Break.no_src_node, + }; + const payload_index = try gz.astgen.addExtra(extra); + const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len); + gz.astgen.instructions.appendAssumeCapacity(.{ .tag = tag, .data = .{ .@"break" = .{ - .block_inst = break_block, .operand = operand, + .payload_index = payload_index, } }, }); + gz.instructions.appendAssumeCapacity(new_index); + return new_index; } fn makeBreak( gz: *GenZir, tag: Zir.Inst.Tag, - break_block: Zir.Inst.Index, + block_inst: Zir.Inst.Index, operand: Zir.Inst.Ref, ) !Zir.Inst.Index { + const gpa = gz.astgen.gpa; + try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1); + + const extra: Zir.Inst.Break = .{ + .block_inst = block_inst, + .operand_src_node = Zir.Inst.Break.no_src_node, + }; + const payload_index = try gz.astgen.addExtra(extra); const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len); - try gz.astgen.instructions.append(gz.astgen.gpa, .{ + gz.astgen.instructions.appendAssumeCapacity(.{ .tag = tag, .data = .{ .@"break" = .{ - .block_inst = break_block, .operand = operand, + .payload_index = payload_index, + } }, + }); + return new_index; + } + + fn addBreakWithSrcNode( + gz: *GenZir, + tag: Zir.Inst.Tag, + block_inst: Zir.Inst.Index, + operand: Zir.Inst.Ref, + operand_src_node: Ast.Node.Index, + ) !Zir.Inst.Index { + const gpa = gz.astgen.gpa; + try gz.instructions.ensureUnusedCapacity(gpa, 1); + try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1); + + const extra: Zir.Inst.Break = .{ + .block_inst = block_inst, + .operand_src_node = gz.nodeIndexToRelative(operand_src_node), + }; + const payload_index = try gz.astgen.addExtra(extra); + const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len); + gz.astgen.instructions.appendAssumeCapacity(.{ + .tag = tag, + .data = .{ .@"break" = .{ + .operand = operand, + .payload_index = payload_index, + } }, + }); + gz.instructions.appendAssumeCapacity(new_index); + return new_index; + } + + fn makeBreakWithSrcNode( + gz: *GenZir, + tag: Zir.Inst.Tag, + block_inst: Zir.Inst.Index, + operand: Zir.Inst.Ref, + operand_src_node: Ast.Node.Index, + ) !Zir.Inst.Index { + const gpa = gz.astgen.gpa; + try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1); + + const extra: Zir.Inst.Break = .{ + .block_inst = block_inst, + .operand_src_node = gz.nodeIndexToRelative(operand_src_node), + }; + const payload_index = try gz.astgen.addExtra(extra); + const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len); + gz.astgen.instructions.appendAssumeCapacity(.{ + .tag = tag, + .data = .{ .@"break" = .{ + .operand = operand, + .payload_index = payload_index, } }, }); return new_index; diff --git a/src/Module.zig b/src/Module.zig index 17016865d1..906bde95c7 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -5949,7 +5949,7 @@ pub const PeerTypeCandidateSrc = union(enum) { none: void, /// When we want to know the the src of candidate i, look up at /// index i in this slice - override: []LazySrcLoc, + override: []?LazySrcLoc, /// resolvePeerTypes originates from a @TypeOf(...) call typeof_builtin_call_node_offset: i32, diff --git a/src/Sema.zig b/src/Sema.zig index d01535cdaa..13327657a8 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -349,6 +349,16 @@ pub const Block = struct { /// if we need to add type coercion at the end of block analysis. /// Same indexes, capacity, length as `results`. br_list: std.ArrayListUnmanaged(Air.Inst.Index), + /// Keeps the source location of the rhs operand of the break instruction, + /// to enable more precise compile errors. + /// Same indexes, capacity, length as `results`. + src_locs: std.ArrayListUnmanaged(?LazySrcLoc), + + pub fn deinit(merges: *@This(), allocator: mem.Allocator) void { + merges.results.deinit(allocator); + merges.br_list.deinit(allocator); + merges.src_locs.deinit(allocator); + } }; /// For debugging purposes. @@ -722,8 +732,7 @@ const LabeledBlock = struct { fn destroy(lb: *LabeledBlock, gpa: Allocator) void { lb.block.instructions.deinit(gpa); - lb.label.merges.results.deinit(gpa); - lb.label.merges.br_list.deinit(gpa); + lb.label.merges.deinit(gpa); gpa.destroy(lb); } }; @@ -777,8 +786,9 @@ fn analyzeBodyRuntimeBreak(sema: *Sema, block: *Block, body: []const Zir.Inst.In error.ComptimeBreak => { const zir_datas = sema.code.instructions.items(.data); const break_data = zir_datas[sema.comptime_break_inst].@"break"; + const extra = sema.code.extraData(Zir.Inst.Break, break_data.payload_index).data; try sema.addRuntimeBreak(block, .{ - .block_inst = break_data.block_inst, + .block_inst = extra.block_inst, .operand = break_data.operand, .inst = sema.comptime_break_inst, }); @@ -817,8 +827,9 @@ pub fn analyzeBodyBreak( sema.typeOf(Air.indexToRef(block.instructions.items[block.instructions.items.len - 1])).isNoReturn()) return null; const break_data = sema.code.instructions.items(.data)[break_inst].@"break"; + const extra = sema.code.extraData(Zir.Inst.Break, break_data.payload_index).data; return BreakData{ - .block_inst = break_data.block_inst, + .block_inst = extra.block_inst, .operand = break_data.operand, .inst = break_inst, }; @@ -5238,6 +5249,7 @@ fn zirLoop(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError var label: Block.Label = .{ .zir_block = inst, .merges = .{ + .src_locs = .{}, .results = .{}, .br_list = .{}, .block_inst = block_inst, @@ -5251,8 +5263,7 @@ fn zirLoop(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError const merges = &child_block.label.?.merges; defer child_block.instructions.deinit(gpa); - defer merges.results.deinit(gpa); - defer merges.br_list.deinit(gpa); + defer merges.deinit(gpa); var loop_block = child_block.makeSubBlock(); defer loop_block.instructions.deinit(gpa); @@ -5422,6 +5433,7 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErro var label: Block.Label = .{ .zir_block = inst, .merges = .{ + .src_locs = .{}, .results = .{}, .br_list = .{}, .block_inst = block_inst, @@ -5450,8 +5462,7 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErro }; defer child_block.instructions.deinit(gpa); - defer label.merges.results.deinit(gpa); - defer label.merges.br_list.deinit(gpa); + defer label.merges.deinit(gpa); return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges); } @@ -5480,7 +5491,8 @@ fn resolveBlockBody( const break_inst = sema.comptime_break_inst; const break_data = sema.code.instructions.items(.data)[break_inst].@"break"; - if (break_data.block_inst == body_inst) { + const extra = sema.code.extraData(Zir.Inst.Break, break_data.payload_index).data; + if (extra.block_inst == body_inst) { return try sema.resolveInst(break_data.operand); } else { return error.ComptimeBreak; @@ -5533,7 +5545,7 @@ fn analyzeBlockBody( // Need to set the type and emit the Block instruction. This allows machine code generation // to emit a jump instruction to after the block when it encounters the break. try parent_block.instructions.append(gpa, merges.block_inst); - const resolved_ty = try sema.resolvePeerTypes(parent_block, src, merges.results.items, .none); + const resolved_ty = try sema.resolvePeerTypes(parent_block, src, merges.results.items, .{ .override = merges.src_locs.items }); // TODO add note "missing else causes void value" const type_src = src; // TODO: better source location @@ -5842,14 +5854,20 @@ fn zirBreak(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) CompileError defer tracy.end(); const inst_data = sema.code.instructions.items(.data)[inst].@"break"; + const extra = sema.code.extraData(Zir.Inst.Break, inst_data.payload_index).data; const operand = try sema.resolveInst(inst_data.operand); - const zir_block = inst_data.block_inst; + const zir_block = extra.block_inst; var block = start_block; while (true) { if (block.label) |label| { if (label.zir_block == zir_block) { const br_ref = try start_block.addBr(label.merges.block_inst, operand); + const src_loc = if (extra.operand_src_node != Zir.Inst.Break.no_src_node) + LazySrcLoc.nodeOffset(extra.operand_src_node) + else + null; + try label.merges.src_locs.append(sema.gpa, src_loc); try label.merges.results.append(sema.gpa, operand); try label.merges.br_list.append(sema.gpa, Air.refToIndex(br_ref).?); block.runtime_index.increment(); @@ -6643,6 +6661,7 @@ fn analyzeCall( .func = null, .comptime_result = undefined, .merges = .{ + .src_locs = .{}, .results = .{}, .br_list = .{}, .block_inst = block_inst, @@ -6692,8 +6711,7 @@ fn analyzeCall( const merges = &child_block.inlining.?.merges; defer child_block.instructions.deinit(gpa); - defer merges.results.deinit(gpa); - defer merges.br_list.deinit(gpa); + defer merges.deinit(gpa); // If it's a comptime function call, we need to memoize it as long as no external // comptime memory is mutated. @@ -10780,6 +10798,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError var label: Block.Label = .{ .zir_block = inst, .merges = .{ + .src_locs = .{}, .results = .{}, .br_list = .{}, .block_inst = block_inst, @@ -10807,8 +10826,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError }; const merges = &child_block.label.?.merges; defer child_block.instructions.deinit(gpa); - defer merges.results.deinit(gpa); - defer merges.br_list.deinit(gpa); + defer merges.deinit(gpa); if (try sema.resolveDefinedValue(&child_block, src, operand)) |operand_val| { var extra_index: usize = special.end; @@ -12298,7 +12316,7 @@ fn zirBitwise( try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); const instructions = &[_]Air.Inst.Ref{ lhs, rhs }; - const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]LazySrcLoc{ lhs_src, rhs_src } }); + const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]?LazySrcLoc{ lhs_src, rhs_src } }); const scalar_type = resolved_type.scalarType(); const scalar_tag = scalar_type.zigTypeTag(); @@ -12502,7 +12520,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai try trash_block.addBitCast(rhs_info.elem_type, .void_value), }; break :t try sema.resolvePeerTypes(block, src, &instructions, .{ - .override = &[_]LazySrcLoc{ lhs_src, rhs_src }, + .override = &[_]?LazySrcLoc{ lhs_src, rhs_src }, }); }; @@ -13002,7 +13020,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins const instructions = &[_]Air.Inst.Ref{ lhs, rhs }; const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ - .override = &[_]LazySrcLoc{ lhs_src, rhs_src }, + .override = &[_]?LazySrcLoc{ lhs_src, rhs_src }, }); const is_vector = resolved_type.zigTypeTag() == .Vector; @@ -13162,7 +13180,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const instructions = &[_]Air.Inst.Ref{ lhs, rhs }; const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ - .override = &[_]LazySrcLoc{ lhs_src, rhs_src }, + .override = &[_]?LazySrcLoc{ lhs_src, rhs_src }, }); const is_vector = resolved_type.zigTypeTag() == .Vector; @@ -13325,7 +13343,7 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const instructions = &[_]Air.Inst.Ref{ lhs, rhs }; const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ - .override = &[_]LazySrcLoc{ lhs_src, rhs_src }, + .override = &[_]?LazySrcLoc{ lhs_src, rhs_src }, }); const is_vector = resolved_type.zigTypeTag() == .Vector; @@ -13441,7 +13459,7 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const instructions = &[_]Air.Inst.Ref{ lhs, rhs }; const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ - .override = &[_]LazySrcLoc{ lhs_src, rhs_src }, + .override = &[_]?LazySrcLoc{ lhs_src, rhs_src }, }); const is_vector = resolved_type.zigTypeTag() == .Vector; @@ -13683,7 +13701,7 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. const instructions = &[_]Air.Inst.Ref{ lhs, rhs }; const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ - .override = &[_]LazySrcLoc{ lhs_src, rhs_src }, + .override = &[_]?LazySrcLoc{ lhs_src, rhs_src }, }); const is_vector = resolved_type.zigTypeTag() == .Vector; @@ -13866,7 +13884,7 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins const instructions = &[_]Air.Inst.Ref{ lhs, rhs }; const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ - .override = &[_]LazySrcLoc{ lhs_src, rhs_src }, + .override = &[_]?LazySrcLoc{ lhs_src, rhs_src }, }); 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 const instructions = &[_]Air.Inst.Ref{ lhs, rhs }; const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ - .override = &[_]LazySrcLoc{ lhs_src, rhs_src }, + .override = &[_]?LazySrcLoc{ lhs_src, rhs_src }, }); const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); @@ -14081,7 +14099,7 @@ fn zirOverflowArithmetic( lhs_ty else try sema.resolvePeerTypes(block, src, instructions, .{ - .override = &[_]LazySrcLoc{ lhs_src, rhs_src }, + .override = &[_]?LazySrcLoc{ lhs_src, rhs_src }, }); const rhs_dest_ty = if (zir_tag == .shl_with_overflow) @@ -14312,7 +14330,7 @@ fn analyzeArithmetic( const instructions = &[_]Air.Inst.Ref{ lhs, rhs }; const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ - .override = &[_]LazySrcLoc{ lhs_src, rhs_src }, + .override = &[_]?LazySrcLoc{ lhs_src, rhs_src }, }); const is_vector = resolved_type.zigTypeTag() == .Vector; @@ -15200,7 +15218,7 @@ fn analyzeCmp( return sema.cmpSelf(block, src, lhs, casted_rhs, op, lhs_src, rhs_src); } const instructions = &[_]Air.Inst.Ref{ lhs, rhs }; - const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]LazySrcLoc{ lhs_src, rhs_src } }); + const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]?LazySrcLoc{ lhs_src, rhs_src } }); if (!resolved_type.isSelfComparable(is_equality_cmp)) { return sema.fail(block, src, "operator {s} not allowed for type '{}'", .{ compareOperatorName(op), resolved_type.fmt(sema.mod), @@ -17024,6 +17042,7 @@ fn addRuntimeBreak(sema: *Sema, child_block: *Block, break_data: BreakData) !voi .label = .{ .zir_block = break_data.block_inst, .merges = .{ + .src_locs = .{}, .results = .{}, .br_list = .{}, .block_inst = new_block_inst, @@ -20605,7 +20624,7 @@ fn checkSimdBinOp( try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); var vec_len: ?usize = if (lhs_ty.zigTypeTag() == .Vector) lhs_ty.vectorLen() else null; const result_ty = try sema.resolvePeerTypes(block, src, &.{ uncasted_lhs, uncasted_rhs }, .{ - .override = &[_]LazySrcLoc{ lhs_src, rhs_src }, + .override = &[_]?LazySrcLoc{ lhs_src, rhs_src }, }); const lhs = try sema.coerce(block, result_ty, uncasted_lhs, lhs_src); const rhs = try sema.coerce(block, result_ty, uncasted_rhs, rhs_src); diff --git a/src/Zir.zig b/src/Zir.zig index 001c4e8101..bc5202c8aa 100644 --- a/src/Zir.zig +++ b/src/Zir.zig @@ -2603,8 +2603,8 @@ pub const Inst = struct { } }, @"break": struct { - block_inst: Index, operand: Ref, + payload_index: u32, }, switch_capture: struct { switch_inst: Index, @@ -2690,6 +2690,13 @@ pub const Inst = struct { }; }; + pub const Break = struct { + pub const no_src_node = std.math.maxInt(i32); + + block_inst: Index, + operand_src_node: i32, + }; + /// Trailing: /// 0. Output for every outputs_len /// 1. Input for every inputs_len diff --git a/src/print_zir.zig b/src/print_zir.zig index 5e7d0d45de..755107cd1a 100644 --- a/src/print_zir.zig +++ b/src/print_zir.zig @@ -2321,8 +2321,9 @@ const Writer = struct { fn writeBreak(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { const inst_data = self.code.instructions.items(.data)[inst].@"break"; + const extra = self.code.extraData(Zir.Inst.Break, inst_data.payload_index).data; - try self.writeInstIndex(stream, inst_data.block_inst); + try self.writeInstIndex(stream, extra.block_inst); try stream.writeAll(", "); try self.writeInstRef(stream, inst_data.operand); try stream.writeAll(")"); diff --git a/test/cases/compile_errors/incompatible sub-byte fields.zig b/test/cases/compile_errors/incompatible sub-byte fields.zig index d765b7cf45..dc6f715c2f 100644 --- a/test/cases/compile_errors/incompatible sub-byte fields.zig +++ b/test/cases/compile_errors/incompatible sub-byte fields.zig @@ -25,3 +25,5 @@ export fn entry() void { // target=native // // :14:17: error: incompatible types: '*align(1:0:1) u2' and '*align(2:8:2) u2' +// :15:14: note: type '*align(1:0:1) u2' here +// :16:14: note: type '*align(2:8:2) u2' here diff --git a/test/cases/compile_errors/missing_else_clause.zig b/test/cases/compile_errors/missing_else_clause.zig index 2e5fe9318f..a27408cb4c 100644 --- a/test/cases/compile_errors/missing_else_clause.zig +++ b/test/cases/compile_errors/missing_else_clause.zig @@ -31,7 +31,9 @@ export fn entry() void { // target=native // // :2:21: error: incompatible types: 'i32' and 'void' +// :6:25: note: type 'i32' here // :6:15: error: incompatible types: 'i32' and 'void' +// :2:31: note: type 'i32' here // :12:16: error: expected type 'tmp.h.T', found 'void' // :11:15: note: struct declared here // :18:9: error: incompatible types: 'void' and 'tmp.k.T' diff --git a/test/cases/compile_errors/missing_result_type_for_phi_node.zig b/test/cases/compile_errors/missing_result_type_for_phi_node.zig index c4bd686b01..9e460ececb 100644 --- a/test/cases/compile_errors/missing_result_type_for_phi_node.zig +++ b/test/cases/compile_errors/missing_result_type_for_phi_node.zig @@ -10,3 +10,5 @@ export fn entry() void { // target=native // // :5:11: error: incompatible types: 'void' and 'comptime_int' +// :5:11: note: type 'void' here +// :5:17: note: type 'comptime_int' here diff --git a/test/cases/compile_errors/unused_value_in_switch_in_loop.zig b/test/cases/compile_errors/unused_value_in_switch_in_loop.zig index 830262db4d..b74e016474 100644 --- a/test/cases/compile_errors/unused_value_in_switch_in_loop.zig +++ b/test/cases/compile_errors/unused_value_in_switch_in_loop.zig @@ -12,3 +12,5 @@ export fn entry() void { // target=native // // :3:18: error: incompatible types: 'comptime_int' and 'void' +// :4:14: note: type 'comptime_int' here +// :5:16: note: type 'void' here