[API Usage] Inject Refiner into KotlinTypeChecker, use it for subtyping
This commit is contained in:
committed by
Dmitry Savvinov
parent
9047ddfc2f
commit
a1b52b2f90
@@ -17,7 +17,7 @@
|
||||
package org.jetbrains.kotlin.frontend.di
|
||||
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.config.*
|
||||
import org.jetbrains.kotlin.container.StorageComponentContainer
|
||||
import org.jetbrains.kotlin.container.useImpl
|
||||
import org.jetbrains.kotlin.container.useInstance
|
||||
@@ -36,6 +36,8 @@ import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
|
||||
import org.jetbrains.kotlin.resolve.checkers.ExperimentalUsageChecker
|
||||
import org.jetbrains.kotlin.resolve.lazy.*
|
||||
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner
|
||||
import org.jetbrains.kotlin.types.checker.NewKotlinTypeCheckerImpl
|
||||
import org.jetbrains.kotlin.types.expressions.DeclarationScopeProviderForLocalClassifierAnalyzer
|
||||
import org.jetbrains.kotlin.types.expressions.LocalClassDescriptorHolder
|
||||
import org.jetbrains.kotlin.types.expressions.LocalLazyDeclarationResolver
|
||||
@@ -66,6 +68,14 @@ fun StorageComponentContainer.configureModule(
|
||||
extension.registerModuleComponents(this, platform, moduleContext.module)
|
||||
}
|
||||
|
||||
useImpl<NewKotlinTypeCheckerImpl>()
|
||||
|
||||
if (languageVersionSettings.isTypeRefinementEnabled) {
|
||||
useImpl<KotlinTypeRefinerImpl>()
|
||||
} else {
|
||||
useInstance(KotlinTypeRefiner.Default)
|
||||
}
|
||||
|
||||
configurePlatformIndependentComponents()
|
||||
}
|
||||
|
||||
|
||||
+8
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory;
|
||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
|
||||
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver;
|
||||
import org.jetbrains.kotlin.types.WrappedTypeFactory;
|
||||
import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@@ -62,6 +63,8 @@ public class ExpressionTypingComponents {
|
||||
/*package*/ EffectSystem effectSystem;
|
||||
/*package*/ ContractParsingServices contractParsingServices;
|
||||
/*package*/ DataFlowValueFactory dataFlowValueFactory;
|
||||
/*package*/ NewKotlinTypeChecker kotlinTypeChecker;
|
||||
|
||||
|
||||
@Inject
|
||||
public void setGlobalContext(@NotNull GlobalContext globalContext) {
|
||||
@@ -237,4 +240,9 @@ public class ExpressionTypingComponents {
|
||||
public void setDataFlowValueFactory(@NotNull DataFlowValueFactory dataFlowValueFactory) {
|
||||
this.dataFlowValueFactory = dataFlowValueFactory;
|
||||
}
|
||||
|
||||
@Inject
|
||||
public void setKotlinTypeChecker(@NotNull NewKotlinTypeChecker kotlinTypeChecker) {
|
||||
this.kotlinTypeChecker = kotlinTypeChecker;
|
||||
}
|
||||
}
|
||||
|
||||
+14
-2
@@ -22,11 +22,23 @@ import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker.transformToNewTyp
|
||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
|
||||
import org.jetbrains.kotlin.types.refinement.TypeRefinement
|
||||
|
||||
open class ClassicTypeCheckerContext(val errorTypeEqualsToAnything: Boolean, val allowedTypeVariable: Boolean = true) : ClassicTypeSystemContext, AbstractTypeCheckerContext() {
|
||||
open class ClassicTypeCheckerContext(
|
||||
val errorTypeEqualsToAnything: Boolean,
|
||||
val allowedTypeVariable: Boolean = true,
|
||||
val kotlinTypeRefiner: KotlinTypeRefiner = KotlinTypeRefiner.Default
|
||||
) : ClassicTypeSystemContext, AbstractTypeCheckerContext() {
|
||||
|
||||
override fun prepareType(type: KotlinTypeMarker): KotlinTypeMarker {
|
||||
return transformToNewType((type as KotlinType).unwrap())
|
||||
require(type is KotlinType, type::errorMessage)
|
||||
return transformToNewType(type.unwrap())
|
||||
}
|
||||
|
||||
@UseExperimental(TypeRefinement::class)
|
||||
override fun refineType(type: KotlinTypeMarker): KotlinTypeMarker {
|
||||
require(type is KotlinType, type::errorMessage)
|
||||
return kotlinTypeRefiner.refineType(type)
|
||||
}
|
||||
|
||||
override val isErrorTypeEqualsToAnything: Boolean
|
||||
|
||||
@@ -56,20 +56,24 @@ object ErrorTypesAreEqualToAnything : KotlinTypeChecker {
|
||||
}
|
||||
|
||||
interface NewKotlinTypeChecker : KotlinTypeChecker {
|
||||
val kotlinTypeRefiner: KotlinTypeRefiner
|
||||
|
||||
fun transformToNewType(type: UnwrappedType): UnwrappedType
|
||||
|
||||
companion object {
|
||||
val Default = NewKotlinTypeCheckerImpl()
|
||||
val Default = NewKotlinTypeCheckerImpl(KotlinTypeRefiner.Default)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class NewKotlinTypeCheckerImpl() : NewKotlinTypeChecker {
|
||||
class NewKotlinTypeCheckerImpl(override val kotlinTypeRefiner: KotlinTypeRefiner) : NewKotlinTypeChecker {
|
||||
|
||||
override fun isSubtypeOf(subtype: KotlinType, supertype: KotlinType): Boolean =
|
||||
ClassicTypeCheckerContext(true).isSubtypeOf(subtype.unwrap(), supertype.unwrap()) // todo fix flag errorTypeEqualsToAnything
|
||||
ClassicTypeCheckerContext(true, kotlinTypeRefiner = kotlinTypeRefiner)
|
||||
.isSubtypeOf(subtype.unwrap(), supertype.unwrap()) // todo fix flag errorTypeEqualsToAnything
|
||||
|
||||
override fun equalTypes(a: KotlinType, b: KotlinType): Boolean =
|
||||
ClassicTypeCheckerContext(false).equalTypes(a.unwrap(), b.unwrap())
|
||||
ClassicTypeCheckerContext(false, kotlinTypeRefiner = kotlinTypeRefiner).equalTypes(a.unwrap(), b.unwrap())
|
||||
|
||||
fun ClassicTypeCheckerContext.equalTypes(a: UnwrappedType, b: UnwrappedType): Boolean {
|
||||
return AbstractTypeChecker.equalTypes(this as AbstractTypeCheckerContext, a, b)
|
||||
|
||||
@@ -25,6 +25,10 @@ abstract class AbstractTypeCheckerContext : TypeSystemContext {
|
||||
return type
|
||||
}
|
||||
|
||||
open fun refineType(type: KotlinTypeMarker): KotlinTypeMarker {
|
||||
return type
|
||||
}
|
||||
|
||||
abstract val isErrorTypeEqualsToAnything: Boolean
|
||||
|
||||
protected var argumentsDepth = 0
|
||||
@@ -157,19 +161,21 @@ object AbstractTypeChecker {
|
||||
|
||||
fun isSubtypeOf(context: AbstractTypeCheckerContext, subType: KotlinTypeMarker, superType: KotlinTypeMarker): Boolean {
|
||||
if (subType === superType) return true
|
||||
return context.completeIsSubTypeOf(context.prepareType(subType), context.prepareType(superType))
|
||||
return with(context) { completeIsSubTypeOf(prepareType(refineType(subType)), prepareType(refineType(superType))) }
|
||||
}
|
||||
|
||||
fun equalTypes(context: AbstractTypeCheckerContext, a: KotlinTypeMarker, b: KotlinTypeMarker): Boolean = with(context) {
|
||||
if (a === b) return true
|
||||
|
||||
if (isCommonDenotableType(a) && isCommonDenotableType(b)) {
|
||||
val simpleA = a.lowerBoundIfFlexible()
|
||||
if (!areEqualTypeConstructors(a.typeConstructor(), b.typeConstructor())) return false
|
||||
val refinedA = refineType(a)
|
||||
val refinedB = refineType(b)
|
||||
val simpleA = refinedA.lowerBoundIfFlexible()
|
||||
if (!areEqualTypeConstructors(refinedA.typeConstructor(), refinedB.typeConstructor())) return false
|
||||
if (simpleA.argumentsCount() == 0) {
|
||||
if (a.hasFlexibleNullability() || b.hasFlexibleNullability()) return true
|
||||
if (refinedA.hasFlexibleNullability() || refinedB.hasFlexibleNullability()) return true
|
||||
|
||||
return simpleA.isMarkedNullable() == b.lowerBoundIfFlexible().isMarkedNullable()
|
||||
return simpleA.isMarkedNullable() == refinedB.lowerBoundIfFlexible().isMarkedNullable()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user