diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/ArgumentTypeResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/ArgumentTypeResolver.java index e23338b921d..cc7e3cfa4b8 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/ArgumentTypeResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/ArgumentTypeResolver.java @@ -60,6 +60,7 @@ public class ArgumentTypeResolver { @NotNull private final ConstantExpressionEvaluator constantExpressionEvaluator; @NotNull private final FunctionPlaceholders functionPlaceholders; @NotNull private final ModuleDescriptor moduleDescriptor; + @NotNull private final KotlinTypeChecker kotlinTypeChecker; private ExpressionTypingServices expressionTypingServices; private DoubleColonExpressionResolver doubleColonExpressionResolver; @@ -70,7 +71,8 @@ public class ArgumentTypeResolver { @NotNull ReflectionTypes reflectionTypes, @NotNull ConstantExpressionEvaluator constantExpressionEvaluator, @NotNull FunctionPlaceholders functionPlaceholders, - @NotNull ModuleDescriptor moduleDescriptor + @NotNull ModuleDescriptor moduleDescriptor, + @NotNull KotlinTypeChecker kotlinTypeChecker ) { this.typeResolver = typeResolver; this.builtIns = builtIns; @@ -78,6 +80,7 @@ public class ArgumentTypeResolver { this.constantExpressionEvaluator = constantExpressionEvaluator; this.functionPlaceholders = functionPlaceholders; this.moduleDescriptor = moduleDescriptor; + this.kotlinTypeChecker = kotlinTypeChecker; } // component dependency cycle @@ -97,12 +100,11 @@ public class ArgumentTypeResolver { ) { if (FunctionPlaceholdersKt.isFunctionPlaceholder(actualType)) { KotlinType functionType = ConstraintSystemBuilderImplKt.createTypeForFunctionPlaceholder(actualType, expectedType); - return KotlinTypeChecker.DEFAULT.isSubtypeOf(functionType, expectedType); + return kotlinTypeChecker.isSubtypeOf(functionType, expectedType); } - return KotlinTypeChecker.DEFAULT.isSubtypeOf(actualType, expectedType); + return kotlinTypeChecker.isSubtypeOf(actualType, expectedType); } - public void checkTypesWithNoCallee( @NotNull CallResolutionContext context ) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/CoroutineInferenceUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/CoroutineInferenceUtil.kt index 6c4a5489fbd..ad49be73958 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/CoroutineInferenceUtil.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/CoroutineInferenceUtil.kt @@ -39,8 +39,8 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE -import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker import org.jetbrains.kotlin.types.checker.ClassicTypeCheckerContext +import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices import org.jetbrains.kotlin.types.expressions.KotlinTypeInfo import org.jetbrains.kotlin.types.model.KotlinTypeMarker @@ -228,7 +228,7 @@ class CoroutineInferenceSupport( forceInferenceForArguments(context) { valueArgument: ValueArgument, kotlinType: KotlinType -> val argumentMatch = resultingCall.getArgumentMapping(valueArgument) as? ArgumentMatch ?: return@forceInferenceForArguments - with(NewKotlinTypeChecker) { + with(NewKotlinTypeChecker.Default) { val parameterType = getEffectiveExpectedType(argumentMatch.valueParameter, valueArgument, context) CoroutineTypeCheckerContext(allowOnlyTrivialConstraints = false).isSubtypeOf(kotlinType.unwrap(), parameterType.unwrap()) } @@ -242,7 +242,7 @@ class CoroutineInferenceSupport( false resultingCall.extensionReceiver?.let { actualReceiver -> - with(NewKotlinTypeChecker) { + with(NewKotlinTypeChecker.Default) { CoroutineTypeCheckerContext(allowOnlyTrivialConstraints = allowOnlyTrivialConstraintsForReceiver).isSubtypeOf( actualReceiver.type.unwrap(), extensionReceiver.value.type.unwrap() ) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DataFlowAnalyzer.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DataFlowAnalyzer.java index fa601dc12cc..8a740859c43 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DataFlowAnalyzer.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DataFlowAnalyzer.java @@ -62,6 +62,7 @@ public class DataFlowAnalyzer { private final EffectSystem effectSystem; private final DataFlowValueFactory dataFlowValueFactory; private final SmartCastManager smartCastManager; + private final KotlinTypeChecker kotlinTypeChecker; public DataFlowAnalyzer( @NotNull Iterable additionalTypeCheckers, @@ -72,7 +73,8 @@ public class DataFlowAnalyzer { @NotNull LanguageVersionSettings languageVersionSettings, @NotNull EffectSystem effectSystem, @NotNull DataFlowValueFactory factory, - @NotNull SmartCastManager smartCastManager + @NotNull SmartCastManager smartCastManager, + @NotNull KotlinTypeChecker kotlinTypeChecker ) { this.additionalTypeCheckers = additionalTypeCheckers; this.constantExpressionEvaluator = constantExpressionEvaluator; @@ -83,6 +85,7 @@ public class DataFlowAnalyzer { this.effectSystem = effectSystem; this.dataFlowValueFactory = factory; this.smartCastManager = smartCastManager; + this.kotlinTypeChecker = kotlinTypeChecker; } // NB: use this method only for functions from 'Any' @@ -285,7 +288,7 @@ public class DataFlowAnalyzer { boolean reportErrorForTypeMismatch ) { if (noExpectedType(c.expectedType) || !c.expectedType.getConstructor().isDenotable() || - KotlinTypeChecker.DEFAULT.isSubtypeOf(expressionType, c.expectedType)) { + kotlinTypeChecker.isSubtypeOf(expressionType, c.expectedType)) { return expressionType; } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt index 7510e22b59b..c0cc3005056 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt @@ -273,9 +273,9 @@ class NewConstraintSystemImpl( val resultTypeIsInputType = projectedInputCallTypes.any { inputType -> val constructor = inputType.constructor if (constructor is IntersectionTypeConstructor) - constructor.supertypes.any { NewKotlinTypeChecker.equalTypes(resultType, it) } + constructor.supertypes.any { NewKotlinTypeChecker.Default.equalTypes(resultType, it) } else - NewKotlinTypeChecker.equalTypes(resultType, inputType) + NewKotlinTypeChecker.Default.equalTypes(resultType, inputType) } if (!resultTypeIsInputType) { addError(OnlyInputTypesDiagnostic(variableWithConstraints.typeVariable as NewTypeVariable)) diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectedActualResolver.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectedActualResolver.kt index a121a02e057..26092d71b77 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectedActualResolver.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectedActualResolver.kt @@ -325,7 +325,7 @@ object ExpectedActualResolver { if (a == null) return b == null if (b == null) return false - with(NewKotlinTypeChecker) { + with(NewKotlinTypeChecker.Default) { val context = object : ClassicTypeCheckerContext(false) { override fun areEqualTypeConstructors(a: TypeConstructor, b: TypeConstructor): Boolean { return isExpectedClassAndActualTypeAlias(a, b, platformModule) || diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt b/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt index 03586174fe9..2c6945c436d 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.types.typeUtil.contains import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract +import kotlin.math.max interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSystemCommonBackendContext { override fun TypeConstructorMarker.isDenotable(): Boolean { @@ -427,7 +428,7 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy override fun prepareType(type: KotlinTypeMarker): KotlinTypeMarker { require(type is UnwrappedType, type::errorMessage) - return NewKotlinTypeChecker.transformToNewType(type) + return NewKotlinTypeChecker.Default.transformToNewType(type) } override fun DefinitelyNotNullTypeMarker.original(): SimpleTypeMarker { diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/checker/IntersectionType.kt b/core/descriptors/src/org/jetbrains/kotlin/types/checker/IntersectionType.kt index 22c5f5340e6..7852fa189e1 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/checker/IntersectionType.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/checker/IntersectionType.kt @@ -114,7 +114,7 @@ object TypeIntersector { IntegerLiteralTypeConstructor.findIntersectionType(filteredEqualTypes)?.let { return it } - val filteredSuperAndEqualTypes = filterTypes(filteredEqualTypes, NewKotlinTypeChecker::equalTypes) + val filteredSuperAndEqualTypes = filterTypes(filteredEqualTypes, NewKotlinTypeChecker.Default::equalTypes) assert(filteredSuperAndEqualTypes.isNotEmpty(), errorMessage) if (filteredSuperAndEqualTypes.size < 2) return filteredSuperAndEqualTypes.single() @@ -145,7 +145,7 @@ object TypeIntersector { } private fun isStrictSupertype(subtype: KotlinType, supertype: KotlinType): Boolean { - return with(NewKotlinTypeChecker) { + return with(NewKotlinTypeChecker.Default) { isSubtypeOf(subtype, supertype) && !isSubtypeOf(supertype, subtype) } } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/checker/KotlinTypeChecker.java b/core/descriptors/src/org/jetbrains/kotlin/types/checker/KotlinTypeChecker.java index a000066ae6a..dbc5e389f37 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/checker/KotlinTypeChecker.java +++ b/core/descriptors/src/org/jetbrains/kotlin/types/checker/KotlinTypeChecker.java @@ -26,7 +26,7 @@ public interface KotlinTypeChecker { boolean equals(@NotNull TypeConstructor a, @NotNull TypeConstructor b); } - KotlinTypeChecker DEFAULT = NewKotlinTypeChecker.INSTANCE; + KotlinTypeChecker DEFAULT = NewKotlinTypeChecker.Companion.getDefault(); boolean isSubtypeOf(@NotNull KotlinType subtype, @NotNull KotlinType supertype); boolean equalTypes(@NotNull KotlinType a, @NotNull KotlinType b); diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/checker/NewCapturedType.kt b/core/descriptors/src/org/jetbrains/kotlin/types/checker/NewCapturedType.kt index 526c502171e..d8bacde6526 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/checker/NewCapturedType.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/checker/NewCapturedType.kt @@ -32,7 +32,7 @@ import org.jetbrains.kotlin.utils.DO_NOTHING_2 // if input type is capturedType, then we approximate it to UpperBound // null means that type should be leaved as is fun prepareArgumentTypeRegardingCaptureTypes(argumentType: UnwrappedType): UnwrappedType? { - val simpleType = NewKotlinTypeChecker.transformToNewType(argumentType.lowerIfFlexible()) + val simpleType = NewKotlinTypeChecker.Default.transformToNewType(argumentType.lowerIfFlexible()) if (simpleType.constructor is IntersectionTypeConstructor) { var changed = false val preparedSuperTypes = simpleType.constructor.supertypes.map { @@ -97,10 +97,10 @@ fun captureFromArguments( if (oldProjection.projectionKind == Variance.INVARIANT) continue var upperBounds = type.constructor.parameters[index].upperBounds.map { - NewKotlinTypeChecker.transformToNewType(substitutor.safeSubstitute(it, Variance.INVARIANT).unwrap()) + NewKotlinTypeChecker.Default.transformToNewType(substitutor.safeSubstitute(it, Variance.INVARIANT).unwrap()) } if (!oldProjection.isStarProjection && oldProjection.projectionKind == Variance.OUT_VARIANCE) { - upperBounds += NewKotlinTypeChecker.transformToNewType(oldProjection.type.unwrap()) + upperBounds += NewKotlinTypeChecker.Default.transformToNewType(oldProjection.type.unwrap()) } val capturedType = newProjection.type as NewCapturedType diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/checker/NewKotlinTypeChecker.kt b/core/descriptors/src/org/jetbrains/kotlin/types/checker/NewKotlinTypeChecker.kt index 67033c86a8d..30ea12d9fec 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/checker/NewKotlinTypeChecker.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/checker/NewKotlinTypeChecker.kt @@ -49,13 +49,22 @@ object StrictEqualityTypeChecker { object ErrorTypesAreEqualToAnything : KotlinTypeChecker { override fun isSubtypeOf(subtype: KotlinType, supertype: KotlinType): Boolean = - NewKotlinTypeChecker.run { ClassicTypeCheckerContext(true).isSubtypeOf(subtype.unwrap(), supertype.unwrap()) } + NewKotlinTypeChecker.Default.run { ClassicTypeCheckerContext(true).isSubtypeOf(subtype.unwrap(), supertype.unwrap()) } override fun equalTypes(a: KotlinType, b: KotlinType): Boolean = - NewKotlinTypeChecker.run { ClassicTypeCheckerContext(true).equalTypes(a.unwrap(), b.unwrap()) } + NewKotlinTypeChecker.Default.run { ClassicTypeCheckerContext(true).equalTypes(a.unwrap(), b.unwrap()) } } -object NewKotlinTypeChecker : KotlinTypeChecker { +interface NewKotlinTypeChecker : KotlinTypeChecker { + fun transformToNewType(type: UnwrappedType): UnwrappedType + + companion object { + val Default = NewKotlinTypeCheckerImpl() + } +} + + +class NewKotlinTypeCheckerImpl() : NewKotlinTypeChecker { override fun isSubtypeOf(subtype: KotlinType, supertype: KotlinType): Boolean = ClassicTypeCheckerContext(true).isSubtypeOf(subtype.unwrap(), supertype.unwrap()) // todo fix flag errorTypeEqualsToAnything @@ -115,7 +124,7 @@ object NewKotlinTypeChecker : KotlinTypeChecker { return type } - fun transformToNewType(type: UnwrappedType): UnwrappedType = + override fun transformToNewType(type: UnwrappedType): UnwrappedType = when (type) { is SimpleType -> transformToNewType(type) is FlexibleType -> { diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceVariable/KotlinIntroduceVariableHandler.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceVariable/KotlinIntroduceVariableHandler.kt index 66743c85c38..5413808616b 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceVariable/KotlinIntroduceVariableHandler.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceVariable/KotlinIntroduceVariableHandler.kt @@ -93,7 +93,7 @@ object KotlinIntroduceVariableHandler : RefactoringActionHandler { } override fun equalTypes(a: KotlinType, b: KotlinType): Boolean { - return with(NewKotlinTypeChecker) { + return with(NewKotlinTypeChecker.Default) { ContextImpl().equalTypes(a.unwrap(), b.unwrap()) } }