[FIR] Report CONFLICTING_OVERLOADS for local functions

^KT-59186 Fixed
This commit is contained in:
Nikolay Lunyak
2023-08-09 12:14:10 +03:00
committed by Space Team
parent 6fa5363cf4
commit cf655fd5ad
10 changed files with 163 additions and 80 deletions
@@ -729,6 +729,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia
runTest("compiler/testData/diagnostics/tests/missedTypeArgumentsInAnnotationCall.kt");
}
@Test
@TestMetadata("missingConflictingOverloads.kt")
public void testMissingConflictingOverloads() throws Exception {
runTest("compiler/testData/diagnostics/tests/missingConflictingOverloads.kt");
}
@Test
@TestMetadata("missingIteratorMissing.kt")
public void testMissingIteratorMissing() throws Exception {
@@ -729,6 +729,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated
runTest("compiler/testData/diagnostics/tests/missedTypeArgumentsInAnnotationCall.kt");
}
@Test
@TestMetadata("missingConflictingOverloads.kt")
public void testMissingConflictingOverloads() throws Exception {
runTest("compiler/testData/diagnostics/tests/missingConflictingOverloads.kt");
}
@Test
@TestMetadata("missingIteratorMissing.kt")
public void testMissingIteratorMissing() throws Exception {
@@ -729,6 +729,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir
runTest("compiler/testData/diagnostics/tests/missedTypeArgumentsInAnnotationCall.kt");
}
@Test
@TestMetadata("missingConflictingOverloads.kt")
public void testMissingConflictingOverloads() throws Exception {
runTest("compiler/testData/diagnostics/tests/missingConflictingOverloads.kt");
}
@Test
@TestMetadata("missingIteratorMissing.kt")
public void testMissingIteratorMissing() throws Exception {
@@ -729,6 +729,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia
runTest("compiler/testData/diagnostics/tests/missedTypeArgumentsInAnnotationCall.kt");
}
@Test
@TestMetadata("missingConflictingOverloads.kt")
public void testMissingConflictingOverloads() throws Exception {
runTest("compiler/testData/diagnostics/tests/missingConflictingOverloads.kt");
}
@Test
@TestMetadata("missingIteratorMissing.kt")
public void testMissingIteratorMissing() throws Exception {
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.fir.declarations.FirOuterClassTypeParameterRef
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl.Companion.DEFAULT_STATUS_FOR_STATUSLESS_DECLARATIONS
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl.Companion.DEFAULT_STATUS_FOR_SUSPEND_MAIN_FUNCTION
import org.jetbrains.kotlin.fir.declarations.impl.modifiersRepresentation
import org.jetbrains.kotlin.fir.expressions.FirBlock
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
import org.jetbrains.kotlin.fir.scopes.impl.FirPackageMemberScope
@@ -140,6 +141,7 @@ fun FirDeclarationCollector<FirDeclaration>.collectClassMembers(klass: FirRegula
val otherDeclarations = mutableMapOf<String, MutableList<FirDeclaration>>()
val functionDeclarations = mutableMapOf<String, MutableList<FirDeclaration>>()
// TODO, KT-61243: Use declaredMemberScope
for (it in klass.declarations) {
if (!it.isCollectable()) continue
@@ -153,9 +155,32 @@ fun FirDeclarationCollector<FirDeclaration>.collectClassMembers(klass: FirRegula
}
}
private fun collect(declaration: FirDeclaration, representation: String, map: MutableMap<String, MutableList<FirDeclaration>>) {
map.getOrPut(representation, ::mutableListOf).also {
it.add(declaration)
fun collectConflictingLocalFunctionsFrom(block: FirBlock, context: CheckerContext): Map<FirFunction, Set<FirBasedSymbol<*>>> {
val collectables =
block.statements.filter {
(it is FirSimpleFunction || it is FirRegularClass) && (it as FirDeclaration).isCollectable()
}
if (collectables.isEmpty()) return emptyMap()
val inspector = FirDeclarationCollector<FirFunction>(context)
val functionDeclarations = mutableMapOf<String, MutableList<FirFunction>>()
for (collectable in collectables) {
when (collectable) {
is FirSimpleFunction ->
inspector.collect(collectable, FirRedeclarationPresenter.represent(collectable), functionDeclarations)
is FirRegularClass ->
// TODO, KT-61243: Use declaredMemberScope
collectable.declarations.filterIsInstance<FirConstructor>().forEach {
inspector.collect(it, FirRedeclarationPresenter.represent(it, collectable), functionDeclarations)
}
else -> {}
}
}
return inspector.declarationConflictingSymbols
}
private fun <D : FirDeclaration> FirDeclarationCollector<D>.collect(
declaration: D,
@@ -6,12 +6,28 @@
package org.jetbrains.kotlin.fir.analysis.checkers.expression
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.checkForLocalRedeclarations
import org.jetbrains.kotlin.fir.analysis.checkers.collectConflictingLocalFunctionsFrom
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.expressions.FirBlock
object FirConflictsExpressionChecker : FirBlockChecker() {
override fun check(expression: FirBlock, context: CheckerContext, reporter: DiagnosticReporter) {
checkForLocalRedeclarations(expression.statements, context, reporter)
checkForLocalConflictingFunctions(expression, context, reporter)
}
private fun checkForLocalConflictingFunctions(expression: FirBlock, context: CheckerContext, reporter: DiagnosticReporter) {
val conflictingFunctions = collectConflictingLocalFunctionsFrom(expression, context)
for ((function, otherFunctionsThatConflictWithIt) in conflictingFunctions) {
if (otherFunctionsThatConflictWithIt.isEmpty()) {
continue
}
reporter.reportOn(function.source, FirErrors.CONFLICTING_OVERLOADS, otherFunctionsThatConflictWithIt, context)
}
}
}
@@ -1,9 +1,9 @@
fun foo() {
class A
fun bar() {}
(fun bar() {})
fun A.foo() {}
(fun A.foo() {})
<!CONFLICTING_OVERLOADS!>fun bar()<!> {}
(<!CONFLICTING_OVERLOADS!>fun bar()<!> {})
<!CONFLICTING_OVERLOADS!>fun A.foo()<!> {}
(<!CONFLICTING_OVERLOADS!>fun A.foo()<!> {})
<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>run<!>(<!ANONYMOUS_FUNCTION_WITH_NAME!>fun foo() {}<!>)
}
@@ -0,0 +1,12 @@
// FIR_IDENTICAL
// ISSUE: KT-59186
fun main() {
<!CONFLICTING_OVERLOADS!>fun p () : Char<!> {
return 'c'
}
<!CONFLICTING_OVERLOADS!>fun p () : Float<!> {
return 13.0f
}
}
@@ -1,15 +1,15 @@
fun test() {
fun test1() {}
fun test1() {}
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
fun Any.test2() {}
fun test2(x: Any) = x
fun Any.test3() {}
fun Any.test3() {}
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
fun test4(): Int = 0
fun test4(): String = ""
<!CONFLICTING_OVERLOADS!>fun test4(): Int<!> = 0
<!CONFLICTING_OVERLOADS!>fun test4(): String<!> = ""
class Test5(val x: Int) {
constructor(): this(0)
@@ -18,17 +18,17 @@ fun test() {
fun Test5(x: Int) = x
fun local() {
fun test1() {}
fun test1() {}
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
fun Any.test2() {}
fun test2(x: Any) = x
fun Any.test3() {}
fun Any.test3() {}
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
fun test4(): Int = 0
fun test4(): String = ""
<!CONFLICTING_OVERLOADS!>fun test4(): Int<!> = 0
<!CONFLICTING_OVERLOADS!>fun test4(): String<!> = ""
class Test5(val x: Int) {
constructor(): this(0)
@@ -40,37 +40,37 @@ fun test() {
class Test {
init {
fun test1() {}
fun test1() {}
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
fun Any.test2() {}
fun test2(x: Any) = x
fun Any.test3() {}
fun Any.test3() {}
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
fun test4(): Int = 0
fun test4(): String = ""
<!CONFLICTING_OVERLOADS!>fun test4(): Int<!> = 0
<!CONFLICTING_OVERLOADS!>fun test4(): String<!> = ""
class Test5(val x: Int) {
constructor(): this(0)
class Test5<!CONFLICTING_OVERLOADS!>(val x: Int)<!> {
<!CONFLICTING_OVERLOADS!>constructor()<!>: this(0)
}
fun Test5() {}
fun Test5(x: Int) = x
<!CONFLICTING_OVERLOADS!>fun Test5()<!> {}
<!CONFLICTING_OVERLOADS!>fun Test5(x: Int)<!> = x
}
fun test() {
fun test1() {}
fun test1() {}
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
fun Any.test2() {}
fun test2(x: Any) = x
fun Any.test3() {}
fun Any.test3() {}
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
fun test4(): Int = 0
fun test4(): String = ""
<!CONFLICTING_OVERLOADS!>fun test4(): Int<!> = 0
<!CONFLICTING_OVERLOADS!>fun test4(): String<!> = ""
class Test5(val x: Int) {
constructor(): this(0)
@@ -80,17 +80,17 @@ class Test {
}
val property: Any get() {
fun test1() {}
fun test1() {}
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
fun Any.test2() {}
fun test2(x: Any) = x
fun Any.test3() {}
fun Any.test3() {}
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
fun test4(): Int = 0
fun test4(): String = ""
<!CONFLICTING_OVERLOADS!>fun test4(): Int<!> = 0
<!CONFLICTING_OVERLOADS!>fun test4(): String<!> = ""
class Test5(val x: Int) {
constructor(): this(0)
@@ -103,17 +103,17 @@ class Test {
}
val property: Any get() {
fun test1() {}
fun test1() {}
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
fun Any.test2() {}
fun test2(x: Any) = x
fun Any.test3() {}
fun Any.test3() {}
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
fun test4(): Int = 0
fun test4(): String = ""
<!CONFLICTING_OVERLOADS!>fun test4(): Int<!> = 0
<!CONFLICTING_OVERLOADS!>fun test4(): String<!> = ""
class Test5(val x: Int) {
constructor(): this(0)
@@ -126,17 +126,17 @@ val property: Any get() {
object Object {
fun test() {
fun test1() {}
fun test1() {}
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
fun Any.test2() {}
fun test2(x: Any) = x
fun Any.test3() {}
fun Any.test3() {}
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
fun test4(): Int = 0
fun test4(): String = ""
<!CONFLICTING_OVERLOADS!>fun test4(): Int<!> = 0
<!CONFLICTING_OVERLOADS!>fun test4(): String<!> = ""
class Test5(val x: Int) {
constructor(): this(0)
@@ -146,17 +146,17 @@ object Object {
}
val property: Any get() {
fun test1() {}
fun test1() {}
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
fun Any.test2() {}
fun test2(x: Any) = x
fun Any.test3() {}
fun Any.test3() {}
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
fun test4(): Int = 0
fun test4(): String = ""
<!CONFLICTING_OVERLOADS!>fun test4(): Int<!> = 0
<!CONFLICTING_OVERLOADS!>fun test4(): String<!> = ""
class Test5(val x: Int) {
constructor(): this(0)
@@ -170,44 +170,44 @@ object Object {
val obj = object {
fun test() {
fun test1() {}
fun test1() {}
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
fun Any.test2() {}
fun test2(x: Any) = x
fun Any.test3() {}
fun Any.test3() {}
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
fun test4(): Int = 0
fun test4(): String = ""
<!CONFLICTING_OVERLOADS!>fun test4(): Int<!> = 0
<!CONFLICTING_OVERLOADS!>fun test4(): String<!> = ""
class Test5(val x: Int) {
constructor(): this(0)
class Test5<!CONFLICTING_OVERLOADS!>(val x: Int)<!> {
<!CONFLICTING_OVERLOADS!>constructor()<!>: this(0)
}
fun Test5() {}
fun Test5(x: Int) = x
<!CONFLICTING_OVERLOADS!>fun Test5()<!> {}
<!CONFLICTING_OVERLOADS!>fun Test5(x: Int)<!> = x
}
val property: Any get() {
fun test1() {}
fun test1() {}
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
fun Any.test2() {}
fun test2(x: Any) = x
fun Any.test3() {}
fun Any.test3() {}
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
fun test4(): Int = 0
fun test4(): String = ""
<!CONFLICTING_OVERLOADS!>fun test4(): Int<!> = 0
<!CONFLICTING_OVERLOADS!>fun test4(): String<!> = ""
class Test5(val x: Int) {
constructor(): this(0)
class Test5<!CONFLICTING_OVERLOADS!>(val x: Int)<!> {
<!CONFLICTING_OVERLOADS!>constructor()<!>: this(0)
}
fun Test5() {}
fun Test5(x: Int) = x
<!CONFLICTING_OVERLOADS!>fun Test5()<!> {}
<!CONFLICTING_OVERLOADS!>fun Test5(x: Int)<!> = x
return 0
}
}
}
@@ -729,6 +729,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/missedTypeArgumentsInAnnotationCall.kt");
}
@Test
@TestMetadata("missingConflictingOverloads.kt")
public void testMissingConflictingOverloads() throws Exception {
runTest("compiler/testData/diagnostics/tests/missingConflictingOverloads.kt");
}
@Test
@TestMetadata("missingIteratorMissing.kt")
public void testMissingIteratorMissing() throws Exception {