Commit 394252c9db

Mitchell Hashimoto <mitchell.hashimoto@gmail.com>
2022-03-15 22:33:23
stage2: move duplicate error set check to AstGen
1 parent 9a6fa67
Changed files (3)
src/AstGen.zig
@@ -4723,14 +4723,36 @@ fn errorSetDecl(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir
     const payload_index = try reserveExtra(astgen, @typeInfo(Zir.Inst.ErrorSetDecl).Struct.fields.len);
     var fields_len: usize = 0;
     {
+        var idents: std.AutoHashMapUnmanaged(u32, Ast.TokenIndex) = .{};
+        defer idents.deinit(gpa);
+
         const error_token = main_tokens[node];
         var tok_i = error_token + 2;
         while (true) : (tok_i += 1) {
             switch (token_tags[tok_i]) {
                 .doc_comment, .comma => {},
                 .identifier => {
-                    try astgen.extra.ensureUnusedCapacity(gpa, 2);
                     const str_index = try astgen.identAsString(tok_i);
+                    const gop = try idents.getOrPut(gpa, str_index);
+                    if (gop.found_existing) {
+                        const name = try gpa.dupe(u8, mem.span(astgen.nullTerminatedString(str_index)));
+                        defer gpa.free(name);
+                        return astgen.failTokNotes(
+                            tok_i,
+                            "duplicate error set field '{s}'",
+                            .{name},
+                            &[_]u32{
+                                try astgen.errNoteTok(
+                                    gop.value_ptr.*,
+                                    "previous declaration here",
+                                    .{},
+                                ),
+                            },
+                        );
+                    }
+                    gop.value_ptr.* = tok_i;
+
+                    try astgen.extra.ensureUnusedCapacity(gpa, 2);
                     astgen.extra.appendAssumeCapacity(str_index);
                     const doc_comment_index = try astgen.docCommentAsString(tok_i);
                     astgen.extra.appendAssumeCapacity(doc_comment_index);
src/Sema.zig
@@ -2220,12 +2220,8 @@ fn zirErrorSetDecl(
     while (extra_index < extra_index_end) : (extra_index += 2) { // +2 to skip over doc_string
         const str_index = sema.code.extra[extra_index];
         const name = try new_decl_arena_allocator.dupe(u8, sema.code.nullTerminatedString(str_index));
-
-        // TODO: This check should be performed in AstGen instead.
         const result = names.getOrPutAssumeCapacity(name);
-        if (result.found_existing) {
-            return sema.fail(block, src, "duplicate error set field {s}", .{name});
-        }
+        assert(!result.found_existing); // verified in AstGen
     }
 
     // names must be sorted.
test/compile_errors.zig
@@ -4487,8 +4487,8 @@ pub fn addCases(ctx: *TestContext) !void {
         \\    _ = a;
         \\}
     , &[_][]const u8{
-        "tmp.zig:3:5: error: duplicate error: 'Bar'",
-        "tmp.zig:2:5: note: other error here",
+        "tmp.zig:3:5: error: duplicate error set field 'Bar'",
+        "tmp.zig:2:5: note: previous declaration here",
     });
 
     ctx.objErrStage1("cast negative integer literal to usize",