[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 <Nikolay.Lunyak@jetbrains.com>
This commit is contained in:
Nikolay Lunyak
2023-09-18 11:41:42 +00:00
committed by Space Team
parent 777df2d923
commit 93958ec73d
12 changed files with 95 additions and 14 deletions
@@ -825,6 +825,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia
runTest("compiler/testData/diagnostics/tests/NamedFunctionTypeParameterInSupertype.kt"); runTest("compiler/testData/diagnostics/tests/NamedFunctionTypeParameterInSupertype.kt");
} }
@Test
@TestMetadata("nestedClassConstructorVsMemberFunctionConflict.kt")
public void testNestedClassConstructorVsMemberFunctionConflict() throws Exception {
runTest("compiler/testData/diagnostics/tests/nestedClassConstructorVsMemberFunctionConflict.kt");
}
@Test @Test
@TestMetadata("noLibraryProvidersDuplication.kt") @TestMetadata("noLibraryProvidersDuplication.kt")
public void testNoLibraryProvidersDuplication() throws Exception { public void testNoLibraryProvidersDuplication() throws Exception {
@@ -825,6 +825,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated
runTest("compiler/testData/diagnostics/tests/NamedFunctionTypeParameterInSupertype.kt"); runTest("compiler/testData/diagnostics/tests/NamedFunctionTypeParameterInSupertype.kt");
} }
@Test
@TestMetadata("nestedClassConstructorVsMemberFunctionConflict.kt")
public void testNestedClassConstructorVsMemberFunctionConflict() throws Exception {
runTest("compiler/testData/diagnostics/tests/nestedClassConstructorVsMemberFunctionConflict.kt");
}
@Test @Test
@TestMetadata("noLibraryProvidersDuplication.kt") @TestMetadata("noLibraryProvidersDuplication.kt")
public void testNoLibraryProvidersDuplication() throws Exception { public void testNoLibraryProvidersDuplication() throws Exception {
@@ -825,6 +825,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir
runTest("compiler/testData/diagnostics/tests/NamedFunctionTypeParameterInSupertype.kt"); runTest("compiler/testData/diagnostics/tests/NamedFunctionTypeParameterInSupertype.kt");
} }
@Test
@TestMetadata("nestedClassConstructorVsMemberFunctionConflict.kt")
public void testNestedClassConstructorVsMemberFunctionConflict() throws Exception {
runTest("compiler/testData/diagnostics/tests/nestedClassConstructorVsMemberFunctionConflict.kt");
}
@Test @Test
@TestMetadata("noLibraryProvidersDuplication.kt") @TestMetadata("noLibraryProvidersDuplication.kt")
public void testNoLibraryProvidersDuplication() throws Exception { public void testNoLibraryProvidersDuplication() throws Exception {
@@ -825,6 +825,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia
runTest("compiler/testData/diagnostics/tests/NamedFunctionTypeParameterInSupertype.kt"); runTest("compiler/testData/diagnostics/tests/NamedFunctionTypeParameterInSupertype.kt");
} }
@Test
@TestMetadata("nestedClassConstructorVsMemberFunctionConflict.kt")
public void testNestedClassConstructorVsMemberFunctionConflict() throws Exception {
runTest("compiler/testData/diagnostics/tests/nestedClassConstructorVsMemberFunctionConflict.kt");
}
@Test @Test
@TestMetadata("noLibraryProvidersDuplication.kt") @TestMetadata("noLibraryProvidersDuplication.kt")
public void testNoLibraryProvidersDuplication() throws Exception { public void testNoLibraryProvidersDuplication() throws Exception {
@@ -159,7 +159,20 @@ fun FirDeclarationCollector<FirBasedSymbol<*>>.collectClassMembers(klass: FirReg
when (it) { when (it) {
is FirSimpleFunction -> collect(it.symbol, FirRedeclarationPresenter.represent(it.symbol), functionDeclarations) 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 FirTypeAlias -> collect(it.symbol, FirRedeclarationPresenter.represent(it.symbol), otherDeclarations)
is FirVariable -> collect(it.symbol, FirRedeclarationPresenter.represent(it.symbol), otherDeclarations) is FirVariable -> collect(it.symbol, FirRedeclarationPresenter.represent(it.symbol), otherDeclarations)
else -> {} else -> {}
@@ -59,7 +59,13 @@ object FirConflictsDeclarationChecker : FirBasicDeclarationChecker() {
declarationConflictingSymbols.forEach { (conflictingDeclaration, symbols) -> declarationConflictingSymbols.forEach { (conflictingDeclaration, symbols) ->
val typeAliasForConstructorSource = (conflictingDeclaration as? FirConstructorSymbol)?.typeAliasForConstructor?.source val typeAliasForConstructorSource = (conflictingDeclaration as? FirConstructorSymbol)?.typeAliasForConstructor?.source
val source = typeAliasForConstructorSource ?: conflictingDeclaration.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 = val factory =
if (conflictingDeclaration is FirNamedFunctionSymbol || conflictingDeclaration is FirConstructorSymbol) { 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<FirBasedSymbol<*>>, context: CheckerContext) { private fun checkFile(file: FirFile, inspector: FirDeclarationCollector<FirBasedSymbol<*>>, context: CheckerContext) {
val packageMemberScope: FirPackageMemberScope = context.sessionHolder.scopeSession.getOrBuild(file.packageFqName, PACKAGE_MEMBER) { val packageMemberScope: FirPackageMemberScope = context.sessionHolder.scopeSession.getOrBuild(file.packageFqName, PACKAGE_MEMBER) {
FirPackageMemberScope(file.packageFqName, context.sessionHolder.session) FirPackageMemberScope(file.packageFqName, context.sessionHolder.session)
@@ -0,0 +1,10 @@
// FIR_IDENTICAL
// ISSUE: KT-62005
class A {
class NestedInA<!CONFLICTING_OVERLOADS!>()<!>
<!CONFLICTING_OVERLOADS!>fun NestedInA()<!> {}
class <!CONFLICTING_OVERLOADS!>NestedInA2<!>
<!CONFLICTING_OVERLOADS!>fun NestedInA2()<!> {}
}
@@ -15,16 +15,16 @@ class a<!CONFLICTING_OVERLOADS!>()<!> { }
<!CONFLICTING_OVERLOADS!>fun a()<!> = 1 <!CONFLICTING_OVERLOADS!>fun a()<!> = 1
class Tram { class Tram {
fun f() { } <!CONFLICTING_OVERLOADS!>fun f()<!> { }
class f() { } class f<!CONFLICTING_OVERLOADS!>()<!> { }
} }
class Yvayva { class Yvayva {
companion object { companion object {
fun fghj() { } <!CONFLICTING_OVERLOADS!>fun fghj()<!> { }
class fghj() { } class fghj<!CONFLICTING_OVERLOADS!>()<!> { }
} }
} }
@@ -7,17 +7,21 @@ package kt2438
class B { class B {
class <!REDECLARATION!>C<!> class <!REDECLARATION!>C<!>
class <!REDECLARATION!>C<!> class <!REDECLARATION!>C<!>
class <!CONFLICTING_OVERLOADS, REDECLARATION!>D<!>
class <!CONFLICTING_OVERLOADS, REDECLARATION!>D<!>
<!CONFLICTING_OVERLOADS!>fun D()<!> {}
} }
class A { class A {
class <!REDECLARATION!>B<!> class <!REDECLARATION!>B<!>
companion object { companion object {
class <!REDECLARATION!>B<!> class <!REDECLARATION!>B<!>
class <!REDECLARATION!>B<!> class <!REDECLARATION!>B<!>
} }
class <!REDECLARATION!>B<!> class <!REDECLARATION!>B<!>
} }
@@ -46,6 +46,7 @@ package kt2438 {
public final class B { public final class B {
public constructor 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 equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String 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 hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String 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
}
} }
} }
@@ -13,15 +13,15 @@ class B {
<!CONFLICTING_OVERLOADS!>fun B(x: Int)<!> {} <!CONFLICTING_OVERLOADS!>fun B(x: Int)<!> {}
class Outer { class Outer {
class A(x: String = "", y: String = "") { class A<!CONFLICTING_OVERLOADS!>(x: String = "", y: String = "")<!> {
constructor(x: String, y: String): <!OVERLOAD_RESOLUTION_AMBIGUITY!>this<!>(x, y) <!CONFLICTING_OVERLOADS!>constructor(x: String, y: String)<!>: <!OVERLOAD_RESOLUTION_AMBIGUITY!>this<!>(x, y)
constructor(): <!OVERLOAD_RESOLUTION_AMBIGUITY!>this<!>("", "") <!CONFLICTING_OVERLOADS!>constructor()<!>: <!OVERLOAD_RESOLUTION_AMBIGUITY!>this<!>("", "")
constructor(): <!OVERLOAD_RESOLUTION_AMBIGUITY!>this<!>("", "") <!CONFLICTING_OVERLOADS!>constructor()<!>: <!OVERLOAD_RESOLUTION_AMBIGUITY!>this<!>("", "")
} }
class B { class B {
constructor(x: Int) <!CONFLICTING_OVERLOADS!>constructor(x: Int)<!>
} }
fun B(x: Int) {} <!CONFLICTING_OVERLOADS!>fun B(x: Int)<!> {}
} }
@@ -825,6 +825,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/NamedFunctionTypeParameterInSupertype.kt"); runTest("compiler/testData/diagnostics/tests/NamedFunctionTypeParameterInSupertype.kt");
} }
@Test
@TestMetadata("nestedClassConstructorVsMemberFunctionConflict.kt")
public void testNestedClassConstructorVsMemberFunctionConflict() throws Exception {
runTest("compiler/testData/diagnostics/tests/nestedClassConstructorVsMemberFunctionConflict.kt");
}
@Test @Test
@TestMetadata("noLibraryProvidersDuplication.kt") @TestMetadata("noLibraryProvidersDuplication.kt")
public void testNoLibraryProvidersDuplication() throws Exception { public void testNoLibraryProvidersDuplication() throws Exception {