Do not build enhanced descriptors if they are unchanged

This commit is contained in:
Denis Zharkov
2016-02-01 19:41:26 +03:00
parent 924d706e79
commit c1f57b743b
12 changed files with 60 additions and 34 deletions
@@ -2,5 +2,5 @@ package test
public open class MethodWithMappedClasses {
public constructor MethodWithMappedClasses()
public open fun </*0*/ T : kotlin.Any!> copy(/*0*/ p0: (kotlin.collections.MutableList<in T!>..kotlin.collections.List<*>?), /*1*/ p1: kotlin.collections.(Mutable)List<T!>!): kotlin.Unit
public open fun </*0*/ T : kotlin.Any!> copy(/*0*/ p0: kotlin.collections.(Mutable)List<in T!>!, /*1*/ p1: kotlin.collections.(Mutable)List<T!>!): kotlin.Unit
}
@@ -2,5 +2,5 @@ package test
public open class MethodWithTypeParameters {
public constructor MethodWithTypeParameters()
public open fun </*0*/ A : kotlin.Any!, /*1*/ B : java.lang.Runnable!> foo(/*0*/ p0: A!, /*1*/ p1: (kotlin.collections.MutableList<out B!>..kotlin.collections.List<B!>?), /*2*/ p2: (kotlin.collections.MutableList<in kotlin.String!>..kotlin.collections.List<*>?)): kotlin.Unit where B : kotlin.collections.(Mutable)List<kotlin.Cloneable!>!
public open fun </*0*/ A : kotlin.Any!, /*1*/ B : java.lang.Runnable!> foo(/*0*/ p0: A!, /*1*/ p1: (kotlin.collections.MutableList<out B!>..kotlin.collections.List<B!>?), /*2*/ p2: kotlin.collections.(Mutable)List<in kotlin.String!>!): kotlin.Unit where B : kotlin.collections.(Mutable)List<kotlin.Cloneable!>!
}
@@ -33,19 +33,24 @@ private fun <D : CallableMemberDescriptor> D.enhanceSignature(): D {
if (this !is JavaCallableMemberDescriptor) return this
val enhancedReceiverType =
val receiverTypeEnhancement =
if (extensionReceiverParameter != null)
parts(isCovariant = false) { it.extensionReceiverParameter!!.type }.enhance()
else null
val enhancedValueParametersTypes = valueParameters.map {
val valueParameterEnhancements = valueParameters.map {
p -> parts(isCovariant = false) { it.valueParameters[p.index].type }.enhance()
}
val enhancedReturnType = parts(isCovariant = true) { it.returnType!! }.enhance()
val returnTypeEnhancement = parts(isCovariant = true) { it.returnType!! }.enhance()
@Suppress("UNCHECKED_CAST")
return this.enhance(enhancedReceiverType, enhancedValueParametersTypes, enhancedReturnType) as D
if ((receiverTypeEnhancement?.wereChanges ?: false)
|| returnTypeEnhancement.wereChanges || valueParameterEnhancements.any { it.wereChanges }) {
@Suppress("UNCHECKED_CAST")
return this.enhance(receiverTypeEnhancement?.type, valueParameterEnhancements.map { it.type }, returnTypeEnhancement.type) as D
}
return this
}
private class SignatureParts(
@@ -53,12 +58,16 @@ private class SignatureParts(
val fromOverridden: Collection<KotlinType>,
val isCovariant: Boolean
) {
fun enhance(): KotlinType {
fun enhance(): PartEnhancementResult {
val qualifiers = fromOverride.computeIndexedQualifiersForOverride(this.fromOverridden, isCovariant)
return fromOverride.enhance(qualifiers)
return fromOverride.enhance(qualifiers)?.let {
enhanced -> PartEnhancementResult(enhanced, wereChanges = true)
} ?: PartEnhancementResult(fromOverride, wereChanges = false)
}
}
private data class PartEnhancementResult(val type: KotlinType, val wereChanges: Boolean)
private fun <D : CallableMemberDescriptor> D.parts(isCovariant: Boolean, collector: (D) -> KotlinType): SignatureParts {
return SignatureParts(
collector(this),
@@ -33,13 +33,14 @@ import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.createProjection
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
import org.jetbrains.kotlin.utils.addToStdlib.check
import org.jetbrains.kotlin.utils.toReadOnlyList
// The index in the lambda is the position of the type component:
// Example: for `A<B, C<D, E>>`, indices go as follows: `0 - A<...>, 1 - B, 2 - C<D, E>, 3 - D, 4 - E`,
// which corresponds to the left-to-right breadth-first walk of the tree representation of the type.
// For flexible types, both bounds are indexed in the same way: `(A<B>..C<D>)` gives `0 - (A<B>..C<D>), 1 - B and D`.
fun KotlinType.enhance(qualifiers: (Int) -> JavaTypeQualifiers) = this.enhancePossiblyFlexible(qualifiers, 0).type
fun KotlinType.enhance(qualifiers: (Int) -> JavaTypeQualifiers) = this.enhancePossiblyFlexible(qualifiers, 0).typeIfChanged
private enum class TypeComponentPosition {
@@ -48,10 +49,12 @@ private enum class TypeComponentPosition {
INFLEXIBLE
}
private data class Result(val type: KotlinType, val subtreeSize: Int)
private data class Result(val type: KotlinType, val subtreeSize: Int, val wereChanges: Boolean) {
val typeIfChanged: KotlinType? get() = type.check { wereChanges }
}
private fun KotlinType.enhancePossiblyFlexible(qualifiers: (Int) -> JavaTypeQualifiers, index: Int): Result {
if (this.isError()) return Result(this, 1)
if (this.isError) return Result(this, 1, false)
return if (this.isFlexible()) {
with(this.flexibility()) {
val lowerResult = lowerBound.enhanceInflexible(qualifiers, index, TypeComponentPosition.FLEXIBLE_LOWER)
@@ -61,8 +64,15 @@ private fun KotlinType.enhancePossiblyFlexible(qualifiers: (Int) -> JavaTypeQual
"lower = ($lowerBound, ${lowerResult.subtreeSize}), " +
"upper = ($upperBound, ${upperResult.subtreeSize})"
}
val wereChanges = lowerResult.wereChanges || upperResult.wereChanges
Result(
DelegatingFlexibleType.create(lowerResult.type, upperResult.type, extraCapabilities), lowerResult.subtreeSize
if (wereChanges)
DelegatingFlexibleType.create(lowerResult.type, upperResult.type, extraCapabilities)
else
this@enhancePossiblyFlexible,
lowerResult.subtreeSize,
wereChanges
)
}
}
@@ -71,10 +81,10 @@ private fun KotlinType.enhancePossiblyFlexible(qualifiers: (Int) -> JavaTypeQual
private fun KotlinType.enhanceInflexible(qualifiers: (Int) -> JavaTypeQualifiers, index: Int, position: TypeComponentPosition): Result {
val shouldEnhance = position.shouldEnhance()
if (!shouldEnhance && getArguments().isEmpty()) return Result(this, 1)
if (!shouldEnhance && arguments.isEmpty()) return Result(this, 1, false)
val originalClass = getConstructor().declarationDescriptor
?: return Result(this, 1)
val originalClass = constructor.declarationDescriptor
?: return Result(this, 1, false)
val effectiveQualifiers = qualifiers(index)
val (enhancedClassifier, enhancedMutabilityAnnotations) = originalClass.enhanceMutability(effectiveQualifiers, position)
@@ -82,6 +92,7 @@ private fun KotlinType.enhanceInflexible(qualifiers: (Int) -> JavaTypeQualifiers
val typeConstructor = enhancedClassifier.typeConstructor
var globalArgIndex = index + 1
var wereChanges = enhancedMutabilityAnnotations != null
val enhancedArguments = getArguments().mapIndexed {
localArgIndex, arg ->
if (arg.isStarProjection) {
@@ -89,13 +100,19 @@ private fun KotlinType.enhanceInflexible(qualifiers: (Int) -> JavaTypeQualifiers
TypeUtils.makeStarProjection(enhancedClassifier.typeConstructor.parameters[localArgIndex])
}
else {
val (enhancedType, subtreeSize) = arg.type.enhancePossiblyFlexible(qualifiers, globalArgIndex)
val (enhancedType, subtreeSize, wasChangeInArgument) = arg.type.enhancePossiblyFlexible(qualifiers, globalArgIndex)
wereChanges = wereChanges || wasChangeInArgument
globalArgIndex += subtreeSize
createProjection(enhancedType, arg.projectionKind, typeParameterDescriptor = typeConstructor.parameters[localArgIndex])
}
}
val (enhancedNullability, enhancedNullabilityAnnotations) = this.getEnhancedNullability(effectiveQualifiers, position)
wereChanges = wereChanges || enhancedNullabilityAnnotations != null
val subtreeSize = globalArgIndex - index
if (!wereChanges) return Result(this, subtreeSize, wereChanges = false)
val newAnnotations = listOf(
getAnnotations(),
enhancedMutabilityAnnotations,
@@ -123,7 +140,7 @@ private fun KotlinType.enhanceInflexible(qualifiers: (Int) -> JavaTypeQualifiers
else enhancedClassifier.getDefaultType().getMemberScope(),
newCapabilities
)
return Result(enhancedType, globalArgIndex - index)
return Result(enhancedType, subtreeSize, wereChanges = true)
}
private fun List<Annotations>.compositeAnnotationsOrSingle() = when (size) {
@@ -1,7 +1,7 @@
// WITH_RUNTIME
// SUGGESTED_RETURN_TYPES: kotlin.Boolean?, kotlin.Boolean
// PARAM_DESCRIPTOR: value-parameter val it: kotlin.collections.Map.Entry<(kotlin.Boolean..kotlin.Boolean?), (kotlin.Boolean..kotlin.Boolean?)> defined in test.<anonymous>
// PARAM_TYPES: kotlin.collections.Map.Entry<(kotlin.Boolean..kotlin.Boolean?), (kotlin.Boolean..kotlin.Boolean?)>
// PARAM_DESCRIPTOR: value-parameter val it: kotlin.collections.Map.Entry<(Boolean..Boolean?), (Boolean..Boolean?)> defined in test.<anonymous>
// PARAM_TYPES: kotlin.collections.Map.Entry<(Boolean..Boolean?), (Boolean..Boolean?)>
fun test() {
J.getMap().filter { <selection>it.key</selection> }
}
@@ -1,7 +1,7 @@
// WITH_RUNTIME
// SUGGESTED_RETURN_TYPES: kotlin.Boolean?, kotlin.Boolean
// PARAM_DESCRIPTOR: value-parameter val it: kotlin.collections.Map.Entry<(kotlin.Boolean..kotlin.Boolean?), (kotlin.Boolean..kotlin.Boolean?)> defined in test.<anonymous>
// PARAM_TYPES: kotlin.collections.Map.Entry<(kotlin.Boolean..kotlin.Boolean?), (kotlin.Boolean..kotlin.Boolean?)>
// PARAM_DESCRIPTOR: value-parameter val it: kotlin.collections.Map.Entry<(Boolean..Boolean?), (Boolean..Boolean?)> defined in test.<anonymous>
// PARAM_TYPES: kotlin.collections.Map.Entry<(Boolean..Boolean?), (Boolean..Boolean?)>
fun test() {
J.getMap().filter { b(it) }
}
@@ -1,7 +1,7 @@
// WITH_RUNTIME
// SUGGESTED_NAMES: i, getN
// PARAM_TYPES: kotlin.String?, kotlin.String, kotlin.CharSequence?, CharSequence
// PARAM_DESCRIPTOR: val property: (kotlin.String..kotlin.String?) defined in test
// PARAM_TYPES: String?, String, kotlin.CharSequence?, CharSequence
// PARAM_DESCRIPTOR: val property: (String..String?) defined in test
fun test() {
val property = System.getProperty("some")
val n = <selection>property?.length</selection>
@@ -1,7 +1,7 @@
// WITH_RUNTIME
// SUGGESTED_NAMES: i, getN
// PARAM_TYPES: kotlin.String?, kotlin.String, kotlin.CharSequence?, CharSequence
// PARAM_DESCRIPTOR: val property: (kotlin.String..kotlin.String?) defined in test
// PARAM_TYPES: String?, String, kotlin.CharSequence?, CharSequence
// PARAM_DESCRIPTOR: val property: (String..String?) defined in test
fun test() {
val property = System.getProperty("some")
val n = i(property)
@@ -1,7 +1,7 @@
// WITH_RUNTIME
// SUGGESTED_NAMES: i, getN
// PARAM_TYPES: kotlin.String, CharSequence
// PARAM_DESCRIPTOR: val property: (kotlin.String..kotlin.String?) defined in test
// PARAM_TYPES: String, CharSequence
// PARAM_DESCRIPTOR: val property: (String..String?) defined in test
fun test() {
val property = System.getProperty("some")
val n = <selection>property.length</selection>
@@ -1,7 +1,7 @@
// WITH_RUNTIME
// SUGGESTED_NAMES: i, getN
// PARAM_TYPES: kotlin.String, CharSequence
// PARAM_DESCRIPTOR: val property: (kotlin.String..kotlin.String?) defined in test
// PARAM_TYPES: String, CharSequence
// PARAM_DESCRIPTOR: val property: (String..String?) defined in test
fun test() {
val property = System.getProperty("some")
val n = i(property)
@@ -1,6 +1,6 @@
// WITH_RUNTIME
// PARAM_DESCRIPTOR: val data: (kotlin.collections.MutableList<(kotlin.String..kotlin.String?)>..kotlin.collections.List<(kotlin.String..kotlin.String?)>) defined in test
// PARAM_TYPES: kotlin.collections.List<(kotlin.String..kotlin.String?)>, kotlin.collections.MutableList<(kotlin.String..kotlin.String?)>, kotlin.collections.MutableCollection<(kotlin.String..kotlin.String?)>, kotlin.collections.Collection<(kotlin.String..kotlin.String?)>
// PARAM_DESCRIPTOR: val data: (kotlin.collections.MutableList<(String..String?)>..kotlin.collections.List<(String..String?)>) defined in test
// PARAM_TYPES: kotlin.collections.List<(String..String?)>, kotlin.collections.MutableList<(String..String?)>, kotlin.collections.MutableCollection<(String..String?)>, kotlin.collections.Collection<(String..String?)>
fun test(): Boolean {
val j: J? = null
val data = j?.getData() ?: return false
@@ -1,6 +1,6 @@
// WITH_RUNTIME
// PARAM_DESCRIPTOR: val data: (kotlin.collections.MutableList<(kotlin.String..kotlin.String?)>..kotlin.collections.List<(kotlin.String..kotlin.String?)>) defined in test
// PARAM_TYPES: kotlin.collections.List<(kotlin.String..kotlin.String?)>, kotlin.collections.MutableList<(kotlin.String..kotlin.String?)>, kotlin.collections.MutableCollection<(kotlin.String..kotlin.String?)>, kotlin.collections.Collection<(kotlin.String..kotlin.String?)>
// PARAM_DESCRIPTOR: val data: (kotlin.collections.MutableList<(String..String?)>..kotlin.collections.List<(String..String?)>) defined in test
// PARAM_TYPES: kotlin.collections.List<(String..String?)>, kotlin.collections.MutableList<(String..String?)>, kotlin.collections.MutableCollection<(String..String?)>, kotlin.collections.Collection<(String..String?)>
fun test(): Boolean {
val j: J? = null
val data = j?.getData() ?: return false