Diagnose redundant redeclarations in impl files (#7695)

While forward declarations in impl files are allowed, having one in the
impl file is redundant when we also have one in the API file.
This commit is contained in:
Özgür T. Önsoy
2026-09-08 23:15:42 +00:00
committed by GitHub
parent ca9e985fa8
commit c6d8d29172
4 changed files with 104 additions and 18 deletions
+5
View File
@@ -137,6 +137,11 @@ auto DiagnoseIfInvalidRedecl(Context& context, Lex::TokenKind decl_kind,
prev_decl.loc_id);
return;
}
if (!new_decl.is_definition) {
DiagnoseRedundant(context, decl_kind, name_id, new_decl.loc_id,
prev_decl.loc_id);
return;
}
return;
}
@@ -16,13 +16,10 @@ library "[[@TEST_NAME]]";
class A;
// --- todo_fail_decl_in_api_definition_in_impl.impl.carbon
// --- decl_in_api_definition_in_impl.impl.carbon
impl library "[[@TEST_NAME]]";
// TODO: This should be diagnosed per #3762: A declaration should always add new information.
class A;
class A {}
// --- use_decl_in_api.carbon
@@ -55,12 +52,42 @@ class C;
impl library "[[@TEST_NAME]]";
// CHECK:STDERR: fail_decl_in_api_decl_in_impl.impl.carbon:[[@LINE+12]]:1: error: redeclaration of `class C` is redundant [RedeclRedundant]
// CHECK:STDERR: class C;
// CHECK:STDERR: ^~~~~~~~
// CHECK:STDERR: fail_decl_in_api_decl_in_impl.impl.carbon:[[@LINE-5]]:1: in import [InImport]
// CHECK:STDERR: decl_in_api_decl_in_impl.carbon:4:1: note: previously declared here [RedeclPrevDecl]
// CHECK:STDERR: class C;
// CHECK:STDERR: ^~~~~~~~
// CHECK:STDERR:
// CHECK:STDERR: fail_decl_in_api_decl_in_impl.impl.carbon:[[@LINE+4]]:1: error: no definition found for declaration in impl file [MissingDefinitionInImpl]
// CHECK:STDERR: class C;
// CHECK:STDERR: ^~~~~~~~
// CHECK:STDERR:
class C;
// --- decl_in_api_decl_and_definition_in_impl.carbon
library "[[@TEST_NAME]]";
class D;
// --- fail_decl_in_api_decl_and_definition_in_impl.impl.carbon
impl library "[[@TEST_NAME]]";
// CHECK:STDERR: fail_decl_in_api_decl_and_definition_in_impl.impl.carbon:[[@LINE+8]]:1: error: redeclaration of `class D` is redundant [RedeclRedundant]
// CHECK:STDERR: class D;
// CHECK:STDERR: ^~~~~~~~
// CHECK:STDERR: fail_decl_in_api_decl_and_definition_in_impl.impl.carbon:[[@LINE-5]]:1: in import [InImport]
// CHECK:STDERR: decl_in_api_decl_and_definition_in_impl.carbon:4:1: note: previously declared here [RedeclPrevDecl]
// CHECK:STDERR: class D;
// CHECK:STDERR: ^~~~~~~~
// CHECK:STDERR:
class D;
class D {}
// --- decl_only_in_impl.carbon
library "[[@TEST_NAME]]";
@@ -70,7 +97,7 @@ library "[[@TEST_NAME]]";
impl library "[[@TEST_NAME]]";
// CHECK:STDERR: fail_decl_only_in_impl.impl.carbon:[[@LINE+4]]:1: error: no definition found for declaration in impl file [MissingDefinitionInImpl]
// CHECK:STDERR: class D;
// CHECK:STDERR: class E;
// CHECK:STDERR: ^~~~~~~~
// CHECK:STDERR:
class D;
class E;
@@ -16,13 +16,10 @@ library "[[@TEST_NAME]]";
fn A();
// --- todo_fail_decl_in_api_definition_in_impl.impl.carbon
// --- decl_in_api_definition_in_impl.impl.carbon
impl library "[[@TEST_NAME]]";
// TODO: This should be diagnosed per #3762: A declaration should always add new information.
fn A();
fn A() {}
// --- use_decl_in_api.carbon
@@ -55,12 +52,42 @@ fn C();
impl library "[[@TEST_NAME]]";
// CHECK:STDERR: fail_decl_in_api_decl_in_impl.impl.carbon:[[@LINE+12]]:1: error: redeclaration of `fn C` is redundant [RedeclRedundant]
// CHECK:STDERR: fn C();
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR: fail_decl_in_api_decl_in_impl.impl.carbon:[[@LINE-5]]:1: in import [InImport]
// CHECK:STDERR: decl_in_api_decl_in_impl.carbon:4:1: note: previously declared here [RedeclPrevDecl]
// CHECK:STDERR: fn C();
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR:
// CHECK:STDERR: fail_decl_in_api_decl_in_impl.impl.carbon:[[@LINE+4]]:1: error: no definition found for declaration in impl file [MissingDefinitionInImpl]
// CHECK:STDERR: fn C();
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR:
fn C();
// --- decl_in_api_decl_and_definition_in_impl.carbon
library "[[@TEST_NAME]]";
fn D();
// --- fail_decl_in_api_decl_and_definition_in_impl.impl.carbon
impl library "[[@TEST_NAME]]";
// CHECK:STDERR: fail_decl_in_api_decl_and_definition_in_impl.impl.carbon:[[@LINE+8]]:1: error: redeclaration of `fn D` is redundant [RedeclRedundant]
// CHECK:STDERR: fn D();
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR: fail_decl_in_api_decl_and_definition_in_impl.impl.carbon:[[@LINE-5]]:1: in import [InImport]
// CHECK:STDERR: decl_in_api_decl_and_definition_in_impl.carbon:4:1: note: previously declared here [RedeclPrevDecl]
// CHECK:STDERR: fn D();
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR:
fn D();
fn D() {}
// --- decl_only_in_impl.carbon
library "[[@TEST_NAME]]";
@@ -70,7 +97,7 @@ library "[[@TEST_NAME]]";
impl library "[[@TEST_NAME]]";
// CHECK:STDERR: fail_decl_only_in_impl.impl.carbon:[[@LINE+4]]:1: error: no definition found for declaration in impl file [MissingDefinitionInImpl]
// CHECK:STDERR: fn D();
// CHECK:STDERR: fn E();
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR:
fn D();
fn E();
@@ -16,13 +16,10 @@ library "[[@TEST_NAME]]";
interface A;
// --- todo_fail_decl_in_api_definition_in_impl.impl.carbon
// --- decl_in_api_definition_in_impl.impl.carbon
impl library "[[@TEST_NAME]]";
// TODO: This should be diagnosed per #3762: A declaration should always add new information.
interface A;
interface A {}
// --- use_decl_in_api.carbon
@@ -55,12 +52,42 @@ interface C;
impl library "[[@TEST_NAME]]";
// CHECK:STDERR: fail_decl_in_api_decl_in_impl.impl.carbon:[[@LINE+12]]:1: error: redeclaration of `interface C` is redundant [RedeclRedundant]
// CHECK:STDERR: interface C;
// CHECK:STDERR: ^~~~~~~~~~~~
// CHECK:STDERR: fail_decl_in_api_decl_in_impl.impl.carbon:[[@LINE-5]]:1: in import [InImport]
// CHECK:STDERR: decl_in_api_decl_in_impl.carbon:4:1: note: previously declared here [RedeclPrevDecl]
// CHECK:STDERR: interface C;
// CHECK:STDERR: ^~~~~~~~~~~~
// CHECK:STDERR:
// CHECK:STDERR: fail_decl_in_api_decl_in_impl.impl.carbon:[[@LINE+4]]:1: error: no definition found for declaration in impl file [MissingDefinitionInImpl]
// CHECK:STDERR: interface C;
// CHECK:STDERR: ^~~~~~~~~~~~
// CHECK:STDERR:
interface C;
// --- decl_in_api_decl_and_definition_in_impl.carbon
library "[[@TEST_NAME]]";
interface D;
// --- fail_decl_in_api_decl_and_definition_in_impl.impl.carbon
impl library "[[@TEST_NAME]]";
// CHECK:STDERR: fail_decl_in_api_decl_and_definition_in_impl.impl.carbon:[[@LINE+8]]:1: error: redeclaration of `interface D` is redundant [RedeclRedundant]
// CHECK:STDERR: interface D;
// CHECK:STDERR: ^~~~~~~~~~~~
// CHECK:STDERR: fail_decl_in_api_decl_and_definition_in_impl.impl.carbon:[[@LINE-5]]:1: in import [InImport]
// CHECK:STDERR: decl_in_api_decl_and_definition_in_impl.carbon:4:1: note: previously declared here [RedeclPrevDecl]
// CHECK:STDERR: interface D;
// CHECK:STDERR: ^~~~~~~~~~~~
// CHECK:STDERR:
interface D;
interface D {}
// --- decl_only_in_impl.carbon
library "[[@TEST_NAME]]";
@@ -70,7 +97,7 @@ library "[[@TEST_NAME]]";
impl library "[[@TEST_NAME]]";
// CHECK:STDERR: fail_decl_only_in_impl.impl.carbon:[[@LINE+4]]:1: error: no definition found for declaration in impl file [MissingDefinitionInImpl]
// CHECK:STDERR: interface D;
// CHECK:STDERR: interface E;
// CHECK:STDERR: ^~~~~~~~~~~~
// CHECK:STDERR:
interface D;
interface E;