authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-07-19 13:19:23+03:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-21 12:21:30-07:00
log83b2d2cd3eb701b43d17404e73933bc00f7be828
treefae2a1c6e8e32ed4056b59ae639133e207a43916
parent9fb8d21a019deab308a63f7959dab2ee05385969

Sema: better source location for incompatible capture group


4 files changed, 63 insertions(+), 30 deletions(-)

src/Module.zig+28
......@@ -2348,6 +2348,26 @@ pub const SrcLoc = struct {
23482348 }
23492349 } else unreachable;
23502350 },
2351 .node_offset_switch_prong_capture => |node_off| {
2352 const tree = try src_loc.file_scope.getTree(gpa);
2353 const case_node = src_loc.declRelativeToNodeIndex(node_off);
2354 const node_tags = tree.nodes.items(.tag);
2355 const case = switch (node_tags[case_node]) {
2356 .switch_case_one => tree.switchCaseOne(case_node),
2357 .switch_case => tree.switchCase(case_node),
2358 else => unreachable,
2359 };
2360 const start_tok = case.payload_token.?;
2361 const token_tags = tree.tokens.items(.tag);
2362 const end_tok = switch (token_tags[start_tok]) {
2363 .asterisk => start_tok + 1,
2364 else => start_tok,
2365 };
2366 const start = tree.tokens.items(.start)[start_tok];
2367 const end_start = tree.tokens.items(.start)[end_tok];
2368 const end = end_start + @intCast(u32, tree.tokenSlice(end_tok).len);
2369 return Span{ .start = start, .end = end, .main = start };
2370 },
23512371 .node_offset_fn_type_align => |node_off| {
23522372 const tree = try src_loc.file_scope.getTree(gpa);
23532373 const node_datas = tree.nodes.items(.data);
......@@ -2877,6 +2897,9 @@ pub const LazySrcLoc = union(enum) {
28772897 /// range nodes. The error applies to all of them.
28782898 /// The Decl is determined contextually.
28792899 node_offset_switch_range: i32,
2900 /// The source location points to the capture of a switch_prong.
2901 /// The Decl is determined contextually.
2902 node_offset_switch_prong_capture: i32,
28802903 /// The source location points to the align expr of a function type
28812904 /// expression, found by taking this AST node index offset from the containing
28822905 /// Decl AST node, which points to a function type AST node. Next, navigate to
......@@ -3017,6 +3040,7 @@ pub const LazySrcLoc = union(enum) {
30173040 .node_offset_switch_operand,
30183041 .node_offset_switch_special_prong,
30193042 .node_offset_switch_range,
3043 .node_offset_switch_prong_capture,
30203044 .node_offset_fn_type_align,
30213045 .node_offset_fn_type_addrspace,
30223046 .node_offset_fn_type_section,
......@@ -5602,6 +5626,7 @@ pub const SwitchProngSrc = union(enum) {
56025626 scalar: u32,
56035627 multi: Multi,
56045628 range: Multi,
5629 multi_capture: u32,
56055630
56065631 pub const Multi = struct {
56075632 prong: u32,
......@@ -5657,6 +5682,9 @@ pub const SwitchProngSrc = union(enum) {
56575682 .scalar => |i| if (!is_multi and i == scalar_i) return LazySrcLoc.nodeOffset(
56585683 decl.nodeIndexToRelative(case.ast.values[0]),
56595684 ),
5685 .multi_capture => |i| if (is_multi and i == multi_i) {
5686 return LazySrcLoc{ .node_offset_switch_prong_capture = decl.nodeIndexToRelative(case_node) };
5687 },
56605688 .multi => |s| if (is_multi and s.prong == multi_i) {
56615689 var item_i: u32 = 0;
56625690 for (case.ast.values) |item_node| {
src/Sema.zig+14-9
......@@ -8197,7 +8197,6 @@ fn zirSwitchCapture(
81978197 const switch_info = zir_datas[capture_info.switch_inst].pl_node;
81988198 const switch_extra = sema.code.extraData(Zir.Inst.SwitchBlock, switch_info.payload_index);
81998199 const operand_src: LazySrcLoc = .{ .node_offset_switch_operand = switch_info.src_node };
8200 const switch_src = switch_info.src();
82018200 const operand_is_ref = switch_extra.data.bits.is_ref;
82028201 const cond_inst = Zir.refToIndex(switch_extra.data.operand).?;
82038202 const cond_info = sema.code.instructions.items(.data)[cond_inst].un_node;
......@@ -8247,7 +8246,7 @@ fn zirSwitchCapture(
82478246 const first_field_index = @intCast(u32, enum_ty.enumTagFieldIndex(first_item_val, sema.mod).?);
82488247 const first_field = union_obj.fields.values()[first_field_index];
82498248
8250 for (items[1..]) |item| {
8249 for (items[1..]) |item, i| {
82518250 const item_ref = try sema.resolveInst(item);
82528251 // Previous switch validation ensured this will succeed
82538252 const item_val = sema.resolveConstValue(block, .unneeded, item_ref, undefined) catch unreachable;
......@@ -8255,11 +8254,17 @@ fn zirSwitchCapture(
82558254 const field_index = enum_ty.enumTagFieldIndex(item_val, sema.mod).?;
82568255 const field = union_obj.fields.values()[field_index];
82578256 if (!field.ty.eql(first_field.ty, sema.mod)) {
8258 const first_item_src = switch_src; // TODO better source location
8259 const item_src = switch_src;
82608257 const msg = msg: {
8261 const msg = try sema.errMsg(block, switch_src, "capture group with incompatible types", .{});
8258 const raw_capture_src = Module.SwitchProngSrc{ .multi_capture = capture_info.prong_index };
8259 const capture_src = raw_capture_src.resolve(sema.gpa, sema.mod.declPtr(block.src_decl), switch_info.src_node, .first);
8260
8261 const msg = try sema.errMsg(block, capture_src, "capture group with incompatible types", .{});
82628262 errdefer msg.destroy(sema.gpa);
8263
8264 const raw_first_item_src = Module.SwitchProngSrc{ .multi = .{ .prong = capture_info.prong_index, .item = 0 } };
8265 const first_item_src = raw_first_item_src.resolve(sema.gpa, sema.mod.declPtr(block.src_decl), switch_info.src_node, .first);
8266 const raw_item_src = Module.SwitchProngSrc{ .multi = .{ .prong = capture_info.prong_index, .item = 1 + @intCast(u32, i) } };
8267 const item_src = raw_item_src.resolve(sema.gpa, sema.mod.declPtr(block.src_decl), switch_info.src_node, .first);
82638268 try sema.errNote(block, first_item_src, msg, "type '{}' here", .{first_field.ty.fmt(sema.mod)});
82648269 try sema.errNote(block, item_src, msg, "type '{}' here", .{field.ty.fmt(sema.mod)});
82658270 break :msg msg;
......@@ -21094,17 +21099,17 @@ const InMemoryCoercionResult = union(enum) {
2109421099 }
2109521100 }
2109621101 if (!actual_noalias) {
21097 try sema.errNote(block, src, msg, "regular paramter {d} cannot cast into a noalias paramter", .{index});
21102 try sema.errNote(block, src, msg, "regular parameter {d} cannot cast into a noalias parameter", .{index});
2109821103 } else {
21099 try sema.errNote(block, src, msg, "noalias paramter {d} cannot cast into a regular paramter", .{index});
21104 try sema.errNote(block, src, msg, "noalias parameter {d} cannot cast into a regular parameter", .{index});
2110021105 }
2110121106 break;
2110221107 },
2110321108 .fn_param_comptime => |param| {
2110421109 if (param.wanted) {
21105 try sema.errNote(block, src, msg, "non-comptime paramter {d} cannot cast into a comptime paramter", .{param.index});
21110 try sema.errNote(block, src, msg, "non-comptime parameter {d} cannot cast into a comptime parameter", .{param.index});
2110621111 } else {
21107 try sema.errNote(block, src, msg, "comptime paramter {d} cannot cast into a non-comptime paramter", .{param.index});
21112 try sema.errNote(block, src, msg, "comptime parameter {d} cannot cast into a non-comptime parameter", .{param.index});
2110821113 }
2110921114 break;
2111021115 },
test/cases/compile_errors/capture_group_on_switch_prong_with_incompatible_payload_types.zig created+21
......@@ -0,0 +1,21 @@
1const Union = union(enum) {
2 A: usize,
3 B: isize,
4};
5comptime {
6 var u = Union{ .A = 8 };
7 switch (u) {
8 .A, .B => |e| {
9 _ = e;
10 unreachable;
11 },
12 }
13}
14
15// error
16// backend=stage2
17// target=native
18//
19// :8:20: error: capture group with incompatible types
20// :8:10: note: type 'usize' here
21// :8:14: note: type 'isize' here
test/cases/compile_errors/stage1/obj/capture_group_on_switch_prong_with_incompatible_payload_types.zig deleted-21
......@@ -1,21 +0,0 @@
1const Union = union(enum) {
2 A: usize,
3 B: isize,
4};
5comptime {
6 var u = Union{ .A = 8 };
7 switch (u) {
8 .A, .B => |e| {
9 _ = e;
10 unreachable;
11 },
12 }
13}
14
15// error
16// backend=stage1
17// target=native
18//
19// tmp.zig:8:20: error: capture group with incompatible types
20// tmp.zig:8:9: note: type 'usize' here
21// tmp.zig:8:13: note: type 'isize' here