From b3be21146c5941405884fc78d0265ccd2595c802 Mon Sep 17 00:00:00 2001 From: Stanislav Erokhin Date: Wed, 24 May 2017 10:50:08 +0300 Subject: [PATCH] [NI] Add more hacks. --- .../TypeCheckerContextForConstraintSystem.kt | 8 +++-- .../kotlin/resolve/calls/tower/TowerLevels.kt | 29 +++++++++++++++---- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/TypeCheckerContextForConstraintSystem.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/TypeCheckerContextForConstraintSystem.kt index 8eab74bb77a..0dc9d681894 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/TypeCheckerContextForConstraintSystem.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/TypeCheckerContextForConstraintSystem.kt @@ -32,8 +32,12 @@ abstract class TypeCheckerContextForConstraintSystem : TypeCheckerContext(errorT override fun allowSubtypeViaLowerTypeForCapturedType(subType: SimpleType, superType: NewCapturedType) = !subType.contains { it.anyBound(this::isMyTypeVariable) } - override val sameConstructorPolicy get() = SeveralSupertypesWithSameConstructorPolicy.TAKE_FIRST_FOR_SUBTYPING - + /** + * todo: possible we should override this method, because otherwise OR in subtyping transformed to AND in constraint system + * Now we cannot do this, because sometimes we have proper intersection type as lower type and if we first supertype, + * then we can get wrong result. + * override val sameConstructorPolicy get() = SeveralSupertypesWithSameConstructorPolicy.TAKE_FIRST_FOR_SUBTYPING + */ override final fun addSubtypeConstraint(subType: UnwrappedType, superType: UnwrappedType): Boolean? { assertInputTypes(subType, superType) diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerLevels.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerLevels.kt index 263c00897d0..cee2f639914 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerLevels.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerLevels.kt @@ -35,9 +35,7 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastI import org.jetbrains.kotlin.resolve.scopes.utils.collectFunctions import org.jetbrains.kotlin.resolve.scopes.utils.collectVariables import org.jetbrains.kotlin.resolve.selectMostSpecificInEachOverridableGroup -import org.jetbrains.kotlin.types.ErrorUtils -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.isDynamic +import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.typeUtil.getImmediateSuperclassNotAny import org.jetbrains.kotlin.utils.SmartList import org.jetbrains.kotlin.utils.addIfNotNull @@ -113,10 +111,10 @@ internal class MemberScopeTowerLevel( if (dispatchReceiver.possibleTypes.isNotEmpty()) { if (unstableCandidates == null) { - result.retainAll(result.selectMostSpecificInEachOverridableGroup { descriptor }) + result.retainAll(result.selectMostSpecificInEachOverridableGroup { descriptor.approximateCapturedTypes() }) } else { - result.addAll(unstableCandidates.selectMostSpecificInEachOverridableGroup { descriptor }) + result.addAll(unstableCandidates.selectMostSpecificInEachOverridableGroup { descriptor.approximateCapturedTypes() }) } } @@ -129,6 +127,27 @@ internal class MemberScopeTowerLevel( return result } + /** + * this is bad hack for test like BlackBoxCodegenTestGenerated.Reflection.Properties#testGetPropertiesMutableVsReadonly (see last get call) + * Main reason for this hack: when we have List<*> we do capturing and transform receiver type to List. + * So method get has signature get(Int): Capture(*). If we also have smartcast to MutableList, then there is also method get(Int): String. + * And we should chose get(Int): String. + */ + private fun CallableDescriptor.approximateCapturedTypes(): CallableDescriptor { + if (!USE_NEW_INFERENCE) return this + + val approximator = TypeApproximator() + val wrappedSubstitution = object : TypeSubstitution() { + override fun get(key: KotlinType): TypeProjection? = null + override fun prepareTopLevelType(topLevelType: KotlinType, position: Variance) = when (position) { + Variance.INVARIANT -> null + Variance.OUT_VARIANCE -> approximator.approximateToSuperType(topLevelType.unwrap(), TypeApproximatorConfiguration.CapturedTypesApproximation) + Variance.IN_VARIANCE -> approximator.approximateToSubType(topLevelType.unwrap(), TypeApproximatorConfiguration.CapturedTypesApproximation) + } ?: topLevelType + } + return substitute(TypeSubstitutor.create(wrappedSubstitution)) + } + private fun ReceiverValueWithSmartCastInfo.smartCastReceiver(targetType: KotlinType): ReceiverValueWithSmartCastInfo { if (receiverValue !is ImplicitClassReceiver) return this