mirror of
https://github.com/ziglang/zig.git
synced 2025-12-13 01:33:09 +00:00
Sema: fix enum value without tag name used as switch item
Previously stage2 would report a false positive compile error saying there was no tag for this value.
This commit is contained in:
parent
1d5f865cfa
commit
0efc6a35be
28
src/Sema.zig
28
src/Sema.zig
@ -8378,9 +8378,12 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
|
|||||||
.Enum => {
|
.Enum => {
|
||||||
var seen_fields = try gpa.alloc(?Module.SwitchProngSrc, operand_ty.enumFieldCount());
|
var seen_fields = try gpa.alloc(?Module.SwitchProngSrc, operand_ty.enumFieldCount());
|
||||||
defer gpa.free(seen_fields);
|
defer gpa.free(seen_fields);
|
||||||
|
|
||||||
mem.set(?Module.SwitchProngSrc, seen_fields, null);
|
mem.set(?Module.SwitchProngSrc, seen_fields, null);
|
||||||
|
|
||||||
|
// This is used for non-exhaustive enum values that do not correspond to any tags.
|
||||||
|
var range_set = RangeSet.init(gpa, sema.mod);
|
||||||
|
defer range_set.deinit();
|
||||||
|
|
||||||
var extra_index: usize = special.end;
|
var extra_index: usize = special.end;
|
||||||
{
|
{
|
||||||
var scalar_i: u32 = 0;
|
var scalar_i: u32 = 0;
|
||||||
@ -8394,6 +8397,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
|
|||||||
try sema.validateSwitchItemEnum(
|
try sema.validateSwitchItemEnum(
|
||||||
block,
|
block,
|
||||||
seen_fields,
|
seen_fields,
|
||||||
|
&range_set,
|
||||||
item_ref,
|
item_ref,
|
||||||
src_node_offset,
|
src_node_offset,
|
||||||
.{ .scalar = scalar_i },
|
.{ .scalar = scalar_i },
|
||||||
@ -8416,6 +8420,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
|
|||||||
try sema.validateSwitchItemEnum(
|
try sema.validateSwitchItemEnum(
|
||||||
block,
|
block,
|
||||||
seen_fields,
|
seen_fields,
|
||||||
|
&range_set,
|
||||||
item_ref,
|
item_ref,
|
||||||
src_node_offset,
|
src_node_offset,
|
||||||
.{ .multi = .{ .prong = multi_i, .item = @intCast(u32, item_i) } },
|
.{ .multi = .{ .prong = multi_i, .item = @intCast(u32, item_i) } },
|
||||||
@ -9317,30 +9322,15 @@ fn validateSwitchItemEnum(
|
|||||||
sema: *Sema,
|
sema: *Sema,
|
||||||
block: *Block,
|
block: *Block,
|
||||||
seen_fields: []?Module.SwitchProngSrc,
|
seen_fields: []?Module.SwitchProngSrc,
|
||||||
|
range_set: *RangeSet,
|
||||||
item_ref: Zir.Inst.Ref,
|
item_ref: Zir.Inst.Ref,
|
||||||
src_node_offset: i32,
|
src_node_offset: i32,
|
||||||
switch_prong_src: Module.SwitchProngSrc,
|
switch_prong_src: Module.SwitchProngSrc,
|
||||||
) CompileError!void {
|
) CompileError!void {
|
||||||
const item_tv = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none);
|
const item_tv = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none);
|
||||||
const field_index = item_tv.ty.enumTagFieldIndex(item_tv.val, sema.mod) orelse {
|
const field_index = item_tv.ty.enumTagFieldIndex(item_tv.val, sema.mod) orelse {
|
||||||
const msg = msg: {
|
const maybe_prev_src = try range_set.add(item_tv.val, item_tv.val, item_tv.ty, switch_prong_src);
|
||||||
const src = switch_prong_src.resolve(sema.gpa, sema.mod.declPtr(block.src_decl), src_node_offset, .none);
|
return sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset);
|
||||||
const msg = try sema.errMsg(
|
|
||||||
block,
|
|
||||||
src,
|
|
||||||
"enum '{}' has no tag with value '{}'",
|
|
||||||
.{ item_tv.ty.fmt(sema.mod), item_tv.val.fmtValue(item_tv.ty, sema.mod) },
|
|
||||||
);
|
|
||||||
errdefer msg.destroy(sema.gpa);
|
|
||||||
try sema.mod.errNoteNonLazy(
|
|
||||||
item_tv.ty.declSrcLoc(sema.mod),
|
|
||||||
msg,
|
|
||||||
"enum declared here",
|
|
||||||
.{},
|
|
||||||
);
|
|
||||||
break :msg msg;
|
|
||||||
};
|
|
||||||
return sema.failWithOwnedErrorMsg(block, msg);
|
|
||||||
};
|
};
|
||||||
const maybe_prev_src = seen_fields[field_index];
|
const maybe_prev_src = seen_fields[field_index];
|
||||||
seen_fields[field_index] = switch_prong_src;
|
seen_fields[field_index] = switch_prong_src;
|
||||||
|
|||||||
@ -672,3 +672,21 @@ test "capture of integer forwards the switch condition directly" {
|
|||||||
comptime try S.foo(42);
|
comptime try S.foo(42);
|
||||||
comptime try S.foo(100);
|
comptime try S.foo(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "enum value without tag name used as switch item" {
|
||||||
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||||
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||||
|
|
||||||
|
const E = enum(u32) {
|
||||||
|
a = 1,
|
||||||
|
b = 2,
|
||||||
|
_,
|
||||||
|
};
|
||||||
|
var e: E = @intToEnum(E, 0);
|
||||||
|
switch (e) {
|
||||||
|
@intToEnum(E, 0) => {},
|
||||||
|
.a => return error.TestFailed,
|
||||||
|
.b => return error.TestFailed,
|
||||||
|
_ => return error.TestFailed,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user