FIR: look for conflicting declarations more precisely
This commit is contained in:
committed by
teamcity
parent
3092a84b6b
commit
4737bb07df
+2
-2
@@ -61,9 +61,9 @@ class L {
|
|||||||
fun B.foo() {}
|
fun B.foo() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun mest() {}
|
<!CONFLICTING_OVERLOADS!>fun mest()<!> {}
|
||||||
|
|
||||||
class mest
|
class <!CONFLICTING_OVERLOADS!>mest<!>
|
||||||
|
|
||||||
<!FUNCTION_DECLARATION_WITH_NO_NAME!>fun()<!> {}
|
<!FUNCTION_DECLARATION_WITH_NO_NAME!>fun()<!> {}
|
||||||
|
|
||||||
|
|||||||
+11
-3
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||||
|
|
||||||
import org.jetbrains.kotlin.KtFakeSourceElementKind
|
import org.jetbrains.kotlin.KtFakeSourceElementKind
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.fir.*
|
import org.jetbrains.kotlin.fir.*
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.FirDeclarationInspector
|
import org.jetbrains.kotlin.fir.analysis.checkers.FirDeclarationInspector
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.FirDeclarationPresenter
|
import org.jetbrains.kotlin.fir.analysis.checkers.FirDeclarationPresenter
|
||||||
@@ -95,13 +96,18 @@ object FirConflictsChecker : FirBasicDeclarationChecker() {
|
|||||||
is FirCallableSymbol<*> -> session.firProvider.getFirCallableContainerFile(conflictingSymbol)
|
is FirCallableSymbol<*> -> session.firProvider.getFirCallableContainerFile(conflictingSymbol)
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
if (containingFile == actualConflictingFile) return // TODO: rewrite local decls checker to the same logic and then remove the check
|
if (containingFile == actualConflictingFile && conflicting.origin == FirDeclarationOrigin.Precompiled) {
|
||||||
|
return // TODO: rewrite local decls checker to the same logic and then remove the check
|
||||||
|
}
|
||||||
if (areCompatibleMainFunctions(declaration, containingFile, conflicting, actualConflictingFile)) return
|
if (areCompatibleMainFunctions(declaration, containingFile, conflicting, actualConflictingFile)) return
|
||||||
if (isExpectAndActual(declaration, conflicting)) return
|
if (isExpectAndActual(declaration, conflicting)) return
|
||||||
if (
|
if (
|
||||||
conflicting is FirMemberDeclaration &&
|
conflicting is FirMemberDeclaration &&
|
||||||
!session.visibilityChecker.isVisible(conflicting, session, containingFile, emptyList(), null)
|
!session.visibilityChecker.isVisible(conflicting, session, containingFile, emptyList(), null)
|
||||||
) return
|
) return
|
||||||
|
val declarationIsLowPriority = hasLowPriorityAnnotation(declaration.annotations)
|
||||||
|
val conflictingIsLowPriority = hasLowPriorityAnnotation(conflicting.annotations)
|
||||||
|
if (declarationIsLowPriority != conflictingIsLowPriority) return
|
||||||
declarationConflictingSymbols.getOrPut(declaration) { SmartSet.create() }.add(conflictingSymbol)
|
declarationConflictingSymbols.getOrPut(declaration) { SmartSet.create() }.add(conflictingSymbol)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,7 +361,7 @@ class FirNameConflictsTracker : FirNameConflictsTrackerComponent() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun FirDeclaration.onConstructors(action: (ctor: FirConstructor) -> Unit) {
|
private fun FirRegularClass.onConstructors(action: (ctor: FirConstructor) -> Unit) {
|
||||||
|
|
||||||
class ClassConstructorVisitor : FirVisitorVoid() {
|
class ClassConstructorVisitor : FirVisitorVoid() {
|
||||||
override fun visitElement(element: FirElement) {}
|
override fun visitElement(element: FirElement) {}
|
||||||
@@ -370,7 +376,9 @@ private fun FirDeclaration.onConstructors(action: (ctor: FirConstructor) -> Unit
|
|||||||
override fun visitSimpleFunction(simpleFunction: FirSimpleFunction) {}
|
override fun visitSimpleFunction(simpleFunction: FirSimpleFunction) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
acceptChildren(ClassConstructorVisitor())
|
if (classKind != ClassKind.OBJECT && classKind != ClassKind.ENUM_ENTRY) {
|
||||||
|
acceptChildren(ClassConstructorVisitor())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
|||||||
import org.jetbrains.kotlin.fir.types.coneType
|
import org.jetbrains.kotlin.fir.types.coneType
|
||||||
import org.jetbrains.kotlin.fir.types.coneTypeSafe
|
import org.jetbrains.kotlin.fir.types.coneTypeSafe
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.name.StandardClassIds
|
import org.jetbrains.kotlin.name.StandardClassIds
|
||||||
|
|
||||||
@@ -186,3 +187,11 @@ val FirAnnotation.resolved: Boolean
|
|||||||
if (this !is FirAnnotationCall) return true
|
if (this !is FirAnnotationCall) return true
|
||||||
return calleeReference is FirResolvedNamedReference || calleeReference is FirErrorNamedReference
|
return calleeReference is FirResolvedNamedReference || calleeReference is FirErrorNamedReference
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val LOW_PRIORITY_IN_OVERLOAD_RESOLUTION_CLASS_ID: ClassId =
|
||||||
|
ClassId(FqName("kotlin.internal"), Name.identifier("LowPriorityInOverloadResolution"))
|
||||||
|
|
||||||
|
fun hasLowPriorityAnnotation(annotations: List<FirAnnotation>) = annotations.any {
|
||||||
|
val lookupTag = it.annotationTypeRef.coneTypeSafe<ConeClassLikeType>()?.lookupTag ?: return@any false
|
||||||
|
lookupTag.classId == LOW_PRIORITY_IN_OVERLOAD_RESOLUTION_CLASS_ID
|
||||||
|
}
|
||||||
|
|||||||
+1
-12
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.fir.resolve.calls
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.fir.FirVisibilityChecker
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isInfix
|
import org.jetbrains.kotlin.fir.declarations.utils.isInfix
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isOperator
|
import org.jetbrains.kotlin.fir.declarations.utils.isOperator
|
||||||
@@ -33,8 +32,6 @@ import org.jetbrains.kotlin.fir.symbols.impl.*
|
|||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.fir.visibilityChecker
|
import org.jetbrains.kotlin.fir.visibilityChecker
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
|
||||||
import org.jetbrains.kotlin.name.Name
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.isSubtypeConstraintCompatible
|
import org.jetbrains.kotlin.resolve.calls.inference.isSubtypeConstraintCompatible
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.SimpleConstraintSystemConstraintPosition
|
import org.jetbrains.kotlin.resolve.calls.inference.model.SimpleConstraintSystemConstraintPosition
|
||||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.*
|
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.*
|
||||||
@@ -542,9 +539,6 @@ internal object CheckVisibility : CheckerStage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal object CheckLowPriorityInOverloadResolution : CheckerStage() {
|
internal object CheckLowPriorityInOverloadResolution : CheckerStage() {
|
||||||
private val LOW_PRIORITY_IN_OVERLOAD_RESOLUTION_CLASS_ID: ClassId =
|
|
||||||
ClassId(FqName("kotlin.internal"), Name.identifier("LowPriorityInOverloadResolution"))
|
|
||||||
|
|
||||||
override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) {
|
override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) {
|
||||||
val annotations = when (val fir = candidate.symbol.fir) {
|
val annotations = when (val fir = candidate.symbol.fir) {
|
||||||
is FirSimpleFunction -> fir.annotations
|
is FirSimpleFunction -> fir.annotations
|
||||||
@@ -553,12 +547,7 @@ internal object CheckLowPriorityInOverloadResolution : CheckerStage() {
|
|||||||
else -> return
|
else -> return
|
||||||
}
|
}
|
||||||
|
|
||||||
val hasLowPriorityAnnotation = annotations.any {
|
if (hasLowPriorityAnnotation(annotations)) {
|
||||||
val lookupTag = it.annotationTypeRef.coneTypeSafe<ConeClassLikeType>()?.lookupTag ?: return@any false
|
|
||||||
lookupTag.classId == LOW_PRIORITY_IN_OVERLOAD_RESOLUTION_CLASS_ID
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasLowPriorityAnnotation) {
|
|
||||||
sink.reportDiagnostic(ResolvedWithLowPriority)
|
sink.reportDiagnostic(ResolvedWithLowPriority)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
package constructorVsFun
|
package constructorVsFun
|
||||||
|
|
||||||
class a() { }
|
class a<!CONFLICTING_OVERLOADS!>()<!> { }
|
||||||
|
|
||||||
fun a() = 1
|
<!CONFLICTING_OVERLOADS!>fun a()<!> = 1
|
||||||
|
|
||||||
class Tram {
|
class Tram {
|
||||||
fun f() { }
|
fun f() { }
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@ object Foo {
|
|||||||
|
|
||||||
fun En() = 239
|
fun En() = 239
|
||||||
|
|
||||||
enum class En {
|
enum class <!CONFLICTING_OVERLOADS!>En<!> {
|
||||||
ENTRY,
|
ENTRY,
|
||||||
|
|
||||||
SUBCLASS { };
|
SUBCLASS { };
|
||||||
|
|||||||
-34
@@ -1,34 +0,0 @@
|
|||||||
//If this test hangs, it means something is broken.
|
|
||||||
package c
|
|
||||||
|
|
||||||
fun z(view: () -> Unit) {}
|
|
||||||
|
|
||||||
<!CONFLICTING_OVERLOADS!>fun x()<!> = z { z { z { z { z { z { z { z { } } } } } } } }
|
|
||||||
<!CONFLICTING_OVERLOADS!>fun x()<!> = z { z { z { z { z { z { z { z { } } } } } } } }
|
|
||||||
<!CONFLICTING_OVERLOADS!>fun x()<!> = z { z { z { z { z { z { z { z { } } } } } } } }
|
|
||||||
<!CONFLICTING_OVERLOADS!>fun x()<!> = z { z { z { z { z { z { z { z { } } } } } } } }
|
|
||||||
<!CONFLICTING_OVERLOADS!>fun x()<!> = z { z { z { z { z { z { z { z { } } } } } } } }
|
|
||||||
<!CONFLICTING_OVERLOADS!>fun x()<!> = z { z { z { z { z { z { z { z { } } } } } } } }
|
|
||||||
<!CONFLICTING_OVERLOADS!>fun x()<!> = z { z { z { z { z { z { z { z { } } } } } } } }
|
|
||||||
<!CONFLICTING_OVERLOADS!>fun x()<!> = z { z { z { z { z { z { z { z { } } } } } } } }
|
|
||||||
<!CONFLICTING_OVERLOADS!>fun x()<!> = z { z { z { z { z { z { z { z { } } } } } } } }
|
|
||||||
<!CONFLICTING_OVERLOADS!>fun x()<!> = z { z { z { z { z { z { z { z { } } } } } } } }
|
|
||||||
<!CONFLICTING_OVERLOADS!>fun x()<!> = z { z { z { z { z { z { z { z { } } } } } } } }
|
|
||||||
<!CONFLICTING_OVERLOADS!>fun x()<!> = z { z { z { z { z { z { z { z { } } } } } } } }
|
|
||||||
<!CONFLICTING_OVERLOADS!>fun x()<!> = z { z { z { z { z { z { z { z { } } } } } } } }
|
|
||||||
<!CONFLICTING_OVERLOADS!>fun x()<!> = z { z { z { z { z { z { z { z { } } } } } } } }
|
|
||||||
<!CONFLICTING_OVERLOADS!>fun x()<!> = z { z { z { z { z { z { z { z { } } } } } } } }
|
|
||||||
<!CONFLICTING_OVERLOADS!>fun x()<!> = z { z { z { z { z { z { z { z { } } } } } } } }
|
|
||||||
<!CONFLICTING_OVERLOADS!>fun x()<!> = z { z { z { z { z { z { z { z { } } } } } } } }
|
|
||||||
<!CONFLICTING_OVERLOADS!>fun x()<!> = z { z { z { z { z { z { z { z { } } } } } } } }
|
|
||||||
<!CONFLICTING_OVERLOADS!>fun x()<!> = z { z { z { z { z { z { z { z { } } } } } } } }
|
|
||||||
<!CONFLICTING_OVERLOADS!>fun x()<!> = z { z { z { z { z { z { z { z { } } } } } } } }
|
|
||||||
<!CONFLICTING_OVERLOADS!>fun x()<!> = z { z { z { z { z { z { z { z { } } } } } } } }
|
|
||||||
<!CONFLICTING_OVERLOADS!>fun x()<!> = z { z { z { z { z { z { z { z { } } } } } } } }
|
|
||||||
<!CONFLICTING_OVERLOADS!>fun x()<!> = z { z { z { z { z { z { z { z { } } } } } } } }
|
|
||||||
<!CONFLICTING_OVERLOADS!>fun x()<!> = z { z { z { z { z { z { z { z { } } } } } } } }
|
|
||||||
<!CONFLICTING_OVERLOADS!>fun x()<!> = z { z { z { z { z { z { z { z { } } } } } } } }
|
|
||||||
<!CONFLICTING_OVERLOADS!>fun x()<!> = z { z { z { z { z { z { z { z { } } } } } } } }
|
|
||||||
<!CONFLICTING_OVERLOADS!>fun x()<!> = z { z { z { z { z { z { z { z { } } } } } } } }
|
|
||||||
|
|
||||||
class x() {}
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
//If this test hangs, it means something is broken.
|
//If this test hangs, it means something is broken.
|
||||||
package c
|
package c
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -7,10 +7,10 @@ class A(x: String = "", y: String = "") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class B {
|
class B {
|
||||||
constructor(x: Int)
|
<!CONFLICTING_OVERLOADS!>constructor(x: Int)<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
fun B(x: Int) {}
|
<!CONFLICTING_OVERLOADS!>fun B(x: Int)<!> {}
|
||||||
|
|
||||||
class Outer {
|
class Outer {
|
||||||
class A(x: String = "", y: String = "") {
|
class A(x: String = "", y: String = "") {
|
||||||
|
|||||||
Reference in New Issue
Block a user