authorgravatar for r00ster91@proton.meWooster <r00ster91@proton.me> 2022-12-01 21:03:46+01:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-12-04 14:12:24+02:00
logf094c4bce513f2b17f9c29ae40c244626f945fb4
treecce9d8c5415cfbcccdc10cdc3106e7b41dfacdc9
parent19dd6de180275cc3f79a514b5cbc05eb9cbadb75

Sema: detect duplicate enum tag values


3 files changed, 64 insertions(+), 8 deletions(-)

src/Sema.zig+22-8
...@@ -18264,9 +18264,9 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in...@@ -18264,9 +18264,9 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in
18264 .mod = mod,18264 .mod = mod,
18265 });18265 });
1826618266
18267 var i: usize = 0;18267 var field_i: usize = 0;
18268 while (i < fields_len) : (i += 1) {18268 while (field_i < fields_len) : (field_i += 1) {
18269 const elem_val = try fields_val.elemValue(sema.mod, sema.arena, i);18269 const elem_val = try fields_val.elemValue(sema.mod, sema.arena, field_i);
18270 const field_struct_val: []const Value = elem_val.castTag(.aggregate).?.data;18270 const field_struct_val: []const Value = elem_val.castTag(.aggregate).?.data;
18271 // TODO use reflection instead of magic numbers here18271 // TODO use reflection instead of magic numbers here
18272 // name: []const u818272 // name: []const u8
...@@ -18289,17 +18289,31 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in...@@ -18289,17 +18289,31 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in
18289 });18289 });
18290 }18290 }
1829118291
18292 const gop = enum_obj.fields.getOrPutAssumeCapacity(field_name);18292 const gop_field = enum_obj.fields.getOrPutAssumeCapacity(field_name);
18293 if (gop.found_existing) {18293 if (gop_field.found_existing) {
18294 // TODO: better source location18294 const msg = msg: {
18295 return sema.fail(block, src, "duplicate enum tag {s}", .{field_name});18295 const msg = try sema.errMsg(block, src, "duplicate enum field '{s}'", .{field_name});
18296 errdefer msg.destroy(gpa);
18297 try sema.errNote(block, src, msg, "other field here", .{});
18298 break :msg msg;
18299 };
18300 return sema.failWithOwnedErrorMsg(msg);
18296 }18301 }
1829718302
18298 const copied_tag_val = try value_val.copy(new_decl_arena_allocator);18303 const copied_tag_val = try value_val.copy(new_decl_arena_allocator);
18299 enum_obj.values.putAssumeCapacityNoClobberContext(copied_tag_val, {}, .{18304 const gop_val = enum_obj.values.getOrPutAssumeCapacityContext(copied_tag_val, .{
18300 .ty = enum_obj.tag_ty,18305 .ty = enum_obj.tag_ty,
18301 .mod = mod,18306 .mod = mod,
18302 });18307 });
18308 if (gop_val.found_existing) {
18309 const msg = msg: {
18310 const msg = try sema.errMsg(block, src, "enum tag value {} already taken", .{value_val.fmtValue(Type.comptime_int, mod)});
18311 errdefer msg.destroy(gpa);
18312 try sema.errNote(block, src, msg, "other enum tag value here", .{});
18313 break :msg msg;
18314 };
18315 return sema.failWithOwnedErrorMsg(msg);
18316 }
18303 }18317 }
1830418318
18305 try new_decl.finalizeNewArena(&new_decl_arena);18319 try new_decl.finalizeNewArena(&new_decl_arena);
test/cases/compile_errors/reify_enum_with_duplicate_field.zig created+21
...@@ -0,0 +1,21 @@
1export fn entry() void {
2 _ = @Type(.{
3 .Enum = .{
4 .layout = .Auto,
5 .tag_type = u32,
6 .fields = &.{
7 .{ .name = "A", .value = 0 },
8 .{ .name = "A", .value = 1 },
9 },
10 .decls = &.{},
11 .is_exhaustive = false,
12 },
13 });
14}
15
16// error
17// backend=stage2
18// target=native
19//
20// :2:9: error: duplicate enum field 'A'
21// :2:9: note: other field here
test/cases/compile_errors/reify_enum_with_duplicate_tag_value.zig created+21
...@@ -0,0 +1,21 @@
1export fn entry() void {
2 _ = @Type(.{
3 .Enum = .{
4 .layout = .Auto,
5 .tag_type = u32,
6 .fields = &.{
7 .{ .name = "A", .value = 10 },
8 .{ .name = "B", .value = 10 },
9 },
10 .decls = &.{},
11 .is_exhaustive = false,
12 },
13 });
14}
15
16// error
17// backend=stage2
18// target=native
19//
20// :2:9: error: enum tag value 10 already taken
21// :2:9: note: other enum tag value here