diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/CollectionStubMethodGenerator.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/CollectionStubMethodGenerator.kt index 542ea8cdd9c..c9439ba3204 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/CollectionStubMethodGenerator.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/CollectionStubMethodGenerator.kt @@ -199,7 +199,7 @@ class CollectionStubMethodGenerator( child.setVisibility(Visibilities.PUBLIC) val typeParameters = descriptor.getTypeConstructor().getParameters() val newTypeParameters = ArrayList(typeParameters.size()) - DescriptorSubstitutor.substituteTypeParameters(typeParameters, TypeSubstitutor.EMPTY, child, newTypeParameters) + DescriptorSubstitutor.substituteTypeParameters(typeParameters, TypeSubstitution.EMPTY, child, newTypeParameters) child.setTypeParameterDescriptors(typeParameters) return Pair(child, newTypeParameters) } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/JavaResolverUtils.java b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/JavaResolverUtils.java index 5daaa7dd5c5..62188840bf6 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/JavaResolverUtils.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/JavaResolverUtils.java @@ -141,6 +141,7 @@ public class JavaResolverUtils { typeSubstitutionContext.put(originalToAltTypeParameter.getKey().getTypeConstructor(), new TypeProjectionImpl(originalToAltTypeParameter.getValue().getDefaultType())); } + // TODO: Use IndexedParametersSubstitution here instead of map creation return TypeSubstitutor.create(typeSubstitutionContext); } } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/JavaSyntheticExtensionsScope.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/JavaSyntheticExtensionsScope.kt index 91cc5e7d961..df0c227ad28 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/JavaSyntheticExtensionsScope.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/JavaSyntheticExtensionsScope.kt @@ -271,7 +271,7 @@ class JavaSyntheticExtensionsScope(storageManager: StorageManager) : JetScope by init { val classTypeParams = ownerClass.typeConstructor.parameters val typeParameters = ArrayList(classTypeParams.size()) - val typeSubstitutor = DescriptorSubstitutor.substituteTypeParameters(classTypeParams, TypeSubstitutor.EMPTY, this, typeParameters) + val typeSubstitutor = DescriptorSubstitutor.substituteTypeParameters(classTypeParams, TypeSubstitution.EMPTY, this, typeParameters) val propertyType = typeSubstitutor.safeSubstitute(type, Variance.INVARIANT) val receiverType = typeSubstitutor.safeSubstitute(ownerClass.defaultType, Variance.INVARIANT) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorUtil.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorUtil.java index bf47571826b..465b39eb59b 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorUtil.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorUtil.java @@ -29,6 +29,7 @@ import org.jetbrains.kotlin.resolve.scopes.RedeclarationHandler; import org.jetbrains.kotlin.resolve.scopes.WritableScope; import org.jetbrains.kotlin.resolve.scopes.WritableScopeImpl; import org.jetbrains.kotlin.types.*; +import org.jetbrains.kotlin.types.typeUtil.TypeUtilPackage; import java.util.*; @@ -36,7 +37,7 @@ public class FunctionDescriptorUtil { private static final TypeSubstitutor MAKE_TYPE_PARAMETERS_FRESH = TypeSubstitutor.create(new TypeSubstitution() { @Override - public TypeProjection get(TypeConstructor key) { + public TypeProjection get(@NotNull JetType key) { return null; } @@ -49,23 +50,13 @@ public class FunctionDescriptorUtil { private FunctionDescriptorUtil() { } - public static Map createSubstitutionContext( + public static TypeSubstitution createSubstitution( @NotNull FunctionDescriptor functionDescriptor, @NotNull List typeArguments ) { - if (functionDescriptor.getTypeParameters().isEmpty()) return Collections.emptyMap(); + if (functionDescriptor.getTypeParameters().isEmpty()) return TypeSubstitution.getEMPTY(); - Map result = new HashMap(); - - List typeParameters = functionDescriptor.getTypeParameters(); - assert typeArguments.size() >= typeParameters.size() : - "Insufficient number of type arguments.\nType arguments: " + typeArguments + "\nType parameters: " + typeParameters; - for (int i = 0; i < typeParameters.size(); i++) { - TypeParameterDescriptor typeParameterDescriptor = typeParameters.get(i); - JetType typeArgument = typeArguments.get(i); - result.put(typeParameterDescriptor.getTypeConstructor(), new TypeProjectionImpl(typeArgument)); - } - return result; + return new IndexedParametersSubstitution(functionDescriptor.getTypeParameters(), TypeUtilPackage.defaultProjections(typeArguments)); } @NotNull diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverrideResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverrideResolver.java index 0672d778104..fb15707fb0f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverrideResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverrideResolver.java @@ -645,16 +645,12 @@ public class OverrideResolver { List subTypeParameters = subDescriptor.getTypeParameters(); if (subTypeParameters.size() != superTypeParameters.size()) return null; - Map substitutionContext = Maps.newHashMapWithExpectedSize(superTypeParameters.size()); + ArrayList arguments = new ArrayList(subTypeParameters.size()); for (int i = 0; i < superTypeParameters.size(); i++) { - TypeParameterDescriptor superTypeParameter = superTypeParameters.get(i); - TypeParameterDescriptor subTypeParameter = subTypeParameters.get(i); - substitutionContext.put( - superTypeParameter.getTypeConstructor(), - new TypeProjectionImpl(subTypeParameter.getDefaultType()) - ); + arguments.add(new TypeProjectionImpl(subTypeParameters.get(i).getDefaultType())); } - return TypeSubstitutor.create(substitutionContext); + + return new IndexedParametersSubstitution(superTypeParameters, arguments).buildSubstitutor(); } public static boolean isPropertyTypeOkForOverride( diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt index 849d4ae0c27..0c229dba823 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt @@ -139,8 +139,8 @@ public class CandidateResolver( typeArguments.add(ErrorUtils.createErrorType( "Explicit type argument expected for " + candidateDescriptor.getTypeParameters().get(index).getName())) } - val substitutionContext = FunctionDescriptorUtil.createSubstitutionContext(candidateDescriptor as FunctionDescriptor, typeArguments) - val substitutor = TypeSubstitutor.create(substitutionContext) + val substitution = FunctionDescriptorUtil.createSubstitution(candidateDescriptor as FunctionDescriptor, typeArguments) + val substitutor = TypeSubstitutor.create(substitution) if (expectedTypeArgumentCount != jetTypeArguments.size()) { candidateCall.addStatus(OTHER_ERROR) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/model/ResolvedCallImpl.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/model/ResolvedCallImpl.java index 5b6ac901d68..03b81b35dbe 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/model/ResolvedCallImpl.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/model/ResolvedCallImpl.java @@ -162,7 +162,7 @@ public class ResolvedCallImpl implements MutableRe assert resultingDescriptor != null : candidateDescriptor; for (TypeParameterDescriptor typeParameter : candidateDescriptor.getTypeParameters()) { - TypeProjection typeArgumentProjection = substitutor.getSubstitution().get(typeParameter.getTypeConstructor()); + TypeProjection typeArgumentProjection = substitutor.getSubstitution().get(typeParameter.getDefaultType()); if (typeArgumentProjection != null) { typeArguments.put(typeParameter, typeArgumentProjection.getType()); } 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 5ed6bfc0e36..5503ff7e0bc 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractClassDescriptor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractClassDescriptor.java @@ -90,10 +90,7 @@ public abstract class AbstractClassDescriptor implements ClassDescriptor { + " for " + getTypeConstructor() + " " + getTypeConstructor().getParameters(); if (typeArguments.isEmpty()) return getUnsubstitutedMemberScope(); - List typeParameters = getTypeConstructor().getParameters(); - Map substitutionContext = TypeSubstitutor.buildSubstitutionContext(typeParameters, typeArguments); - - TypeSubstitutor substitutor = TypeSubstitutor.create(substitutionContext); + TypeSubstitutor substitutor = new IndexedParametersSubstitution(getTypeConstructor(), typeArguments).buildSubstitutor(); return new SubstitutingScope(getUnsubstitutedMemberScope(), substitutor); } diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/FunctionDescriptorImpl.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/FunctionDescriptorImpl.java index dfb6b614f3e..aa5d32855c5 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/FunctionDescriptorImpl.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/FunctionDescriptorImpl.java @@ -228,7 +228,7 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorNonRoo List originalTypeParameters = getTypeParameters(); List substitutedTypeParameters = new ArrayList(originalTypeParameters.size()); TypeSubstitutor substitutor = DescriptorSubstitutor.substituteTypeParameters( - originalTypeParameters, originalSubstitutor, substitutedDescriptor, substitutedTypeParameters + originalTypeParameters, originalSubstitutor.getSubstitution(), substitutedDescriptor, substitutedTypeParameters ); JetType substitutedReceiverParameterType = null; diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/LazySubstitutingClassDescriptor.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/LazySubstitutingClassDescriptor.java index 6783de5f75e..fcb5372501f 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/LazySubstitutingClassDescriptor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/LazySubstitutingClassDescriptor.java @@ -50,7 +50,7 @@ public class LazySubstitutingClassDescriptor implements ClassDescriptor { List originalTypeParameters = original.getTypeConstructor().getParameters(); typeParameters = new ArrayList(originalTypeParameters.size()); newSubstitutor = DescriptorSubstitutor.substituteTypeParameters( - originalTypeParameters, originalSubstitutor, this, typeParameters + originalTypeParameters, originalSubstitutor.getSubstitution(), this, typeParameters ); } } diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PropertyDescriptorImpl.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PropertyDescriptorImpl.java index cd3c802a72d..441c70181ed 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PropertyDescriptorImpl.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PropertyDescriptorImpl.java @@ -212,7 +212,7 @@ public class PropertyDescriptorImpl extends VariableDescriptorImpl implements Pr List originalTypeParameters = getTypeParameters(); List substitutedTypeParameters = new ArrayList(originalTypeParameters.size()); TypeSubstitutor substitutor = DescriptorSubstitutor.substituteTypeParameters( - originalTypeParameters, originalSubstitutor, substitutedDescriptor, substitutedTypeParameters + originalTypeParameters, originalSubstitutor.getSubstitution(), substitutedDescriptor, substitutedTypeParameters ); JetType originalOutType = getType(); diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemImpl.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemImpl.kt index 47817f8ae1a..d3812434118 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemImpl.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemImpl.kt @@ -131,7 +131,7 @@ public class ConstraintSystemImpl : ConstraintSystem { substituteOriginal: Boolean ): TypeSubstitutor { val parameterToInferredValueMap = getParameterToInferredValueMap(allTypeParameterBounds, getDefaultValue, substituteOriginal) - return TypeUtils.makeSubstitutorForTypeParametersMap(parameterToInferredValueMap) + return TypeConstructorSubstitution.createByParametersMap(parameterToInferredValueMap).buildSubstitutor() } override fun getStatus(): ConstraintSystemStatus = constraintSystemStatus @@ -525,7 +525,7 @@ private fun TypeSubstitutor.setApproximateCapturedTypes(): TypeSubstitutor { } private class SubstitutionWithCapturedTypeApproximation(val substitution: TypeSubstitution) : TypeSubstitution() { - override fun get(key: TypeConstructor) = substitution[key] + override fun get(key: JetType) = substitution[key] override fun isEmpty() = substitution.isEmpty() override fun approximateCapturedTypes() = true } @@ -542,7 +542,7 @@ public fun ConstraintSystemImpl.registerTypeVariables( } public fun createTypeSubstitutor(conversion: (TypeParameterDescriptor) -> TypeParameterDescriptor?): TypeSubstitutor { - return TypeSubstitutor.create(object : TypeSubstitution() { + return TypeSubstitutor.create(object : TypeConstructorSubstitution() { override fun get(key: TypeConstructor): TypeProjection? { val descriptor = key.getDeclarationDescriptor() if (descriptor !is TypeParameterDescriptor) return null diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/CapturedTypeApproximation.kt b/core/descriptors/src/org/jetbrains/kotlin/types/CapturedTypeApproximation.kt index 3b8da38336f..93801aa2fa9 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/CapturedTypeApproximation.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/CapturedTypeApproximation.kt @@ -16,23 +16,14 @@ package org.jetbrains.kotlin.types.typesApproximation -import org.jetbrains.kotlin.types.JetType -import org.jetbrains.kotlin.types.checker.JetTypeChecker -import org.jetbrains.kotlin.types.TypeProjection -import org.jetbrains.kotlin.types.TypeProjectionImpl import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.types.Variance -import java.util.ArrayList -import org.jetbrains.kotlin.types.JetTypeImpl -import org.jetbrains.kotlin.types.TypeUtils -import org.jetbrains.kotlin.resolve.calls.inference.CapturedTypeConstructor -import org.jetbrains.kotlin.types.TypeSubstitutor -import org.jetbrains.kotlin.types.TypeSubstitution -import org.jetbrains.kotlin.types.TypeConstructor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor -import org.jetbrains.kotlin.types.LazyType +import org.jetbrains.kotlin.resolve.calls.inference.CapturedTypeConstructor import org.jetbrains.kotlin.resolve.calls.inference.isCaptured import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns +import org.jetbrains.kotlin.types.* +import org.jetbrains.kotlin.types.checker.JetTypeChecker +import java.util.ArrayList public data class ApproximationBounds( public val lower: T, @@ -89,7 +80,7 @@ public fun approximateCapturedTypesIfNecessary(typeProjection: TypeProjection?): } private fun substituteCapturedTypes(typeProjection: TypeProjection): TypeProjection? { - val typeSubstitutor = TypeSubstitutor.create(object : TypeSubstitution() { + val typeSubstitutor = TypeSubstitutor.create(object : TypeConstructorSubstitution() { override fun get(key: TypeConstructor): TypeProjection? { return (key as? CapturedTypeConstructor)?.typeProjection } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/CompositeTypeSubstitution.java b/core/descriptors/src/org/jetbrains/kotlin/types/CompositeTypeSubstitution.java index 2e6aaab36f3..59373320558 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/CompositeTypeSubstitution.java +++ b/core/descriptors/src/org/jetbrains/kotlin/types/CompositeTypeSubstitution.java @@ -26,7 +26,7 @@ public class CompositeTypeSubstitution extends TypeSubstitution { } @Override - public TypeProjection get(TypeConstructor key) { + public TypeProjection get(@NotNull JetType key) { for (TypeSubstitution substitution : inner) { TypeProjection value = substitution.get(key); if (value != null) return value; diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/DescriptorSubstitutor.java b/core/descriptors/src/org/jetbrains/kotlin/types/DescriptorSubstitutor.java index d8f90e6c230..6ad0fd36e1b 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/DescriptorSubstitutor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/types/DescriptorSubstitutor.java @@ -35,35 +35,11 @@ public class DescriptorSubstitutor { @NotNull public static TypeSubstitutor substituteTypeParameters( @ReadOnly @NotNull List typeParameters, - @NotNull final TypeSubstitutor originalSubstitutor, + @NotNull TypeSubstitution originalSubstitution, @NotNull DeclarationDescriptor newContainingDeclaration, @NotNull @Mutable List result ) { - final Map mutableSubstitution = new HashMap(); - TypeSubstitutor substitutor = TypeSubstitutor.create(new TypeSubstitution() { - @Override - public TypeProjection get(TypeConstructor key) { - if (originalSubstitutor.inRange(key)) { - return originalSubstitutor.getSubstitution().get(key); - } - return mutableSubstitution.get(key); - } - - @Override - public boolean isEmpty() { - return originalSubstitutor.isEmpty() && mutableSubstitution.isEmpty(); - } - - @Override - public boolean approximateCapturedTypes() { - return originalSubstitutor.getSubstitution().approximateCapturedTypes(); - } - - @Override - public String toString() { - return "DescriptorSubstitutor.substituteTypeParameters(" + mutableSubstitution + " / " + originalSubstitutor.getSubstitution() + ")"; - } - }); + Map mutableSubstitution = new HashMap(); Map substitutedMap = new HashMap(); @@ -85,6 +61,10 @@ public class DescriptorSubstitutor { result.add(substituted); } + TypeSubstitutor substitutor = TypeSubstitutor.create( + originalSubstitution, TypeConstructorSubstitution.createByConstructorsMap(mutableSubstitution) + ); + for (TypeParameterDescriptor descriptor : typeParameters) { TypeParameterDescriptorImpl substituted = substitutedMap.get(descriptor); for (JetType upperBound : descriptor.getUpperBounds()) { diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/StarProjectionImpl.kt b/core/descriptors/src/org/jetbrains/kotlin/types/StarProjectionImpl.kt index e76ac3eac5f..b34264f361f 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/StarProjectionImpl.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/StarProjectionImpl.kt @@ -38,7 +38,7 @@ public fun TypeParameterDescriptor.starProjectionType(): JetType { val classDescriptor = this.getContainingDeclaration() as ClassDescriptor val typeParameters = classDescriptor.getTypeConstructor().getParameters().map { it.getTypeConstructor() } return TypeSubstitutor.create( - object : TypeSubstitution() { + object : TypeConstructorSubstitution() { override fun get(key: TypeConstructor) = if (key in typeParameters) TypeUtils.makeStarProjection(key.getDeclarationDescriptor() as TypeParameterDescriptor) diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitution.kt b/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitution.kt index 345a803cbb9..67b725244a3 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitution.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitution.kt @@ -16,20 +16,77 @@ package org.jetbrains.kotlin.types +import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import kotlin.platform.platformStatic public abstract class TypeSubstitution { companion object { platformStatic public val EMPTY: TypeSubstitution = object : TypeSubstitution() { - override fun get(key: TypeConstructor) = null + override fun get(key: JetType) = null override fun isEmpty() = true override fun toString() = "Empty TypeSubstitution" } } - public abstract fun get(key: TypeConstructor): TypeProjection? + public abstract fun get(key: JetType): TypeProjection? public open fun isEmpty(): Boolean = false public open fun approximateCapturedTypes(): Boolean = false + + public fun buildSubstitutor(): TypeSubstitutor = TypeSubstitutor.create(this) +} + +public abstract class TypeConstructorSubstitution : TypeSubstitution() { + override fun get(key: JetType) = get(key.constructor) + + public abstract fun get(key: TypeConstructor): TypeProjection? + + companion object { + platformStatic + public fun createByConstructorsMap(map: Map): TypeConstructorSubstitution = + object : TypeConstructorSubstitution() { + override fun get(key: TypeConstructor) = map[key] + override fun isEmpty() = map.isEmpty() + } + + platformStatic + public fun createByParametersMap(map: Map): TypeConstructorSubstitution = + object : TypeConstructorSubstitution() { + override fun get(key: TypeConstructor) = map[key.declarationDescriptor] + override fun isEmpty() = map.isEmpty() + } + } +} + +public class IndexedParametersSubstitution( + private val parameters: Array, + private val arguments: Array +) : TypeSubstitution() { + init { + assert(parameters.size() <= arguments.size()) { + "Number of arguments should not be less then number of parameters, but: parameters=${parameters.size()}, args=${arguments.size()}" + } + } + + constructor( + typeConstructor: TypeConstructor, argumentsList: List + ) : this(typeConstructor.parameters, argumentsList) + + constructor( + parameters: List, argumentsList: List + ) : this(parameters.toTypedArray(), argumentsList.toTypedArray()) + + override fun isEmpty(): Boolean = arguments.isEmpty() + + override fun get(key: JetType): TypeProjection? { + val parameter = key.constructor.declarationDescriptor as? TypeParameterDescriptor ?: return null + val index = parameter.index + + if (index < parameters.size() && parameters[index].typeConstructor == parameter.typeConstructor) { + return arguments[index] + } + + return null + } } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitutor.java b/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitutor.java index 55bcc9e499a..b551ba6f38a 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitutor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitutor.java @@ -32,29 +32,6 @@ public class TypeSubstitutor { private static final int MAX_RECURSION_DEPTH = 100; - public static class MapToTypeSubstitutionAdapter extends TypeSubstitution { - private final @NotNull Map substitutionContext; - - public MapToTypeSubstitutionAdapter(@NotNull Map substitutionContext) { - this.substitutionContext = substitutionContext; - } - - @Override - public TypeProjection get(TypeConstructor key) { - return substitutionContext.get(key); - } - - @Override - public boolean isEmpty() { - return substitutionContext.isEmpty(); - } - - @Override - public String toString() { - return substitutionContext.toString(); - } - } - public static final TypeSubstitutor EMPTY = create(TypeSubstitution.EMPTY); private static final class SubstitutionException extends Exception { @@ -75,29 +52,12 @@ public class TypeSubstitutor { @NotNull public static TypeSubstitutor create(@NotNull Map substitutionContext) { - return create(new MapToTypeSubstitutionAdapter(substitutionContext)); + return create(TypeConstructorSubstitution.createByConstructorsMap(substitutionContext)); } @NotNull public static TypeSubstitutor create(@NotNull JetType context) { - return create(buildSubstitutionContext(context.getConstructor().getParameters(), context.getArguments())); - } - - @NotNull - public static Map buildSubstitutionContext( - @NotNull List parameters, - @NotNull List contextArguments - ) { - Map parameterValues = new HashMap(); - if (parameters.size() != contextArguments.size()) { - throw new IllegalArgumentException("type parameter count != context arguments: \n" + - "parameters=" + parameters + "\n" + - "contextArgs=" + contextArguments); - } - for (int i = 0, size = parameters.size(); i < size; i++) { - parameterValues.put(parameters.get(i).getTypeConstructor(), contextArguments.get(i)); - } - return parameterValues; + return create(new IndexedParametersSubstitution(context.getConstructor(), context.getArguments())); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -108,10 +68,6 @@ public class TypeSubstitutor { this.substitution = substitution; } - public boolean inRange(@NotNull TypeConstructor typeConstructor) { - return substitution.get(typeConstructor) != null; - } - public boolean isEmpty() { return substitution.isEmpty(); } @@ -170,8 +126,9 @@ public class TypeSubstitutor { // The type is within the substitution range, i.e. T or T? JetType type = originalProjection.getType(); + TypeProjection replacement = substitution.get(type); Variance originalProjectionKind = originalProjection.getProjectionKind(); - if (TypesPackage.isFlexible(type) && !TypesPackage.isCustomTypeVariable(type)) { + if (replacement == null && TypesPackage.isFlexible(type) && !TypesPackage.isCustomTypeVariable(type)) { Flexibility flexibility = TypesPackage.flexibility(type); TypeProjection substitutedLower = unsafeSubstitute(new TypeProjectionImpl(originalProjectionKind, flexibility.getLowerBound()), recursionDepth + 1); @@ -190,8 +147,6 @@ public class TypeSubstitutor { if (KotlinBuiltIns.isNothing(type) || type.isError()) return originalProjection; - TypeProjection replacement = substitution.get(type.getConstructor()); - if (replacement != null) { VarianceConflictType varianceConflict = conflictType(originalProjectionKind, replacement.getProjectionKind()); @@ -262,8 +217,8 @@ public class TypeSubstitutor { @Nullable @Override - public TypeProjection get(TypeConstructor key) { - return containedOrCapturedTypeParameters.contains(key) ? substitution.get(key) : null; + public TypeProjection get(@NotNull JetType key) { + return containedOrCapturedTypeParameters.contains(key.getConstructor()) ? substitution.get(key) : null; } @Override diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.java b/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.java index 9c03dd4c489..68f8da36eeb 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.java +++ b/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.java @@ -714,9 +714,9 @@ public class TypeUtils { } final TypeProjection projection = new TypeProjectionImpl(type); - return TypeSubstitutor.create(new TypeSubstitution() { + return TypeSubstitutor.create(new TypeConstructorSubstitution() { @Override - public TypeProjection get(TypeConstructor key) { + public TypeProjection get(@NotNull TypeConstructor key) { if (constructors.contains(key)) { return projection; } @@ -730,34 +730,6 @@ public class TypeUtils { }); } - @NotNull - public static TypeSubstitutor makeSubstitutorForTypeParametersMap( - @NotNull final Map substitutionContext - ) { - return TypeSubstitutor.create(new TypeSubstitution() { - @Nullable - @Override - public TypeProjection get(TypeConstructor key) { - DeclarationDescriptor declarationDescriptor = key.getDeclarationDescriptor(); - if (declarationDescriptor instanceof TypeParameterDescriptor) { - TypeParameterDescriptor descriptor = (TypeParameterDescriptor) declarationDescriptor; - return substitutionContext.get(descriptor); - } - return null; - } - - @Override - public boolean isEmpty() { - return substitutionContext.isEmpty(); - } - - @Override - public String toString() { - return substitutionContext.toString(); - } - }); - } - public static boolean isTypeParameter(@NotNull JetType type) { return getTypeParameterDescriptorOrNull(type) != null; } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.kt b/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.kt index ab40691203b..a8ada261c7d 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.kt @@ -131,4 +131,6 @@ fun JetType.getNestedArguments(): List { fun JetType.containsError() = ErrorUtils.containsErrorType(this) +public fun List.defaultProjections(): List = map { TypeProjectionImpl(it) } + public fun JetType.isDefaultBound(): Boolean = KotlinBuiltIns.isDefaultBound(getSupertypeRepresentative()) 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 d085495ac27..8531de163b3 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.DescriptorUtils import org.jetbrains.kotlin.resolve.scopes.ChainedScope import org.jetbrains.kotlin.resolve.scopes.JetScope import org.jetbrains.kotlin.resolve.scopes.UsageLocation -import org.jetbrains.kotlin.types.JetType -import org.jetbrains.kotlin.types.SubstitutionUtils -import org.jetbrains.kotlin.types.TypeUtils -import org.jetbrains.kotlin.types.Variance +import org.jetbrains.kotlin.types.* import java.util.HashMap public object HeuristicSignatures { @@ -89,9 +86,7 @@ public object HeuristicSignatures { val type = typeFromText(typeStr, typeParameters, moduleDescriptor, project) - // now substitute type parameters with actual arguments - val typeArgsMap = typeParameters.zip(ownerType.getArguments()).toMap() - val substitutor = TypeUtils.makeSubstitutorForTypeParametersMap(typeArgsMap) + val substitutor = IndexedParametersSubstitution(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 c88709e193c..c5bcf14b46f 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/SuperClassNotInitialized.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/SuperClassNotInitialized.kt @@ -39,6 +39,7 @@ import org.jetbrains.kotlin.idea.core.replaced import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.types.JetType +import org.jetbrains.kotlin.types.IndexedParametersSubstitution import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf import java.util.ArrayList @@ -66,8 +67,7 @@ public object SuperClassNotInitialized : JetIntentionActionsFactory() { if (classOrObjectDeclaration is JetClass) { val superType = classDescriptor.getTypeConstructor().getSupertypes().firstOrNull { it.getConstructor().getDeclarationDescriptor() == superClass } if (superType != null) { - val typeArgsMap = superClass.getTypeConstructor().getParameters().zip(superType.getArguments()).toMap() - val substitutor = TypeUtils.makeSubstitutorForTypeParametersMap(typeArgsMap) + val substitutor = IndexedParametersSubstitution(superClass.typeConstructor, superType.arguments).buildSubstitutor() val substitutedConstructors = constructors .filter { it.getValueParameters().isNotEmpty() }