[FIR] Only check conflicting callables that may clash with declared ones

This change improves performance, as
checking callables via scopes in
`4e587157` turns out to be quite
slow, and it also prevents some redundant
diagnostics.
This commit is contained in:
Nikolay Lunyak
2023-10-16 14:07:06 +03:00
committed by Space Team
parent 9e57aba448
commit 44d6d10233
4 changed files with 40 additions and 81 deletions
@@ -153,11 +153,20 @@ class FirDeclarationCollector<D : FirBasedSymbol<*>>(
fun FirDeclarationCollector<FirBasedSymbol<*>>.collectClassMembers(klass: FirRegularClassSymbol) {
val otherDeclarations = mutableMapOf<String, MutableList<FirBasedSymbol<*>>>()
val functionDeclarations = mutableMapOf<String, MutableList<FirBasedSymbol<*>>>()
val scope = klass.unsubstitutedScope(context)
val declaredMemberScope = klass.declaredMemberScope(context)
val unsubstitutedScope = klass.unsubstitutedScope(context)
scope.collectLeafFunctions().forEach {
if (it.isCollectable() && it.isVisibleInClass(klass)) {
collect(it, FirRedeclarationPresenter.represent(it), functionDeclarations)
declaredMemberScope.processAllFunctions { declaredFunction ->
if (!declaredFunction.isCollectable()) {
return@processAllFunctions
}
collect(declaredFunction, FirRedeclarationPresenter.represent(declaredFunction), functionDeclarations)
unsubstitutedScope.collectLeafFunctionsByName(declaredFunction.name).forEach { anotherFunction ->
if (anotherFunction != declaredFunction && anotherFunction.isCollectable() && anotherFunction.isVisibleInClass(klass)) {
collect(anotherFunction, FirRedeclarationPresenter.represent(anotherFunction), functionDeclarations)
}
}
}
@@ -167,25 +176,24 @@ fun FirDeclarationCollector<FirBasedSymbol<*>>.collectClassMembers(klass: FirReg
// with functions from this outer class,
// so we should avoid checking them twice.
if (context.isTopLevel) {
scope.processDeclaredConstructors {
unsubstitutedScope.processDeclaredConstructors {
if (it.isCollectable() && it.isVisibleInClass(klass)) {
collect(it, FirRedeclarationPresenter.represent(it, klass), functionDeclarations)
}
}
}
val visitedProperties = mutableSetOf<FirVariableSymbol<*>>()
scope.collectLeafProperties().forEach {
if (it.isCollectable() && it.isVisibleInClass(klass)) {
collect(it, FirRedeclarationPresenter.represent(it), otherDeclarations)
declaredMemberScope.processAllProperties { declaredProperty ->
if (!declaredProperty.isCollectable()) {
return@processAllProperties
}
visitedProperties.add(it)
}
klass.declaredMemberScope(context).processAllProperties {
if (it !in visitedProperties && it.isCollectable()) {
collect(it, FirRedeclarationPresenter.represent(it), otherDeclarations)
collect(declaredProperty, FirRedeclarationPresenter.represent(declaredProperty), otherDeclarations)
unsubstitutedScope.collectLeafPropertiesByName(declaredProperty.name).forEach { anotherProperty ->
if (anotherProperty != declaredProperty && anotherProperty.isCollectable() && anotherProperty.isVisibleInClass(klass)) {
collect(anotherProperty, FirRedeclarationPresenter.represent(anotherProperty), otherDeclarations)
}
}
}
@@ -216,25 +224,30 @@ fun FirDeclarationCollector<FirBasedSymbol<*>>.collectClassMembers(klass: FirReg
}
}
val visitedClassifiers = mutableSetOf<FirClassifierSymbol<*>>()
scope.processAllClassifiers {
processClassifier(it)
visitedClassifiers.add(it)
}
// Scopes refer to inner classifiers
// through maps indexed by names,
// so only the last declaration is
// observed when processing all
// classifiers
for (it in klass.declarationSymbols) {
if (it is FirClassifierSymbol<*> && it !in visitedClassifiers) {
processClassifier(it)
for (declaredClassifier in klass.declarationSymbols) {
if (declaredClassifier is FirClassifierSymbol<*>) {
processClassifier(declaredClassifier)
unsubstitutedScope.processClassifiersByName(declaredClassifier.name) { anotherClassifier ->
if (anotherClassifier != declaredClassifier) {
processClassifier(anotherClassifier)
}
}
}
}
}
private val FirClassifierSymbol<*>.name: Name
get() = when (this) {
is FirClassLikeSymbol -> name
is FirTypeParameterSymbol -> name
}
fun collectConflictingLocalFunctionsFrom(block: FirBlock, context: CheckerContext): Map<FirFunctionSymbol<*>, Set<FirBasedSymbol<*>>> {
val collectables =
block.statements.filter {
@@ -1,55 +0,0 @@
open class Final {
fun foo() {}
val bar: Int = 0
var qux: Int = 0
}
open class Derived : Final()
interface IFoo {
fun foo()
}
class CFoo : IFoo {
override fun foo() {}
}
interface IBar {
val bar: Int
}
class CBar : IBar {
override val bar: Int get() = 0
}
interface IQux {
val qux: Int
}
class CQux : IQux {
override val qux: Int get() = 0
}
interface IBarT<T> {
val bar: T
}
class CBarT<T> : IBarT<T> {
override val bar: T get() = null!!
}
<!OVERRIDING_FINAL_MEMBER_BY_DELEGATION!>class <!CONFLICTING_OVERLOADS, CONFLICTING_OVERLOADS!>Test1<!><!> : Final(), IFoo by CFoo()
<!OVERRIDING_FINAL_MEMBER_BY_DELEGATION!>class <!REDECLARATION, REDECLARATION!>Test2<!><!> : Final(), IBar by CBar()
<!OVERRIDING_FINAL_MEMBER_BY_DELEGATION, VAR_OVERRIDDEN_BY_VAL_BY_DELEGATION!>class <!REDECLARATION, REDECLARATION!>Test3<!><!> : Final(), IQux by CQux()
<!OVERRIDING_FINAL_MEMBER_BY_DELEGATION!>class <!CONFLICTING_OVERLOADS, CONFLICTING_OVERLOADS!>Test4<!><!> : Derived(), IFoo by CFoo()
<!OVERRIDING_FINAL_MEMBER_BY_DELEGATION!>class <!REDECLARATION, REDECLARATION!>Test5<!><!> : Derived(), IBar by CBar()
<!OVERRIDING_FINAL_MEMBER_BY_DELEGATION, VAR_OVERRIDDEN_BY_VAL_BY_DELEGATION!>class <!REDECLARATION, REDECLARATION!>Test6<!><!> : Derived(), IQux by CQux()
<!OVERRIDING_FINAL_MEMBER_BY_DELEGATION!>class <!REDECLARATION, REDECLARATION!>Test7<!><!> : Final(), IBarT<Int> by CBarT<Int>()
<!OVERRIDING_FINAL_MEMBER_BY_DELEGATION!>class <!REDECLARATION, REDECLARATION!>Test8<!><!> : Final(), IBarT<Int> by <!TYPE_MISMATCH!>CBar()<!>
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
open class Final {
fun foo() {}
val bar: Int = 0
@@ -1,7 +1,7 @@
import org.jetbrains.kotlin.fir.plugin.MyComposable
import kotlin.reflect.*
abstract class <!CONFLICTING_OVERLOADS, CONFLICTING_OVERLOADS!>MyClass<!>: <!MIXING_SUSPEND_AND_NON_SUSPEND_SUPERTYPES!>KSuspendFunction0<Unit>, () -> Unit<!>
abstract class MyClass: <!MIXING_SUSPEND_AND_NON_SUSPEND_SUPERTYPES!>KSuspendFunction0<Unit>, () -> Unit<!>
abstract class OurClass: <!MIXING_FUNCTIONAL_KINDS_IN_SUPERTYPES!>@MyComposable (Int) -> Unit, () -> Unit<!>
abstract class YourClass: @MyComposable KFunction1<Boolean, Unit>, () -> Unit