mirror of
https://github.com/ziglang/zig.git
synced 2026-02-20 16:24:51 +00:00
Fix bad source locations in switch capture errors
To do this, I expanded SwitchProngSrc a bit. Several of the tags there aren't actually used by any current errors, but they're there for consistency and if we ever need them. Also delete a now-redundant test and fix another.
This commit is contained in:
parent
bcb673d94a
commit
42dc7539c5
142
src/Module.zig
142
src/Module.zig
@ -2471,12 +2471,23 @@ pub const SrcLoc = struct {
|
||||
}
|
||||
} else unreachable;
|
||||
},
|
||||
.node_offset_switch_prong_capture => |node_off| {
|
||||
.node_offset_switch_prong_capture,
|
||||
.node_offset_switch_prong_tag_capture,
|
||||
=> |node_off| {
|
||||
const tree = try src_loc.file_scope.getTree(gpa);
|
||||
const case_node = src_loc.declRelativeToNodeIndex(node_off);
|
||||
const case = tree.fullSwitchCase(case_node).?;
|
||||
const start_tok = case.payload_token.?;
|
||||
const token_tags = tree.tokens.items(.tag);
|
||||
const start_tok = switch (src_loc.lazy) {
|
||||
.node_offset_switch_prong_capture => case.payload_token.?,
|
||||
.node_offset_switch_prong_tag_capture => blk: {
|
||||
var tok = case.payload_token.?;
|
||||
if (token_tags[tok] == .asterisk) tok += 1;
|
||||
tok += 2; // skip over comma
|
||||
break :blk tok;
|
||||
},
|
||||
else => unreachable,
|
||||
};
|
||||
const end_tok = switch (token_tags[start_tok]) {
|
||||
.asterisk => start_tok + 1,
|
||||
else => start_tok,
|
||||
@ -2957,6 +2968,9 @@ pub const LazySrcLoc = union(enum) {
|
||||
/// The source location points to the capture of a switch_prong.
|
||||
/// The Decl is determined contextually.
|
||||
node_offset_switch_prong_capture: i32,
|
||||
/// The source location points to the tag capture of a switch_prong.
|
||||
/// The Decl is determined contextually.
|
||||
node_offset_switch_prong_tag_capture: i32,
|
||||
/// The source location points to the align expr of a function type
|
||||
/// expression, found by taking this AST node index offset from the containing
|
||||
/// Decl AST node, which points to a function type AST node. Next, navigate to
|
||||
@ -3130,6 +3144,7 @@ pub const LazySrcLoc = union(enum) {
|
||||
.node_offset_switch_special_prong,
|
||||
.node_offset_switch_range,
|
||||
.node_offset_switch_prong_capture,
|
||||
.node_offset_switch_prong_tag_capture,
|
||||
.node_offset_fn_type_align,
|
||||
.node_offset_fn_type_addrspace,
|
||||
.node_offset_fn_type_section,
|
||||
@ -5867,11 +5882,26 @@ fn lockAndClearFileCompileError(mod: *Module, file: *File) void {
|
||||
}
|
||||
|
||||
pub const SwitchProngSrc = union(enum) {
|
||||
/// The item for a scalar prong.
|
||||
scalar: u32,
|
||||
/// A given single item for a multi prong.
|
||||
multi: Multi,
|
||||
/// A given range item for a multi prong.
|
||||
range: Multi,
|
||||
multi_capture: u32,
|
||||
/// The item for the special prong.
|
||||
special,
|
||||
/// The main capture for a scalar prong.
|
||||
scalar_capture: u32,
|
||||
/// The main capture for a multi prong.
|
||||
multi_capture: u32,
|
||||
/// The main capture for the special prong.
|
||||
special_capture,
|
||||
/// The tag capture for a scalar prong.
|
||||
scalar_tag_capture: u32,
|
||||
/// The tag capture for a multi prong.
|
||||
multi_tag_capture: u32,
|
||||
/// The tag capture for the special prong.
|
||||
special_tag_capture,
|
||||
|
||||
pub const Multi = struct {
|
||||
prong: u32,
|
||||
@ -5887,6 +5917,7 @@ pub const SwitchProngSrc = union(enum) {
|
||||
mod: *Module,
|
||||
decl: *Decl,
|
||||
switch_node_offset: i32,
|
||||
/// Ignored if `prong_src` is not `.range`
|
||||
range_expand: RangeExpand,
|
||||
) LazySrcLoc {
|
||||
@setCold(true);
|
||||
@ -5907,7 +5938,7 @@ pub const SwitchProngSrc = union(enum) {
|
||||
|
||||
var multi_i: u32 = 0;
|
||||
var scalar_i: u32 = 0;
|
||||
for (case_nodes) |case_node| {
|
||||
const case_node = for (case_nodes) |case_node| {
|
||||
const case = tree.fullSwitchCase(case_node).?;
|
||||
|
||||
const is_special = special: {
|
||||
@ -5919,60 +5950,85 @@ pub const SwitchProngSrc = union(enum) {
|
||||
};
|
||||
|
||||
if (is_special) {
|
||||
if (prong_src != .special) continue;
|
||||
return LazySrcLoc.nodeOffset(
|
||||
decl.nodeIndexToRelative(case.ast.values[0]),
|
||||
);
|
||||
switch (prong_src) {
|
||||
.special, .special_capture, .special_tag_capture => break case_node,
|
||||
else => continue,
|
||||
}
|
||||
}
|
||||
|
||||
const is_multi = case.ast.values.len != 1 or
|
||||
node_tags[case.ast.values[0]] == .switch_range;
|
||||
|
||||
switch (prong_src) {
|
||||
.scalar => |i| if (!is_multi and i == scalar_i) return LazySrcLoc.nodeOffset(
|
||||
decl.nodeIndexToRelative(case.ast.values[0]),
|
||||
),
|
||||
.multi_capture => |i| if (is_multi and i == multi_i) {
|
||||
return LazySrcLoc{ .node_offset_switch_prong_capture = decl.nodeIndexToRelative(case_node) };
|
||||
},
|
||||
.multi => |s| if (is_multi and s.prong == multi_i) {
|
||||
var item_i: u32 = 0;
|
||||
for (case.ast.values) |item_node| {
|
||||
if (node_tags[item_node] == .switch_range) continue;
|
||||
.scalar,
|
||||
.scalar_capture,
|
||||
.scalar_tag_capture,
|
||||
=> |i| if (!is_multi and i == scalar_i) break case_node,
|
||||
|
||||
if (item_i == s.item) return LazySrcLoc.nodeOffset(
|
||||
decl.nodeIndexToRelative(item_node),
|
||||
);
|
||||
item_i += 1;
|
||||
} else unreachable;
|
||||
},
|
||||
.range => |s| if (is_multi and s.prong == multi_i) {
|
||||
var range_i: u32 = 0;
|
||||
for (case.ast.values) |range| {
|
||||
if (node_tags[range] != .switch_range) continue;
|
||||
.multi_capture,
|
||||
.multi_tag_capture,
|
||||
=> |i| if (is_multi and i == multi_i) break case_node,
|
||||
|
||||
if (range_i == s.item) switch (range_expand) {
|
||||
.none => return LazySrcLoc.nodeOffset(
|
||||
decl.nodeIndexToRelative(range),
|
||||
),
|
||||
.first => return LazySrcLoc.nodeOffset(
|
||||
decl.nodeIndexToRelative(node_datas[range].lhs),
|
||||
),
|
||||
.last => return LazySrcLoc.nodeOffset(
|
||||
decl.nodeIndexToRelative(node_datas[range].rhs),
|
||||
),
|
||||
};
|
||||
range_i += 1;
|
||||
} else unreachable;
|
||||
},
|
||||
.special => {},
|
||||
.multi,
|
||||
.range,
|
||||
=> |m| if (is_multi and m.prong == multi_i) break case_node,
|
||||
|
||||
.special,
|
||||
.special_capture,
|
||||
.special_tag_capture,
|
||||
=> {},
|
||||
}
|
||||
|
||||
if (is_multi) {
|
||||
multi_i += 1;
|
||||
} else {
|
||||
scalar_i += 1;
|
||||
}
|
||||
} else unreachable;
|
||||
|
||||
const case = tree.fullSwitchCase(case_node).?;
|
||||
|
||||
switch (prong_src) {
|
||||
.scalar, .special => return LazySrcLoc.nodeOffset(
|
||||
decl.nodeIndexToRelative(case.ast.values[0]),
|
||||
),
|
||||
.multi => |m| {
|
||||
var item_i: u32 = 0;
|
||||
for (case.ast.values) |item_node| {
|
||||
if (node_tags[item_node] == .switch_range) continue;
|
||||
if (item_i == m.item) return LazySrcLoc.nodeOffset(
|
||||
decl.nodeIndexToRelative(item_node),
|
||||
);
|
||||
item_i += 1;
|
||||
}
|
||||
unreachable;
|
||||
},
|
||||
.range => |m| {
|
||||
var range_i: u32 = 0;
|
||||
for (case.ast.values) |range| {
|
||||
if (node_tags[range] != .switch_range) continue;
|
||||
if (range_i == m.item) switch (range_expand) {
|
||||
.none => return LazySrcLoc.nodeOffset(
|
||||
decl.nodeIndexToRelative(range),
|
||||
),
|
||||
.first => return LazySrcLoc.nodeOffset(
|
||||
decl.nodeIndexToRelative(node_datas[range].lhs),
|
||||
),
|
||||
.last => return LazySrcLoc.nodeOffset(
|
||||
decl.nodeIndexToRelative(node_datas[range].rhs),
|
||||
),
|
||||
};
|
||||
range_i += 1;
|
||||
}
|
||||
unreachable;
|
||||
},
|
||||
.scalar_capture, .multi_capture, .special_capture => {
|
||||
return .{ .node_offset_switch_prong_capture = decl.nodeIndexToRelative(case_node) };
|
||||
},
|
||||
.scalar_tag_capture, .multi_tag_capture, .special_tag_capture => {
|
||||
return .{ .node_offset_switch_prong_tag_capture = decl.nodeIndexToRelative(case_node) };
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
32
src/Sema.zig
32
src/Sema.zig
@ -10129,7 +10129,7 @@ const SwitchProngAnalysis = struct {
|
||||
prong_type: enum { normal, special },
|
||||
prong_body: []const Zir.Inst.Index,
|
||||
capture: Zir.Inst.SwitchBlock.ProngInfo.Capture,
|
||||
/// Must use the `scalar`, `special`, or `multi_capture` union field.
|
||||
/// Must use the `scalar_capture`, `special_capture`, or `multi_capture` union field.
|
||||
raw_capture_src: Module.SwitchProngSrc,
|
||||
/// The set of all values which can reach this prong. May be undefined
|
||||
/// if the prong is special or contains ranges.
|
||||
@ -10247,7 +10247,13 @@ const SwitchProngAnalysis = struct {
|
||||
if (operand_ty.zigTypeTag(mod) != .Union) {
|
||||
const zir_datas = sema.code.instructions.items(.data);
|
||||
const switch_node_offset = zir_datas[spa.switch_block_inst].pl_node.src_node;
|
||||
const capture_src = raw_capture_src.resolve(mod, mod.declPtr(block.src_decl), switch_node_offset, .none);
|
||||
const raw_tag_capture_src: Module.SwitchProngSrc = switch (raw_capture_src) {
|
||||
.scalar_capture => |i| .{ .scalar_tag_capture = i },
|
||||
.multi_capture => |i| .{ .multi_tag_capture = i },
|
||||
.special_capture => .special_tag_capture,
|
||||
else => unreachable,
|
||||
};
|
||||
const capture_src = raw_tag_capture_src.resolve(mod, mod.declPtr(block.src_decl), switch_node_offset, .none);
|
||||
const msg = msg: {
|
||||
const msg = try sema.errMsg(block, capture_src, "cannot capture tag of non-union type '{}'", .{
|
||||
operand_ty.fmt(mod),
|
||||
@ -10712,7 +10718,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
|
||||
}
|
||||
};
|
||||
|
||||
const operand = try sema.switchCond(block, src, raw_operand.val);
|
||||
const operand = try sema.switchCond(block, operand_src, raw_operand.val);
|
||||
|
||||
// AstGen guarantees that the instruction immediately preceding
|
||||
// switch_block(_ref) is a dbg_stmt
|
||||
@ -11377,7 +11383,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
|
||||
.normal,
|
||||
body,
|
||||
info.capture,
|
||||
.{ .scalar = @intCast(u32, scalar_i) },
|
||||
.{ .scalar_capture = @intCast(u32, scalar_i) },
|
||||
&.{item},
|
||||
if (info.is_inline) operand else .none,
|
||||
info.has_tag_capture,
|
||||
@ -11460,7 +11466,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
|
||||
.special,
|
||||
special.body,
|
||||
special.capture,
|
||||
.special,
|
||||
.special_capture,
|
||||
undefined, // case_vals may be undefined for special prongs
|
||||
if (special.is_inline) operand else .none,
|
||||
special.has_tag_capture,
|
||||
@ -11491,7 +11497,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
|
||||
.special,
|
||||
special.body,
|
||||
special.capture,
|
||||
.special,
|
||||
.special_capture,
|
||||
undefined, // case_vals may be undefined for special prongs
|
||||
.none,
|
||||
false,
|
||||
@ -11551,7 +11557,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
|
||||
.normal,
|
||||
body,
|
||||
info.capture,
|
||||
.{ .scalar = @intCast(u32, scalar_i) },
|
||||
.{ .scalar_capture = @intCast(u32, scalar_i) },
|
||||
&.{item},
|
||||
if (info.is_inline) item else .none,
|
||||
info.has_tag_capture,
|
||||
@ -11885,7 +11891,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
|
||||
.special,
|
||||
special.body,
|
||||
special.capture,
|
||||
.special,
|
||||
.special_capture,
|
||||
&.{item_ref},
|
||||
item_ref,
|
||||
special.has_tag_capture,
|
||||
@ -11929,7 +11935,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
|
||||
.special,
|
||||
special.body,
|
||||
special.capture,
|
||||
.special,
|
||||
.special_capture,
|
||||
&.{item_ref},
|
||||
item_ref,
|
||||
special.has_tag_capture,
|
||||
@ -11960,7 +11966,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
|
||||
.special,
|
||||
special.body,
|
||||
special.capture,
|
||||
.special,
|
||||
.special_capture,
|
||||
&.{item_ref},
|
||||
item_ref,
|
||||
special.has_tag_capture,
|
||||
@ -11988,7 +11994,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
|
||||
.special,
|
||||
special.body,
|
||||
special.capture,
|
||||
.special,
|
||||
.special_capture,
|
||||
&.{Air.Inst.Ref.bool_true},
|
||||
Air.Inst.Ref.bool_true,
|
||||
special.has_tag_capture,
|
||||
@ -12014,7 +12020,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
|
||||
.special,
|
||||
special.body,
|
||||
special.capture,
|
||||
.special,
|
||||
.special_capture,
|
||||
&.{Air.Inst.Ref.bool_false},
|
||||
Air.Inst.Ref.bool_false,
|
||||
special.has_tag_capture,
|
||||
@ -12065,7 +12071,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
|
||||
.special,
|
||||
special.body,
|
||||
special.capture,
|
||||
.special,
|
||||
.special_capture,
|
||||
undefined, // case_vals may be undefined for special prongs
|
||||
.none,
|
||||
false,
|
||||
|
||||
@ -1,21 +0,0 @@
|
||||
const Union = union(enum) {
|
||||
A: usize,
|
||||
B: isize,
|
||||
};
|
||||
comptime {
|
||||
var u = Union{ .A = 8 };
|
||||
switch (u) {
|
||||
.A, .B => |e| {
|
||||
_ = e;
|
||||
unreachable;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :8:20: error: capture group with incompatible types
|
||||
// :8:10: note: type 'usize' here
|
||||
// :8:14: note: type 'isize' here
|
||||
@ -4,12 +4,12 @@ const Payload = union {
|
||||
C: bool,
|
||||
};
|
||||
export fn entry() void {
|
||||
const a = Payload { .A = 1234 };
|
||||
const a = Payload{ .A = 1234 };
|
||||
foo(&a);
|
||||
}
|
||||
fn foo(a: *const Payload) void {
|
||||
switch (a.*) {
|
||||
Payload.A => {},
|
||||
.A => {},
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user