From 93958ec73d7efd6f98b772e9b8b4d2ac95a21c0d Mon Sep 17 00:00:00 2001 From: Nikolay Lunyak Date: Mon, 18 Sep 2023 11:41:42 +0000 Subject: [PATCH] [FIR] Check conflicts between nested classes' constructors and member functions For an example of an object with an implicit primary constructor, see `FirPsiOldFrontendDiagnosticsTestGenerated.testSingletonAndFunctionSameName`. ^KT-62005 Fixed Merge-request: KT-MR-12242 Merged-by: Nikolay Lunyak --- ...ticCompilerTestFE10TestdataTestGenerated.java | 6 ++++++ ...gnosticCompilerFE10TestDataTestGenerated.java | 6 ++++++ ...tTreeOldFrontendDiagnosticsTestGenerated.java | 6 ++++++ ...irPsiOldFrontendDiagnosticsTestGenerated.java | 6 ++++++ .../fir/analysis/checkers/FirConflictsHelpers.kt | 15 ++++++++++++++- .../FirConflictsDeclarationChecker.kt | 10 +++++++++- ...edClassConstructorVsMemberFunctionConflict.kt | 10 ++++++++++ .../overload/ConstructorVsFunOverload.fir.kt | 8 ++++---- .../diagnostics/tests/redeclarations/kt2438.kt | 8 ++++++-- .../diagnostics/tests/redeclarations/kt2438.txt | 16 ++++++++++++++++ .../secondaryConstructors/redeclarations.fir.kt | 12 ++++++------ .../test/runners/DiagnosticTestGenerated.java | 6 ++++++ 12 files changed, 95 insertions(+), 14 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/nestedClassConstructorVsMemberFunctionConflict.kt diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java index 18cc3b3ce6f..97e71074dfa 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java @@ -825,6 +825,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia runTest("compiler/testData/diagnostics/tests/NamedFunctionTypeParameterInSupertype.kt"); } + @Test + @TestMetadata("nestedClassConstructorVsMemberFunctionConflict.kt") + public void testNestedClassConstructorVsMemberFunctionConflict() throws Exception { + runTest("compiler/testData/diagnostics/tests/nestedClassConstructorVsMemberFunctionConflict.kt"); + } + @Test @TestMetadata("noLibraryProvidersDuplication.kt") public void testNoLibraryProvidersDuplication() throws Exception { diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java index d5b4196ace6..0137f1e8ccb 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java @@ -825,6 +825,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated runTest("compiler/testData/diagnostics/tests/NamedFunctionTypeParameterInSupertype.kt"); } + @Test + @TestMetadata("nestedClassConstructorVsMemberFunctionConflict.kt") + public void testNestedClassConstructorVsMemberFunctionConflict() throws Exception { + runTest("compiler/testData/diagnostics/tests/nestedClassConstructorVsMemberFunctionConflict.kt"); + } + @Test @TestMetadata("noLibraryProvidersDuplication.kt") public void testNoLibraryProvidersDuplication() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java index 5e7bd803b76..973edb2679d 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java @@ -825,6 +825,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir runTest("compiler/testData/diagnostics/tests/NamedFunctionTypeParameterInSupertype.kt"); } + @Test + @TestMetadata("nestedClassConstructorVsMemberFunctionConflict.kt") + public void testNestedClassConstructorVsMemberFunctionConflict() throws Exception { + runTest("compiler/testData/diagnostics/tests/nestedClassConstructorVsMemberFunctionConflict.kt"); + } + @Test @TestMetadata("noLibraryProvidersDuplication.kt") public void testNoLibraryProvidersDuplication() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java index 337e0ac6a77..7d107442ff5 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java @@ -825,6 +825,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia runTest("compiler/testData/diagnostics/tests/NamedFunctionTypeParameterInSupertype.kt"); } + @Test + @TestMetadata("nestedClassConstructorVsMemberFunctionConflict.kt") + public void testNestedClassConstructorVsMemberFunctionConflict() throws Exception { + runTest("compiler/testData/diagnostics/tests/nestedClassConstructorVsMemberFunctionConflict.kt"); + } + @Test @TestMetadata("noLibraryProvidersDuplication.kt") public void testNoLibraryProvidersDuplication() throws Exception { diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirConflictsHelpers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirConflictsHelpers.kt index 4711849deab..03d70a31977 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirConflictsHelpers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirConflictsHelpers.kt @@ -159,7 +159,20 @@ fun FirDeclarationCollector>.collectClassMembers(klass: FirReg when (it) { is FirSimpleFunction -> collect(it.symbol, FirRedeclarationPresenter.represent(it.symbol), functionDeclarations) - is FirRegularClass -> collect(it.symbol, FirRedeclarationPresenter.represent(it.symbol), otherDeclarations) + is FirRegularClass -> { + collect(it.symbol, FirRedeclarationPresenter.represent(it.symbol), otherDeclarations) + + // Objects have implicit FirPrimaryConstructors + if (it.symbol.classKind == ClassKind.OBJECT) { + continue + } + + it.symbol.expandedClassWithConstructorsScope(context)?.let { (_, scopeWithConstructors) -> + scopeWithConstructors.processDeclaredConstructors { constructor -> + collect(constructor, FirRedeclarationPresenter.represent(constructor, it.symbol), functionDeclarations) + } + } + } is FirTypeAlias -> collect(it.symbol, FirRedeclarationPresenter.represent(it.symbol), otherDeclarations) is FirVariable -> collect(it.symbol, FirRedeclarationPresenter.represent(it.symbol), otherDeclarations) else -> {} diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirConflictsDeclarationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirConflictsDeclarationChecker.kt index eb7c44c3274..fa149de3e46 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirConflictsDeclarationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirConflictsDeclarationChecker.kt @@ -59,7 +59,13 @@ object FirConflictsDeclarationChecker : FirBasicDeclarationChecker() { declarationConflictingSymbols.forEach { (conflictingDeclaration, symbols) -> val typeAliasForConstructorSource = (conflictingDeclaration as? FirConstructorSymbol)?.typeAliasForConstructor?.source val source = typeAliasForConstructorSource ?: conflictingDeclaration.source - if (symbols.isEmpty()) return@forEach + if ( + symbols.isEmpty() || + // For every implicit constructor there is a parent, + // FirRegularClass declaration, and those clash too, + // resulting in REDECLARATION. + conflictingDeclaration.isImplicitConstructor && symbols.all { it.isImplicitConstructor } + ) return@forEach val factory = if (conflictingDeclaration is FirNamedFunctionSymbol || conflictingDeclaration is FirConstructorSymbol) { @@ -77,6 +83,8 @@ object FirConflictsDeclarationChecker : FirBasicDeclarationChecker() { } } + private val FirBasedSymbol<*>.isImplicitConstructor get() = source?.kind is KtFakeSourceElementKind.ImplicitConstructor + private fun checkFile(file: FirFile, inspector: FirDeclarationCollector>, context: CheckerContext) { val packageMemberScope: FirPackageMemberScope = context.sessionHolder.scopeSession.getOrBuild(file.packageFqName, PACKAGE_MEMBER) { FirPackageMemberScope(file.packageFqName, context.sessionHolder.session) diff --git a/compiler/testData/diagnostics/tests/nestedClassConstructorVsMemberFunctionConflict.kt b/compiler/testData/diagnostics/tests/nestedClassConstructorVsMemberFunctionConflict.kt new file mode 100644 index 00000000000..bc3c1d58946 --- /dev/null +++ b/compiler/testData/diagnostics/tests/nestedClassConstructorVsMemberFunctionConflict.kt @@ -0,0 +1,10 @@ +// FIR_IDENTICAL +// ISSUE: KT-62005 + +class A { + class NestedInA() + fun NestedInA() {} + + class NestedInA2 + fun NestedInA2() {} +} diff --git a/compiler/testData/diagnostics/tests/overload/ConstructorVsFunOverload.fir.kt b/compiler/testData/diagnostics/tests/overload/ConstructorVsFunOverload.fir.kt index 017df6c37dc..f9e3b17f7a1 100644 --- a/compiler/testData/diagnostics/tests/overload/ConstructorVsFunOverload.fir.kt +++ b/compiler/testData/diagnostics/tests/overload/ConstructorVsFunOverload.fir.kt @@ -15,16 +15,16 @@ class a() { } fun a() = 1 class Tram { - fun f() { } + fun f() { } - class f() { } + class f() { } } class Yvayva { companion object { - fun fghj() { } + fun fghj() { } - class fghj() { } + class fghj() { } } } diff --git a/compiler/testData/diagnostics/tests/redeclarations/kt2438.kt b/compiler/testData/diagnostics/tests/redeclarations/kt2438.kt index 2952251a5fe..625553d94a5 100644 --- a/compiler/testData/diagnostics/tests/redeclarations/kt2438.kt +++ b/compiler/testData/diagnostics/tests/redeclarations/kt2438.kt @@ -7,17 +7,21 @@ package kt2438 class B { class C class C + + class D + class D + fun D() {} } class A { class B - + companion object { class B class B } - + class B } diff --git a/compiler/testData/diagnostics/tests/redeclarations/kt2438.txt b/compiler/testData/diagnostics/tests/redeclarations/kt2438.txt index 24186c28411..679e9ffecfe 100644 --- a/compiler/testData/diagnostics/tests/redeclarations/kt2438.txt +++ b/compiler/testData/diagnostics/tests/redeclarations/kt2438.txt @@ -46,6 +46,7 @@ package kt2438 { public final class B { public constructor B() + public final fun D(): kotlin.Unit public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String @@ -63,5 +64,20 @@ package kt2438 { public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } + + public final class D { + public constructor D() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + public final class D { + public constructor D() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } } } + diff --git a/compiler/testData/diagnostics/tests/secondaryConstructors/redeclarations.fir.kt b/compiler/testData/diagnostics/tests/secondaryConstructors/redeclarations.fir.kt index adcde08d4c4..e9b668ea62f 100644 --- a/compiler/testData/diagnostics/tests/secondaryConstructors/redeclarations.fir.kt +++ b/compiler/testData/diagnostics/tests/secondaryConstructors/redeclarations.fir.kt @@ -13,15 +13,15 @@ class B { fun B(x: Int) {} class Outer { - class A(x: String = "", y: String = "") { - constructor(x: String, y: String): this(x, y) - constructor(): this("", "") - constructor(): this("", "") + class A(x: String = "", y: String = "") { + constructor(x: String, y: String): this(x, y) + constructor(): this("", "") + constructor(): this("", "") } class B { - constructor(x: Int) + constructor(x: Int) } - fun B(x: Int) {} + fun B(x: Int) {} } diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java index 965afb75033..d99dac657ad 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java @@ -825,6 +825,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/NamedFunctionTypeParameterInSupertype.kt"); } + @Test + @TestMetadata("nestedClassConstructorVsMemberFunctionConflict.kt") + public void testNestedClassConstructorVsMemberFunctionConflict() throws Exception { + runTest("compiler/testData/diagnostics/tests/nestedClassConstructorVsMemberFunctionConflict.kt"); + } + @Test @TestMetadata("noLibraryProvidersDuplication.kt") public void testNoLibraryProvidersDuplication() throws Exception {