Optimize retaining most specific methods in LazyJavaScope
See 62a55b7b00
Previously, it was working for O(n^2)
Now, we first group it by jvm descriptor,
then for each groups of size g_i finding the most specific for O(g_i^2)
It should help for the cases when we have a lot of overloads with
different JVM descriptors (modulo return type)
NB: Having the same JVM descriptors is rather rare, because
in Java one cannot generate such a class.
Looks like it's only possible for Scala or some other JVM languages (KT-17560)
It should help a lot for KT-35135
This commit is contained in:
+5
-5
@@ -11,7 +11,7 @@ public class A {
|
||||
void foo(Map<Object, Object> x) {}
|
||||
void foo(Map.Entry<Object, Object> x) {}
|
||||
|
||||
void foo(List<List<Object>> x) {}
|
||||
void foo1(List<List<Object>> x) {}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
@@ -59,9 +59,9 @@ fun main(
|
||||
a.foo(me as Map.Entry<Any, Any>)
|
||||
|
||||
// Lists of lists
|
||||
a.foo(mll)
|
||||
a.foo(ll)
|
||||
a.foo(mll as MutableList<MutableList<Any>>)
|
||||
a.foo(ll as List<List<Any>>)
|
||||
a.foo1(mll)
|
||||
a.foo1(ll)
|
||||
a.foo1(mll as MutableList<MutableList<Any>>)
|
||||
a.foo1(ll as List<List<Any>>)
|
||||
|
||||
}
|
||||
|
||||
+5
-5
@@ -11,7 +11,7 @@ public class A {
|
||||
void foo(Map<Object, Object> x) {}
|
||||
void foo(Map.Entry<Object, Object> x) {}
|
||||
|
||||
void foo(List<List<Object>> x) {}
|
||||
void foo1(List<List<Object>> x) {}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
@@ -59,9 +59,9 @@ fun main(
|
||||
a.foo(me as Map.Entry<Any, Any>)
|
||||
|
||||
// Lists of lists
|
||||
a.foo(<!JAVA_TYPE_MISMATCH!>mll<!>)
|
||||
a.foo(ll)
|
||||
a.foo(mll <!UNCHECKED_CAST!>as MutableList<MutableList<Any>><!>)
|
||||
a.foo(ll as List<List<Any>>)
|
||||
a.foo1(<!JAVA_TYPE_MISMATCH!>mll<!>)
|
||||
a.foo1(ll)
|
||||
a.foo1(mll <!UNCHECKED_CAST!>as MutableList<MutableList<Any>><!>)
|
||||
a.foo1(ll as List<List<Any>>)
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -8,10 +8,10 @@ public open class A {
|
||||
public/*package*/ open fun foo(/*0*/ x: kotlin.collections.(Mutable)Iterable<kotlin.Any!>!): kotlin.Unit
|
||||
public/*package*/ open fun foo(/*0*/ x: kotlin.collections.(Mutable)Iterator<kotlin.Any!>!): kotlin.Unit
|
||||
public/*package*/ open fun foo(/*0*/ x: kotlin.collections.(Mutable)List<kotlin.Any!>!): kotlin.Unit
|
||||
public/*package*/ open fun foo(/*0*/ x: kotlin.collections.(Mutable)List<kotlin.collections.(Mutable)List<kotlin.Any!>!>!): kotlin.Unit
|
||||
public/*package*/ open fun foo(/*0*/ x: kotlin.collections.(Mutable)Map.(Mutable)Entry<kotlin.Any!, kotlin.Any!>!): kotlin.Unit
|
||||
public/*package*/ open fun foo(/*0*/ x: kotlin.collections.(Mutable)Map<kotlin.Any!, kotlin.Any!>!): kotlin.Unit
|
||||
public/*package*/ open fun foo(/*0*/ x: kotlin.collections.(Mutable)Set<kotlin.Any!>!): kotlin.Unit
|
||||
public/*package*/ open fun foo1(/*0*/ x: kotlin.collections.(Mutable)List<kotlin.collections.(Mutable)List<kotlin.Any!>!>!): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
+13
-4
@@ -35,12 +35,11 @@ import org.jetbrains.kotlin.load.java.structure.JavaArrayType
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaField
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaMethod
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaValueParameter
|
||||
import org.jetbrains.kotlin.load.kotlin.computeJvmDescriptor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorFactory
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.constants.StringValue
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.firstArgument
|
||||
import org.jetbrains.kotlin.resolve.retainMostSpecificInEachOverridableGroup
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindExclude.NonExtensions
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
@@ -116,13 +115,23 @@ abstract class LazyJavaScope(
|
||||
private val functions = c.storageManager.createMemoizedFunction<Name, Collection<SimpleFunctionDescriptor>> { name ->
|
||||
val result = LinkedHashSet<SimpleFunctionDescriptor>(declaredFunctions(name))
|
||||
|
||||
result.retainMostSpecificInEachOverridableGroup()
|
||||
result.retainMostSpecificMethods()
|
||||
|
||||
computeNonDeclaredFunctions(result, name)
|
||||
|
||||
c.components.signatureEnhancement.enhanceSignatures(c, result).toList()
|
||||
}
|
||||
|
||||
private fun MutableSet<SimpleFunctionDescriptor>.retainMostSpecificMethods() {
|
||||
val groups = groupBy { it.computeJvmDescriptor(withReturnType = false) }.values
|
||||
for (group in groups) {
|
||||
if (group.size == 1) continue
|
||||
val mostSpecificMethods = group.selectMostSpecificFromOverridableGroup()
|
||||
removeAll(group)
|
||||
addAll(mostSpecificMethods)
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun JavaMethodDescriptor.isVisibleAsFunction() = true
|
||||
|
||||
protected data class MethodSignatureData(
|
||||
|
||||
@@ -66,12 +66,7 @@ fun <H : Any> Collection<H>.selectMostSpecificInEachOverridableGroup(
|
||||
continue
|
||||
}
|
||||
|
||||
val mostSpecific = OverridingUtil.selectMostSpecificMember(overridableGroup, descriptorByHandle)
|
||||
val mostSpecificDescriptor = mostSpecific.descriptorByHandle()
|
||||
|
||||
overridableGroup.filterNotTo(conflictedHandles) {
|
||||
OverridingUtil.isMoreSpecific(mostSpecificDescriptor, it.descriptorByHandle())
|
||||
}
|
||||
val mostSpecific = mostSpecific(overridableGroup, conflictedHandles, descriptorByHandle)
|
||||
|
||||
if (conflictedHandles.isNotEmpty()) {
|
||||
result.addAll(conflictedHandles)
|
||||
@@ -82,8 +77,23 @@ fun <H : Any> Collection<H>.selectMostSpecificInEachOverridableGroup(
|
||||
return result
|
||||
}
|
||||
|
||||
fun <D : CallableDescriptor> MutableCollection<D>.retainMostSpecificInEachOverridableGroup() {
|
||||
val newResult = selectMostSpecificInEachOverridableGroup { this }
|
||||
if (size == newResult.size) return
|
||||
retainAll(newResult)
|
||||
private fun <H : Any> mostSpecific(
|
||||
overridableGroup: Collection<H>,
|
||||
conflictedHandles: MutableSet<H>,
|
||||
descriptorByHandle: H.() -> CallableDescriptor
|
||||
): H {
|
||||
val mostSpecific = OverridingUtil.selectMostSpecificMember(overridableGroup, descriptorByHandle)
|
||||
val mostSpecificDescriptor = mostSpecific.descriptorByHandle()
|
||||
|
||||
overridableGroup.filterNotTo(conflictedHandles) {
|
||||
OverridingUtil.isMoreSpecific(mostSpecificDescriptor, it.descriptorByHandle())
|
||||
}
|
||||
return mostSpecific
|
||||
}
|
||||
|
||||
// Return multiple elements in case of conflicts
|
||||
fun <D : CallableDescriptor> Collection<D>.selectMostSpecificFromOverridableGroup(): Collection<D> {
|
||||
val result = mutableSetOf<D>()
|
||||
result.add(mostSpecific(this, conflictedHandles = result) { this })
|
||||
return result
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user