[FIR] Report CONFLICTING_OVERLOADS for local functions
^KT-59186 Fixed
This commit is contained in:
committed by
Space Team
parent
6fa5363cf4
commit
cf655fd5ad
+6
@@ -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 {
|
||||
|
||||
+6
@@ -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 {
|
||||
|
||||
+6
@@ -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 {
|
||||
|
||||
+6
@@ -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 {
|
||||
|
||||
+28
-3
@@ -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,
|
||||
|
||||
+16
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+6
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user