[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
|
package org.jetbrains.kotlin.frontend.di
|
||||||
|
|
||||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
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.StorageComponentContainer
|
||||||
import org.jetbrains.kotlin.container.useImpl
|
import org.jetbrains.kotlin.container.useImpl
|
||||||
import org.jetbrains.kotlin.container.useInstance
|
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.checkers.ExperimentalUsageChecker
|
||||||
import org.jetbrains.kotlin.resolve.lazy.*
|
import org.jetbrains.kotlin.resolve.lazy.*
|
||||||
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
|
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.DeclarationScopeProviderForLocalClassifierAnalyzer
|
||||||
import org.jetbrains.kotlin.types.expressions.LocalClassDescriptorHolder
|
import org.jetbrains.kotlin.types.expressions.LocalClassDescriptorHolder
|
||||||
import org.jetbrains.kotlin.types.expressions.LocalLazyDeclarationResolver
|
import org.jetbrains.kotlin.types.expressions.LocalLazyDeclarationResolver
|
||||||
@@ -66,6 +68,14 @@ fun StorageComponentContainer.configureModule(
|
|||||||
extension.registerModuleComponents(this, platform, moduleContext.module)
|
extension.registerModuleComponents(this, platform, moduleContext.module)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useImpl<NewKotlinTypeCheckerImpl>()
|
||||||
|
|
||||||
|
if (languageVersionSettings.isTypeRefinementEnabled) {
|
||||||
|
useImpl<KotlinTypeRefinerImpl>()
|
||||||
|
} else {
|
||||||
|
useInstance(KotlinTypeRefiner.Default)
|
||||||
|
}
|
||||||
|
|
||||||
configurePlatformIndependentComponents()
|
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.constants.evaluate.ConstantExpressionEvaluator;
|
||||||
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver;
|
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver;
|
||||||
import org.jetbrains.kotlin.types.WrappedTypeFactory;
|
import org.jetbrains.kotlin.types.WrappedTypeFactory;
|
||||||
|
import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
@@ -62,6 +63,8 @@ public class ExpressionTypingComponents {
|
|||||||
/*package*/ EffectSystem effectSystem;
|
/*package*/ EffectSystem effectSystem;
|
||||||
/*package*/ ContractParsingServices contractParsingServices;
|
/*package*/ ContractParsingServices contractParsingServices;
|
||||||
/*package*/ DataFlowValueFactory dataFlowValueFactory;
|
/*package*/ DataFlowValueFactory dataFlowValueFactory;
|
||||||
|
/*package*/ NewKotlinTypeChecker kotlinTypeChecker;
|
||||||
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public void setGlobalContext(@NotNull GlobalContext globalContext) {
|
public void setGlobalContext(@NotNull GlobalContext globalContext) {
|
||||||
@@ -237,4 +240,9 @@ public class ExpressionTypingComponents {
|
|||||||
public void setDataFlowValueFactory(@NotNull DataFlowValueFactory dataFlowValueFactory) {
|
public void setDataFlowValueFactory(@NotNull DataFlowValueFactory dataFlowValueFactory) {
|
||||||
this.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.KotlinTypeMarker
|
||||||
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
|
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
|
||||||
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
|
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 {
|
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
|
override val isErrorTypeEqualsToAnything: Boolean
|
||||||
|
|||||||
@@ -56,20 +56,24 @@ object ErrorTypesAreEqualToAnything : KotlinTypeChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface NewKotlinTypeChecker : KotlinTypeChecker {
|
interface NewKotlinTypeChecker : KotlinTypeChecker {
|
||||||
|
val kotlinTypeRefiner: KotlinTypeRefiner
|
||||||
|
|
||||||
fun transformToNewType(type: UnwrappedType): UnwrappedType
|
fun transformToNewType(type: UnwrappedType): UnwrappedType
|
||||||
|
|
||||||
companion object {
|
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 =
|
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 =
|
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 {
|
fun ClassicTypeCheckerContext.equalTypes(a: UnwrappedType, b: UnwrappedType): Boolean {
|
||||||
return AbstractTypeChecker.equalTypes(this as AbstractTypeCheckerContext, a, b)
|
return AbstractTypeChecker.equalTypes(this as AbstractTypeCheckerContext, a, b)
|
||||||
|
|||||||
@@ -25,6 +25,10 @@ abstract class AbstractTypeCheckerContext : TypeSystemContext {
|
|||||||
return type
|
return type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open fun refineType(type: KotlinTypeMarker): KotlinTypeMarker {
|
||||||
|
return type
|
||||||
|
}
|
||||||
|
|
||||||
abstract val isErrorTypeEqualsToAnything: Boolean
|
abstract val isErrorTypeEqualsToAnything: Boolean
|
||||||
|
|
||||||
protected var argumentsDepth = 0
|
protected var argumentsDepth = 0
|
||||||
@@ -157,19 +161,21 @@ object AbstractTypeChecker {
|
|||||||
|
|
||||||
fun isSubtypeOf(context: AbstractTypeCheckerContext, subType: KotlinTypeMarker, superType: KotlinTypeMarker): Boolean {
|
fun isSubtypeOf(context: AbstractTypeCheckerContext, subType: KotlinTypeMarker, superType: KotlinTypeMarker): Boolean {
|
||||||
if (subType === superType) return true
|
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) {
|
fun equalTypes(context: AbstractTypeCheckerContext, a: KotlinTypeMarker, b: KotlinTypeMarker): Boolean = with(context) {
|
||||||
if (a === b) return true
|
if (a === b) return true
|
||||||
|
|
||||||
if (isCommonDenotableType(a) && isCommonDenotableType(b)) {
|
if (isCommonDenotableType(a) && isCommonDenotableType(b)) {
|
||||||
val simpleA = a.lowerBoundIfFlexible()
|
val refinedA = refineType(a)
|
||||||
if (!areEqualTypeConstructors(a.typeConstructor(), b.typeConstructor())) return false
|
val refinedB = refineType(b)
|
||||||
|
val simpleA = refinedA.lowerBoundIfFlexible()
|
||||||
|
if (!areEqualTypeConstructors(refinedA.typeConstructor(), refinedB.typeConstructor())) return false
|
||||||
if (simpleA.argumentsCount() == 0) {
|
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