Refine method's contract and rename it

Basically what's it checked before is that
receiver is a valid override of raw version of builtinWithErasedParameters

While we need to check that method has the same JVM descriptor as builtinWithErasedParameters,
but it's not a valid override of latter

It's important for 'getOrDefault(Object k, V value)' ('getOrDefault(K k, V value)' in Kotlin):
'getOrDefault(Object k, V value)' is not override of 'getOrDefault(Object k, Object value)',
that leads to incorrect loading of former method (like it's not an override of declaration in Map)
This commit is contained in:
Denis Zharkov
2016-07-25 16:15:50 +03:00
parent 15b94bb8df
commit 169acf2f31
2 changed files with 15 additions and 26 deletions
@@ -39,17 +39,16 @@ import org.jetbrains.kotlin.load.java.descriptors.copyValueParameters
import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext
import org.jetbrains.kotlin.load.java.lazy.child import org.jetbrains.kotlin.load.java.lazy.child
import org.jetbrains.kotlin.load.java.lazy.resolveAnnotations import org.jetbrains.kotlin.load.java.lazy.resolveAnnotations
import org.jetbrains.kotlin.load.java.lazy.types.RawSubstitution
import org.jetbrains.kotlin.load.java.lazy.types.toAttributes import org.jetbrains.kotlin.load.java.lazy.types.toAttributes
import org.jetbrains.kotlin.load.java.structure.JavaArrayType import org.jetbrains.kotlin.load.java.structure.JavaArrayType
import org.jetbrains.kotlin.load.java.structure.JavaClass import org.jetbrains.kotlin.load.java.structure.JavaClass
import org.jetbrains.kotlin.load.java.structure.JavaConstructor import org.jetbrains.kotlin.load.java.structure.JavaConstructor
import org.jetbrains.kotlin.load.java.structure.JavaMethod import org.jetbrains.kotlin.load.java.structure.JavaMethod
import org.jetbrains.kotlin.load.java.typeEnhancement.enhanceSignatures import org.jetbrains.kotlin.load.java.typeEnhancement.enhanceSignatures
import org.jetbrains.kotlin.load.kotlin.computeJvmDescriptor
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.DescriptorFactory import org.jetbrains.kotlin.resolve.DescriptorFactory
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.ExternalOverridabilityCondition
import org.jetbrains.kotlin.resolve.OverridingUtil import org.jetbrains.kotlin.resolve.OverridingUtil
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.serialization.deserialization.ErrorReporter import org.jetbrains.kotlin.serialization.deserialization.ErrorReporter
@@ -132,7 +131,7 @@ class LazyJavaClassMemberScope(
return candidatesToOverride.any { return candidatesToOverride.any {
candidate -> candidate ->
doesOverrideBuiltinFunctionWithErasedValueParameters(candidate) hasSameJvmDescriptorButDoesNotOverride(candidate)
} }
} }
@@ -355,7 +354,7 @@ class LazyJavaClassMemberScope(
functions: (Name) -> Collection<SimpleFunctionDescriptor> functions: (Name) -> Collection<SimpleFunctionDescriptor>
): SimpleFunctionDescriptor? { ): SimpleFunctionDescriptor? {
return functions(overridden.name).firstOrNull { return functions(overridden.name).firstOrNull {
it.doesOverrideBuiltinFunctionWithErasedValueParameters(overridden) it.hasSameJvmDescriptorButDoesNotOverride(overridden)
}?.let { }?.let {
override -> override ->
override.newCopyBuilder().apply { override.newCopyBuilder().apply {
@@ -496,24 +495,12 @@ class LazyJavaClassMemberScope(
) )
} }
private fun SimpleFunctionDescriptor.doesOverrideBuiltinFunctionWithErasedValueParameters( private fun SimpleFunctionDescriptor.hasSameJvmDescriptorButDoesNotOverride(
builtinWithErasedParameters: FunctionDescriptor builtinWithErasedParameters: FunctionDescriptor
): Boolean { ): Boolean {
if (this.valueParameters.size != builtinWithErasedParameters.valueParameters.size) return false return computeJvmDescriptor(withReturnType = false) ==
if (!this.typeParameters.isEmpty() || !builtinWithErasedParameters.typeParameters.isEmpty()) return false builtinWithErasedParameters.original.computeJvmDescriptor(withReturnType = false)
if (this.extensionReceiverParameter != null || builtinWithErasedParameters.extensionReceiverParameter != null) return false && !doesOverride(builtinWithErasedParameters)
return this.valueParameters.indices.all {
index ->
val currentType = valueParameters[index].type
val overriddenCandidate = RawSubstitution.eraseType(
builtinWithErasedParameters.original.valueParameters[index].type)
KotlinTypeChecker.DEFAULT.equalTypes(currentType, overriddenCandidate)
} && returnType.isSubtypeOf(builtinWithErasedParameters.returnType)
}
private fun KotlinType?.isSubtypeOf(other: KotlinType?): Boolean {
return KotlinTypeChecker.DEFAULT.isSubtypeOf(this ?: return false, other ?: return false)
} }
private fun resolveConstructor(constructor: JavaConstructor): JavaConstructorDescriptor { private fun resolveConstructor(constructor: JavaConstructor): JavaConstructorDescriptor {
@@ -29,7 +29,7 @@ import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
fun FunctionDescriptor.computeJvmDescriptor() fun FunctionDescriptor.computeJvmDescriptor(withReturnType: Boolean = true)
= StringBuilder().apply { = StringBuilder().apply {
append(if (this@computeJvmDescriptor is ConstructorDescriptor) "<init>" else name.asString()) append(if (this@computeJvmDescriptor is ConstructorDescriptor) "<init>" else name.asString())
append("(") append("(")
@@ -40,11 +40,13 @@ fun FunctionDescriptor.computeJvmDescriptor()
append(")") append(")")
if (hasVoidReturnType(this@computeJvmDescriptor)) { if (withReturnType) {
append("V") if (hasVoidReturnType(this@computeJvmDescriptor)) {
} append("V")
else { }
appendErasedType(returnType!!) else {
appendErasedType(returnType!!)
}
} }
}.toString() }.toString()