Introduce TypeConstructorSubstitution.create

After latest changes type constructors of inner classes contains
additional type parameters that are copies of ones from outer class.

Their indices are correct, but they used only for subtyping check,
all entries within inner classes are still refers to original
descriptors having different indices.

Example:
class Outer<E> {
   inner class Inner<F> { // Inner's type constructor looks like Inner<F, E>
      fun foo(): E // refers to E in outer having index 0
   }
}

Indexed substitution does not work here because of intersecting indices,
so we replace it with common map substituion in such cases.
This commit is contained in:
Denis Zharkov
2015-11-05 20:43:18 +03:00
parent c57dbcc602
commit 188bcf0a03
10 changed files with 29 additions and 24 deletions
@@ -456,7 +456,7 @@ private object ConstantStarSubstitution : TypeSubstitution() {
val newProjections = key.constructor.parameters.map(::StarProjectionImpl)
val substitution = IndexedParametersSubstitution(key.constructor, newProjections)
val substitution = TypeConstructorSubstitution.create(key.constructor, newProjections)
return TypeProjectionImpl(
TypeSubstitutor.create(substitution).substitute(key.constructor.declarationDescriptor!!.defaultType, Variance.INVARIANT)!!
@@ -101,7 +101,7 @@ private fun KotlinType.enhanceInflexible(qualifiers: (Int) -> JavaTypeQualifiers
).filterNotNull().compositeAnnotationsOrSingle()
val newSubstitution = computeNewSubstitution(
typeConstructor.parameters, enhancedArguments
typeConstructor, enhancedArguments
)
val enhancedType = KotlinTypeImpl.create(
@@ -89,7 +89,7 @@ public abstract class AbstractClassDescriptor implements ClassDescriptor {
+ " for " + getTypeConstructor() + " " + getTypeConstructor().getParameters();
if (typeArguments.isEmpty()) return getUnsubstitutedMemberScope();
TypeSubstitutor substitutor = new IndexedParametersSubstitution(getTypeConstructor(), typeArguments).buildSubstitutor();
TypeSubstitutor substitutor = TypeConstructorSubstitution.create(getTypeConstructor(), typeArguments).buildSubstitutor();
return new SubstitutingScope(getUnsubstitutedMemberScope(), substitutor);
}
@@ -34,7 +34,7 @@ public abstract class AbstractLazyType(storageManager: StorageManager) : Abstrac
protected abstract fun computeArguments(): List<TypeProjection>
override fun getSubstitution() = computeCustomSubstitution() ?: IndexedParametersSubstitution(constructor, getArguments())
override fun getSubstitution() = computeCustomSubstitution() ?: TypeConstructorSubstitution.create(constructor, getArguments())
protected open fun computeCustomSubstitution(): TypeSubstitution? = getCapability<CustomSubstitutionCapability>()?.substitution
@@ -512,7 +512,7 @@ public class ErrorUtils {
@NotNull
@Override
public TypeSubstitution getSubstitution() {
return new IndexedParametersSubstitution(constructor, arguments);
return TypeConstructorSubstitution.create(constructor, arguments);
}
@Override
@@ -88,7 +88,7 @@ private constructor(
override fun getSubstitution(): TypeSubstitution {
if (substitution == null) {
return IndexedParametersSubstitution(getConstructor(), getArguments())
return TypeConstructorSubstitution.create(getConstructor(), getArguments())
}
return substitution
}
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.types
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotations
@@ -59,10 +60,21 @@ public abstract class TypeConstructorSubstitution : TypeSubstitution() {
override fun get(key: TypeConstructor) = map[key.declarationDescriptor]
override fun isEmpty() = map.isEmpty()
}
@JvmStatic
public fun create(typeConstructor: TypeConstructor, arguments: List<TypeProjection>): TypeSubstitution {
val parameters = typeConstructor.parameters
if (parameters.lastOrNull()?.isCapturedFromOuterDeclaration ?: false) {
return createByConstructorsMap(typeConstructor.parameters.map { it.typeConstructor }.zip(arguments).toMap())
}
return IndexedParametersSubstitution(parameters, arguments)
}
}
}
public class IndexedParametersSubstitution(
public class IndexedParametersSubstitution private constructor(
private val parameters: Array<TypeParameterDescriptor>,
private val arguments: Array<TypeProjection>
) : TypeSubstitution() {
@@ -72,10 +84,6 @@ public class IndexedParametersSubstitution(
}
}
constructor(
typeConstructor: TypeConstructor, argumentsList: List<TypeProjection>
) : this(typeConstructor.parameters, argumentsList)
constructor(
parameters: List<TypeParameterDescriptor>, argumentsList: List<TypeProjection>
) : this(parameters.toTypedArray(), argumentsList.toTypedArray())
@@ -95,20 +103,20 @@ public class IndexedParametersSubstitution(
}
public fun KotlinType.computeNewSubstitution(
newParameters: List<TypeParameterDescriptor>,
newArguments: List<TypeProjection>
typeConstructor: TypeConstructor,
newArguments: List<TypeProjection>
): TypeSubstitution {
val previousSubstitution = getSubstitution()
if (newArguments.isEmpty()) return previousSubstitution
val newIndexedSubstitution = IndexedParametersSubstitution(newParameters, newArguments)
val newSubstitution = TypeConstructorSubstitution.create(typeConstructor, newArguments)
// If previous substitution was trivial just replace it with indexed one
if (previousSubstitution is IndexedParametersSubstitution || previousSubstitution.isEmpty()) {
return newIndexedSubstitution
return newSubstitution
}
val composedSubstitution = CompositeTypeSubstitution(newIndexedSubstitution, previousSubstitution)
val composedSubstitution = CompositeTypeSubstitution(newSubstitution, previousSubstitution)
return composedSubstitution
}
@@ -64,7 +64,7 @@ public class TypeSubstitutor {
@NotNull
public static TypeSubstitutor create(@NotNull KotlinType context) {
return create(new IndexedParametersSubstitution(context.getConstructor(), context.getArguments()));
return create(TypeConstructorSubstitution.create(context.getConstructor(), context.getArguments()));
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -31,10 +31,7 @@ import org.jetbrains.kotlin.resolve.TypeResolver
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.LexicalScopeImpl
import org.jetbrains.kotlin.resolve.scopes.utils.memberScopeAsImportingScope
import org.jetbrains.kotlin.types.IndexedParametersSubstitution
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.SubstitutionUtils
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.*
import java.util.*
public class HeuristicSignatures(
@@ -70,7 +67,7 @@ public class HeuristicSignatures(
val type = typeFromText(typeStr, typeParameters)
val substitutor = IndexedParametersSubstitution(ownerClass.typeConstructor, ownerType.arguments).buildSubstitutor()
val substitutor = TypeConstructorSubstitution.create(ownerClass.typeConstructor, ownerType.arguments).buildSubstitutor()
return substitutor.substitute(type, Variance.INVARIANT)
}
}
@@ -39,8 +39,8 @@ import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.renderer.render
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.types.IndexedParametersSubstitution
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeConstructorSubstitution
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
import org.jetbrains.kotlin.utils.addIfNotNull
import java.util.*
@@ -68,7 +68,7 @@ public object SuperClassNotInitialized : KotlinIntentionActionsFactory() {
if (classOrObjectDeclaration is KtClass) {
val superType = classDescriptor.getTypeConstructor().getSupertypes().firstOrNull { it.getConstructor().getDeclarationDescriptor() == superClass }
if (superType != null) {
val substitutor = IndexedParametersSubstitution(superClass.typeConstructor, superType.arguments).buildSubstitutor()
val substitutor = TypeConstructorSubstitution.create(superClass.typeConstructor, superType.arguments).buildSubstitutor()
val substitutedConstructors = constructors
.filter { it.getValueParameters().isNotEmpty() }