Decouple TypeCheckerContext and TypeSystemContext
This commit is contained in:
committed by
TeamCityServer
parent
53a7dc1126
commit
3909e3c54c
@@ -31,7 +31,7 @@ import org.jetbrains.kotlin.fir.scopes.processOverriddenFunctions
|
|||||||
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
|
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||||
import org.jetbrains.kotlin.fir.typeCheckerContext
|
import org.jetbrains.kotlin.fir.typeContext
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
@@ -317,4 +317,4 @@ val FirFunctionCall.isIterator
|
|||||||
internal fun throwableClassLikeType(session: FirSession) = session.builtinTypes.throwableType.type
|
internal fun throwableClassLikeType(session: FirSession) = session.builtinTypes.throwableType.type
|
||||||
|
|
||||||
fun ConeKotlinType.isSubtypeOfThrowable(session: FirSession) =
|
fun ConeKotlinType.isSubtypeOfThrowable(session: FirSession) =
|
||||||
throwableClassLikeType(session).isSupertypeOf(session.typeCheckerContext, this.fullyExpandedType(session))
|
throwableClassLikeType(session).isSupertypeOf(session.typeContext, this.fullyExpandedType(session))
|
||||||
|
|||||||
+12
-18
@@ -22,7 +22,6 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
|||||||
import org.jetbrains.kotlin.fir.typeContext
|
import org.jetbrains.kotlin.fir.typeContext
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||||
import org.jetbrains.kotlin.types.AbstractTypeCheckerContext
|
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.min
|
import org.jetbrains.kotlin.utils.addToStdlib.min
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
@@ -63,18 +62,13 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
|
|||||||
parameterPairs.mapValues { it.value.coneType }
|
parameterPairs.mapValues { it.value.coneType }
|
||||||
)
|
)
|
||||||
|
|
||||||
val typeCheckerContext = context.session.typeContext.newBaseTypeCheckerContext(
|
|
||||||
errorTypesEqualToAnything = false,
|
|
||||||
stubTypesEqualToAnything = false
|
|
||||||
)
|
|
||||||
|
|
||||||
parameterPairs.forEach { (proto, actual) ->
|
parameterPairs.forEach { (proto, actual) ->
|
||||||
if (actual.source == null) {
|
if (actual.source == null) {
|
||||||
// inferred types don't report INAPPLICABLE_CANDIDATE for type aliases!
|
// inferred types don't report INAPPLICABLE_CANDIDATE for type aliases!
|
||||||
return@forEach
|
return@forEach
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!satisfiesBounds(proto, actual.coneType, substitutor, typeCheckerContext)) {
|
if (!satisfiesBounds(proto, actual.coneType, substitutor, context.session.typeContext)) {
|
||||||
reporter.reportOn(actual.source, proto, actual.coneType, context)
|
reporter.reportOn(actual.source, proto, actual.coneType, context)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -82,7 +76,7 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
|
|||||||
// we must analyze nested things like
|
// we must analyze nested things like
|
||||||
// S<S<K, L>, T<K, L>>()
|
// S<S<K, L>, T<K, L>>()
|
||||||
actual.coneType.safeAs<ConeClassLikeType>()?.let {
|
actual.coneType.safeAs<ConeClassLikeType>()?.let {
|
||||||
val errorOccurred = analyzeTypeParameters(it, context, reporter, typeCheckerContext, actual.source)
|
val errorOccurred = analyzeTypeParameters(it, context, reporter, context.session.typeContext, actual.source)
|
||||||
|
|
||||||
if (errorOccurred) {
|
if (errorOccurred) {
|
||||||
return
|
return
|
||||||
@@ -99,14 +93,14 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
|
|||||||
// typealias A<G> = B<List<G>>
|
// typealias A<G> = B<List<G>>
|
||||||
// val a = A<Int>()
|
// val a = A<Int>()
|
||||||
when (calleeFir) {
|
when (calleeFir) {
|
||||||
is FirConstructor -> analyzeConstructorCall(expression, substitutor, typeCheckerContext, reporter, context)
|
is FirConstructor -> analyzeConstructorCall(expression, substitutor, context.session.typeContext, reporter, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun analyzeConstructorCall(
|
private fun analyzeConstructorCall(
|
||||||
functionCall: FirQualifiedAccessExpression,
|
functionCall: FirQualifiedAccessExpression,
|
||||||
callSiteSubstitutor: ConeSubstitutor,
|
callSiteSubstitutor: ConeSubstitutor,
|
||||||
typeCheckerContext: AbstractTypeCheckerContext,
|
typeSystemContext: ConeTypeContext,
|
||||||
reporter: DiagnosticReporter,
|
reporter: DiagnosticReporter,
|
||||||
context: CheckerContext
|
context: CheckerContext
|
||||||
) {
|
) {
|
||||||
@@ -157,7 +151,7 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
|
|||||||
|
|
||||||
constructorsParameterPairs.forEach { (proto, actual) ->
|
constructorsParameterPairs.forEach { (proto, actual) ->
|
||||||
// just in case
|
// just in case
|
||||||
var intersection = typeCheckerContext.intersectTypes(
|
var intersection = typeSystemContext.intersectTypes(
|
||||||
proto.fir.bounds.map { it.coneType }
|
proto.fir.bounds.map { it.coneType }
|
||||||
).safeAs<ConeKotlinType>() ?: return@forEach
|
).safeAs<ConeKotlinType>() ?: return@forEach
|
||||||
|
|
||||||
@@ -167,7 +161,7 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
|
|||||||
// substitute Int for G from
|
// substitute Int for G from
|
||||||
// the example above
|
// the example above
|
||||||
val target = callSiteSubstitutor.substituteOrSelf(actual)
|
val target = callSiteSubstitutor.substituteOrSelf(actual)
|
||||||
val satisfiesBounds = AbstractTypeChecker.isSubtypeOf(typeCheckerContext, target, intersection)
|
val satisfiesBounds = AbstractTypeChecker.isSubtypeOf(typeSystemContext, target, intersection)
|
||||||
|
|
||||||
if (!satisfiesBounds) {
|
if (!satisfiesBounds) {
|
||||||
reporter.reportOn(functionCall.source, proto, actual, context)
|
reporter.reportOn(functionCall.source, proto, actual, context)
|
||||||
@@ -187,7 +181,7 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
|
|||||||
type: ConeClassLikeType,
|
type: ConeClassLikeType,
|
||||||
context: CheckerContext,
|
context: CheckerContext,
|
||||||
reporter: DiagnosticReporter,
|
reporter: DiagnosticReporter,
|
||||||
typeCheckerContext: AbstractTypeCheckerContext,
|
typeSystemContext: ConeTypeContext,
|
||||||
reportTarget: FirSourceElement?
|
reportTarget: FirSourceElement?
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val prototypeClass = type.lookupTag.toSymbol(context.session)
|
val prototypeClass = type.lookupTag.toSymbol(context.session)
|
||||||
@@ -218,13 +212,13 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
parameterPairs.forEach { (proto, actual) ->
|
parameterPairs.forEach { (proto, actual) ->
|
||||||
if (!satisfiesBounds(proto, actual.type, substitutor, typeCheckerContext)) {
|
if (!satisfiesBounds(proto, actual.type, substitutor, typeSystemContext)) {
|
||||||
// should report on the parameter instead!
|
// should report on the parameter instead!
|
||||||
reporter.reportOn(reportTarget, proto, actual, context)
|
reporter.reportOn(reportTarget, proto, actual, context)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
val errorOccurred = analyzeTypeParameters(actual, context, reporter, typeCheckerContext, reportTarget)
|
val errorOccurred = analyzeTypeParameters(actual, context, reporter, typeSystemContext, reportTarget)
|
||||||
|
|
||||||
if (errorOccurred) {
|
if (errorOccurred) {
|
||||||
return true
|
return true
|
||||||
@@ -242,14 +236,14 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
|
|||||||
prototypeSymbol: FirTypeParameterSymbol,
|
prototypeSymbol: FirTypeParameterSymbol,
|
||||||
target: ConeKotlinType,
|
target: ConeKotlinType,
|
||||||
substitutor: ConeSubstitutor,
|
substitutor: ConeSubstitutor,
|
||||||
typeCheckerContext: AbstractTypeCheckerContext
|
typeSystemContext: ConeTypeContext
|
||||||
): Boolean {
|
): Boolean {
|
||||||
var intersection = typeCheckerContext.intersectTypes(
|
var intersection = typeSystemContext.intersectTypes(
|
||||||
prototypeSymbol.fir.bounds.map { it.coneType }
|
prototypeSymbol.fir.bounds.map { it.coneType }
|
||||||
).safeAs<ConeKotlinType>() ?: return true
|
).safeAs<ConeKotlinType>() ?: return true
|
||||||
|
|
||||||
intersection = substitutor.substituteOrSelf(intersection)
|
intersection = substitutor.substituteOrSelf(intersection)
|
||||||
return AbstractTypeChecker.isSubtypeOf(typeCheckerContext, target, intersection)
|
return AbstractTypeChecker.isSubtypeOf(typeSystemContext, target, intersection, stubTypesEqualToAnything = false)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun DiagnosticReporter.reportOn(
|
private fun DiagnosticReporter.reportOn(
|
||||||
|
|||||||
+3
-2
@@ -30,6 +30,9 @@ import org.jetbrains.kotlin.fir.types.FirCorrespondingSupertypesCache
|
|||||||
|
|
||||||
@OptIn(SessionConfiguration::class)
|
@OptIn(SessionConfiguration::class)
|
||||||
fun FirSession.registerCommonComponents(languageVersionSettings: LanguageVersionSettings) {
|
fun FirSession.registerCommonComponents(languageVersionSettings: LanguageVersionSettings) {
|
||||||
|
register(FirLanguageSettingsComponent::class, FirLanguageSettingsComponent(languageVersionSettings))
|
||||||
|
register(InferenceComponents::class, InferenceComponents(this))
|
||||||
|
|
||||||
register(FirDeclaredMemberScopeProvider::class, FirDeclaredMemberScopeProvider())
|
register(FirDeclaredMemberScopeProvider::class, FirDeclaredMemberScopeProvider())
|
||||||
register(FirCorrespondingSupertypesCache::class, FirCorrespondingSupertypesCache(this))
|
register(FirCorrespondingSupertypesCache::class, FirCorrespondingSupertypesCache(this))
|
||||||
register(FirDefaultParametersResolver::class, FirDefaultParametersResolver())
|
register(FirDefaultParametersResolver::class, FirDefaultParametersResolver())
|
||||||
@@ -38,8 +41,6 @@ fun FirSession.registerCommonComponents(languageVersionSettings: LanguageVersion
|
|||||||
register(FirRegisteredPluginAnnotations::class, FirRegisteredPluginAnnotations.create(this))
|
register(FirRegisteredPluginAnnotations::class, FirRegisteredPluginAnnotations.create(this))
|
||||||
register(FirPredicateBasedProvider::class, FirPredicateBasedProvider.create(this))
|
register(FirPredicateBasedProvider::class, FirPredicateBasedProvider.create(this))
|
||||||
register(GeneratedClassIndex::class, GeneratedClassIndex.create())
|
register(GeneratedClassIndex::class, GeneratedClassIndex.create())
|
||||||
register(FirLanguageSettingsComponent::class, FirLanguageSettingsComponent(languageVersionSettings))
|
|
||||||
register(InferenceComponents::class, InferenceComponents(this))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(SessionConfiguration::class)
|
@OptIn(SessionConfiguration::class)
|
||||||
|
|||||||
+1
-1
@@ -636,7 +636,7 @@ class CallAndReferenceGenerator(
|
|||||||
// If the type of the argument is already an explicitly subtype of the type of the parameter, we don't need SAM conversion.
|
// If the type of the argument is already an explicitly subtype of the type of the parameter, we don't need SAM conversion.
|
||||||
if (argument.typeRef !is FirResolvedTypeRef ||
|
if (argument.typeRef !is FirResolvedTypeRef ||
|
||||||
AbstractTypeChecker.isSubtypeOf(
|
AbstractTypeChecker.isSubtypeOf(
|
||||||
session.inferenceComponents.ctx,
|
session.inferenceComponents.ctx.newBaseTypeCheckerContext(errorTypesEqualToAnything = false, stubTypesEqualToAnything = true),
|
||||||
argument.typeRef.coneType,
|
argument.typeRef.coneType,
|
||||||
parameter.returnTypeRef.coneType,
|
parameter.returnTypeRef.coneType,
|
||||||
isFromNullabilityConstraint = true
|
isFromNullabilityConstraint = true
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.fir.resolve.toSymbol
|
|||||||
import org.jetbrains.kotlin.fir.resolve.transformers.resolveSupertypesInTheAir
|
import org.jetbrains.kotlin.fir.resolve.transformers.resolveSupertypesInTheAir
|
||||||
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.typeContext
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
@@ -241,9 +242,7 @@ private fun ConeClassLikeType.mapToCanonicalNoExpansionString(session: FirSessio
|
|||||||
} + "[]"
|
} + "[]"
|
||||||
}
|
}
|
||||||
|
|
||||||
val context = ConeTypeCheckerContext(isErrorTypeEqualsToAnything = false, isStubTypeEqualsToAnything = true, session = session)
|
with(session.typeContext) {
|
||||||
|
|
||||||
with(context) {
|
|
||||||
val typeConstructor = typeConstructor()
|
val typeConstructor = typeConstructor()
|
||||||
typeConstructor.getPrimitiveType()?.let { return JvmPrimitiveType.get(it).wrapperFqName.asString() }
|
typeConstructor.getPrimitiveType()?.let { return JvmPrimitiveType.get(it).wrapperFqName.asString() }
|
||||||
typeConstructor.getPrimitiveArrayType()?.let { return JvmPrimitiveType.get(it).javaKeywordName + "[]" }
|
typeConstructor.getPrimitiveArrayType()?.let { return JvmPrimitiveType.get(it).javaKeywordName + "[]" }
|
||||||
|
|||||||
@@ -6,21 +6,19 @@
|
|||||||
package org.jetbrains.kotlin.fir
|
package org.jetbrains.kotlin.fir
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.Visibility
|
import org.jetbrains.kotlin.descriptors.Visibility
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.visibility
|
||||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||||
import org.jetbrains.kotlin.fir.resolve.inference.inferenceComponents
|
import org.jetbrains.kotlin.fir.resolve.inference.inferenceComponents
|
||||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||||
import org.jetbrains.kotlin.fir.scopes.processOverriddenFunctions
|
import org.jetbrains.kotlin.fir.scopes.processOverriddenFunctions
|
||||||
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
|
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
|
||||||
import org.jetbrains.kotlin.fir.types.ConeInferenceContext
|
import org.jetbrains.kotlin.fir.types.ConeInferenceContext
|
||||||
import org.jetbrains.kotlin.fir.types.ConeTypeCheckerContext
|
|
||||||
|
|
||||||
val FirSession.typeContext: ConeInferenceContext
|
val FirSession.typeContext: ConeInferenceContext
|
||||||
get() = inferenceComponents.ctx
|
get() = inferenceComponents.ctx
|
||||||
|
|
||||||
val FirSession.typeCheckerContext: ConeTypeCheckerContext
|
|
||||||
get() = inferenceComponents.ctx
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the list of functions that overridden by given
|
* Returns the list of functions that overridden by given
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolvedTypeDeclarati
|
|||||||
import org.jetbrains.kotlin.fir.returnExpressions
|
import org.jetbrains.kotlin.fir.returnExpressions
|
||||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
||||||
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
||||||
import org.jetbrains.kotlin.fir.typeCheckerContext
|
|
||||||
import org.jetbrains.kotlin.fir.typeContext
|
import org.jetbrains.kotlin.fir.typeContext
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
@@ -26,6 +25,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.addSubtypeConstraintIfCompat
|
|||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.SimpleConstraintSystemConstraintPosition
|
import org.jetbrains.kotlin.resolve.calls.inference.model.SimpleConstraintSystemConstraintPosition
|
||||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||||
import org.jetbrains.kotlin.types.model.CaptureStatus
|
import org.jetbrains.kotlin.types.model.CaptureStatus
|
||||||
|
import org.jetbrains.kotlin.types.model.TypeSystemCommonSuperTypesContext
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.runIf
|
import org.jetbrains.kotlin.utils.addToStdlib.runIf
|
||||||
|
|
||||||
fun Candidate.resolveArgumentExpression(
|
fun Candidate.resolveArgumentExpression(
|
||||||
@@ -416,7 +416,10 @@ fun FirExpression.isFunctional(
|
|||||||
val returnTypeCompatible =
|
val returnTypeCompatible =
|
||||||
expectedReturnType is ConeTypeParameterType ||
|
expectedReturnType is ConeTypeParameterType ||
|
||||||
AbstractTypeChecker.isSubtypeOf(
|
AbstractTypeChecker.isSubtypeOf(
|
||||||
session.inferenceComponents.ctx,
|
session.inferenceComponents.ctx.newBaseTypeCheckerContext(
|
||||||
|
errorTypesEqualToAnything = false,
|
||||||
|
stubTypesEqualToAnything = true
|
||||||
|
),
|
||||||
invokeSymbol.fir.returnTypeRef.coneType,
|
invokeSymbol.fir.returnTypeRef.coneType,
|
||||||
expectedReturnType,
|
expectedReturnType,
|
||||||
isFromNullabilityConstraint = false
|
isFromNullabilityConstraint = false
|
||||||
@@ -433,7 +436,10 @@ fun FirExpression.isFunctional(
|
|||||||
val expectedParameterType = expectedParameter!!.lowerBoundIfFlexible()
|
val expectedParameterType = expectedParameter!!.lowerBoundIfFlexible()
|
||||||
expectedParameterType is ConeTypeParameterType ||
|
expectedParameterType is ConeTypeParameterType ||
|
||||||
AbstractTypeChecker.isSubtypeOf(
|
AbstractTypeChecker.isSubtypeOf(
|
||||||
session.inferenceComponents.ctx,
|
session.inferenceComponents.ctx.newBaseTypeCheckerContext(
|
||||||
|
errorTypesEqualToAnything = false,
|
||||||
|
stubTypesEqualToAnything = true
|
||||||
|
),
|
||||||
invokeParameter.returnTypeRef.coneType,
|
invokeParameter.returnTypeRef.coneType,
|
||||||
expectedParameterType,
|
expectedParameterType,
|
||||||
isFromNullabilityConstraint = false
|
isFromNullabilityConstraint = false
|
||||||
@@ -488,7 +494,7 @@ internal fun captureFromTypeParameterUpperBoundIfNeeded(
|
|||||||
val simplifiedArgumentType = argumentType.lowerBoundIfFlexible() as? ConeTypeParameterType ?: return argumentType
|
val simplifiedArgumentType = argumentType.lowerBoundIfFlexible() as? ConeTypeParameterType ?: return argumentType
|
||||||
val typeParameter = simplifiedArgumentType.lookupTag.typeParameterSymbol.fir
|
val typeParameter = simplifiedArgumentType.lookupTag.typeParameterSymbol.fir
|
||||||
|
|
||||||
val context = session.typeCheckerContext
|
val context = session.typeContext
|
||||||
|
|
||||||
val chosenSupertype = typeParameter.bounds.map { it.coneType }
|
val chosenSupertype = typeParameter.bounds.map { it.coneType }
|
||||||
.singleOrNull { it.hasSupertypeWithGivenClassId(expectedTypeClassId, context) } ?: return argumentType
|
.singleOrNull { it.hasSupertypeWithGivenClassId(expectedTypeClassId, context) } ?: return argumentType
|
||||||
@@ -501,7 +507,7 @@ internal fun captureFromTypeParameterUpperBoundIfNeeded(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ConeKotlinType.hasSupertypeWithGivenClassId(classId: ClassId, context: ConeTypeCheckerContext): Boolean {
|
private fun ConeKotlinType.hasSupertypeWithGivenClassId(classId: ClassId, context: TypeSystemCommonSuperTypesContext): Boolean {
|
||||||
return with(context) {
|
return with(context) {
|
||||||
anySuperTypeConstructor {
|
anySuperTypeConstructor {
|
||||||
it is ConeClassLikeLookupTag && it.classId == classId
|
it is ConeClassLikeLookupTag && it.classId == classId
|
||||||
|
|||||||
+4
-2
@@ -7,14 +7,16 @@ package org.jetbrains.kotlin.fir.resolve.inference
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.fir.*
|
import org.jetbrains.kotlin.fir.*
|
||||||
import org.jetbrains.kotlin.fir.types.ConeInferenceContext
|
import org.jetbrains.kotlin.fir.types.ConeInferenceContext
|
||||||
import org.jetbrains.kotlin.fir.types.ConeTypeCheckerContext
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.components.*
|
import org.jetbrains.kotlin.resolve.calls.inference.components.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl
|
import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl
|
||||||
import org.jetbrains.kotlin.types.AbstractTypeApproximator
|
import org.jetbrains.kotlin.types.AbstractTypeApproximator
|
||||||
|
|
||||||
@NoMutableState
|
@NoMutableState
|
||||||
class InferenceComponents(val session: FirSession) : FirSessionComponent {
|
class InferenceComponents(val session: FirSession) : FirSessionComponent {
|
||||||
val ctx: ConeTypeCheckerContext = ConeTypeCheckerContext(isErrorTypeEqualsToAnything = false, isStubTypeEqualsToAnything = true, session)
|
val ctx: ConeInferenceContext = object : ConeInferenceContext {
|
||||||
|
override val session: FirSession
|
||||||
|
get() = this@InferenceComponents.session
|
||||||
|
}
|
||||||
|
|
||||||
val approximator: AbstractTypeApproximator = object : AbstractTypeApproximator(ctx) {}
|
val approximator: AbstractTypeApproximator = object : AbstractTypeApproximator(ctx) {}
|
||||||
val trivialConstraintTypeInferenceOracle = TrivialConstraintTypeInferenceOracle.create(ctx)
|
val trivialConstraintTypeInferenceOracle = TrivialConstraintTypeInferenceOracle.create(ctx)
|
||||||
|
|||||||
+2
-1
@@ -496,7 +496,8 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
|
|||||||
if (baseType !is ConeClassLikeType) return this
|
if (baseType !is ConeClassLikeType) return this
|
||||||
val baseFirClass = baseType.lookupTag.toSymbol(session)?.fir ?: return this
|
val baseFirClass = baseType.lookupTag.toSymbol(session)?.fir ?: return this
|
||||||
|
|
||||||
val newArguments = if (AbstractTypeChecker.isSubtypeOfClass(session.typeCheckerContext, baseType.lookupTag, type.lookupTag)) {
|
val newArguments = if (AbstractTypeChecker.isSubtypeOfClass(
|
||||||
|
session.typeContext.newBaseTypeCheckerContext(errorTypesEqualToAnything = false, stubTypesEqualToAnything = true), baseType.lookupTag, type.lookupTag)) {
|
||||||
// If actual type of declaration is more specific than bare type then we should just find
|
// If actual type of declaration is more specific than bare type then we should just find
|
||||||
// corresponding supertype with proper arguments
|
// corresponding supertype with proper arguments
|
||||||
with(session.typeContext) {
|
with(session.typeContext) {
|
||||||
|
|||||||
+4
-3
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
|||||||
import org.jetbrains.kotlin.fir.scopes.*
|
import org.jetbrains.kotlin.fir.scopes.*
|
||||||
import org.jetbrains.kotlin.fir.symbols.CallableId
|
import org.jetbrains.kotlin.fir.symbols.CallableId
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||||
|
import org.jetbrains.kotlin.fir.typeContext
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||||
@@ -33,7 +34,7 @@ class FirTypeIntersectionScope private constructor(
|
|||||||
private val absentProperties: MutableSet<Name> = mutableSetOf()
|
private val absentProperties: MutableSet<Name> = mutableSetOf()
|
||||||
private val absentClassifiers: MutableSet<Name> = mutableSetOf()
|
private val absentClassifiers: MutableSet<Name> = mutableSetOf()
|
||||||
|
|
||||||
private val typeContext = ConeTypeCheckerContext(isErrorTypeEqualsToAnything = false, isStubTypeEqualsToAnything = false, session)
|
private val typeCheckerContext = session.typeContext.newBaseTypeCheckerContext(false, false)
|
||||||
|
|
||||||
private val overriddenSymbols: MutableMap<FirCallableSymbol<*>, Collection<MemberWithBaseScope<out FirCallableSymbol<*>>>> =
|
private val overriddenSymbols: MutableMap<FirCallableSymbol<*>, Collection<MemberWithBaseScope<out FirCallableSymbol<*>>>> =
|
||||||
mutableMapOf()
|
mutableMapOf()
|
||||||
@@ -357,7 +358,7 @@ class FirTypeIntersectionScope private constructor(
|
|||||||
require(bFir is FirProperty) { "b is " + b.javaClass }
|
require(bFir is FirProperty) { "b is " + b.javaClass }
|
||||||
// TODO: if (!OverridingUtil.isAccessorMoreSpecific(pa.getSetter(), pb.getSetter())) return false
|
// TODO: if (!OverridingUtil.isAccessorMoreSpecific(pa.getSetter(), pb.getSetter())) return false
|
||||||
return if (aFir.isVar && bFir.isVar) {
|
return if (aFir.isVar && bFir.isVar) {
|
||||||
AbstractTypeChecker.equalTypes(typeContext as AbstractTypeCheckerContext, aReturnType, bReturnType)
|
AbstractTypeChecker.equalTypes(typeCheckerContext as AbstractTypeCheckerContext, aReturnType, bReturnType)
|
||||||
} else { // both vals or var vs val: val can't be more specific then var
|
} else { // both vals or var vs val: val can't be more specific then var
|
||||||
!(!aFir.isVar && bFir.isVar) && isTypeMoreSpecific(aReturnType, bReturnType)
|
!(!aFir.isVar && bFir.isVar) && isTypeMoreSpecific(aReturnType, bReturnType)
|
||||||
}
|
}
|
||||||
@@ -366,7 +367,7 @@ class FirTypeIntersectionScope private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun isTypeMoreSpecific(a: ConeKotlinType, b: ConeKotlinType): Boolean =
|
private fun isTypeMoreSpecific(a: ConeKotlinType, b: ConeKotlinType): Boolean =
|
||||||
AbstractTypeChecker.isSubtypeOf(typeContext as AbstractTypeCheckerContext, a, b)
|
AbstractTypeChecker.isSubtypeOf(typeCheckerContext as AbstractTypeCheckerContext, a, b)
|
||||||
|
|
||||||
private fun <D : FirCallableSymbol<*>> findMemberWithMaxVisibility(members: Collection<MemberWithBaseScope<D>>): MemberWithBaseScope<D> {
|
private fun <D : FirCallableSymbol<*>> findMemberWithMaxVisibility(members: Collection<MemberWithBaseScope<D>>): MemberWithBaseScope<D> {
|
||||||
assert(members.isNotEmpty())
|
assert(members.isNotEmpty())
|
||||||
|
|||||||
@@ -97,8 +97,8 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
|
|||||||
override fun newBaseTypeCheckerContext(
|
override fun newBaseTypeCheckerContext(
|
||||||
errorTypesEqualToAnything: Boolean,
|
errorTypesEqualToAnything: Boolean,
|
||||||
stubTypesEqualToAnything: Boolean
|
stubTypesEqualToAnything: Boolean
|
||||||
): AbstractTypeCheckerContext =
|
): ConeTypeCheckerContext =
|
||||||
ConeTypeCheckerContext(errorTypesEqualToAnything, stubTypesEqualToAnything, session)
|
ConeTypeCheckerContext(errorTypesEqualToAnything, stubTypesEqualToAnything, this)
|
||||||
|
|
||||||
override fun KotlinTypeMarker.canHaveUndefinedNullability(): Boolean {
|
override fun KotlinTypeMarker.canHaveUndefinedNullability(): Boolean {
|
||||||
require(this is ConeKotlinType)
|
require(this is ConeKotlinType)
|
||||||
@@ -483,4 +483,12 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
|
|||||||
return session.symbolProvider.getClassLikeSymbolByFqName(classId)?.toLookupTag()
|
return session.symbolProvider.getClassLikeSymbolByFqName(classId)?.toLookupTag()
|
||||||
?: error("Can't find KFunction type")
|
?: error("Can't find KFunction type")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun createTypeWithAlternativeForIntersectionResult(
|
||||||
|
firstCandidate: KotlinTypeMarker,
|
||||||
|
secondCandidate: KotlinTypeMarker
|
||||||
|
): KotlinTypeMarker {
|
||||||
|
// TODO
|
||||||
|
return firstCandidate
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.name.FqName
|
|||||||
import org.jetbrains.kotlin.name.FqNameUnsafe
|
import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.types.AbstractTypeCheckerContext
|
import org.jetbrains.kotlin.types.AbstractTypeCheckerContext
|
||||||
|
import org.jetbrains.kotlin.types.AbstractTypeCheckerContext.SupertypesPolicy.*
|
||||||
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
|
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
|
||||||
import org.jetbrains.kotlin.types.model.*
|
import org.jetbrains.kotlin.types.model.*
|
||||||
|
|
||||||
@@ -540,10 +541,13 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
|
|||||||
class ConeTypeCheckerContext(
|
class ConeTypeCheckerContext(
|
||||||
override val isErrorTypeEqualsToAnything: Boolean,
|
override val isErrorTypeEqualsToAnything: Boolean,
|
||||||
override val isStubTypeEqualsToAnything: Boolean,
|
override val isStubTypeEqualsToAnything: Boolean,
|
||||||
override val session: FirSession
|
override val typeSystemContext: ConeInferenceContext
|
||||||
) : AbstractTypeCheckerContext(), ConeInferenceContext {
|
) : AbstractTypeCheckerContext() {
|
||||||
override fun substitutionSupertypePolicy(type: SimpleTypeMarker): SupertypesPolicy {
|
|
||||||
if (type.argumentsCount() == 0) return SupertypesPolicy.LowerIfFlexible
|
val session: FirSession = typeSystemContext.session
|
||||||
|
|
||||||
|
override fun substitutionSupertypePolicy(type: SimpleTypeMarker): SupertypesPolicy = with(typeSystemContext) {
|
||||||
|
if (type.argumentsCount() == 0) return LowerIfFlexible
|
||||||
require(type is ConeKotlinType)
|
require(type is ConeKotlinType)
|
||||||
val declaration = when (type) {
|
val declaration = when (type) {
|
||||||
is ConeClassLikeType -> type.lookupTag.toSymbol(session)?.firUnsafe<FirClassLikeDeclaration<*>>()
|
is ConeClassLikeType -> type.lookupTag.toSymbol(session)?.firUnsafe<FirClassLikeDeclaration<*>>()
|
||||||
@@ -560,7 +564,7 @@ class ConeTypeCheckerContext(
|
|||||||
} else {
|
} else {
|
||||||
ConeSubstitutor.Empty
|
ConeSubstitutor.Empty
|
||||||
}
|
}
|
||||||
return object : SupertypesPolicy.DoCustomTransform() {
|
return object : DoCustomTransform() {
|
||||||
override fun transformType(context: AbstractTypeCheckerContext, type: KotlinTypeMarker): SimpleTypeMarker {
|
override fun transformType(context: AbstractTypeCheckerContext, type: KotlinTypeMarker): SimpleTypeMarker {
|
||||||
val lowerBound = type.lowerBoundIfFlexible()
|
val lowerBound = type.lowerBoundIfFlexible()
|
||||||
require(lowerBound is ConeKotlinType)
|
require(lowerBound is ConeKotlinType)
|
||||||
@@ -570,35 +574,10 @@ class ConeTypeCheckerContext(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun areEqualTypeConstructors(c1: TypeConstructorMarker, c2: TypeConstructorMarker): Boolean {
|
|
||||||
return c1 == c2
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun prepareType(type: KotlinTypeMarker): KotlinTypeMarker {
|
|
||||||
return super<ConeInferenceContext>.prepareType(type)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun refineType(type: KotlinTypeMarker): KotlinTypeMarker {
|
override fun refineType(type: KotlinTypeMarker): KotlinTypeMarker {
|
||||||
return prepareType(type)
|
return typeSystemContext.prepareType(type)
|
||||||
}
|
}
|
||||||
|
|
||||||
override val KotlinTypeMarker.isAllowedTypeVariable: Boolean
|
override val KotlinTypeMarker.isAllowedTypeVariable: Boolean
|
||||||
get() = this is ConeKotlinType && this is ConeTypeVariableType
|
get() = this is ConeKotlinType && this is ConeTypeVariableType
|
||||||
|
|
||||||
override fun newBaseTypeCheckerContext(
|
|
||||||
errorTypesEqualToAnything: Boolean,
|
|
||||||
stubTypesEqualToAnything: Boolean
|
|
||||||
): AbstractTypeCheckerContext =
|
|
||||||
if (this.isErrorTypeEqualsToAnything == errorTypesEqualToAnything && this.isStubTypeEqualsToAnything == stubTypesEqualToAnything)
|
|
||||||
this
|
|
||||||
else
|
|
||||||
ConeTypeCheckerContext(errorTypesEqualToAnything, stubTypesEqualToAnything, session)
|
|
||||||
|
|
||||||
override fun createTypeWithAlternativeForIntersectionResult(
|
|
||||||
firstCandidate: KotlinTypeMarker,
|
|
||||||
secondCandidate: KotlinTypeMarker
|
|
||||||
): KotlinTypeMarker {
|
|
||||||
// TODO
|
|
||||||
return firstCandidate
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-7
@@ -13,10 +13,12 @@ import org.jetbrains.kotlin.fir.declarations.FirTypeParameterRefsOwner
|
|||||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.typeContext
|
||||||
import org.jetbrains.kotlin.types.AbstractTypeCheckerContext
|
import org.jetbrains.kotlin.types.AbstractTypeCheckerContext
|
||||||
import org.jetbrains.kotlin.types.model.CaptureStatus
|
import org.jetbrains.kotlin.types.model.CaptureStatus
|
||||||
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.model.TypeSystemContext
|
||||||
|
|
||||||
@ThreadSafeMutableState
|
@ThreadSafeMutableState
|
||||||
class FirCorrespondingSupertypesCache(private val session: FirSession) : FirSessionComponent {
|
class FirCorrespondingSupertypesCache(private val session: FirSession) : FirSessionComponent {
|
||||||
@@ -28,9 +30,13 @@ class FirCorrespondingSupertypesCache(private val session: FirSession) : FirSess
|
|||||||
): List<ConeClassLikeType>? {
|
): List<ConeClassLikeType>? {
|
||||||
if (type !is ConeClassLikeType || supertypeConstructor !is ConeClassLikeLookupTag) return null
|
if (type !is ConeClassLikeType || supertypeConstructor !is ConeClassLikeLookupTag) return null
|
||||||
|
|
||||||
val context = ConeTypeCheckerContext(isErrorTypeEqualsToAnything = false, isStubTypeEqualsToAnything = true, session = session)
|
val context = session.typeContext.newBaseTypeCheckerContext(
|
||||||
|
errorTypesEqualToAnything = false,
|
||||||
|
stubTypesEqualToAnything = true
|
||||||
|
)
|
||||||
|
|
||||||
val lookupTag = type.lookupTag
|
val lookupTag = type.lookupTag
|
||||||
if (lookupTag == supertypeConstructor) return listOf(captureType(type, context))
|
if (lookupTag == supertypeConstructor) return listOf(captureType(type, context.typeSystemContext))
|
||||||
if (lookupTag !in cache) {
|
if (lookupTag !in cache) {
|
||||||
cache[lookupTag] = computeSupertypesMap(lookupTag, context)
|
cache[lookupTag] = computeSupertypesMap(lookupTag, context)
|
||||||
}
|
}
|
||||||
@@ -38,15 +44,15 @@ class FirCorrespondingSupertypesCache(private val session: FirSession) : FirSess
|
|||||||
val resultTypes = cache[lookupTag]?.getOrDefault(supertypeConstructor, emptyList()) ?: return null
|
val resultTypes = cache[lookupTag]?.getOrDefault(supertypeConstructor, emptyList()) ?: return null
|
||||||
if (type.typeArguments.isEmpty()) return resultTypes
|
if (type.typeArguments.isEmpty()) return resultTypes
|
||||||
|
|
||||||
val capturedType = captureType(type, context)
|
val capturedType = captureType(type, context.typeSystemContext)
|
||||||
val substitutionSupertypePolicy = context.substitutionSupertypePolicy(capturedType)
|
val substitutionSupertypePolicy = context.substitutionSupertypePolicy(capturedType)
|
||||||
return resultTypes.map {
|
return resultTypes.map {
|
||||||
substitutionSupertypePolicy.transformType(context, it) as ConeClassLikeType
|
substitutionSupertypePolicy.transformType(context, it) as ConeClassLikeType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun captureType(type: ConeClassLikeType, context: ConeTypeCheckerContext): ConeClassLikeType =
|
private fun captureType(type: ConeClassLikeType, typeSystemContext: ConeTypeContext): ConeClassLikeType =
|
||||||
(context.captureFromArguments(type, CaptureStatus.FOR_SUBTYPING) ?: type) as ConeClassLikeType
|
(typeSystemContext.captureFromArguments(type, CaptureStatus.FOR_SUBTYPING) ?: type) as ConeClassLikeType
|
||||||
|
|
||||||
private fun computeSupertypesMap(
|
private fun computeSupertypesMap(
|
||||||
subtypeLookupTag: ConeClassLikeLookupTag,
|
subtypeLookupTag: ConeClassLikeLookupTag,
|
||||||
@@ -82,12 +88,13 @@ class FirCorrespondingSupertypesCache(private val session: FirSession) : FirSess
|
|||||||
context: ConeTypeCheckerContext
|
context: ConeTypeCheckerContext
|
||||||
): AbstractTypeCheckerContext.SupertypesPolicy {
|
): AbstractTypeCheckerContext.SupertypesPolicy {
|
||||||
val supertypeLookupTag = (supertype as ConeClassLikeType).lookupTag
|
val supertypeLookupTag = (supertype as ConeClassLikeType).lookupTag
|
||||||
val captured = context.captureFromArguments(supertype, CaptureStatus.FOR_SUBTYPING) as ConeClassLikeType? ?: supertype
|
val captured =
|
||||||
|
context.typeSystemContext.captureFromArguments(supertype, CaptureStatus.FOR_SUBTYPING) as ConeClassLikeType? ?: supertype
|
||||||
|
|
||||||
resultingMap[supertypeLookupTag] = listOf(captured)
|
resultingMap[supertypeLookupTag] = listOf(captured)
|
||||||
|
|
||||||
return when {
|
return when {
|
||||||
with(context) { captured.argumentsCount() } == 0 -> {
|
with(context.typeSystemContext) { captured.argumentsCount() } == 0 -> {
|
||||||
AbstractTypeCheckerContext.SupertypesPolicy.LowerIfFlexible
|
AbstractTypeCheckerContext.SupertypesPolicy.LowerIfFlexible
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
|
|||||||
+1
-1
@@ -1374,7 +1374,7 @@ class ExpressionCodegen(
|
|||||||
val reifiedTypeInliner = ReifiedTypeInliner(
|
val reifiedTypeInliner = ReifiedTypeInliner(
|
||||||
mappings,
|
mappings,
|
||||||
IrInlineIntrinsicsSupport(context, typeMapper),
|
IrInlineIntrinsicsSupport(context, typeMapper),
|
||||||
IrTypeCheckerContext(context.irBuiltIns),
|
IrTypeSystemContextImpl(context.irBuiltIns),
|
||||||
state.languageVersionSettings,
|
state.languageVersionSettings,
|
||||||
state.unifiedNullChecks,
|
state.unifiedNullChecks,
|
||||||
)
|
)
|
||||||
|
|||||||
+1
-1
@@ -39,7 +39,7 @@ import org.jetbrains.kotlin.ir.types.isKClass as isKClassImpl
|
|||||||
import org.jetbrains.kotlin.ir.util.isSuspendFunction as isSuspendFunctionImpl
|
import org.jetbrains.kotlin.ir.util.isSuspendFunction as isSuspendFunctionImpl
|
||||||
|
|
||||||
class IrTypeMapper(private val context: JvmBackendContext) : KotlinTypeMapperBase(), TypeMappingContext<JvmSignatureWriter> {
|
class IrTypeMapper(private val context: JvmBackendContext) : KotlinTypeMapperBase(), TypeMappingContext<JvmSignatureWriter> {
|
||||||
internal val typeSystem = IrTypeCheckerContext(context.irBuiltIns)
|
internal val typeSystem = IrTypeSystemContextImpl(context.irBuiltIns)
|
||||||
override val typeContext: TypeSystemCommonBackendContextForTypeMapping = IrTypeCheckerContextForTypeMapping(typeSystem, context)
|
override val typeContext: TypeSystemCommonBackendContextForTypeMapping = IrTypeCheckerContextForTypeMapping(typeSystem, context)
|
||||||
|
|
||||||
override fun mapClass(classifier: ClassifierDescriptor): Type =
|
override fun mapClass(classifier: ClassifierDescriptor): Type =
|
||||||
|
|||||||
+7
-1
@@ -229,7 +229,13 @@ internal class CollectionStubMethodLowering(val context: JvmBackendContext) : Cl
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun createTypeChecker(overrideFun: IrSimpleFunction, parentFun: IrSimpleFunction): AbstractTypeCheckerContext =
|
private fun createTypeChecker(overrideFun: IrSimpleFunction, parentFun: IrSimpleFunction): AbstractTypeCheckerContext =
|
||||||
IrTypeCheckerContextWithAdditionalAxioms(context.irBuiltIns, overrideFun.typeParameters, parentFun.typeParameters)
|
IrTypeCheckerContext(
|
||||||
|
IrTypeSystemContextWithAdditionalAxioms(
|
||||||
|
context.irBuiltIns,
|
||||||
|
overrideFun.typeParameters,
|
||||||
|
parentFun.typeParameters
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
private fun areTypeParametersEquivalent(
|
private fun areTypeParametersEquivalent(
|
||||||
overrideFun: IrSimpleFunction,
|
overrideFun: IrSimpleFunction,
|
||||||
|
|||||||
@@ -425,14 +425,14 @@ class IrOverridingUtil(
|
|||||||
return if (a == null || b == null) true else isVisibilityMoreSpecific(a, b)
|
return if (a == null || b == null) true else isVisibilityMoreSpecific(a, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrTypeCheckerContextWithAdditionalAxioms.isSubtypeOf(a: IrType, b: IrType) =
|
private fun IrTypeCheckerContext.isSubtypeOf(a: IrType, b: IrType) =
|
||||||
AbstractTypeChecker.isSubtypeOf(this as AbstractTypeCheckerContext, a, b)
|
AbstractTypeChecker.isSubtypeOf(this as AbstractTypeCheckerContext, a, b)
|
||||||
|
|
||||||
private fun IrTypeCheckerContextWithAdditionalAxioms.equalTypes(a: IrType, b: IrType) =
|
private fun IrTypeCheckerContext.equalTypes(a: IrType, b: IrType) =
|
||||||
AbstractTypeChecker.equalTypes(this as AbstractTypeCheckerContext, a, b)
|
AbstractTypeChecker.equalTypes(this as AbstractTypeCheckerContext, a, b)
|
||||||
|
|
||||||
private fun createTypeChecker(a: List<IrTypeParameter>, b: List<IrTypeParameter>) =
|
private fun createTypeChecker(a: List<IrTypeParameter>, b: List<IrTypeParameter>) =
|
||||||
IrTypeCheckerContextWithAdditionalAxioms(irBuiltIns, a, b)
|
IrTypeCheckerContext(IrTypeSystemContextWithAdditionalAxioms(irBuiltIns, a, b))
|
||||||
|
|
||||||
private fun isReturnTypeMoreSpecific(
|
private fun isReturnTypeMoreSpecific(
|
||||||
a: IrOverridableMember,
|
a: IrOverridableMember,
|
||||||
@@ -661,10 +661,12 @@ class IrOverridingUtil(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val typeCheckerContext =
|
val typeCheckerContext =
|
||||||
IrTypeCheckerContextWithAdditionalAxioms(
|
IrTypeCheckerContext(
|
||||||
irBuiltIns,
|
IrTypeSystemContextWithAdditionalAxioms(
|
||||||
superTypeParameters,
|
irBuiltIns,
|
||||||
subTypeParameters
|
superTypeParameters,
|
||||||
|
subTypeParameters
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
/* TODO: check the bounds. See OverridingUtil.areTypeParametersEquivalent()
|
/* TODO: check the bounds. See OverridingUtil.areTypeParametersEquivalent()
|
||||||
|
|||||||
@@ -10,7 +10,9 @@ import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
|||||||
import org.jetbrains.kotlin.types.AbstractTypeCheckerContext
|
import org.jetbrains.kotlin.types.AbstractTypeCheckerContext
|
||||||
import org.jetbrains.kotlin.types.model.*
|
import org.jetbrains.kotlin.types.model.*
|
||||||
|
|
||||||
open class IrTypeCheckerContext(override val irBuiltIns: IrBuiltIns) : IrTypeSystemContext, AbstractTypeCheckerContext() {
|
open class IrTypeCheckerContext(override val typeSystemContext: IrTypeSystemContext): AbstractTypeCheckerContext() {
|
||||||
|
|
||||||
|
val irBuiltIns: IrBuiltIns get() = typeSystemContext.irBuiltIns
|
||||||
|
|
||||||
override fun substitutionSupertypePolicy(type: SimpleTypeMarker): SupertypesPolicy.DoCustomTransform {
|
override fun substitutionSupertypePolicy(type: SimpleTypeMarker): SupertypesPolicy.DoCustomTransform {
|
||||||
require(type is IrSimpleType)
|
require(type is IrSimpleType)
|
||||||
@@ -30,32 +32,4 @@ open class IrTypeCheckerContext(override val irBuiltIns: IrBuiltIns) : IrTypeSys
|
|||||||
|
|
||||||
override val KotlinTypeMarker.isAllowedTypeVariable: Boolean
|
override val KotlinTypeMarker.isAllowedTypeVariable: Boolean
|
||||||
get() = false
|
get() = false
|
||||||
|
|
||||||
override fun newBaseTypeCheckerContext(
|
|
||||||
errorTypesEqualToAnything: Boolean,
|
|
||||||
stubTypesEqualToAnything: Boolean
|
|
||||||
): AbstractTypeCheckerContext = IrTypeCheckerContext(irBuiltIns)
|
|
||||||
|
|
||||||
override fun KotlinTypeMarker.isUninferredParameter(): Boolean = false
|
|
||||||
override fun KotlinTypeMarker.withNullability(nullable: Boolean): KotlinTypeMarker {
|
|
||||||
if (this.isSimpleType()) {
|
|
||||||
return this.asSimpleType()!!.withNullability(nullable)
|
|
||||||
} else {
|
|
||||||
error("withNullability for non-simple types is not supported in IR")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun captureFromExpression(type: KotlinTypeMarker): KotlinTypeMarker? =
|
|
||||||
error("Captured type is unsupported in IR")
|
|
||||||
|
|
||||||
override fun DefinitelyNotNullTypeMarker.original(): SimpleTypeMarker =
|
|
||||||
error("DefinitelyNotNull type is unsupported in IR")
|
|
||||||
|
|
||||||
override fun KotlinTypeMarker.makeDefinitelyNotNullOrNotNull(): KotlinTypeMarker {
|
|
||||||
error("makeDefinitelyNotNullOrNotNull is not supported in IR")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun SimpleTypeMarker.makeSimpleTypeDefinitelyNotNullOrNotNull(): SimpleTypeMarker {
|
|
||||||
error("makeSimpleTypeDefinitelyNotNullOrNotNull is not yet supported in IR")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,11 +9,11 @@ import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
|
|||||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||||
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
|
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
|
||||||
|
|
||||||
open class IrTypeCheckerContextWithAdditionalAxioms(
|
class IrTypeSystemContextWithAdditionalAxioms(
|
||||||
override val irBuiltIns: IrBuiltIns,
|
override val irBuiltIns: IrBuiltIns,
|
||||||
firstParameters: List<IrTypeParameter>,
|
firstParameters: List<IrTypeParameter>,
|
||||||
secondParameters: List<IrTypeParameter>
|
secondParameters: List<IrTypeParameter>
|
||||||
) : IrTypeCheckerContext(irBuiltIns) {
|
) : IrTypeSystemContext {
|
||||||
init {
|
init {
|
||||||
assert(firstParameters.size == secondParameters.size) {
|
assert(firstParameters.size == secondParameters.size) {
|
||||||
"different length of type parameter lists: $firstParameters vs $secondParameters"
|
"different length of type parameter lists: $firstParameters vs $secondParameters"
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.ir.util.*
|
|||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.FqNameUnsafe
|
import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.types.AbstractTypeCheckerContext
|
||||||
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
|
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
|
||||||
import org.jetbrains.kotlin.types.Variance
|
import org.jetbrains.kotlin.types.Variance
|
||||||
import org.jetbrains.kotlin.types.model.*
|
import org.jetbrains.kotlin.types.model.*
|
||||||
@@ -454,6 +455,39 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon
|
|||||||
val irClass = (this as IrType).classOrNull?.owner
|
val irClass = (this as IrType).classOrNull?.owner
|
||||||
return irClass != null && (irClass.isInterface || irClass.isAnnotationClass)
|
return irClass != null && (irClass.isInterface || irClass.isAnnotationClass)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun newBaseTypeCheckerContext(
|
||||||
|
errorTypesEqualToAnything: Boolean,
|
||||||
|
stubTypesEqualToAnything: Boolean
|
||||||
|
): AbstractTypeCheckerContext = IrTypeCheckerContext(this)
|
||||||
|
|
||||||
|
override fun KotlinTypeMarker.isUninferredParameter(): Boolean = false
|
||||||
|
override fun KotlinTypeMarker.withNullability(nullable: Boolean): KotlinTypeMarker {
|
||||||
|
if (this.isSimpleType()) {
|
||||||
|
return this.asSimpleType()!!.withNullability(nullable)
|
||||||
|
} else {
|
||||||
|
error("withNullability for non-simple types is not supported in IR")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun captureFromExpression(type: KotlinTypeMarker): KotlinTypeMarker? =
|
||||||
|
error("Captured type is unsupported in IR")
|
||||||
|
|
||||||
|
override fun DefinitelyNotNullTypeMarker.original(): SimpleTypeMarker =
|
||||||
|
error("DefinitelyNotNull type is unsupported in IR")
|
||||||
|
|
||||||
|
override fun KotlinTypeMarker.makeDefinitelyNotNullOrNotNull(): KotlinTypeMarker {
|
||||||
|
error("makeDefinitelyNotNullOrNotNull is not supported in IR")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun SimpleTypeMarker.makeSimpleTypeDefinitelyNotNullOrNotNull(): SimpleTypeMarker {
|
||||||
|
error("makeSimpleTypeDefinitelyNotNullOrNotNull is not yet supported in IR")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun prepareType(type: KotlinTypeMarker): KotlinTypeMarker {
|
||||||
|
return type
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun extractTypeParameters(parent: IrDeclarationParent): List<IrTypeParameter> {
|
fun extractTypeParameters(parent: IrDeclarationParent): List<IrTypeParameter> {
|
||||||
@@ -480,3 +514,6 @@ fun extractTypeParameters(parent: IrDeclarationParent): List<IrTypeParameter> {
|
|||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class IrTypeSystemContextImpl(override val irBuiltIns: IrBuiltIns) : IrTypeSystemContext
|
||||||
@@ -32,7 +32,11 @@ fun IrType.isSubtypeOfClass(superClass: IrClassSymbol): Boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun IrType.isSubtypeOf(superType: IrType, irBuiltIns: IrBuiltIns): Boolean {
|
fun IrType.isSubtypeOf(superType: IrType, irBuiltIns: IrBuiltIns): Boolean {
|
||||||
return AbstractTypeChecker.isSubtypeOf(IrTypeCheckerContext(irBuiltIns) as AbstractTypeCheckerContext, this, superType)
|
return AbstractTypeChecker.isSubtypeOf(
|
||||||
|
IrTypeCheckerContext(IrTypeSystemContextImpl(irBuiltIns)) as AbstractTypeCheckerContext,
|
||||||
|
this,
|
||||||
|
superType
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun IrType.isNullable(): Boolean =
|
fun IrType.isNullable(): Boolean =
|
||||||
|
|||||||
+1
-3
@@ -267,9 +267,7 @@ object NewCommonSuperTypeCalculator {
|
|||||||
* but it is too complicated and we will return not so accurate type: CS(List<Int>, List<Double>, List<String>)
|
* but it is too complicated and we will return not so accurate type: CS(List<Int>, List<Double>, List<String>)
|
||||||
*/
|
*/
|
||||||
val correspondingSuperTypes = types.flatMap {
|
val correspondingSuperTypes = types.flatMap {
|
||||||
with(AbstractTypeChecker) {
|
AbstractTypeChecker.findCorrespondingSupertypes(typeCheckerContext, it, constructor)
|
||||||
typeCheckerContext.findCorrespondingSupertypes(it, constructor)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val arguments = ArrayList<TypeArgumentMarker>(constructor.parametersCount())
|
val arguments = ArrayList<TypeArgumentMarker>(constructor.parametersCount())
|
||||||
|
|||||||
+80
-72
@@ -10,7 +10,8 @@ import org.jetbrains.kotlin.types.AbstractTypeChecker
|
|||||||
import org.jetbrains.kotlin.types.AbstractTypeCheckerContext
|
import org.jetbrains.kotlin.types.AbstractTypeCheckerContext
|
||||||
import org.jetbrains.kotlin.types.model.*
|
import org.jetbrains.kotlin.types.model.*
|
||||||
|
|
||||||
abstract class AbstractTypeCheckerContextForConstraintSystem : AbstractTypeCheckerContext(), TypeSystemInferenceExtensionContext {
|
abstract class AbstractTypeCheckerContextForConstraintSystem(override val typeSystemContext: TypeSystemInferenceExtensionContext) :
|
||||||
|
AbstractTypeCheckerContext() {
|
||||||
|
|
||||||
override val KotlinTypeMarker.isAllowedTypeVariable: Boolean
|
override val KotlinTypeMarker.isAllowedTypeVariable: Boolean
|
||||||
get() = false
|
get() = false
|
||||||
@@ -36,21 +37,22 @@ abstract class AbstractTypeCheckerContextForConstraintSystem : AbstractTypeCheck
|
|||||||
|
|
||||||
abstract fun addEqualityConstraint(typeVariable: TypeConstructorMarker, type: KotlinTypeMarker)
|
abstract fun addEqualityConstraint(typeVariable: TypeConstructorMarker, type: KotlinTypeMarker)
|
||||||
|
|
||||||
override fun getLowerCapturedTypePolicy(subType: SimpleTypeMarker, superType: CapturedTypeMarker): LowerCapturedTypePolicy {
|
override fun getLowerCapturedTypePolicy(subType: SimpleTypeMarker, superType: CapturedTypeMarker): LowerCapturedTypePolicy =
|
||||||
return when {
|
with(typeSystemContext) {
|
||||||
isMyTypeVariable(subType) -> {
|
return when {
|
||||||
val projection = superType.typeConstructorProjection()
|
isMyTypeVariable(subType) -> {
|
||||||
val type = projection.getType().asSimpleType()
|
val projection = superType.typeConstructorProjection()
|
||||||
if (projection.getVariance() == TypeVariance.IN && type != null && isMyTypeVariable(type)) {
|
val type = projection.getType().asSimpleType()
|
||||||
LowerCapturedTypePolicy.CHECK_ONLY_LOWER
|
if (projection.getVariance() == TypeVariance.IN && type != null && isMyTypeVariable(type)) {
|
||||||
} else {
|
LowerCapturedTypePolicy.CHECK_ONLY_LOWER
|
||||||
LowerCapturedTypePolicy.SKIP_LOWER
|
} else {
|
||||||
|
LowerCapturedTypePolicy.SKIP_LOWER
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
subType.contains { it.anyBound(::isMyTypeVariable) } -> LowerCapturedTypePolicy.CHECK_ONLY_LOWER
|
||||||
|
else -> LowerCapturedTypePolicy.CHECK_SUBTYPE_AND_LOWER
|
||||||
}
|
}
|
||||||
subType.contains { it.anyBound(this::isMyTypeVariable) } -> LowerCapturedTypePolicy.CHECK_ONLY_LOWER
|
|
||||||
else -> LowerCapturedTypePolicy.CHECK_SUBTYPE_AND_LOWER
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* todo: possible we should override this method, because otherwise OR in subtyping transformed to AND in constraint system
|
* todo: possible we should override this method, because otherwise OR in subtyping transformed to AND in constraint system
|
||||||
@@ -70,9 +72,11 @@ abstract class AbstractTypeCheckerContextForConstraintSystem : AbstractTypeCheck
|
|||||||
|
|
||||||
// we should strip annotation's because we have incorporation operation and they should be not affected
|
// we should strip annotation's because we have incorporation operation and they should be not affected
|
||||||
val mySubType =
|
val mySubType =
|
||||||
if (hasExact) extractTypeForProjectedType(subType, out = true) ?: subType.removeExactAnnotation() else subType
|
if (hasExact) extractTypeForProjectedType(subType, out = true)
|
||||||
|
?: with(typeSystemContext) { subType.removeExactAnnotation() } else subType
|
||||||
val mySuperType =
|
val mySuperType =
|
||||||
if (hasExact) extractTypeForProjectedType(superType, out = false) ?: superType.removeExactAnnotation() else superType
|
if (hasExact) extractTypeForProjectedType(superType, out = false)
|
||||||
|
?: with(typeSystemContext) { superType.removeExactAnnotation() } else superType
|
||||||
|
|
||||||
val result = internalAddSubtypeConstraint(mySubType, mySuperType, isFromNullabilityConstraint)
|
val result = internalAddSubtypeConstraint(mySubType, mySuperType, isFromNullabilityConstraint)
|
||||||
if (!hasExact) return result
|
if (!hasExact) return result
|
||||||
@@ -83,7 +87,7 @@ abstract class AbstractTypeCheckerContextForConstraintSystem : AbstractTypeCheck
|
|||||||
return (result ?: true) && (result2 ?: true)
|
return (result ?: true) && (result2 ?: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun extractTypeForProjectedType(type: KotlinTypeMarker, out: Boolean): KotlinTypeMarker? {
|
private fun extractTypeForProjectedType(type: KotlinTypeMarker, out: Boolean): KotlinTypeMarker? = with(typeSystemContext) {
|
||||||
val typeMarker = type.asSimpleType()?.asCapturedType() ?: return null
|
val typeMarker = type.asSimpleType()?.asCapturedType() ?: return null
|
||||||
|
|
||||||
val projection = typeMarker.typeConstructorProjection()
|
val projection = typeMarker.typeConstructorProjection()
|
||||||
@@ -98,10 +102,10 @@ abstract class AbstractTypeCheckerContextForConstraintSystem : AbstractTypeCheck
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun KotlinTypeMarker.isTypeVariableWithExact() =
|
private fun KotlinTypeMarker.isTypeVariableWithExact() =
|
||||||
hasExactAnnotation() && anyBound(this@AbstractTypeCheckerContextForConstraintSystem::isMyTypeVariable)
|
with(typeSystemContext) { hasExactAnnotation() } && anyBound(this@AbstractTypeCheckerContextForConstraintSystem::isMyTypeVariable)
|
||||||
|
|
||||||
private fun KotlinTypeMarker.isTypeVariableWithNoInfer() =
|
private fun KotlinTypeMarker.isTypeVariableWithNoInfer() =
|
||||||
hasNoInferAnnotation() && anyBound(this@AbstractTypeCheckerContextForConstraintSystem::isMyTypeVariable)
|
with(typeSystemContext) { hasNoInferAnnotation() } && anyBound(this@AbstractTypeCheckerContextForConstraintSystem::isMyTypeVariable)
|
||||||
|
|
||||||
private fun internalAddSubtypeConstraint(
|
private fun internalAddSubtypeConstraint(
|
||||||
subType: KotlinTypeMarker,
|
subType: KotlinTypeMarker,
|
||||||
@@ -128,32 +132,33 @@ abstract class AbstractTypeCheckerContextForConstraintSystem : AbstractTypeCheck
|
|||||||
}
|
}
|
||||||
|
|
||||||
// extract type variable only from type like Captured(out T)
|
// extract type variable only from type like Captured(out T)
|
||||||
private fun extractTypeVariableForSubtype(subType: KotlinTypeMarker, superType: KotlinTypeMarker): KotlinTypeMarker? {
|
private fun extractTypeVariableForSubtype(subType: KotlinTypeMarker, superType: KotlinTypeMarker): KotlinTypeMarker? =
|
||||||
|
with(typeSystemContext) {
|
||||||
|
|
||||||
val typeMarker = subType.asSimpleType()?.asCapturedType() ?: return null
|
val typeMarker = subType.asSimpleType()?.asCapturedType() ?: return null
|
||||||
|
|
||||||
val projection = typeMarker.typeConstructorProjection()
|
val projection = typeMarker.typeConstructorProjection()
|
||||||
if (projection.isStarProjection()) return null
|
if (projection.isStarProjection()) return null
|
||||||
if (projection.getVariance() == TypeVariance.IN) {
|
if (projection.getVariance() == TypeVariance.IN) {
|
||||||
val type = projection.getType().asSimpleType() ?: return null
|
val type = projection.getType().asSimpleType() ?: return null
|
||||||
if (isMyTypeVariable(type)) {
|
if (isMyTypeVariable(type)) {
|
||||||
simplifyLowerConstraint(type, superType)
|
simplifyLowerConstraint(type, superType)
|
||||||
if (isMyTypeVariable(superType.asSimpleType() ?: return null)) {
|
if (isMyTypeVariable(superType.asSimpleType() ?: return null)) {
|
||||||
addLowerConstraint(superType.typeConstructor(), nullableAnyType())
|
addLowerConstraint(superType.typeConstructor(), nullableAnyType())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return if (projection.getVariance() == TypeVariance.OUT) {
|
return if (projection.getVariance() == TypeVariance.OUT) {
|
||||||
val type = projection.getType()
|
val type = projection.getType()
|
||||||
when {
|
when {
|
||||||
type is SimpleTypeMarker && isMyTypeVariable(type) -> type.asSimpleType()
|
type is SimpleTypeMarker && isMyTypeVariable(type) -> type.asSimpleType()
|
||||||
type is FlexibleTypeMarker && isMyTypeVariable(type.lowerBound()) -> type.asFlexibleType()?.lowerBound()
|
type is FlexibleTypeMarker && isMyTypeVariable(type.lowerBound()) -> type.asFlexibleType()?.lowerBound()
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
} else null
|
} else null
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Foo <: T -- leave as is
|
* Foo <: T -- leave as is
|
||||||
@@ -196,7 +201,7 @@ abstract class AbstractTypeCheckerContextForConstraintSystem : AbstractTypeCheck
|
|||||||
typeVariable: KotlinTypeMarker,
|
typeVariable: KotlinTypeMarker,
|
||||||
subType: KotlinTypeMarker,
|
subType: KotlinTypeMarker,
|
||||||
isFromNullabilityConstraint: Boolean = false
|
isFromNullabilityConstraint: Boolean = false
|
||||||
): Boolean {
|
): Boolean = with(typeSystemContext) {
|
||||||
val lowerConstraint = when (typeVariable) {
|
val lowerConstraint = when (typeVariable) {
|
||||||
is SimpleTypeMarker ->
|
is SimpleTypeMarker ->
|
||||||
/*
|
/*
|
||||||
@@ -256,7 +261,7 @@ abstract class AbstractTypeCheckerContextForConstraintSystem : AbstractTypeCheck
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun assertFlexibleTypeVariable(typeVariable: FlexibleTypeMarker) {
|
private fun assertFlexibleTypeVariable(typeVariable: FlexibleTypeMarker) = with(typeSystemContext) {
|
||||||
assert(typeVariable.lowerBound().typeConstructor() == typeVariable.upperBound().typeConstructor()) {
|
assert(typeVariable.lowerBound().typeConstructor() == typeVariable.upperBound().typeConstructor()) {
|
||||||
"Flexible type variable ($typeVariable) should have bounds with the same type constructor, i.e. (T..T?)"
|
"Flexible type variable ($typeVariable) should have bounds with the same type constructor, i.e. (T..T?)"
|
||||||
}
|
}
|
||||||
@@ -267,7 +272,7 @@ abstract class AbstractTypeCheckerContextForConstraintSystem : AbstractTypeCheck
|
|||||||
* T? <: Foo <=> T <: Foo && Nothing? <: Foo
|
* T? <: Foo <=> T <: Foo && Nothing? <: Foo
|
||||||
* T <: Foo -- leave as is
|
* T <: Foo -- leave as is
|
||||||
*/
|
*/
|
||||||
private fun simplifyUpperConstraint(typeVariable: KotlinTypeMarker, superType: KotlinTypeMarker): Boolean {
|
private fun simplifyUpperConstraint(typeVariable: KotlinTypeMarker, superType: KotlinTypeMarker): Boolean = with(typeSystemContext) {
|
||||||
val typeVariableLowerBound = typeVariable.lowerBoundIfFlexible()
|
val typeVariableLowerBound = typeVariable.lowerBoundIfFlexible()
|
||||||
val simplifiedSuperType = if (typeVariableLowerBound.isDefinitelyNotNullType()) {
|
val simplifiedSuperType = if (typeVariableLowerBound.isDefinitelyNotNullType()) {
|
||||||
superType.withNullability(true)
|
superType.withNullability(true)
|
||||||
@@ -279,37 +284,38 @@ abstract class AbstractTypeCheckerContextForConstraintSystem : AbstractTypeCheck
|
|||||||
|
|
||||||
if (typeVariableLowerBound.isMarkedNullable()) {
|
if (typeVariableLowerBound.isMarkedNullable()) {
|
||||||
// here is important that superType is singleClassifierType
|
// here is important that superType is singleClassifierType
|
||||||
return simplifiedSuperType.anyBound(this::isMyTypeVariable) ||
|
return simplifiedSuperType.anyBound(::isMyTypeVariable) ||
|
||||||
isSubtypeOfByTypeChecker(nullableNothingType(), simplifiedSuperType)
|
isSubtypeOfByTypeChecker(nullableNothingType(), simplifiedSuperType)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun simplifyConstraintForPossibleIntersectionSubType(subType: KotlinTypeMarker, superType: KotlinTypeMarker): Boolean? {
|
private fun simplifyConstraintForPossibleIntersectionSubType(subType: KotlinTypeMarker, superType: KotlinTypeMarker): Boolean? =
|
||||||
@Suppress("NAME_SHADOWING")
|
with(typeSystemContext) {
|
||||||
val subType = subType.lowerBoundIfFlexible()
|
@Suppress("NAME_SHADOWING")
|
||||||
|
val subType = subType.lowerBoundIfFlexible()
|
||||||
|
|
||||||
if (!subType.typeConstructor().isIntersection()) return null
|
if (!subType.typeConstructor().isIntersection()) return null
|
||||||
|
|
||||||
assert(!subType.isMarkedNullable()) { "Intersection type should not be marked nullable!: $subType" }
|
assert(!subType.isMarkedNullable()) { "Intersection type should not be marked nullable!: $subType" }
|
||||||
|
|
||||||
// TODO: may be we lose flexibility here
|
// TODO: may be we lose flexibility here
|
||||||
val subIntersectionTypes = (subType.typeConstructor().supertypes()).map { it.lowerBoundIfFlexible() }
|
val subIntersectionTypes = (subType.typeConstructor().supertypes()).map { it.lowerBoundIfFlexible() }
|
||||||
|
|
||||||
val typeVariables = subIntersectionTypes.filter(this::isMyTypeVariable).takeIf { it.isNotEmpty() } ?: return null
|
val typeVariables = subIntersectionTypes.filter(::isMyTypeVariable).takeIf { it.isNotEmpty() } ?: return null
|
||||||
val notTypeVariables = subIntersectionTypes.filterNot(this::isMyTypeVariable)
|
val notTypeVariables = subIntersectionTypes.filterNot(::isMyTypeVariable)
|
||||||
|
|
||||||
// todo: may be we can do better then that.
|
// todo: may be we can do better then that.
|
||||||
if (notTypeVariables.isNotEmpty() &&
|
if (notTypeVariables.isNotEmpty() &&
|
||||||
AbstractTypeChecker.isSubtypeOf(
|
AbstractTypeChecker.isSubtypeOf(
|
||||||
this as TypeCheckerProviderContext,
|
this as TypeCheckerProviderContext,
|
||||||
intersectTypes(notTypeVariables),
|
intersectTypes(notTypeVariables),
|
||||||
superType
|
superType
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Consider the following example:
|
// Consider the following example:
|
||||||
// fun <T> id(x: T): T = x
|
// fun <T> id(x: T): T = x
|
||||||
@@ -326,23 +332,25 @@ abstract class AbstractTypeCheckerContextForConstraintSystem : AbstractTypeCheck
|
|||||||
// here we try to add constraint {Any & T} <: S from `id(a)`
|
// here we try to add constraint {Any & T} <: S from `id(a)`
|
||||||
// Previously we thought that if `Any` isn't a subtype of S => T <: S, which is wrong, now we use weaker upper constraint
|
// Previously we thought that if `Any` isn't a subtype of S => T <: S, which is wrong, now we use weaker upper constraint
|
||||||
// TODO: rethink, maybe we should take nullability into account somewhere else
|
// TODO: rethink, maybe we should take nullability into account somewhere else
|
||||||
if (notTypeVariables.any { AbstractNullabilityChecker.isSubtypeOfAny(this as TypeCheckerProviderContext, it) }) {
|
if (notTypeVariables.any { AbstractNullabilityChecker.isSubtypeOfAny(this as TypeCheckerProviderContext, it) }) {
|
||||||
return typeVariables.all { simplifyUpperConstraint(it, superType.withNullability(true)) }
|
return typeVariables.all { simplifyUpperConstraint(it, superType.withNullability(true)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
return typeVariables.all { simplifyUpperConstraint(it, superType) }
|
return typeVariables.all { simplifyUpperConstraint(it, superType) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isSubtypeOfByTypeChecker(subType: KotlinTypeMarker, superType: KotlinTypeMarker) =
|
private fun isSubtypeOfByTypeChecker(subType: KotlinTypeMarker, superType: KotlinTypeMarker) =
|
||||||
AbstractTypeChecker.isSubtypeOf(this as AbstractTypeCheckerContext, subType, superType)
|
AbstractTypeChecker.isSubtypeOf(this as AbstractTypeCheckerContext, subType, superType)
|
||||||
|
|
||||||
private fun assertInputTypes(subType: KotlinTypeMarker, superType: KotlinTypeMarker) {
|
private fun assertInputTypes(subType: KotlinTypeMarker, superType: KotlinTypeMarker) = with(typeSystemContext) {
|
||||||
if (!AbstractTypeChecker.RUN_SLOW_ASSERTIONS) return
|
if (!AbstractTypeChecker.RUN_SLOW_ASSERTIONS) return
|
||||||
fun correctSubType(subType: SimpleTypeMarker) =
|
fun correctSubType(subType: SimpleTypeMarker) =
|
||||||
subType.isSingleClassifierType() || subType.typeConstructor().isIntersection() || isMyTypeVariable(subType) || subType.isError() || subType.isIntegerLiteralType()
|
subType.isSingleClassifierType() || subType.typeConstructor()
|
||||||
|
.isIntersection() || isMyTypeVariable(subType) || subType.isError() || subType.isIntegerLiteralType()
|
||||||
|
|
||||||
fun correctSuperType(superType: SimpleTypeMarker) =
|
fun correctSuperType(superType: SimpleTypeMarker) =
|
||||||
superType.isSingleClassifierType() || superType.typeConstructor().isIntersection() || isMyTypeVariable(superType) || superType.isError() || superType.isIntegerLiteralType()
|
superType.isSingleClassifierType() || superType.typeConstructor()
|
||||||
|
.isIntersection() || isMyTypeVariable(superType) || superType.isError() || superType.isIntegerLiteralType()
|
||||||
|
|
||||||
assert(subType.bothBounds(::correctSubType)) {
|
assert(subType.bothBounds(::correctSubType)) {
|
||||||
"Not singleClassifierType and not intersection subType: $subType"
|
"Not singleClassifierType and not intersection subType: $subType"
|
||||||
@@ -354,13 +362,13 @@ abstract class AbstractTypeCheckerContextForConstraintSystem : AbstractTypeCheck
|
|||||||
|
|
||||||
private inline fun KotlinTypeMarker.bothBounds(f: (SimpleTypeMarker) -> Boolean) = when (this) {
|
private inline fun KotlinTypeMarker.bothBounds(f: (SimpleTypeMarker) -> Boolean) = when (this) {
|
||||||
is SimpleTypeMarker -> f(this)
|
is SimpleTypeMarker -> f(this)
|
||||||
is FlexibleTypeMarker -> f(lowerBound()) && f(upperBound())
|
is FlexibleTypeMarker -> with(typeSystemContext) { f(lowerBound()) && f(upperBound()) }
|
||||||
else -> error("sealed")
|
else -> error("sealed")
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun KotlinTypeMarker.anyBound(f: (SimpleTypeMarker) -> Boolean) = when (this) {
|
private inline fun KotlinTypeMarker.anyBound(f: (SimpleTypeMarker) -> Boolean) = when (this) {
|
||||||
is SimpleTypeMarker -> f(this)
|
is SimpleTypeMarker -> f(this)
|
||||||
is FlexibleTypeMarker -> f(lowerBound()) || f(upperBound())
|
is FlexibleTypeMarker -> with(typeSystemContext) { f(lowerBound()) || f(upperBound()) }
|
||||||
else -> error("sealed")
|
else -> error("sealed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-9
@@ -165,7 +165,7 @@ class ConstraintInjector(
|
|||||||
type.typeDepth() <= maxTypeDepthFromInitialConstraints + ALLOWED_DEPTH_DELTA_FOR_INCORPORATION
|
type.typeDepth() <= maxTypeDepthFromInitialConstraints + ALLOWED_DEPTH_DELTA_FOR_INCORPORATION
|
||||||
|
|
||||||
private inner class TypeCheckerContext(val c: Context, val position: IncorporationConstraintPosition) :
|
private inner class TypeCheckerContext(val c: Context, val position: IncorporationConstraintPosition) :
|
||||||
AbstractTypeCheckerContextForConstraintSystem(), ConstraintIncorporator.Context, TypeSystemInferenceExtensionContext by c {
|
AbstractTypeCheckerContextForConstraintSystem(c), ConstraintIncorporator.Context, TypeSystemInferenceExtensionContext by c {
|
||||||
// We use `var` intentionally to avoid extra allocations as this property is quite "hot"
|
// We use `var` intentionally to avoid extra allocations as this property is quite "hot"
|
||||||
private var possibleNewConstraints: MutableList<Pair<TypeVariableMarker, Constraint>>? = null
|
private var possibleNewConstraints: MutableList<Pair<TypeVariableMarker, Constraint>>? = null
|
||||||
|
|
||||||
@@ -198,14 +198,6 @@ class ConstraintInjector(
|
|||||||
return baseContext.substitutionSupertypePolicy(type)
|
return baseContext.substitutionSupertypePolicy(type)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun areEqualTypeConstructors(c1: TypeConstructorMarker, c2: TypeConstructorMarker): Boolean {
|
|
||||||
return baseContext.areEqualTypeConstructors(c1, c2)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun prepareType(type: KotlinTypeMarker): KotlinTypeMarker {
|
|
||||||
return baseContext.prepareType(type)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun refineType(type: KotlinTypeMarker): KotlinTypeMarker {
|
override fun refineType(type: KotlinTypeMarker): KotlinTypeMarker {
|
||||||
return with(constraintIncorporator.utilContext) {
|
return with(constraintIncorporator.utilContext) {
|
||||||
type.refineType()
|
type.refineType()
|
||||||
|
|||||||
+11
-6
@@ -23,7 +23,9 @@ import org.jetbrains.kotlin.types.TypeConstructor
|
|||||||
import org.jetbrains.kotlin.types.TypeConstructorSubstitution
|
import org.jetbrains.kotlin.types.TypeConstructorSubstitution
|
||||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||||
import org.jetbrains.kotlin.types.checker.ClassicTypeCheckerContext
|
import org.jetbrains.kotlin.types.checker.ClassicTypeCheckerContext
|
||||||
|
import org.jetbrains.kotlin.types.checker.ClassicTypeSystemContext
|
||||||
import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker
|
import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker
|
||||||
|
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
|
||||||
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
|
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
|
||||||
import org.jetbrains.kotlin.utils.SmartList
|
import org.jetbrains.kotlin.utils.SmartList
|
||||||
import org.jetbrains.kotlin.utils.keysToMap
|
import org.jetbrains.kotlin.utils.keysToMap
|
||||||
@@ -326,14 +328,17 @@ object ExpectedActualResolver {
|
|||||||
if (b == null) return false
|
if (b == null) return false
|
||||||
|
|
||||||
with(NewKotlinTypeChecker.Default) {
|
with(NewKotlinTypeChecker.Default) {
|
||||||
val context = object : ClassicTypeCheckerContext(false) {
|
val context = object : ClassicTypeSystemContext {
|
||||||
override fun areEqualTypeConstructors(a: TypeConstructor, b: TypeConstructor): Boolean {
|
override fun areEqualTypeConstructors(c1: TypeConstructorMarker, c2: TypeConstructorMarker): Boolean {
|
||||||
return isExpectedClassAndActualTypeAlias(a, b, platformModule) ||
|
require(c1 is TypeConstructor)
|
||||||
isExpectedClassAndActualTypeAlias(b, a, platformModule) ||
|
require(c2 is TypeConstructor)
|
||||||
super.areEqualTypeConstructors(a, b)
|
return isExpectedClassAndActualTypeAlias(c1, c2, platformModule) ||
|
||||||
|
isExpectedClassAndActualTypeAlias(c2, c1, platformModule) ||
|
||||||
|
super.areEqualTypeConstructors(c1, c2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return context.equalTypes(a.unwrap(), b.unwrap())
|
return ClassicTypeCheckerContext(errorTypeEqualsToAnything = false, typeSystemContext = context)
|
||||||
|
.equalTypes(a.unwrap(), b.unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,15 +13,12 @@ import org.jetbrains.kotlin.utils.SmartSet
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
abstract class AbstractTypeCheckerContext : TypeSystemContext {
|
abstract class AbstractTypeCheckerContext() {
|
||||||
|
|
||||||
|
abstract val typeSystemContext: TypeSystemContext
|
||||||
|
|
||||||
abstract fun substitutionSupertypePolicy(type: SimpleTypeMarker): SupertypesPolicy
|
abstract fun substitutionSupertypePolicy(type: SimpleTypeMarker): SupertypesPolicy
|
||||||
|
|
||||||
override fun prepareType(type: KotlinTypeMarker): KotlinTypeMarker {
|
|
||||||
return type
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun refineType(type: KotlinTypeMarker): KotlinTypeMarker {
|
open fun refineType(type: KotlinTypeMarker): KotlinTypeMarker {
|
||||||
return type
|
return type
|
||||||
}
|
}
|
||||||
@@ -34,7 +31,6 @@ abstract class AbstractTypeCheckerContext : TypeSystemContext {
|
|||||||
|
|
||||||
protected var argumentsDepth = 0
|
protected var argumentsDepth = 0
|
||||||
|
|
||||||
|
|
||||||
internal inline fun <T> runWithArgumentsSettings(subArgument: KotlinTypeMarker, f: AbstractTypeCheckerContext.() -> T): T {
|
internal inline fun <T> runWithArgumentsSettings(subArgument: KotlinTypeMarker, f: AbstractTypeCheckerContext.() -> T): T {
|
||||||
if (argumentsDepth > 100) {
|
if (argumentsDepth > 100) {
|
||||||
error("Arguments depth is too high. Some related argument: $subArgument")
|
error("Arguments depth is too high. Some related argument: $subArgument")
|
||||||
@@ -46,7 +42,8 @@ abstract class AbstractTypeCheckerContext : TypeSystemContext {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun getLowerCapturedTypePolicy(subType: SimpleTypeMarker, superType: CapturedTypeMarker): LowerCapturedTypePolicy = CHECK_SUBTYPE_AND_LOWER
|
open fun getLowerCapturedTypePolicy(subType: SimpleTypeMarker, superType: CapturedTypeMarker): LowerCapturedTypePolicy =
|
||||||
|
CHECK_SUBTYPE_AND_LOWER
|
||||||
|
|
||||||
open fun addSubtypeConstraint(
|
open fun addSubtypeConstraint(
|
||||||
subType: KotlinTypeMarker,
|
subType: KotlinTypeMarker,
|
||||||
@@ -109,7 +106,8 @@ abstract class AbstractTypeCheckerContext : TypeSystemContext {
|
|||||||
if (!visitedSupertypes.add(current)) continue
|
if (!visitedSupertypes.add(current)) continue
|
||||||
|
|
||||||
val policy = supertypesPolicy(current).takeIf { it != SupertypesPolicy.None } ?: continue
|
val policy = supertypesPolicy(current).takeIf { it != SupertypesPolicy.None } ?: continue
|
||||||
for (supertype in current.typeConstructor().supertypes()) {
|
val supertypes = with(typeSystemContext) { current.typeConstructor().supertypes() }
|
||||||
|
for (supertype in supertypes) {
|
||||||
val newType = policy.transformType(this, supertype)
|
val newType = policy.transformType(this, supertype)
|
||||||
if (predicate(newType)) {
|
if (predicate(newType)) {
|
||||||
clear()
|
clear()
|
||||||
@@ -133,18 +131,21 @@ abstract class AbstractTypeCheckerContext : TypeSystemContext {
|
|||||||
|
|
||||||
object UpperIfFlexible : SupertypesPolicy() {
|
object UpperIfFlexible : SupertypesPolicy() {
|
||||||
override fun transformType(context: AbstractTypeCheckerContext, type: KotlinTypeMarker) =
|
override fun transformType(context: AbstractTypeCheckerContext, type: KotlinTypeMarker) =
|
||||||
with(context) { type.upperBoundIfFlexible() }
|
with(context.typeSystemContext) { type.upperBoundIfFlexible() }
|
||||||
}
|
}
|
||||||
|
|
||||||
object LowerIfFlexible : SupertypesPolicy() {
|
object LowerIfFlexible : SupertypesPolicy() {
|
||||||
override fun transformType(context: AbstractTypeCheckerContext, type: KotlinTypeMarker) =
|
override fun transformType(context: AbstractTypeCheckerContext, type: KotlinTypeMarker) =
|
||||||
with(context) { type.lowerBoundIfFlexible() }
|
with(context.typeSystemContext) { type.lowerBoundIfFlexible() }
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class DoCustomTransform : SupertypesPolicy()
|
abstract class DoCustomTransform : SupertypesPolicy()
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract val KotlinTypeMarker.isAllowedTypeVariable: Boolean
|
abstract val KotlinTypeMarker.isAllowedTypeVariable: Boolean
|
||||||
|
|
||||||
|
@JvmName("isAllowedTypeVariableBridge")
|
||||||
|
fun isAllowedTypeVariable(type: KotlinTypeMarker): Boolean = type.isAllowedTypeVariable
|
||||||
}
|
}
|
||||||
|
|
||||||
object AbstractTypeChecker {
|
object AbstractTypeChecker {
|
||||||
@@ -166,7 +167,7 @@ object AbstractTypeChecker {
|
|||||||
superConstructor: TypeConstructorMarker
|
superConstructor: TypeConstructorMarker
|
||||||
): Boolean {
|
): Boolean {
|
||||||
if (typeConstructor == superConstructor) return true
|
if (typeConstructor == superConstructor) return true
|
||||||
with(context) {
|
with(context.typeSystemContext) {
|
||||||
for (superType in typeConstructor.supertypes()) {
|
for (superType in typeConstructor.supertypes()) {
|
||||||
if (isSubtypeOfClass(context, superType.typeConstructor(), superConstructor)) {
|
if (isSubtypeOfClass(context, superType.typeConstructor(), superConstructor)) {
|
||||||
return true
|
return true
|
||||||
@@ -182,7 +183,7 @@ object AbstractTypeChecker {
|
|||||||
b: KotlinTypeMarker,
|
b: KotlinTypeMarker,
|
||||||
stubTypesEqualToAnything: Boolean = true
|
stubTypesEqualToAnything: Boolean = true
|
||||||
): Boolean {
|
): Boolean {
|
||||||
return AbstractTypeChecker.equalTypes(context.newBaseTypeCheckerContext(false, stubTypesEqualToAnything), a, b)
|
return equalTypes(context.newBaseTypeCheckerContext(false, stubTypesEqualToAnything), a, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isSubtypeOf(
|
fun isSubtypeOf(
|
||||||
@@ -195,55 +196,61 @@ object AbstractTypeChecker {
|
|||||||
|
|
||||||
if (!context.customIsSubtypeOf(subType, superType)) return false
|
if (!context.customIsSubtypeOf(subType, superType)) return false
|
||||||
|
|
||||||
return with(context) {
|
return completeIsSubTypeOf(
|
||||||
completeIsSubTypeOf(prepareType(refineType(subType)), prepareType(refineType(superType)), isFromNullabilityConstraint)
|
context,
|
||||||
}
|
context.typeSystemContext.prepareType(context.refineType(subType)),
|
||||||
|
context.typeSystemContext.prepareType(context.refineType(superType)),
|
||||||
|
isFromNullabilityConstraint
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun equalTypes(context: AbstractTypeCheckerContext, a: KotlinTypeMarker, b: KotlinTypeMarker): Boolean = with(context) {
|
fun equalTypes(context: AbstractTypeCheckerContext, a: KotlinTypeMarker, b: KotlinTypeMarker): Boolean =
|
||||||
if (a === b) return true
|
with(context.typeSystemContext) {
|
||||||
|
if (a === b) return true
|
||||||
|
|
||||||
if (isCommonDenotableType(a) && isCommonDenotableType(b)) {
|
if (isCommonDenotableType(a) && isCommonDenotableType(b)) {
|
||||||
val refinedA = refineType(a)
|
val refinedA = context.refineType(a)
|
||||||
val refinedB = refineType(b)
|
val refinedB = context.refineType(b)
|
||||||
val simpleA = refinedA.lowerBoundIfFlexible()
|
val simpleA = refinedA.lowerBoundIfFlexible()
|
||||||
if (!areEqualTypeConstructors(refinedA.typeConstructor(), refinedB.typeConstructor())) return false
|
if (!areEqualTypeConstructors(refinedA.typeConstructor(), refinedB.typeConstructor())) return false
|
||||||
if (simpleA.argumentsCount() == 0) {
|
if (simpleA.argumentsCount() == 0) {
|
||||||
if (refinedA.hasFlexibleNullability() || refinedB.hasFlexibleNullability()) return true
|
if (refinedA.hasFlexibleNullability() || refinedB.hasFlexibleNullability()) return true
|
||||||
|
|
||||||
return simpleA.isMarkedNullable() == refinedB.lowerBoundIfFlexible().isMarkedNullable()
|
return simpleA.isMarkedNullable() == refinedB.lowerBoundIfFlexible().isMarkedNullable()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return isSubtypeOf(context, a, b) && isSubtypeOf(context, b, a)
|
||||||
}
|
}
|
||||||
|
|
||||||
return isSubtypeOf(context, a, b) && isSubtypeOf(context, b, a)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
private fun completeIsSubTypeOf(
|
||||||
private fun AbstractTypeCheckerContext.completeIsSubTypeOf(
|
context: AbstractTypeCheckerContext,
|
||||||
subType: KotlinTypeMarker,
|
subType: KotlinTypeMarker,
|
||||||
superType: KotlinTypeMarker,
|
superType: KotlinTypeMarker,
|
||||||
isFromNullabilityConstraint: Boolean
|
isFromNullabilityConstraint: Boolean
|
||||||
): Boolean {
|
): Boolean = with(context.typeSystemContext) {
|
||||||
checkSubtypeForSpecialCases(subType.lowerBoundIfFlexible(), superType.upperBoundIfFlexible())?.let {
|
checkSubtypeForSpecialCases(context, subType.lowerBoundIfFlexible(), superType.upperBoundIfFlexible())?.let {
|
||||||
addSubtypeConstraint(subType, superType, isFromNullabilityConstraint)
|
context.addSubtypeConstraint(subType, superType, isFromNullabilityConstraint)
|
||||||
return it
|
return it
|
||||||
}
|
}
|
||||||
|
|
||||||
// we should add constraints with flexible types, otherwise we never get flexible type as answer in constraint system
|
// we should add constraints with flexible types, otherwise we never get flexible type as answer in constraint system
|
||||||
addSubtypeConstraint(subType, superType, isFromNullabilityConstraint)?.let { return it }
|
context.addSubtypeConstraint(subType, superType, isFromNullabilityConstraint)?.let { return it }
|
||||||
|
|
||||||
return isSubtypeOfForSingleClassifierType(subType.lowerBoundIfFlexible(), superType.upperBoundIfFlexible())
|
return isSubtypeOfForSingleClassifierType(context, subType.lowerBoundIfFlexible(), superType.upperBoundIfFlexible())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun AbstractTypeCheckerContext.checkSubtypeForIntegerLiteralType(
|
private fun checkSubtypeForIntegerLiteralType(
|
||||||
|
context: AbstractTypeCheckerContext,
|
||||||
subType: SimpleTypeMarker,
|
subType: SimpleTypeMarker,
|
||||||
superType: SimpleTypeMarker
|
superType: SimpleTypeMarker
|
||||||
): Boolean? {
|
): Boolean? = with(context.typeSystemContext) {
|
||||||
if (!subType.isIntegerLiteralType() && !superType.isIntegerLiteralType()) return null
|
if (!subType.isIntegerLiteralType() && !superType.isIntegerLiteralType()) return null
|
||||||
|
|
||||||
fun isTypeInIntegerLiteralType(integerLiteralType: SimpleTypeMarker, type: SimpleTypeMarker, checkSupertypes: Boolean): Boolean =
|
fun isTypeInIntegerLiteralType(integerLiteralType: SimpleTypeMarker, type: SimpleTypeMarker, checkSupertypes: Boolean): Boolean =
|
||||||
integerLiteralType.possibleIntegerTypes().any { possibleType ->
|
integerLiteralType.possibleIntegerTypes().any { possibleType ->
|
||||||
(possibleType.typeConstructor() == type.typeConstructor()) || (checkSupertypes && isSubtypeOf(this, type, possibleType))
|
(possibleType.typeConstructor() == type.typeConstructor()) || (checkSupertypes && isSubtypeOf(context, type, possibleType))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isIntegerLiteralTypeInIntersectionComponents(type: SimpleTypeMarker): Boolean {
|
fun isIntegerLiteralTypeInIntersectionComponents(type: SimpleTypeMarker): Boolean {
|
||||||
@@ -276,12 +283,12 @@ object AbstractTypeChecker {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun AbstractTypeCheckerContext.hasNothingSupertype(type: SimpleTypeMarker): Boolean {
|
private fun hasNothingSupertype(context: AbstractTypeCheckerContext, type: SimpleTypeMarker): Boolean = with(context.typeSystemContext) {
|
||||||
val typeConstructor = type.typeConstructor()
|
val typeConstructor = type.typeConstructor()
|
||||||
if (typeConstructor.isClassTypeConstructor()) {
|
if (typeConstructor.isClassTypeConstructor()) {
|
||||||
return typeConstructor.isNothingConstructor()
|
return typeConstructor.isNothingConstructor()
|
||||||
}
|
}
|
||||||
return anySupertype(type, { it.typeConstructor().isNothingConstructor() }) {
|
return context.anySupertype(type, { it.typeConstructor().isNothingConstructor() }) {
|
||||||
if (it.isClassType()) {
|
if (it.isClassType()) {
|
||||||
SupertypesPolicy.None
|
SupertypesPolicy.None
|
||||||
} else {
|
} else {
|
||||||
@@ -290,20 +297,24 @@ object AbstractTypeChecker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun AbstractTypeCheckerContext.isSubtypeOfForSingleClassifierType(subType: SimpleTypeMarker, superType: SimpleTypeMarker): Boolean {
|
private fun isSubtypeOfForSingleClassifierType(
|
||||||
|
context: AbstractTypeCheckerContext,
|
||||||
|
subType: SimpleTypeMarker,
|
||||||
|
superType: SimpleTypeMarker
|
||||||
|
): Boolean = with(context.typeSystemContext) {
|
||||||
if (AbstractTypeChecker.RUN_SLOW_ASSERTIONS) {
|
if (AbstractTypeChecker.RUN_SLOW_ASSERTIONS) {
|
||||||
assert(subType.isSingleClassifierType() || subType.typeConstructor().isIntersection() || subType.isAllowedTypeVariable) {
|
assert(subType.isSingleClassifierType() || subType.typeConstructor().isIntersection() || context.isAllowedTypeVariable(subType)) {
|
||||||
"Not singleClassifierType and not intersection subType: $subType"
|
"Not singleClassifierType and not intersection subType: $subType"
|
||||||
}
|
}
|
||||||
assert(superType.isSingleClassifierType() || superType.isAllowedTypeVariable) {
|
assert(superType.isSingleClassifierType() || context .isAllowedTypeVariable(superType)) {
|
||||||
"Not singleClassifierType superType: $superType"
|
"Not singleClassifierType superType: $superType"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!AbstractNullabilityChecker.isPossibleSubtype(this, subType, superType)) return false
|
if (!AbstractNullabilityChecker.isPossibleSubtype(context, subType, superType)) return false
|
||||||
|
|
||||||
checkSubtypeForIntegerLiteralType(subType.lowerBoundIfFlexible(), superType.upperBoundIfFlexible())?.let {
|
checkSubtypeForIntegerLiteralType(context, subType.lowerBoundIfFlexible(), superType.upperBoundIfFlexible())?.let {
|
||||||
addSubtypeConstraint(subType, superType)
|
context.addSubtypeConstraint(subType, superType)
|
||||||
return it
|
return it
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -312,10 +323,10 @@ object AbstractTypeChecker {
|
|||||||
if (areEqualTypeConstructors(subType.typeConstructor(), superConstructor) && superConstructor.parametersCount() == 0) return true
|
if (areEqualTypeConstructors(subType.typeConstructor(), superConstructor) && superConstructor.parametersCount() == 0) return true
|
||||||
if (superType.typeConstructor().isAnyConstructor()) return true
|
if (superType.typeConstructor().isAnyConstructor()) return true
|
||||||
|
|
||||||
val supertypesWithSameConstructor = findCorrespondingSupertypes(subType, superConstructor)
|
val supertypesWithSameConstructor = findCorrespondingSupertypes(context, subType, superConstructor)
|
||||||
when (supertypesWithSameConstructor.size) {
|
when (supertypesWithSameConstructor.size) {
|
||||||
0 -> return hasNothingSupertype(subType) // todo Nothing & Array<Number> <: Array<String>
|
0 -> return hasNothingSupertype(context, subType) // todo Nothing & Array<Number> <: Array<String>
|
||||||
1 -> return isSubtypeForSameConstructor(supertypesWithSameConstructor.first().asArgumentList(), superType)
|
1 -> return context.isSubtypeForSameConstructor(supertypesWithSameConstructor.first().asArgumentList(), superType)
|
||||||
|
|
||||||
else -> { // at least 2 supertypes with same constructors. Such case is rare
|
else -> { // at least 2 supertypes with same constructors. Such case is rare
|
||||||
val newArguments = ArgumentList(superConstructor.parametersCount())
|
val newArguments = ArgumentList(superConstructor.parametersCount())
|
||||||
@@ -333,10 +344,10 @@ object AbstractTypeChecker {
|
|||||||
newArguments.add(intersection)
|
newArguments.add(intersection)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!anyNonOutParameter && isSubtypeForSameConstructor(newArguments, superType)) return true
|
if (!anyNonOutParameter && context.isSubtypeForSameConstructor(newArguments, superType)) return true
|
||||||
|
|
||||||
// TODO: rethink this; now components order in intersection type affects semantic due to run subtyping (which can add constraints) only until the first successful candidate
|
// TODO: rethink this; now components order in intersection type affects semantic due to run subtyping (which can add constraints) only until the first successful candidate
|
||||||
return supertypesWithSameConstructor.any { isSubtypeForSameConstructor(it.asArgumentList(), superType) }
|
return supertypesWithSameConstructor.any { context.isSubtypeForSameConstructor(it.asArgumentList(), superType) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -344,7 +355,7 @@ object AbstractTypeChecker {
|
|||||||
fun AbstractTypeCheckerContext.isSubtypeForSameConstructor(
|
fun AbstractTypeCheckerContext.isSubtypeForSameConstructor(
|
||||||
capturedSubArguments: TypeArgumentListMarker,
|
capturedSubArguments: TypeArgumentListMarker,
|
||||||
superType: SimpleTypeMarker
|
superType: SimpleTypeMarker
|
||||||
): Boolean {
|
): Boolean = with(this.typeSystemContext) {
|
||||||
// No way to check, as no index sometimes
|
// No way to check, as no index sometimes
|
||||||
//if (capturedSubArguments === superType.arguments) return true
|
//if (capturedSubArguments === superType.arguments) return true
|
||||||
|
|
||||||
@@ -375,7 +386,7 @@ object AbstractTypeChecker {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun AbstractTypeCheckerContext.isCommonDenotableType(type: KotlinTypeMarker): Boolean =
|
private fun TypeSystemContext.isCommonDenotableType(type: KotlinTypeMarker): Boolean =
|
||||||
type.typeConstructor().isDenotable() &&
|
type.typeConstructor().isDenotable() &&
|
||||||
!type.isDynamic() && !type.isDefinitelyNotNullType() &&
|
!type.isDynamic() && !type.isDefinitelyNotNullType() &&
|
||||||
type.lowerBoundIfFlexible().typeConstructor() == type.upperBoundIfFlexible().typeConstructor()
|
type.lowerBoundIfFlexible().typeConstructor() == type.upperBoundIfFlexible().typeConstructor()
|
||||||
@@ -391,9 +402,13 @@ object AbstractTypeChecker {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun AbstractTypeCheckerContext.checkSubtypeForSpecialCases(subType: SimpleTypeMarker, superType: SimpleTypeMarker): Boolean? {
|
private fun checkSubtypeForSpecialCases(
|
||||||
|
context: AbstractTypeCheckerContext,
|
||||||
|
subType: SimpleTypeMarker,
|
||||||
|
superType: SimpleTypeMarker
|
||||||
|
): Boolean? = with(context.typeSystemContext) {
|
||||||
if (subType.isError() || superType.isError()) {
|
if (subType.isError() || superType.isError()) {
|
||||||
if (isErrorTypeEqualsToAnything) return true
|
if (context.isErrorTypeEqualsToAnything) return true
|
||||||
|
|
||||||
if (subType.isMarkedNullable() && !superType.isMarkedNullable()) return false
|
if (subType.isMarkedNullable() && !superType.isMarkedNullable()) return false
|
||||||
|
|
||||||
@@ -404,7 +419,7 @@ object AbstractTypeChecker {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subType.isStubType() || superType.isStubType()) return isStubTypeEqualsToAnything
|
if (subType.isStubType() || superType.isStubType()) return context.isStubTypeEqualsToAnything
|
||||||
|
|
||||||
// superType might be a definitely notNull type (see KT-42824)
|
// superType might be a definitely notNull type (see KT-42824)
|
||||||
val superOriginalType = superType.asDefinitelyNotNullType()?.original() ?: superType
|
val superOriginalType = superType.asDefinitelyNotNullType()?.original() ?: superType
|
||||||
@@ -418,9 +433,9 @@ object AbstractTypeChecker {
|
|||||||
} else {
|
} else {
|
||||||
if (superType.isDefinitelyNotNullType()) lowerType.makeDefinitelyNotNullOrNotNull() else lowerType
|
if (superType.isDefinitelyNotNullType()) lowerType.makeDefinitelyNotNullOrNotNull() else lowerType
|
||||||
}
|
}
|
||||||
when (getLowerCapturedTypePolicy(subType, superTypeCaptured)) {
|
when (context.getLowerCapturedTypePolicy(subType, superTypeCaptured)) {
|
||||||
CHECK_ONLY_LOWER -> return isSubtypeOf(this, subType, nullableLowerType)
|
CHECK_ONLY_LOWER -> return isSubtypeOf(context, subType, nullableLowerType)
|
||||||
CHECK_SUBTYPE_AND_LOWER -> if (isSubtypeOf(this, subType, nullableLowerType)) return true
|
CHECK_SUBTYPE_AND_LOWER -> if (isSubtypeOf(context, subType, nullableLowerType)) return true
|
||||||
SKIP_LOWER -> Unit
|
SKIP_LOWER -> Unit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -429,17 +444,18 @@ object AbstractTypeChecker {
|
|||||||
if (superTypeConstructor.isIntersection()) {
|
if (superTypeConstructor.isIntersection()) {
|
||||||
assert(!superType.isMarkedNullable()) { "Intersection type should not be marked nullable!: $superType" }
|
assert(!superType.isMarkedNullable()) { "Intersection type should not be marked nullable!: $superType" }
|
||||||
|
|
||||||
return superTypeConstructor.supertypes().all { isSubtypeOf(this, subType, it) }
|
return superTypeConstructor.supertypes().all { isSubtypeOf(context, subType, it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun AbstractTypeCheckerContext.collectAllSupertypesWithGivenTypeConstructor(
|
private fun collectAllSupertypesWithGivenTypeConstructor(
|
||||||
|
context: AbstractTypeCheckerContext,
|
||||||
subType: SimpleTypeMarker,
|
subType: SimpleTypeMarker,
|
||||||
superConstructor: TypeConstructorMarker
|
superConstructor: TypeConstructorMarker
|
||||||
): List<SimpleTypeMarker> {
|
): List<SimpleTypeMarker> = with(context.typeSystemContext) {
|
||||||
subType.fastCorrespondingSupertypes(superConstructor)?.let {
|
subType.fastCorrespondingSupertypes(superConstructor)?.let {
|
||||||
return it
|
return it
|
||||||
}
|
}
|
||||||
@@ -455,7 +471,7 @@ object AbstractTypeChecker {
|
|||||||
|
|
||||||
val result: MutableList<SimpleTypeMarker> = SmartList()
|
val result: MutableList<SimpleTypeMarker> = SmartList()
|
||||||
|
|
||||||
anySupertype(subType, { false }) {
|
context.anySupertype(subType, { false }) {
|
||||||
|
|
||||||
val current = captureFromArguments(it, CaptureStatus.FOR_SUBTYPING) ?: it
|
val current = captureFromArguments(it, CaptureStatus.FOR_SUBTYPING) ?: it
|
||||||
|
|
||||||
@@ -468,7 +484,7 @@ object AbstractTypeChecker {
|
|||||||
SupertypesPolicy.LowerIfFlexible
|
SupertypesPolicy.LowerIfFlexible
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
substitutionSupertypePolicy(current)
|
context.substitutionSupertypePolicy(current)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -476,8 +492,12 @@ object AbstractTypeChecker {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun AbstractTypeCheckerContext.collectAndFilter(classType: SimpleTypeMarker, constructor: TypeConstructorMarker) =
|
private fun collectAndFilter(
|
||||||
selectOnlyPureKotlinSupertypes(collectAllSupertypesWithGivenTypeConstructor(classType, constructor))
|
context: AbstractTypeCheckerContext,
|
||||||
|
classType: SimpleTypeMarker,
|
||||||
|
constructor: TypeConstructorMarker
|
||||||
|
) =
|
||||||
|
selectOnlyPureKotlinSupertypes(context, collectAllSupertypesWithGivenTypeConstructor(context, classType, constructor))
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -490,7 +510,10 @@ object AbstractTypeChecker {
|
|||||||
*
|
*
|
||||||
* More tests: javaAndKotlinSuperType & purelyImplementedCollection folder
|
* More tests: javaAndKotlinSuperType & purelyImplementedCollection folder
|
||||||
*/
|
*/
|
||||||
private fun AbstractTypeCheckerContext.selectOnlyPureKotlinSupertypes(supertypes: List<SimpleTypeMarker>): List<SimpleTypeMarker> {
|
private fun selectOnlyPureKotlinSupertypes(
|
||||||
|
context: AbstractTypeCheckerContext,
|
||||||
|
supertypes: List<SimpleTypeMarker>
|
||||||
|
): List<SimpleTypeMarker> = with(context.typeSystemContext) {
|
||||||
if (supertypes.size < 2) return supertypes
|
if (supertypes.size < 2) return supertypes
|
||||||
|
|
||||||
val allPureSupertypes = supertypes.filter {
|
val allPureSupertypes = supertypes.filter {
|
||||||
@@ -502,22 +525,23 @@ object AbstractTypeChecker {
|
|||||||
|
|
||||||
// nullability was checked earlier via nullabilityChecker
|
// nullability was checked earlier via nullabilityChecker
|
||||||
// should be used only if you really sure that it is correct
|
// should be used only if you really sure that it is correct
|
||||||
fun AbstractTypeCheckerContext.findCorrespondingSupertypes(
|
fun findCorrespondingSupertypes(
|
||||||
|
context: AbstractTypeCheckerContext,
|
||||||
subType: SimpleTypeMarker,
|
subType: SimpleTypeMarker,
|
||||||
superConstructor: TypeConstructorMarker
|
superConstructor: TypeConstructorMarker
|
||||||
): List<SimpleTypeMarker> {
|
): List<SimpleTypeMarker> = with(context.typeSystemContext) {
|
||||||
if (subType.isClassType()) {
|
if (subType.isClassType()) {
|
||||||
return collectAndFilter(subType, superConstructor)
|
return collectAndFilter(context, subType, superConstructor)
|
||||||
}
|
}
|
||||||
|
|
||||||
// i.e. superType is not a classType
|
// i.e. superType is not a classType
|
||||||
if (!superConstructor.isClassTypeConstructor() && !superConstructor.isIntegerLiteralTypeConstructor()) {
|
if (!superConstructor.isClassTypeConstructor() && !superConstructor.isIntegerLiteralTypeConstructor()) {
|
||||||
return collectAllSupertypesWithGivenTypeConstructor(subType, superConstructor)
|
return collectAllSupertypesWithGivenTypeConstructor(context, subType, superConstructor)
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo add tests
|
// todo add tests
|
||||||
val classTypeSupertypes = SmartList<SimpleTypeMarker>()
|
val classTypeSupertypes = SmartList<SimpleTypeMarker>()
|
||||||
anySupertype(subType, { false }) {
|
context.anySupertype(subType, { false }) {
|
||||||
if (it.isClassType()) {
|
if (it.isClassType()) {
|
||||||
classTypeSupertypes.add(it)
|
classTypeSupertypes.add(it)
|
||||||
SupertypesPolicy.None
|
SupertypesPolicy.None
|
||||||
@@ -526,7 +550,7 @@ object AbstractTypeChecker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return classTypeSupertypes.flatMap { collectAndFilter(it, superConstructor) }
|
return classTypeSupertypes.flatMap { collectAndFilter(context, it, superConstructor) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -534,7 +558,7 @@ object AbstractTypeChecker {
|
|||||||
object AbstractNullabilityChecker {
|
object AbstractNullabilityChecker {
|
||||||
// this method checks only nullability
|
// this method checks only nullability
|
||||||
fun isPossibleSubtype(context: AbstractTypeCheckerContext, subType: SimpleTypeMarker, superType: SimpleTypeMarker): Boolean =
|
fun isPossibleSubtype(context: AbstractTypeCheckerContext, subType: SimpleTypeMarker, superType: SimpleTypeMarker): Boolean =
|
||||||
context.runIsPossibleSubtype(subType, superType)
|
runIsPossibleSubtype(context, subType, superType)
|
||||||
|
|
||||||
fun isSubtypeOfAny(context: TypeCheckerProviderContext, type: KotlinTypeMarker): Boolean =
|
fun isSubtypeOfAny(context: TypeCheckerProviderContext, type: KotlinTypeMarker): Boolean =
|
||||||
AbstractNullabilityChecker.isSubtypeOfAny(
|
AbstractNullabilityChecker.isSubtypeOfAny(
|
||||||
@@ -546,82 +570,93 @@ object AbstractNullabilityChecker {
|
|||||||
)
|
)
|
||||||
|
|
||||||
fun isSubtypeOfAny(context: AbstractTypeCheckerContext, type: KotlinTypeMarker): Boolean =
|
fun isSubtypeOfAny(context: AbstractTypeCheckerContext, type: KotlinTypeMarker): Boolean =
|
||||||
with(context) {
|
with(context.typeSystemContext) {
|
||||||
hasNotNullSupertype(type.lowerBoundIfFlexible(), SupertypesPolicy.LowerIfFlexible)
|
context.hasNotNullSupertype(type.lowerBoundIfFlexible(), SupertypesPolicy.LowerIfFlexible)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun AbstractTypeCheckerContext.runIsPossibleSubtype(subType: SimpleTypeMarker, superType: SimpleTypeMarker): Boolean {
|
private fun runIsPossibleSubtype(context: AbstractTypeCheckerContext, subType: SimpleTypeMarker, superType: SimpleTypeMarker): Boolean =
|
||||||
if (AbstractTypeChecker.RUN_SLOW_ASSERTIONS) {
|
with(context.typeSystemContext) {
|
||||||
// it makes for case String? & Any <: String
|
if (AbstractTypeChecker.RUN_SLOW_ASSERTIONS) {
|
||||||
assert(subType.isSingleClassifierType() || subType.typeConstructor().isIntersection() || subType.isAllowedTypeVariable) {
|
// it makes for case String? & Any <: String
|
||||||
"Not singleClassifierType and not intersection subType: $subType"
|
assert(
|
||||||
}
|
subType.isSingleClassifierType() || subType.typeConstructor().isIntersection() || context.isAllowedTypeVariable(
|
||||||
assert(superType.isSingleClassifierType() || superType.isAllowedTypeVariable) {
|
subType
|
||||||
"Not singleClassifierType superType: $superType"
|
)
|
||||||
|
) {
|
||||||
|
"Not singleClassifierType and not intersection subType: $subType"
|
||||||
|
}
|
||||||
|
assert(superType.isSingleClassifierType() || context.isAllowedTypeVariable(superType)) {
|
||||||
|
"Not singleClassifierType superType: $superType"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// superType is actually nullable
|
||||||
|
if (superType.isMarkedNullable()) return true
|
||||||
|
|
||||||
|
// i.e. subType is definitely not null
|
||||||
|
if (subType.isDefinitelyNotNullType()) return true
|
||||||
|
|
||||||
|
// i.e. subType is captured type, projection of which is marked not-null
|
||||||
|
if (subType is CapturedTypeMarker && subType.isProjectionNotNull()) return true
|
||||||
|
|
||||||
|
// i.e. subType is not-nullable
|
||||||
|
if (context.hasNotNullSupertype(subType, SupertypesPolicy.LowerIfFlexible)) return true
|
||||||
|
|
||||||
|
// i.e. subType hasn't not-null supertype and isn't definitely not-null, but superType is definitely not-null
|
||||||
|
if (superType.isDefinitelyNotNullType()) return false
|
||||||
|
|
||||||
|
// i.e subType hasn't not-null supertype, but superType has
|
||||||
|
if (context.hasNotNullSupertype(superType, SupertypesPolicy.UpperIfFlexible)) return false
|
||||||
|
|
||||||
|
// both superType and subType hasn't not-null supertype and are not definitely not null.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If we still don't know, it means, that superType is not classType, for example -- type parameter.
|
||||||
|
*
|
||||||
|
* For captured types with lower bound this function can give to you false result. Example:
|
||||||
|
* class A<T>, A<in Number> => \exist Q : Number <: Q. A<Q>
|
||||||
|
* isPossibleSubtype(Number, Q) = false.
|
||||||
|
* Such cases should be taken in to account in [NewKotlinTypeChecker.isSubtypeOf] (same for intersection types)
|
||||||
|
*/
|
||||||
|
|
||||||
|
// classType cannot has special type in supertype list
|
||||||
|
if (subType.isClassType()) return false
|
||||||
|
|
||||||
|
return hasPathByNotMarkedNullableNodes(context, subType, superType.typeConstructor())
|
||||||
}
|
}
|
||||||
|
|
||||||
// superType is actually nullable
|
|
||||||
if (superType.isMarkedNullable()) return true
|
|
||||||
|
|
||||||
// i.e. subType is definitely not null
|
|
||||||
if (subType.isDefinitelyNotNullType()) return true
|
|
||||||
|
|
||||||
// i.e. subType is captured type, projection of which is marked not-null
|
|
||||||
if (subType is CapturedTypeMarker && subType.isProjectionNotNull()) return true
|
|
||||||
|
|
||||||
// i.e. subType is not-nullable
|
|
||||||
if (hasNotNullSupertype(subType, SupertypesPolicy.LowerIfFlexible)) return true
|
|
||||||
|
|
||||||
// i.e. subType hasn't not-null supertype and isn't definitely not-null, but superType is definitely not-null
|
|
||||||
if (superType.isDefinitelyNotNullType()) return false
|
|
||||||
|
|
||||||
// i.e subType hasn't not-null supertype, but superType has
|
|
||||||
if (hasNotNullSupertype(superType, SupertypesPolicy.UpperIfFlexible)) return false
|
|
||||||
|
|
||||||
// both superType and subType hasn't not-null supertype and are not definitely not null.
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If we still don't know, it means, that superType is not classType, for example -- type parameter.
|
|
||||||
*
|
|
||||||
* For captured types with lower bound this function can give to you false result. Example:
|
|
||||||
* class A<T>, A<in Number> => \exist Q : Number <: Q. A<Q>
|
|
||||||
* isPossibleSubtype(Number, Q) = false.
|
|
||||||
* Such cases should be taken in to account in [NewKotlinTypeChecker.isSubtypeOf] (same for intersection types)
|
|
||||||
*/
|
|
||||||
|
|
||||||
// classType cannot has special type in supertype list
|
|
||||||
if (subType.isClassType()) return false
|
|
||||||
|
|
||||||
return hasPathByNotMarkedNullableNodes(subType, superType.typeConstructor())
|
|
||||||
}
|
|
||||||
|
|
||||||
fun AbstractTypeCheckerContext.hasNotNullSupertype(type: SimpleTypeMarker, supertypesPolicy: SupertypesPolicy) =
|
fun AbstractTypeCheckerContext.hasNotNullSupertype(type: SimpleTypeMarker, supertypesPolicy: SupertypesPolicy) =
|
||||||
anySupertype(type, {
|
with(typeSystemContext) {
|
||||||
(it.isClassType() && !it.isMarkedNullable()) || it.isDefinitelyNotNullType()
|
anySupertype(type, {
|
||||||
}) {
|
(it.isClassType() && !it.isMarkedNullable()) || it.isDefinitelyNotNullType()
|
||||||
if (it.isMarkedNullable()) SupertypesPolicy.None else supertypesPolicy
|
}) {
|
||||||
|
if (it.isMarkedNullable()) SupertypesPolicy.None else supertypesPolicy
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun TypeCheckerProviderContext.hasPathByNotMarkedNullableNodes(start: SimpleTypeMarker, end: TypeConstructorMarker) =
|
fun TypeCheckerProviderContext.hasPathByNotMarkedNullableNodes(start: SimpleTypeMarker, end: TypeConstructorMarker) =
|
||||||
newBaseTypeCheckerContext(errorTypesEqualToAnything = false, stubTypesEqualToAnything = true)
|
hasPathByNotMarkedNullableNodes(
|
||||||
.hasPathByNotMarkedNullableNodes(start, end)
|
newBaseTypeCheckerContext(errorTypesEqualToAnything = false, stubTypesEqualToAnything = true), start, end
|
||||||
|
|
||||||
fun AbstractTypeCheckerContext.hasPathByNotMarkedNullableNodes(start: SimpleTypeMarker, end: TypeConstructorMarker) =
|
|
||||||
anySupertype(
|
|
||||||
start,
|
|
||||||
{ isApplicableAsEndNode(it, end) },
|
|
||||||
{ if (it.isMarkedNullable()) SupertypesPolicy.None else SupertypesPolicy.LowerIfFlexible }
|
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun AbstractTypeCheckerContext.isApplicableAsEndNode(type: SimpleTypeMarker, end: TypeConstructorMarker): Boolean {
|
fun hasPathByNotMarkedNullableNodes(context: AbstractTypeCheckerContext, start: SimpleTypeMarker, end: TypeConstructorMarker) =
|
||||||
if (type.isNothing()) return true
|
with(context.typeSystemContext) {
|
||||||
if (type.isMarkedNullable()) return false
|
context.anySupertype(
|
||||||
|
start,
|
||||||
|
{ isApplicableAsEndNode(context, it, end) },
|
||||||
|
{ if (it.isMarkedNullable()) SupertypesPolicy.None else SupertypesPolicy.LowerIfFlexible }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if (isStubTypeEqualsToAnything && type.isStubType()) return true
|
private fun isApplicableAsEndNode(context: AbstractTypeCheckerContext, type: SimpleTypeMarker, end: TypeConstructorMarker): Boolean =
|
||||||
|
with(context.typeSystemContext) {
|
||||||
|
if (type.isNothing()) return true
|
||||||
|
if (type.isMarkedNullable()) return false
|
||||||
|
|
||||||
return areEqualTypeConstructors(type.typeConstructor(), end)
|
if (context.isStubTypeEqualsToAnything && type.isStubType()) return true
|
||||||
}
|
|
||||||
|
return areEqualTypeConstructors(type.typeConstructor(), end)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -393,24 +393,28 @@ public class OverridingUtil {
|
|||||||
"Should be the same number of type parameters: " + firstParameters + " vs " + secondParameters;
|
"Should be the same number of type parameters: " + firstParameters + " vs " + secondParameters;
|
||||||
|
|
||||||
NewKotlinTypeCheckerImpl typeChecker = new NewKotlinTypeCheckerImpl(kotlinTypeRefiner);
|
NewKotlinTypeCheckerImpl typeChecker = new NewKotlinTypeCheckerImpl(kotlinTypeRefiner);
|
||||||
OverridingUtilTypeCheckerContext context = createTypeCheckerContext(firstParameters, secondParameters);
|
ClassicTypeCheckerContext context = createTypeCheckerContext(firstParameters, secondParameters);
|
||||||
|
|
||||||
return new Pair<NewKotlinTypeCheckerImpl, ClassicTypeCheckerContext>(typeChecker, context);
|
return new Pair<NewKotlinTypeCheckerImpl, ClassicTypeCheckerContext>(typeChecker, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private OverridingUtilTypeCheckerContext createTypeCheckerContext(
|
private ClassicTypeCheckerContext createTypeCheckerContext(
|
||||||
@NotNull List<TypeParameterDescriptor> firstParameters,
|
@NotNull List<TypeParameterDescriptor> firstParameters,
|
||||||
@NotNull List<TypeParameterDescriptor> secondParameters
|
@NotNull List<TypeParameterDescriptor> secondParameters
|
||||||
) {
|
) {
|
||||||
if (firstParameters.isEmpty()) return new OverridingUtilTypeCheckerContext(null);
|
if (firstParameters.isEmpty()) {
|
||||||
|
return (ClassicTypeCheckerContext) new OverridingUtilTypeSystemContext(null, equalityAxioms, kotlinTypeRefiner)
|
||||||
|
.newBaseTypeCheckerContext(true, true);
|
||||||
|
}
|
||||||
|
|
||||||
Map<TypeConstructor, TypeConstructor> matchingTypeConstructors = new HashMap<TypeConstructor, TypeConstructor>();
|
Map<TypeConstructor, TypeConstructor> matchingTypeConstructors = new HashMap<TypeConstructor, TypeConstructor>();
|
||||||
for (int i = 0; i < firstParameters.size(); i++) {
|
for (int i = 0; i < firstParameters.size(); i++) {
|
||||||
matchingTypeConstructors.put(firstParameters.get(i).getTypeConstructor(), secondParameters.get(i).getTypeConstructor());
|
matchingTypeConstructors.put(firstParameters.get(i).getTypeConstructor(), secondParameters.get(i).getTypeConstructor());
|
||||||
}
|
}
|
||||||
|
|
||||||
return new OverridingUtilTypeCheckerContext(matchingTypeConstructors);
|
return (ClassicTypeCheckerContext) new OverridingUtilTypeSystemContext(matchingTypeConstructors, equalityAxioms, kotlinTypeRefiner)
|
||||||
|
.newBaseTypeCheckerContext(true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -977,34 +981,6 @@ public class OverridingUtil {
|
|||||||
return maxVisibility;
|
return maxVisibility;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class OverridingUtilTypeCheckerContext extends ClassicTypeCheckerContext {
|
|
||||||
private final @Nullable Map<TypeConstructor, TypeConstructor> matchingTypeConstructors;
|
|
||||||
|
|
||||||
public OverridingUtilTypeCheckerContext(@Nullable Map<TypeConstructor, TypeConstructor> matchingTypeConstructors) {
|
|
||||||
super(
|
|
||||||
/* errorTypesEqualsToAnything = */ true,
|
|
||||||
/* stubTypesEqualsToAnything = */ true,
|
|
||||||
/* allowedTypeVariable = */ true,
|
|
||||||
kotlinTypeRefiner
|
|
||||||
);
|
|
||||||
this.matchingTypeConstructors = matchingTypeConstructors;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean areEqualTypeConstructors(@NotNull TypeConstructor a, @NotNull TypeConstructor b) {
|
|
||||||
return super.areEqualTypeConstructors(a, b) || areEqualTypeConstructorsByAxioms(a, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean areEqualTypeConstructorsByAxioms(@NotNull TypeConstructor a, @NotNull TypeConstructor b) {
|
|
||||||
if (equalityAxioms.equals(a, b)) return true;
|
|
||||||
if (matchingTypeConstructors == null) return false;
|
|
||||||
|
|
||||||
TypeConstructor img1 = matchingTypeConstructors.get(a);
|
|
||||||
TypeConstructor img2 = matchingTypeConstructors.get(b);
|
|
||||||
return (img1 != null && img1.equals(b)) || (img2 != null && img2.equals(a));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class OverrideCompatibilityInfo {
|
public static class OverrideCompatibilityInfo {
|
||||||
public enum Result {
|
public enum Result {
|
||||||
OVERRIDABLE,
|
OVERRIDABLE,
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.resolve
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.types.AbstractTypeCheckerContext
|
||||||
|
import org.jetbrains.kotlin.types.TypeConstructor
|
||||||
|
import org.jetbrains.kotlin.types.checker.ClassicTypeCheckerContext
|
||||||
|
import org.jetbrains.kotlin.types.checker.ClassicTypeSystemContext
|
||||||
|
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||||
|
import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner
|
||||||
|
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
|
||||||
|
|
||||||
|
class OverridingUtilTypeSystemContext(
|
||||||
|
val matchingTypeConstructors: Map<TypeConstructor, TypeConstructor>?,
|
||||||
|
private val equalityAxioms: KotlinTypeChecker.TypeConstructorEquality,
|
||||||
|
val kotlinTypeRefiner: KotlinTypeRefiner
|
||||||
|
) : ClassicTypeSystemContext {
|
||||||
|
|
||||||
|
override fun areEqualTypeConstructors(c1: TypeConstructorMarker, c2: TypeConstructorMarker): Boolean {
|
||||||
|
require(c1 is TypeConstructor)
|
||||||
|
require(c2 is TypeConstructor)
|
||||||
|
return super.areEqualTypeConstructors(c1, c2) || areEqualTypeConstructorsByAxioms(c1, c2)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun newBaseTypeCheckerContext(
|
||||||
|
errorTypesEqualToAnything: Boolean,
|
||||||
|
stubTypesEqualToAnything: Boolean
|
||||||
|
): AbstractTypeCheckerContext {
|
||||||
|
return ClassicTypeCheckerContext(
|
||||||
|
errorTypesEqualToAnything,
|
||||||
|
stubTypesEqualToAnything,
|
||||||
|
allowedTypeVariable = true,
|
||||||
|
kotlinTypeRefiner,
|
||||||
|
this
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun areEqualTypeConstructorsByAxioms(a: TypeConstructor, b: TypeConstructor): Boolean {
|
||||||
|
if (equalityAxioms.equals(a, b)) return true
|
||||||
|
if (matchingTypeConstructors == null) return false
|
||||||
|
val img1 = matchingTypeConstructors[a]
|
||||||
|
val img2 = matchingTypeConstructors[b]
|
||||||
|
return img1 != null && img1 == b || img2 != null && img2 == a
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
-27
@@ -16,24 +16,18 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.types.checker
|
package org.jetbrains.kotlin.types.checker
|
||||||
|
|
||||||
import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor
|
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
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.refinement.TypeRefinement
|
import org.jetbrains.kotlin.types.refinement.TypeRefinement
|
||||||
|
|
||||||
open class ClassicTypeCheckerContext(
|
open class ClassicTypeCheckerContext(
|
||||||
val errorTypeEqualsToAnything: Boolean,
|
val errorTypeEqualsToAnything: Boolean,
|
||||||
val stubTypeEqualsToAnything: Boolean = true,
|
val stubTypeEqualsToAnything: Boolean = true,
|
||||||
val allowedTypeVariable: Boolean = true,
|
val allowedTypeVariable: Boolean = true,
|
||||||
val kotlinTypeRefiner: KotlinTypeRefiner = KotlinTypeRefiner.Default
|
val kotlinTypeRefiner: KotlinTypeRefiner = KotlinTypeRefiner.Default,
|
||||||
) : ClassicTypeSystemContext, AbstractTypeCheckerContext() {
|
override val typeSystemContext: ClassicTypeSystemContext = SimpleClassicTypeSystemContext
|
||||||
|
) : AbstractTypeCheckerContext() {
|
||||||
override fun prepareType(type: KotlinTypeMarker): KotlinTypeMarker {
|
|
||||||
require(type is KotlinType, type::errorMessage)
|
|
||||||
return NewKotlinTypeChecker.Default.transformToNewType(type.unwrap())
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(TypeRefinement::class)
|
@OptIn(TypeRefinement::class)
|
||||||
override fun refineType(type: KotlinTypeMarker): KotlinTypeMarker {
|
override fun refineType(type: KotlinTypeMarker): KotlinTypeMarker {
|
||||||
@@ -47,25 +41,8 @@ open class ClassicTypeCheckerContext(
|
|||||||
override val isStubTypeEqualsToAnything: Boolean
|
override val isStubTypeEqualsToAnything: Boolean
|
||||||
get() = stubTypeEqualsToAnything
|
get() = stubTypeEqualsToAnything
|
||||||
|
|
||||||
override fun areEqualTypeConstructors(c1: TypeConstructorMarker, c2: TypeConstructorMarker): Boolean {
|
|
||||||
require(c1 is TypeConstructor, c1::errorMessage)
|
|
||||||
require(c2 is TypeConstructor, c2::errorMessage)
|
|
||||||
return areEqualTypeConstructors(c1, c2)
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun areEqualTypeConstructors(a: TypeConstructor, b: TypeConstructor): Boolean = when {
|
|
||||||
/*
|
|
||||||
* For integer literal types we have special rules for constructor's equality,
|
|
||||||
* so we have to check it manually
|
|
||||||
* For example: Int in ILT.possibleTypes -> ILT == Int
|
|
||||||
*/
|
|
||||||
a is IntegerLiteralTypeConstructor -> a.checkConstructor(b)
|
|
||||||
b is IntegerLiteralTypeConstructor -> b.checkConstructor(a)
|
|
||||||
else -> a == b
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun substitutionSupertypePolicy(type: SimpleTypeMarker): SupertypesPolicy.DoCustomTransform {
|
override fun substitutionSupertypePolicy(type: SimpleTypeMarker): SupertypesPolicy.DoCustomTransform {
|
||||||
return classicSubstitutionSupertypePolicy(type)
|
return typeSystemContext.classicSubstitutionSupertypePolicy(type)
|
||||||
}
|
}
|
||||||
|
|
||||||
override val KotlinTypeMarker.isAllowedTypeVariable: Boolean get() = this is UnwrappedType && allowedTypeVariable && constructor is NewTypeVariableConstructor
|
override val KotlinTypeMarker.isAllowedTypeVariable: Boolean get() = this is UnwrappedType && allowedTypeVariable && constructor is NewTypeVariableConstructor
|
||||||
|
|||||||
@@ -341,7 +341,7 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy
|
|||||||
errorTypesEqualToAnything: Boolean,
|
errorTypesEqualToAnything: Boolean,
|
||||||
stubTypesEqualToAnything: Boolean
|
stubTypesEqualToAnything: Boolean
|
||||||
): AbstractTypeCheckerContext {
|
): AbstractTypeCheckerContext {
|
||||||
return ClassicTypeCheckerContext(errorTypesEqualToAnything, stubTypesEqualToAnything)
|
return ClassicTypeCheckerContext(errorTypesEqualToAnything, stubTypesEqualToAnything, typeSystemContext = this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun nullableNothingType(): SimpleTypeMarker {
|
override fun nullableNothingType(): SimpleTypeMarker {
|
||||||
@@ -485,8 +485,8 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun prepareType(type: KotlinTypeMarker): KotlinTypeMarker {
|
override fun prepareType(type: KotlinTypeMarker): KotlinTypeMarker {
|
||||||
require(type is UnwrappedType, type::errorMessage)
|
require(type is KotlinType, type::errorMessage)
|
||||||
return NewKotlinTypeChecker.Default.transformToNewType(type)
|
return NewKotlinTypeChecker.Default.transformToNewType(type.unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun DefinitelyNotNullTypeMarker.original(): SimpleTypeMarker {
|
override fun DefinitelyNotNullTypeMarker.original(): SimpleTypeMarker {
|
||||||
|
|||||||
+2
-1
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.fir.FirSession
|
|||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic
|
||||||
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
||||||
|
import org.jetbrains.kotlin.fir.typeContext
|
||||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||||
import org.jetbrains.kotlin.fir.types.ConeTypeCheckerContext
|
import org.jetbrains.kotlin.fir.types.ConeTypeCheckerContext
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.diagnostics.KtDiagnostic
|
import org.jetbrains.kotlin.idea.frontend.api.diagnostics.KtDiagnostic
|
||||||
@@ -33,6 +34,6 @@ internal interface KtFirAnalysisSessionComponent {
|
|||||||
fun createTypeCheckerContext() = ConeTypeCheckerContext(
|
fun createTypeCheckerContext() = ConeTypeCheckerContext(
|
||||||
isErrorTypeEqualsToAnything = true,
|
isErrorTypeEqualsToAnything = true,
|
||||||
isStubTypeEqualsToAnything = true,
|
isStubTypeEqualsToAnything = true,
|
||||||
analysisSession.firResolveState.rootModuleSession //TODO use correct session here
|
analysisSession.firResolveState.rootModuleSession.typeContext //TODO use correct session here
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+11
-3
@@ -52,11 +52,14 @@ import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfoAfter
|
|||||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression
|
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression
|
||||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
import org.jetbrains.kotlin.resolve.source.getPsi
|
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||||
|
import org.jetbrains.kotlin.types.AbstractTypeCheckerContext
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.TypeConstructor
|
import org.jetbrains.kotlin.types.TypeConstructor
|
||||||
import org.jetbrains.kotlin.types.checker.ClassicTypeCheckerContext
|
import org.jetbrains.kotlin.types.checker.ClassicTypeCheckerContext
|
||||||
|
import org.jetbrains.kotlin.types.checker.ClassicTypeSystemContext
|
||||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||||
import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker
|
import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker
|
||||||
|
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
|
||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
import org.jetbrains.kotlin.utils.ifEmpty
|
import org.jetbrains.kotlin.utils.ifEmpty
|
||||||
import org.jetbrains.kotlin.utils.sure
|
import org.jetbrains.kotlin.utils.sure
|
||||||
@@ -73,11 +76,16 @@ object KotlinIntroduceVariableHandler : RefactoringActionHandler {
|
|||||||
private var KtExpression.isOccurrence: Boolean by NotNullablePsiCopyableUserDataProperty(Key.create("OCCURRENCE"), false)
|
private var KtExpression.isOccurrence: Boolean by NotNullablePsiCopyableUserDataProperty(Key.create("OCCURRENCE"), false)
|
||||||
|
|
||||||
private class TypeCheckerImpl(private val project: Project) : KotlinTypeChecker by KotlinTypeChecker.DEFAULT {
|
private class TypeCheckerImpl(private val project: Project) : KotlinTypeChecker by KotlinTypeChecker.DEFAULT {
|
||||||
private inner class ContextImpl : ClassicTypeCheckerContext(false) {
|
private inner class TypeSystemContextImpl : ClassicTypeSystemContext {
|
||||||
override fun areEqualTypeConstructors(a: TypeConstructor, b: TypeConstructor): Boolean =
|
override fun areEqualTypeConstructors(c1: TypeConstructorMarker, c2: TypeConstructorMarker): Boolean {
|
||||||
compareDescriptors(project, a.declarationDescriptor, b.declarationDescriptor)
|
require(c1 is TypeConstructor)
|
||||||
|
require(c2 is TypeConstructor)
|
||||||
|
return compareDescriptors(project, c1.declarationDescriptor, c2.declarationDescriptor)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private inner class ContextImpl : ClassicTypeCheckerContext(false, typeSystemContext = TypeSystemContextImpl())
|
||||||
|
|
||||||
override fun equalTypes(a: KotlinType, b: KotlinType): Boolean = with(NewKotlinTypeChecker.Default) {
|
override fun equalTypes(a: KotlinType, b: KotlinType): Boolean = with(NewKotlinTypeChecker.Default) {
|
||||||
ContextImpl().equalTypes(a.unwrap(), b.unwrap())
|
ContextImpl().equalTypes(a.unwrap(), b.unwrap())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user