From 188bcf0a03ab63720efaeb3a11404f33c7602f68 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Thu, 5 Nov 2015 20:43:18 +0300 Subject: [PATCH] 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 { inner class Inner { // Inner's type constructor looks like Inner 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. --- .../java/lazy/types/LazyJavaTypeResolver.kt | 2 +- .../java/typeEnhacement/typeEnhancement.kt | 2 +- .../impl/AbstractClassDescriptor.java | 2 +- .../kotlin/types/AbstractLazyType.kt | 2 +- .../jetbrains/kotlin/types/ErrorUtils.java | 2 +- .../jetbrains/kotlin/types/KotlinTypeImpl.kt | 2 +- .../kotlin/types/TypeSubstitution.kt | 28 ++++++++++++------- .../kotlin/types/TypeSubstitutor.java | 2 +- .../idea/completion/HeuristicSignatures.kt | 7 ++--- .../idea/quickfix/SuperClassNotInitialized.kt | 4 +-- 10 files changed, 29 insertions(+), 24 deletions(-) diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/types/LazyJavaTypeResolver.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/types/LazyJavaTypeResolver.kt index 57c48db362d..def8c1e84bc 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/types/LazyJavaTypeResolver.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/types/LazyJavaTypeResolver.kt @@ -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)!! diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/typeEnhacement/typeEnhancement.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/typeEnhacement/typeEnhancement.kt index 48926026eb4..f74da347354 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/typeEnhacement/typeEnhancement.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/typeEnhacement/typeEnhancement.kt @@ -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( diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractClassDescriptor.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractClassDescriptor.java index 6a98d99afb4..4c67b8ab5d6 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractClassDescriptor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractClassDescriptor.java @@ -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); } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/AbstractLazyType.kt b/core/descriptors/src/org/jetbrains/kotlin/types/AbstractLazyType.kt index 2a4af142653..fdf31502d4f 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/AbstractLazyType.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/AbstractLazyType.kt @@ -34,7 +34,7 @@ public abstract class AbstractLazyType(storageManager: StorageManager) : Abstrac protected abstract fun computeArguments(): List - override fun getSubstitution() = computeCustomSubstitution() ?: IndexedParametersSubstitution(constructor, getArguments()) + override fun getSubstitution() = computeCustomSubstitution() ?: TypeConstructorSubstitution.create(constructor, getArguments()) protected open fun computeCustomSubstitution(): TypeSubstitution? = getCapability()?.substitution diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/ErrorUtils.java b/core/descriptors/src/org/jetbrains/kotlin/types/ErrorUtils.java index 6a3f90adf3c..0ebce7a7c8d 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/ErrorUtils.java +++ b/core/descriptors/src/org/jetbrains/kotlin/types/ErrorUtils.java @@ -512,7 +512,7 @@ public class ErrorUtils { @NotNull @Override public TypeSubstitution getSubstitution() { - return new IndexedParametersSubstitution(constructor, arguments); + return TypeConstructorSubstitution.create(constructor, arguments); } @Override diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/KotlinTypeImpl.kt b/core/descriptors/src/org/jetbrains/kotlin/types/KotlinTypeImpl.kt index bc281f85e12..fa1b9cf72a8 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/KotlinTypeImpl.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/KotlinTypeImpl.kt @@ -88,7 +88,7 @@ private constructor( override fun getSubstitution(): TypeSubstitution { if (substitution == null) { - return IndexedParametersSubstitution(getConstructor(), getArguments()) + return TypeConstructorSubstitution.create(getConstructor(), getArguments()) } return substitution } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitution.kt b/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitution.kt index e00a1e008d4..98da0a7ea8e 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitution.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitution.kt @@ -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): 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, private val arguments: Array ) : TypeSubstitution() { @@ -72,10 +84,6 @@ public class IndexedParametersSubstitution( } } - constructor( - typeConstructor: TypeConstructor, argumentsList: List - ) : this(typeConstructor.parameters, argumentsList) - constructor( parameters: List, argumentsList: List ) : this(parameters.toTypedArray(), argumentsList.toTypedArray()) @@ -95,20 +103,20 @@ public class IndexedParametersSubstitution( } public fun KotlinType.computeNewSubstitution( - newParameters: List, - newArguments: List + typeConstructor: TypeConstructor, + newArguments: List ): 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 } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitutor.java b/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitutor.java index 58ba9d4f0d5..14237c15fd2 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitutor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitutor.java @@ -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())); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/HeuristicSignatures.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/HeuristicSignatures.kt index 9574611ed66..843791b193e 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/HeuristicSignatures.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/HeuristicSignatures.kt @@ -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) } } diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/SuperClassNotInitialized.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/SuperClassNotInitialized.kt index 62fab84d1b0..19e6ddbcb22 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/SuperClassNotInitialized.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/SuperClassNotInitialized.kt @@ -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() }