[NI] Get rid of FE 1.0 types in AbstractTypeApproximator

This commit is contained in:
Dmitriy Novozhilov
2020-08-25 19:05:04 +03:00
parent 527c5a771d
commit b21a0213df
18 changed files with 766 additions and 713 deletions
@@ -13,8 +13,8 @@ FILE: withInInitializer.kt
super<R|kotlin/Any|>()
}
public final val list: R|kotlin/collections/List<it(kotlin/Comparable<it(kotlin/String & kotlin/Int)> & java/io/Serializable)>| = R|kotlin/collections/listOf|<R|it(kotlin/Comparable<it(kotlin/String & kotlin/Int)> & java/io/Serializable)|>(vararg(Int(1), Int(2), Int(3), String()))
public get(): R|kotlin/collections/List<it(kotlin/Comparable<it(kotlin/String & kotlin/Int)> & java/io/Serializable)>|
public final val list: R|kotlin/collections/List<it(kotlin/Comparable<*> & java/io/Serializable)>| = R|kotlin/collections/listOf|<R|it(kotlin/Comparable<it(kotlin/String & kotlin/Int)> & java/io/Serializable)|>(vararg(Int(1), Int(2), Int(3), String()))
public get(): R|kotlin/collections/List<it(kotlin/Comparable<*> & java/io/Serializable)>|
public final val data: R|First| = R|/First.First|(Int(42))
public get(): R|First|
@@ -235,7 +235,7 @@ class ConeRawType(lowerBound: ConeKotlinType, upperBound: ConeKotlinType) : Cone
*/
class ConeIntersectionType(
val intersectedTypes: Collection<ConeKotlinType>
) : ConeSimpleKotlinType(), TypeConstructorMarker {
) : ConeSimpleKotlinType(), IntersectionTypeConstructorMarker {
override val typeArguments: Array<out ConeTypeProjection>
get() = emptyArray()
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.fir.types
import org.jetbrains.kotlin.fir.diagnostics.ConeIntermediateDiagnostic
import org.jetbrains.kotlin.fir.isPrimitiveNumberOrUnsignedNumberType
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.calls.NoSubstitutor
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
@@ -316,6 +317,11 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
return this.defaultType
}
override fun KotlinTypeMarker.isSpecial(): Boolean {
// TODO
return false
}
override fun TypeConstructorMarker.isTypeVariable(): Boolean {
return this is ConeTypeVariableTypeConstructor
}
@@ -362,4 +368,10 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
require(this is ConeIntegerLiteralType)
return this.getApproximatedType()
}
override fun KotlinTypeMarker.isSignedOrUnsignedNumberType(): Boolean {
require(this is ConeKotlinType)
if (this !is ConeClassLikeType) return false
return isPrimitiveNumberOrUnsignedNumberType()
}
}
@@ -12,29 +12,35 @@ import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.name.ClassId
object PrimitiveTypes {
val Boolean = StandardClassIds.Boolean.createType()
val Char = StandardClassIds.Char.createType()
val Byte = StandardClassIds.Byte.createType()
val Short = StandardClassIds.Short.createType()
val Int = StandardClassIds.Int.createType()
val Long = StandardClassIds.Long.createType()
val Float = StandardClassIds.Float.createType()
val Double = StandardClassIds.Double.createType()
val Boolean: ConeClassLikeType = StandardClassIds.Boolean.createType()
val Char: ConeClassLikeType = StandardClassIds.Char.createType()
val Byte: ConeClassLikeType = StandardClassIds.Byte.createType()
val Short: ConeClassLikeType = StandardClassIds.Short.createType()
val Int: ConeClassLikeType = StandardClassIds.Int.createType()
val Long: ConeClassLikeType = StandardClassIds.Long.createType()
val Float: ConeClassLikeType = StandardClassIds.Float.createType()
val Double: ConeClassLikeType = StandardClassIds.Double.createType()
}
private fun ClassId.createType(): ConeClassLikeType =
ConeClassLikeTypeImpl(ConeClassLikeLookupTagImpl(this), emptyArray(), isNullable = false)
fun ConeClassLikeType.isDouble() = lookupTag.classId == StandardClassIds.Double
fun ConeClassLikeType.isFloat() = lookupTag.classId == StandardClassIds.Float
fun ConeClassLikeType.isLong() = lookupTag.classId == StandardClassIds.Long
fun ConeClassLikeType.isInt() = lookupTag.classId == StandardClassIds.Int
fun ConeClassLikeType.isShort() = lookupTag.classId == StandardClassIds.Short
fun ConeClassLikeType.isByte() = lookupTag.classId == StandardClassIds.Byte
fun ConeClassLikeType.isDouble(): Boolean = lookupTag.classId == StandardClassIds.Double
fun ConeClassLikeType.isFloat(): Boolean = lookupTag.classId == StandardClassIds.Float
fun ConeClassLikeType.isLong(): Boolean = lookupTag.classId == StandardClassIds.Long
fun ConeClassLikeType.isInt(): Boolean = lookupTag.classId == StandardClassIds.Int
fun ConeClassLikeType.isShort(): Boolean = lookupTag.classId == StandardClassIds.Short
fun ConeClassLikeType.isByte(): Boolean = lookupTag.classId == StandardClassIds.Byte
private val PRIMITIVE_NUMBER_CLASS_IDS = setOf(
fun ConeClassLikeType.isPrimitiveNumberType(): Boolean = lookupTag.classId in PRIMITIVE_NUMBER_CLASS_IDS
fun ConeClassLikeType.isPrimitiveUnsignedNumberType(): Boolean = lookupTag.classId in PRIMITIVE_UNSIGNED_NUMBER_CLASS_IDS
fun ConeClassLikeType.isPrimitiveNumberOrUnsignedNumberType(): Boolean = isPrimitiveNumberType() || isPrimitiveUnsignedNumberType()
private val PRIMITIVE_NUMBER_CLASS_IDS: Set<ClassId> = setOf(
StandardClassIds.Double, StandardClassIds.Float, StandardClassIds.Long, StandardClassIds.Int,
StandardClassIds.Short, StandardClassIds.Byte
)
fun ConeClassLikeType.isPrimitiveNumberType() = lookupTag.classId in PRIMITIVE_NUMBER_CLASS_IDS
private val PRIMITIVE_UNSIGNED_NUMBER_CLASS_IDS: Set<ClassId> = setOf(
StandardClassIds.ULong, StandardClassIds.UInt, StandardClassIds.UShort, StandardClassIds.UByte
)
@@ -7,7 +7,8 @@ package org.jetbrains.kotlin.resolve.calls.inference.components
import org.jetbrains.kotlin.resolve.calls.components.CreateFreshVariablesSubstitutor.shouldBeFlexible
import org.jetbrains.kotlin.resolve.calls.inference.model.*
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.AbstractTypeApproximator
import org.jetbrains.kotlin.types.TypeApproximatorConfiguration
import org.jetbrains.kotlin.types.model.*
import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.SmartSet
@@ -0,0 +1,532 @@
/*
* Copyright 2010-2020 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.types
import org.jetbrains.kotlin.resolve.calls.NewCommonSuperTypeCalculator.commonSuperType
import org.jetbrains.kotlin.types.model.*
import java.util.concurrent.ConcurrentHashMap
abstract class AbstractTypeApproximator(val ctx: TypeSystemInferenceExtensionContext) : TypeSystemInferenceExtensionContext by ctx {
private class ApproximationResult(val type: KotlinTypeMarker?)
private val cacheForIncorporationConfigToSuperDirection = ConcurrentHashMap<KotlinTypeMarker, ApproximationResult>()
private val cacheForIncorporationConfigToSubtypeDirection = ConcurrentHashMap<KotlinTypeMarker, ApproximationResult>()
private val referenceApproximateToSuperType: (SimpleTypeMarker, TypeApproximatorConfiguration, Int) -> KotlinTypeMarker?
get() = this::approximateSimpleToSuperType
private val referenceApproximateToSubType: (SimpleTypeMarker, TypeApproximatorConfiguration, Int) -> KotlinTypeMarker?
get() = this::approximateSimpleToSubType
companion object {
const val CACHE_FOR_INCORPORATION_MAX_SIZE = 500
}
abstract fun createErrorType(message: String): SimpleTypeMarker
// null means that this input type is the result, i.e. input type not contains not-allowed kind of types
// type <: resultType
fun approximateToSuperType(type: KotlinTypeMarker, conf: TypeApproximatorConfiguration): KotlinTypeMarker? =
approximateToSuperType(type, conf, -type.typeDepth())
// resultType <: type
fun approximateToSubType(type: KotlinTypeMarker, conf: TypeApproximatorConfiguration): KotlinTypeMarker? =
approximateToSubType(type, conf, -type.typeDepth())
fun clearCache() {
cacheForIncorporationConfigToSubtypeDirection.clear()
cacheForIncorporationConfigToSuperDirection.clear()
}
private fun checkExceptionalCases(
type: KotlinTypeMarker, depth: Int, conf: TypeApproximatorConfiguration, toSuper: Boolean
): ApproximationResult? {
return when {
type.isSpecial() ->
null.toApproximationResult()
type.isError() ->
// todo -- fix builtIns. Now builtIns here is DefaultBuiltIns
(if (conf.errorType) null else type.defaultResult(toSuper)).toApproximationResult()
depth > 3 ->
type.defaultResult(toSuper).toApproximationResult()
else -> null
}
}
private fun KotlinTypeMarker?.toApproximationResult(): ApproximationResult = ApproximationResult(this)
private inline fun cachedValue(
type: KotlinTypeMarker,
conf: TypeApproximatorConfiguration,
toSuper: Boolean,
approximate: () -> KotlinTypeMarker?
): KotlinTypeMarker? {
// Approximator depends on a configuration, so cache should take it into account
// Here, we cache only types for configuration "from incorporation", which is used most intensively
if (conf !is TypeApproximatorConfiguration.IncorporationConfiguration) return approximate()
val cache = if (toSuper) cacheForIncorporationConfigToSuperDirection else cacheForIncorporationConfigToSubtypeDirection
if (cache.size > CACHE_FOR_INCORPORATION_MAX_SIZE) return approximate()
return cache.getOrPut(type, { approximate().toApproximationResult() }).type
}
private fun approximateToSuperType(type: KotlinTypeMarker, conf: TypeApproximatorConfiguration, depth: Int): KotlinTypeMarker? {
checkExceptionalCases(type, depth, conf, toSuper = true)?.let { return it.type }
return cachedValue(type, conf, toSuper = true) {
approximateTo(
prepareType(type), conf, { upperBound() },
referenceApproximateToSuperType, depth
)
}
}
private fun approximateToSubType(type: KotlinTypeMarker, conf: TypeApproximatorConfiguration, depth: Int): KotlinTypeMarker? {
checkExceptionalCases(type, depth, conf, toSuper = false)?.let { return it.type }
return cachedValue(type, conf, toSuper = false) {
approximateTo(
prepareType(type), conf, { lowerBound() },
referenceApproximateToSubType, depth
)
}
}
// Don't call this method directly, it should be used only in approximateToSuperType/approximateToSubType (use these methods instead)
// This method contains detailed implementation only for type approximation, it doesn't check exceptional cases and doesn't use cache
private fun approximateTo(
type: KotlinTypeMarker,
conf: TypeApproximatorConfiguration,
bound: FlexibleTypeMarker.() -> SimpleTypeMarker,
approximateTo: (SimpleTypeMarker, TypeApproximatorConfiguration, depth: Int) -> KotlinTypeMarker?,
depth: Int
): KotlinTypeMarker? {
when (type) {
is SimpleTypeMarker -> return approximateTo(type, conf, depth)
is FlexibleTypeMarker -> {
if (type.isDynamic()) {
return if (conf.dynamic) null else type.bound()
} else if (type.asRawType() != null) {
return if (conf.rawType) null else type.bound()
}
// TODO: Restore check
// TODO: currently we can lose information about enhancement, should be fixed later
// assert(type is FlexibleTypeImpl || type is FlexibleTypeWithEnhancement) {
// "Unexpected subclass of FlexibleType: ${type::class.java.canonicalName}, type = $type"
// }
if (conf.flexible) {
/**
* Let inputType = L_1..U_1; resultType = L_2..U_2
* We should create resultType such as inputType <: resultType.
* It means that if A <: inputType, then A <: U_1. And, because inputType <: resultType,
* A <: resultType => A <: U_2. I.e. for every type A such A <: U_1, A <: U_2 => U_1 <: U_2.
*
* Similar for L_1 <: L_2: Let B : resultType <: B. L_2 <: B and L_1 <: B.
* I.e. for every type B such as L_2 <: B, L_1 <: B. For example B = L_2.
*/
val lowerBound = type.lowerBound()
val upperBound = type.upperBound()
val lowerResult = approximateTo(lowerBound, conf, depth)
val upperResult = if (type !is RawTypeMarker && lowerBound.typeConstructor() == upperBound.typeConstructor())
lowerResult?.withNullability(upperBound.isMarkedNullable())
else
approximateTo(upperBound, conf, depth)
if (lowerResult == null && upperResult == null) return null
/**
* If C <: L..U then C <: L.
* inputType.lower <: lowerResult => inputType.lower <: lowerResult?.lowerIfFlexible()
* i.e. this type is correct. We use this type, because this type more flexible.
*
* If U_1 <: U_2.lower .. U_2.upper, then we know only that U_1 <: U_2.upper.
*/
return createFlexibleType(
lowerResult?.lowerBoundIfFlexible() ?: lowerBound,
upperResult?.upperBoundIfFlexible() ?: upperBound
)
} else {
return type.bound().let { approximateTo(it, conf, depth) ?: it }
}
}
else -> error("sealed")
}
}
private fun isIntersectionTypeEffectivelyNothing(constructor: IntersectionTypeConstructorMarker): Boolean {
// We consider intersection as Nothing only if one of it's component is a primitive number type
// It's intentional we're not trying to prove population of some type as it was in OI
return constructor.supertypes().any {
!it.isMarkedNullable() && it.isSignedOrUnsignedNumberType()
}
}
private fun approximateIntersectionType(
type: SimpleTypeMarker,
conf: TypeApproximatorConfiguration,
toSuper: Boolean,
depth: Int
): KotlinTypeMarker? {
val typeConstructor = type.typeConstructor()
assert(typeConstructor.isIntersection()) {
"Should be intersection type: $type, typeConstructor class: ${typeConstructor::class.java.canonicalName}"
}
assert(typeConstructor.supertypes().isNotEmpty()) {
"Supertypes for intersection type should not be empty: $type"
}
var thereIsApproximation = false
val newTypes = typeConstructor.supertypes().map {
val newType = if (toSuper) approximateToSuperType(it, conf, depth) else approximateToSubType(it, conf, depth)
if (newType != null) {
thereIsApproximation = true
newType
} else it
}
/**
* For case ALLOWED:
* A <: A', B <: B' => A & B <: A' & B'
*
* For other case -- it's impossible to find some type except Nothing as subType for intersection type.
*/
val baseResult = when (conf.intersection) {
TypeApproximatorConfiguration.IntersectionStrategy.ALLOWED -> if (!thereIsApproximation) return null else intersectTypes(newTypes)
TypeApproximatorConfiguration.IntersectionStrategy.TO_FIRST -> if (toSuper) newTypes.first() else return type.defaultResult(toSuper = false)
// commonSupertypeCalculator should handle flexible types correctly
TypeApproximatorConfiguration.IntersectionStrategy.TO_COMMON_SUPERTYPE -> {
if (!toSuper) return type.defaultResult(toSuper = false)
val resultType = commonSuperType(newTypes)
approximateToSuperType(resultType, conf) ?: resultType
}
}
return if (type.isMarkedNullable()) baseResult.withNullability(true) else baseResult
}
private fun approximateCapturedType(
type: CapturedTypeMarker,
conf: TypeApproximatorConfiguration,
toSuper: Boolean,
depth: Int
): KotlinTypeMarker? {
val supertypes = type.typeConstructor().supertypes()
val baseSuperType = when (supertypes.size) {
0 -> nullableAnyType() // Let C = in Int, then superType for C and C? is Any?
1 -> supertypes.single()
// Consider the following example:
// A.getA()::class.java, where `getA()` returns some class from Java
// From `::class` we are getting type KClass<Cap<out A!>>, where Cap<out A!> have two supertypes:
// - Any (from declared upper bound of type parameter for KClass)
// - (A..A?) -- from A!, projection type of captured type
// Now, after approximation we were getting type `KClass<out A>`, because { Any & (A..A?) } = A,
// but in old inference type was equal to `KClass<out A!>`.
// Important note that from the point of type system first type is more specific:
// Here, approximation of KClass<Cap<out A!>> is a type KClass<T> such that KClass<Cap<out A!>> <: KClass<out T> =>
// So, the the more specific type for T would be "some non-null (because of declared upper bound type) subtype of A", which is `out A`
// But for now, to reduce differences in behaviour of old and new inference, we'll approximate such types to `KClass<out A!>`
// Once NI will be more stabilized, we'll use more specific type
else -> {
val projection = type.typeConstructorProjection()
if (projection.isStarProjection()) intersectTypes(supertypes.toList())
else projection.getType()
}
}
val baseSubType = type.lowerType() ?: nothingType()
if (conf.capturedType(ctx, type)) {
/**
* Here everything is ok if bounds for this captured type should not be approximated.
* But. If such bounds contains some unauthorized types, then we cannot leave this captured type "as is".
* And we cannot create new capture type, because meaning of new captured type is not clear.
* So, we will just approximate such types
*
* todo handle flexible types
*/
if (approximateToSuperType(baseSuperType, conf, depth) == null && approximateToSubType(baseSubType, conf, depth) == null) {
return null
}
}
val baseResult = if (toSuper) approximateToSuperType(baseSuperType, conf, depth) ?: baseSuperType else approximateToSubType(
baseSubType,
conf,
depth
) ?: baseSubType
// C = in Int, Int <: C => Int? <: C?
// C = out Number, C <: Number => C? <: Number?
return when {
type.isMarkedNullable() -> baseResult.withNullability(true)
type.isProjectionNotNull() -> baseResult.withNullability(false)
else -> baseResult
}
}
private fun approximateSimpleToSuperType(type: SimpleTypeMarker, conf: TypeApproximatorConfiguration, depth: Int) =
approximateTo(type, conf, toSuper = true, depth = depth)
private fun approximateSimpleToSubType(type: SimpleTypeMarker, conf: TypeApproximatorConfiguration, depth: Int) =
approximateTo(type, conf, toSuper = false, depth = depth)
private fun approximateTo(
type: SimpleTypeMarker,
conf: TypeApproximatorConfiguration,
toSuper: Boolean,
depth: Int
): KotlinTypeMarker? {
if (type.argumentsCount() != 0) {
return approximateParametrizedType(type, conf, toSuper, depth + 1)
}
val definitelyNotNullType = type.asDefinitelyNotNullType()
if (definitelyNotNullType != null) {
return approximateDefinitelyNotNullType(definitelyNotNullType, conf, toSuper, depth)
}
val typeConstructor = type.typeConstructor()
if (typeConstructor.isCapturedTypeConstructor()) {
val capturedType = type.asCapturedType()
require(capturedType != null) {
// KT-16147
"Type is inconsistent -- somewhere we create type with typeConstructor = $typeConstructor " +
"and class: ${type::class.java.canonicalName}. type.toString() = $type"
}
return approximateCapturedType(capturedType, conf, toSuper, depth)
}
if (typeConstructor.isIntersection()) {
return approximateIntersectionType(type, conf, toSuper, depth)
}
if (typeConstructor is TypeVariableTypeConstructorMarker) {
return if (conf.typeVariable(typeConstructor)) null else type.defaultResult(toSuper)
}
if (typeConstructor.isIntegerLiteralTypeConstructor()) {
return if (conf.integerLiteralType)
typeConstructor.getApproximatedIntegerLiteralType().withNullability(type.isMarkedNullable())
else
null
}
return null // simple classifier type
}
private fun approximateDefinitelyNotNullType(
type: DefinitelyNotNullTypeMarker,
conf: TypeApproximatorConfiguration,
toSuper: Boolean,
depth: Int
): KotlinTypeMarker? {
val originalType = type.original()
val approximatedOriginalType =
if (toSuper) approximateToSuperType(originalType, conf, depth) else approximateToSubType(originalType, conf, depth)
return if (conf.definitelyNotNullType) {
approximatedOriginalType?.makeDefinitelyNotNullOrNotNull()
} else {
if (toSuper)
(approximatedOriginalType ?: originalType).withNullability(false)
else
type.defaultResult(toSuper)
}
}
private fun isApproximateDirectionToSuper(effectiveVariance: TypeVariance, toSuper: Boolean) =
when (effectiveVariance) {
TypeVariance.OUT -> toSuper
TypeVariance.IN -> !toSuper
TypeVariance.INV -> throw AssertionError("Incorrect variance $effectiveVariance")
}
private fun approximateParametrizedType(
type: SimpleTypeMarker,
conf: TypeApproximatorConfiguration,
toSuper: Boolean,
depth: Int
): SimpleTypeMarker? {
val typeConstructor = type.typeConstructor()
if (typeConstructor.parametersCount() != type.argumentsCount()) {
return if (conf.errorType) {
createErrorType("Inconsistent type: $type (parameters.size = ${typeConstructor.parametersCount()}, arguments.size = ${type.argumentsCount()})")
} else type.defaultResult(toSuper)
}
val newArguments = arrayOfNulls<TypeArgumentMarker?>(type.argumentsCount())
loop@ for (index in 0 until type.argumentsCount()) {
val parameter = typeConstructor.getParameter(index)
val argument = type.getArgument(index)
if (argument.isStarProjection()) continue
val effectiveVariance = AbstractTypeChecker.effectiveVariance(parameter.getVariance(), argument.getVariance())
val argumentType = newArguments[index]?.getType() ?: argument.getType()
val capturedType = argumentType.lowerBoundIfFlexible().asCapturedType()
val capturedStarProjectionOrNull =
capturedType?.typeConstructorProjection()?.takeIf { it.isStarProjection() }
if (capturedStarProjectionOrNull != null &&
(effectiveVariance == TypeVariance.OUT || effectiveVariance == TypeVariance.INV) &&
toSuper &&
capturedType.typeParameter() == parameter
) {
newArguments[index] = capturedStarProjectionOrNull
continue@loop
}
when (effectiveVariance) {
null -> {
return if (conf.errorType) {
createErrorType(
"Inconsistent type: $type ($index parameter has declared variance: ${parameter.getVariance()}, " +
"but argument variance is ${argument.getVariance()})"
)
} else type.defaultResult(toSuper)
}
TypeVariance.OUT, TypeVariance.IN -> {
if (
conf.intersectionTypesInContravariantPositions &&
effectiveVariance == TypeVariance.IN &&
argumentType.typeConstructor().isIntersection()
) {
val argumentTypeConstructor = argumentType.typeConstructor()
if (argumentTypeConstructor.isIntersection() && isIntersectionTypeEffectivelyNothing(argumentTypeConstructor as IntersectionTypeConstructorMarker)) {
newArguments[index] = createStarProjection(parameter)
continue@loop
}
}
/**
* Out<Foo> <: Out<superType(Foo)>
* Inv<out Foo> <: Inv<out superType(Foo)>
* In<Foo> <: In<subType(Foo)>
* Inv<in Foo> <: Inv<in subType(Foo)>
*/
val approximatedArgument = argumentType.let {
if (isApproximateDirectionToSuper(effectiveVariance, toSuper)) {
approximateToSuperType(it, conf, depth)
} else {
approximateToSubType(it, conf, depth)
}
} ?: continue@loop
if (
conf.intersection != TypeApproximatorConfiguration.IntersectionStrategy.ALLOWED &&
effectiveVariance == TypeVariance.OUT &&
argumentType.typeConstructor().isIntersection()
) {
var shouldReplaceWithStar = false
for (upperBoundIndex in 0 until parameter.upperBoundCount()) {
if (!AbstractTypeChecker.isSubtypeOf(ctx, approximatedArgument, parameter.getUpperBound(upperBoundIndex))) {
shouldReplaceWithStar = true
break
}
}
if (shouldReplaceWithStar) {
newArguments[index] = createStarProjection(parameter)
continue@loop
}
}
if (parameter.getVariance() == TypeVariance.INV) {
newArguments[index] = createTypeArgument(approximatedArgument, effectiveVariance)
} else {
newArguments[index] = approximatedArgument.asTypeArgument()
}
}
TypeVariance.INV -> {
if (!toSuper) {
// Inv<Foo> cannot be approximated to subType
val toSubType = approximateToSubType(argumentType, conf, depth) ?: continue@loop
// Inv<Foo!> is supertype for Inv<Foo?>
if (!AbstractTypeChecker.equalTypes(
this,
argumentType,
toSubType
)
) return type.defaultResult(toSuper)
// also Captured(out Nothing) = Nothing
newArguments[index] = toSubType.asTypeArgument()
continue@loop
}
/**
* Example with non-trivial both type approximations:
* Inv<In<C>> where C = in Int
* Inv<In<C>> <: Inv<out In<Int>>
* Inv<In<C>> <: Inv<in In<Any?>>
*
* So such case is rare and we will chose Inv<out In<Int>> for now.
*
* Note that for case Inv<C> we will chose Inv<in Int>, because it is more informative then Inv<out Any?>.
* May be we should do the same for deeper types, but not now.
*/
if (argumentType.typeConstructor().isCapturedTypeConstructor()) {
val subType = approximateToSubType(argumentType, conf, depth) ?: continue@loop
if (!subType.isTrivialSub()) {
newArguments[index] = createTypeArgument(subType, TypeVariance.IN)
continue@loop
}
}
val approximatedSuperType =
approximateToSuperType(argumentType, conf, depth) ?: continue@loop // null means that this type we can leave as is
if (approximatedSuperType.isTrivialSuper()) {
val approximatedSubType =
approximateToSubType(argumentType, conf, depth) ?: continue@loop // seems like this is never null
if (!approximatedSubType.isTrivialSub()) {
newArguments[index] = createTypeArgument(approximatedSubType, TypeVariance.IN)
continue@loop
}
}
if (AbstractTypeChecker.equalTypes(this, argumentType, approximatedSuperType)) {
newArguments[index] = approximatedSuperType.asTypeArgument()
} else {
newArguments[index] = createTypeArgument(approximatedSuperType, TypeVariance.OUT)
}
}
}
}
if (newArguments.all { it == null }) return null
val newArgumentsList = List(type.argumentsCount()) { index -> newArguments[index] ?: type.getArgument(index) }
return type.replaceArguments(newArgumentsList)
}
private fun KotlinTypeMarker.defaultResult(toSuper: Boolean) = if (toSuper) nullableAnyType() else {
if (this is SimpleTypeMarker && isMarkedNullable()) nullableNothingType() else nothingType()
}
// Any? or Any!
private fun KotlinTypeMarker.isTrivialSuper() = upperBoundIfFlexible().isNullableAny()
// Nothing or Nothing!
private fun KotlinTypeMarker.isTrivialSub() = lowerBoundIfFlexible().isNothing()
}
@@ -19,97 +19,8 @@ package org.jetbrains.kotlin.types
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.resolve.calls.NewCommonSuperTypeCalculator
import org.jetbrains.kotlin.resolve.calls.components.ClassicTypeSystemContextForCS
import org.jetbrains.kotlin.types.TypeApproximatorConfiguration.IntersectionStrategy.*
import org.jetbrains.kotlin.types.checker.NewCapturedTypeConstructor
import org.jetbrains.kotlin.types.model.*
import org.jetbrains.kotlin.types.model.CaptureStatus.*
import org.jetbrains.kotlin.types.typeUtil.isSignedOrUnsignedNumberType
import java.util.concurrent.ConcurrentHashMap
open class TypeApproximatorConfiguration {
enum class IntersectionStrategy {
ALLOWED,
TO_FIRST,
TO_COMMON_SUPERTYPE
}
open val flexible get() = false // simple flexible types (FlexibleTypeImpl)
open val dynamic get() = false // DynamicType
open val rawType get() = false // RawTypeImpl
open val errorType get() = false
open val integerLiteralType: Boolean = false // IntegerLiteralTypeConstructor
open val definitelyNotNullType get() = true
open val intersection: IntersectionStrategy = TO_COMMON_SUPERTYPE
open val intersectionTypesInContravariantPositions = false
open val typeVariable: (TypeVariableTypeConstructorMarker) -> Boolean = { false }
open fun capturedType(ctx: TypeSystemInferenceExtensionContext, type: CapturedTypeMarker): Boolean =
false // true means that this type we can leave as is
abstract class AllFlexibleSameValue : TypeApproximatorConfiguration() {
abstract val allFlexible: Boolean
override val flexible get() = allFlexible
override val dynamic get() = allFlexible
override val rawType get() = allFlexible
}
object LocalDeclaration : AllFlexibleSameValue() {
override val allFlexible get() = true
override val intersection get() = ALLOWED
override val errorType get() = true
override val integerLiteralType: Boolean get() = true
override val intersectionTypesInContravariantPositions: Boolean get() = true
}
object PublicDeclaration : AllFlexibleSameValue() {
override val allFlexible get() = true
override val errorType get() = true
override val definitelyNotNullType get() = false
override val integerLiteralType: Boolean get() = true
override val intersectionTypesInContravariantPositions: Boolean get() = true
}
abstract class AbstractCapturedTypesApproximation(val approximatedCapturedStatus: CaptureStatus) :
TypeApproximatorConfiguration.AllFlexibleSameValue() {
override val allFlexible get() = true
override val errorType get() = true
// i.e. will be approximated only approximatedCapturedStatus captured types
override fun capturedType(ctx: TypeSystemInferenceExtensionContext, type: CapturedTypeMarker): Boolean =
type.captureStatus(ctx) != approximatedCapturedStatus
override val intersection get() = ALLOWED
override val typeVariable: (TypeVariableTypeConstructorMarker) -> Boolean get() = { true }
}
object IncorporationConfiguration : TypeApproximatorConfiguration.AbstractCapturedTypesApproximation(FOR_INCORPORATION)
object SubtypeCapturedTypesApproximation : TypeApproximatorConfiguration.AbstractCapturedTypesApproximation(FOR_SUBTYPING)
object InternalTypesApproximation : TypeApproximatorConfiguration.AbstractCapturedTypesApproximation(FROM_EXPRESSION) {
override val integerLiteralType: Boolean get() = true
override val intersectionTypesInContravariantPositions: Boolean get() = true
}
object FinalApproximationAfterResolutionAndInference :
TypeApproximatorConfiguration.AbstractCapturedTypesApproximation(FROM_EXPRESSION) {
override val integerLiteralType: Boolean get() = true
override val intersectionTypesInContravariantPositions: Boolean get() = true
}
object IntegerLiteralsTypesApproximation : TypeApproximatorConfiguration.AllFlexibleSameValue() {
override val integerLiteralType: Boolean get() = true
override val allFlexible: Boolean get() = true
override val intersection get() = ALLOWED
override val typeVariable: (TypeVariableTypeConstructorMarker) -> Boolean get() = { true }
override val errorType: Boolean get() = true
override fun capturedType(ctx: TypeSystemInferenceExtensionContext, type: CapturedTypeMarker): Boolean = true
}
}
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
class TypeApproximator(builtIns: KotlinBuiltIns) : AbstractTypeApproximator(ClassicTypeSystemContextForCS(builtIns)) {
fun approximateDeclarationType(baseType: KotlinType, local: Boolean, languageVersionSettings: LanguageVersionSettings): UnwrappedType {
@@ -128,524 +39,9 @@ class TypeApproximator(builtIns: KotlinBuiltIns) : AbstractTypeApproximator(Clas
// resultType <: type
fun approximateToSubType(type: UnwrappedType, conf: TypeApproximatorConfiguration): UnwrappedType? =
super.approximateToSubType(type, conf) as UnwrappedType?
override fun createErrorType(message: String): SimpleTypeMarker {
return ErrorUtils.createErrorType(message)
}
}
abstract class AbstractTypeApproximator(val ctx: TypeSystemInferenceExtensionContext) : TypeSystemInferenceExtensionContext by ctx {
private class ApproximationResult(val type: KotlinTypeMarker?)
private val cacheForIncorporationConfigToSuperDirection = ConcurrentHashMap<KotlinTypeMarker, ApproximationResult>()
private val cacheForIncorporationConfigToSubtypeDirection = ConcurrentHashMap<KotlinTypeMarker, ApproximationResult>()
private val referenceApproximateToSuperType get() = this::approximateSimpleToSuperType
private val referenceApproximateToSubType get() = this::approximateSimpleToSubType
companion object {
const val CACHE_FOR_INCORPORATION_MAX_SIZE = 500
}
open fun createErrorType(message: String): SimpleTypeMarker =
ErrorUtils.createErrorType(message)
// null means that this input type is the result, i.e. input type not contains not-allowed kind of types
// type <: resultType
fun approximateToSuperType(type: KotlinTypeMarker, conf: TypeApproximatorConfiguration): KotlinTypeMarker? =
approximateToSuperType(type, conf, -type.typeDepth())
// resultType <: type
fun approximateToSubType(type: KotlinTypeMarker, conf: TypeApproximatorConfiguration): KotlinTypeMarker? =
approximateToSubType(type, conf, -type.typeDepth())
fun clearCache() {
cacheForIncorporationConfigToSubtypeDirection.clear()
cacheForIncorporationConfigToSuperDirection.clear()
}
private fun checkExceptionalCases(
type: KotlinTypeMarker, depth: Int, conf: TypeApproximatorConfiguration, toSuper: Boolean
): ApproximationResult? {
return when {
type is TypeUtils.SpecialType ->
null.toApproximationResult()
type.isError() ->
// todo -- fix builtIns. Now builtIns here is DefaultBuiltIns
(if (conf.errorType) null else type.defaultResult(toSuper)).toApproximationResult()
depth > 3 ->
type.defaultResult(toSuper).toApproximationResult()
else -> null
}
}
private fun KotlinTypeMarker?.toApproximationResult(): ApproximationResult = ApproximationResult(this)
private inline fun cachedValue(
type: KotlinTypeMarker,
conf: TypeApproximatorConfiguration,
toSuper: Boolean,
approximate: () -> KotlinTypeMarker?
): KotlinTypeMarker? {
// Approximator depends on a configuration, so cache should take it into account
// Here, we cache only types for configuration "from incorporation", which is used most intensively
if (conf !is TypeApproximatorConfiguration.IncorporationConfiguration) return approximate()
val cache = if (toSuper) cacheForIncorporationConfigToSuperDirection else cacheForIncorporationConfigToSubtypeDirection
if (cache.size > CACHE_FOR_INCORPORATION_MAX_SIZE) return approximate()
return cache.getOrPut(type, { approximate().toApproximationResult() }).type
}
private fun approximateToSuperType(type: KotlinTypeMarker, conf: TypeApproximatorConfiguration, depth: Int): KotlinTypeMarker? {
checkExceptionalCases(type, depth, conf, toSuper = true)?.let { return it.type }
return cachedValue(type, conf, toSuper = true) {
approximateTo(
prepareType(type), conf, { upperBound() },
referenceApproximateToSuperType, depth
)
}
}
private fun approximateToSubType(type: KotlinTypeMarker, conf: TypeApproximatorConfiguration, depth: Int): KotlinTypeMarker? {
checkExceptionalCases(type, depth, conf, toSuper = false)?.let { return it.type }
return cachedValue(type, conf, toSuper = false) {
approximateTo(
prepareType(type), conf, { lowerBound() },
referenceApproximateToSubType, depth
)
}
}
// Don't call this method directly, it should be used only in approximateToSuperType/approximateToSubType (use these methods instead)
// This method contains detailed implementation only for type approximation, it doesn't check exceptional cases and doesn't use cache
private fun approximateTo(
type: KotlinTypeMarker,
conf: TypeApproximatorConfiguration,
bound: FlexibleTypeMarker.() -> SimpleTypeMarker,
approximateTo: (SimpleTypeMarker, TypeApproximatorConfiguration, depth: Int) -> KotlinTypeMarker?,
depth: Int
): KotlinTypeMarker? {
when (type) {
is SimpleTypeMarker -> return approximateTo(type, conf, depth)
is FlexibleTypeMarker -> {
if (type.isDynamic()) {
return if (conf.dynamic) null else type.bound()
} else if (type.asRawType() != null) {
return if (conf.rawType) null else type.bound()
}
// TODO: Restore check
// TODO: currently we can lose information about enhancement, should be fixed later
// assert(type is FlexibleTypeImpl || type is FlexibleTypeWithEnhancement) {
// "Unexpected subclass of FlexibleType: ${type::class.java.canonicalName}, type = $type"
// }
if (conf.flexible) {
/**
* Let inputType = L_1..U_1; resultType = L_2..U_2
* We should create resultType such as inputType <: resultType.
* It means that if A <: inputType, then A <: U_1. And, because inputType <: resultType,
* A <: resultType => A <: U_2. I.e. for every type A such A <: U_1, A <: U_2 => U_1 <: U_2.
*
* Similar for L_1 <: L_2: Let B : resultType <: B. L_2 <: B and L_1 <: B.
* I.e. for every type B such as L_2 <: B, L_1 <: B. For example B = L_2.
*/
val lowerBound = type.lowerBound()
val upperBound = type.upperBound()
val lowerResult = approximateTo(lowerBound, conf, depth)
val upperResult = if (type !is RawTypeMarker && lowerBound.typeConstructor() == upperBound.typeConstructor())
lowerResult?.withNullability(upperBound.isMarkedNullable())
else
approximateTo(upperBound, conf, depth)
if (lowerResult == null && upperResult == null) return null
/**
* If C <: L..U then C <: L.
* inputType.lower <: lowerResult => inputType.lower <: lowerResult?.lowerIfFlexible()
* i.e. this type is correct. We use this type, because this type more flexible.
*
* If U_1 <: U_2.lower .. U_2.upper, then we know only that U_1 <: U_2.upper.
*/
return createFlexibleType(
lowerResult?.lowerBoundIfFlexible() ?: lowerBound,
upperResult?.upperBoundIfFlexible() ?: upperBound
)
} else {
return type.bound().let { approximateTo(it, conf, depth) ?: it }
}
}
else -> error("sealed")
}
}
private fun isIntersectionTypeEffectivelyNothing(constructor: IntersectionTypeConstructor): Boolean {
// We consider intersection as Nothing only if one of it's component is a primitive number type
// It's intentional we're not trying to prove population of some type as it was in OI
return constructor.supertypes.any { !it.isMarkedNullable && it.isSignedOrUnsignedNumberType() }
}
private fun approximateIntersectionType(
type: SimpleTypeMarker,
conf: TypeApproximatorConfiguration,
toSuper: Boolean,
depth: Int
): KotlinTypeMarker? {
val typeConstructor = type.typeConstructor()
assert(typeConstructor.isIntersection()) {
"Should be intersection type: $type, typeConstructor class: ${typeConstructor::class.java.canonicalName}"
}
assert(typeConstructor.supertypes().isNotEmpty()) {
"Supertypes for intersection type should not be empty: $type"
}
var thereIsApproximation = false
val newTypes = typeConstructor.supertypes().map {
val newType = if (toSuper) approximateToSuperType(it, conf, depth) else approximateToSubType(it, conf, depth)
if (newType != null) {
thereIsApproximation = true
newType
} else it
}
/**
* For case ALLOWED:
* A <: A', B <: B' => A & B <: A' & B'
*
* For other case -- it's impossible to find some type except Nothing as subType for intersection type.
*/
val baseResult = when (conf.intersection) {
ALLOWED -> if (!thereIsApproximation) return null else intersectTypes(newTypes)
TO_FIRST -> if (toSuper) newTypes.first() else return type.defaultResult(toSuper = false)
// commonSupertypeCalculator should handle flexible types correctly
TO_COMMON_SUPERTYPE -> {
if (!toSuper) return type.defaultResult(toSuper = false)
val resultType = with(NewCommonSuperTypeCalculator) { commonSuperType(newTypes) }
approximateToSuperType(resultType, conf) ?: resultType
}
}
return if (type.isMarkedNullable()) baseResult.withNullability(true) else baseResult
}
private fun approximateCapturedType(
type: CapturedTypeMarker,
conf: TypeApproximatorConfiguration,
toSuper: Boolean,
depth: Int
): KotlinTypeMarker? {
val supertypes = type.typeConstructor().supertypes()
val baseSuperType = when (supertypes.size) {
0 -> nullableAnyType() // Let C = in Int, then superType for C and C? is Any?
1 -> supertypes.single()
// Consider the following example:
// A.getA()::class.java, where `getA()` returns some class from Java
// From `::class` we are getting type KClass<Cap<out A!>>, where Cap<out A!> have two supertypes:
// - Any (from declared upper bound of type parameter for KClass)
// - (A..A?) -- from A!, projection type of captured type
// Now, after approximation we were getting type `KClass<out A>`, because { Any & (A..A?) } = A,
// but in old inference type was equal to `KClass<out A!>`.
// Important note that from the point of type system first type is more specific:
// Here, approximation of KClass<Cap<out A!>> is a type KClass<T> such that KClass<Cap<out A!>> <: KClass<out T> =>
// So, the the more specific type for T would be "some non-null (because of declared upper bound type) subtype of A", which is `out A`
// But for now, to reduce differences in behaviour of old and new inference, we'll approximate such types to `KClass<out A!>`
// Once NI will be more stabilized, we'll use more specific type
else -> {
val projection = type.typeConstructorProjection()
if (projection.isStarProjection()) intersectTypes(supertypes.toList())
else projection.getType()
}
}
val baseSubType = type.lowerType() ?: nothingType()
if (conf.capturedType(ctx, type)) {
/**
* Here everything is ok if bounds for this captured type should not be approximated.
* But. If such bounds contains some unauthorized types, then we cannot leave this captured type "as is".
* And we cannot create new capture type, because meaning of new captured type is not clear.
* So, we will just approximate such types
*
* todo handle flexible types
*/
if (approximateToSuperType(baseSuperType, conf, depth) == null && approximateToSubType(baseSubType, conf, depth) == null) {
return null
}
}
val baseResult = if (toSuper) approximateToSuperType(baseSuperType, conf, depth) ?: baseSuperType else approximateToSubType(
baseSubType,
conf,
depth
) ?: baseSubType
// C = in Int, Int <: C => Int? <: C?
// C = out Number, C <: Number => C? <: Number?
return when {
type.isMarkedNullable() -> baseResult.withNullability(true)
type.isProjectionNotNull() -> baseResult.withNullability(false)
else -> baseResult
}
}
private fun approximateSimpleToSuperType(type: SimpleTypeMarker, conf: TypeApproximatorConfiguration, depth: Int) =
approximateTo(type, conf, toSuper = true, depth = depth)
private fun approximateSimpleToSubType(type: SimpleTypeMarker, conf: TypeApproximatorConfiguration, depth: Int) =
approximateTo(type, conf, toSuper = false, depth = depth)
private fun approximateTo(
type: SimpleTypeMarker,
conf: TypeApproximatorConfiguration,
toSuper: Boolean,
depth: Int
): KotlinTypeMarker? {
if (type.argumentsCount() != 0) {
return approximateParametrizedType(type, conf, toSuper, depth + 1)
}
val definitelyNotNullType = type.asDefinitelyNotNullType()
if (definitelyNotNullType != null) {
return approximateDefinitelyNotNullType(definitelyNotNullType, conf, toSuper, depth)
}
val typeConstructor = type.typeConstructor()
if (typeConstructor.isCapturedTypeConstructor()) {
val capturedType = type.asCapturedType()
require(capturedType != null) {
// KT-16147
"Type is inconsistent -- somewhere we create type with typeConstructor = $typeConstructor " +
"and class: ${type::class.java.canonicalName}. type.toString() = $type"
}
return approximateCapturedType(capturedType, conf, toSuper, depth)
}
if (typeConstructor.isIntersection()) {
return approximateIntersectionType(type, conf, toSuper, depth)
}
if (typeConstructor is TypeVariableTypeConstructorMarker) {
return if (conf.typeVariable(typeConstructor)) null else type.defaultResult(toSuper)
}
if (typeConstructor.isIntegerLiteralTypeConstructor()) {
return if (conf.integerLiteralType)
typeConstructor.getApproximatedIntegerLiteralType().withNullability(type.isMarkedNullable())
else
null
}
return null // simple classifier type
}
private fun approximateDefinitelyNotNullType(
type: DefinitelyNotNullTypeMarker,
conf: TypeApproximatorConfiguration,
toSuper: Boolean,
depth: Int
): KotlinTypeMarker? {
val originalType = type.original()
val approximatedOriginalType =
if (toSuper) approximateToSuperType(originalType, conf, depth) else approximateToSubType(originalType, conf, depth)
return if (conf.definitelyNotNullType) {
approximatedOriginalType?.makeDefinitelyNotNullOrNotNull()
} else {
if (toSuper)
(approximatedOriginalType ?: originalType).withNullability(false)
else
type.defaultResult(toSuper)
}
}
private fun isApproximateDirectionToSuper(effectiveVariance: TypeVariance, toSuper: Boolean) =
when (effectiveVariance) {
TypeVariance.OUT -> toSuper
TypeVariance.IN -> !toSuper
TypeVariance.INV -> throw AssertionError("Incorrect variance $effectiveVariance")
}
private fun approximateParametrizedType(
type: SimpleTypeMarker,
conf: TypeApproximatorConfiguration,
toSuper: Boolean,
depth: Int
): SimpleTypeMarker? {
val typeConstructor = type.typeConstructor()
if (typeConstructor.parametersCount() != type.argumentsCount()) {
return if (conf.errorType) {
createErrorType("Inconsistent type: $type (parameters.size = ${typeConstructor.parametersCount()}, arguments.size = ${type.argumentsCount()})")
} else type.defaultResult(toSuper)
}
val newArguments = arrayOfNulls<TypeArgumentMarker?>(type.argumentsCount())
loop@ for (index in 0 until type.argumentsCount()) {
val parameter = typeConstructor.getParameter(index)
val argument = type.getArgument(index)
if (argument.isStarProjection()) continue
val effectiveVariance = AbstractTypeChecker.effectiveVariance(parameter.getVariance(), argument.getVariance())
val argumentType = newArguments[index]?.getType() ?: argument.getType()
val capturedType = argumentType.lowerBoundIfFlexible().asCapturedType()
val capturedStarProjectionOrNull =
capturedType?.typeConstructorProjection()?.takeIf { it.isStarProjection() }
if (capturedStarProjectionOrNull != null &&
(effectiveVariance == TypeVariance.OUT || effectiveVariance == TypeVariance.INV) &&
toSuper &&
capturedType.typeParameter() == parameter
) {
newArguments[index] = capturedStarProjectionOrNull
continue@loop
}
when (effectiveVariance) {
null -> {
return if (conf.errorType) {
createErrorType(
"Inconsistent type: $type ($index parameter has declared variance: ${parameter.getVariance()}, " +
"but argument variance is ${argument.getVariance()})"
)
} else type.defaultResult(toSuper)
}
TypeVariance.OUT, TypeVariance.IN -> {
if (
conf.intersectionTypesInContravariantPositions &&
effectiveVariance == TypeVariance.IN &&
argumentType.typeConstructor().isIntersection()
) {
val intersectionTypeConstructor = argumentType.typeConstructor() as? IntersectionTypeConstructor
if (intersectionTypeConstructor != null && isIntersectionTypeEffectivelyNothing(intersectionTypeConstructor)) {
newArguments[index] = createStarProjection(parameter)
continue@loop
}
}
/**
* Out<Foo> <: Out<superType(Foo)>
* Inv<out Foo> <: Inv<out superType(Foo)>
* In<Foo> <: In<subType(Foo)>
* Inv<in Foo> <: Inv<in subType(Foo)>
*/
val approximatedArgument = argumentType.let {
if (isApproximateDirectionToSuper(effectiveVariance, toSuper)) {
approximateToSuperType(it, conf, depth)
} else {
approximateToSubType(it, conf, depth)
}
} ?: continue@loop
if (
conf.intersection != ALLOWED &&
effectiveVariance == TypeVariance.OUT &&
argumentType.typeConstructor().isIntersection()
) {
var shouldReplaceWithStar = false
for (upperBoundIndex in 0 until parameter.upperBoundCount()) {
if (!AbstractTypeChecker.isSubtypeOf(ctx, approximatedArgument, parameter.getUpperBound(upperBoundIndex))) {
shouldReplaceWithStar = true
break
}
}
if (shouldReplaceWithStar) {
newArguments[index] = createStarProjection(parameter)
continue@loop
}
}
if (parameter.getVariance() == TypeVariance.INV) {
newArguments[index] = createTypeArgument(approximatedArgument, effectiveVariance)
} else {
newArguments[index] = approximatedArgument.asTypeArgument()
}
}
TypeVariance.INV -> {
if (!toSuper) {
// Inv<Foo> cannot be approximated to subType
val toSubType = approximateToSubType(argumentType, conf, depth) ?: continue@loop
// Inv<Foo!> is supertype for Inv<Foo?>
if (!AbstractTypeChecker.equalTypes(
this,
argumentType,
toSubType
)
) return type.defaultResult(toSuper)
// also Captured(out Nothing) = Nothing
newArguments[index] = toSubType.asTypeArgument()
continue@loop
}
/**
* Example with non-trivial both type approximations:
* Inv<In<C>> where C = in Int
* Inv<In<C>> <: Inv<out In<Int>>
* Inv<In<C>> <: Inv<in In<Any?>>
*
* So such case is rare and we will chose Inv<out In<Int>> for now.
*
* Note that for case Inv<C> we will chose Inv<in Int>, because it is more informative then Inv<out Any?>.
* May be we should do the same for deeper types, but not now.
*/
if (argumentType.typeConstructor() is NewCapturedTypeConstructor) {
val subType = approximateToSubType(argumentType, conf, depth) ?: continue@loop
if (!subType.isTrivialSub()) {
newArguments[index] = createTypeArgument(subType, TypeVariance.IN)
continue@loop
}
}
val approximatedSuperType =
approximateToSuperType(argumentType, conf, depth) ?: continue@loop // null means that this type we can leave as is
if (approximatedSuperType.isTrivialSuper()) {
val approximatedSubType =
approximateToSubType(argumentType, conf, depth) ?: continue@loop // seems like this is never null
if (!approximatedSubType.isTrivialSub()) {
newArguments[index] = createTypeArgument(approximatedSubType, TypeVariance.IN)
continue@loop
}
}
if (AbstractTypeChecker.equalTypes(this, argumentType, approximatedSuperType)) {
newArguments[index] = approximatedSuperType.asTypeArgument()
} else {
newArguments[index] = createTypeArgument(approximatedSuperType, TypeVariance.OUT)
}
}
}
}
if (newArguments.all { it == null }) return null
val newArgumentsList = List(type.argumentsCount()) { index -> newArguments[index] ?: type.getArgument(index) }
return type.replaceArguments(newArgumentsList)
}
private fun KotlinTypeMarker.defaultResult(toSuper: Boolean) = if (toSuper) nullableAnyType() else {
if (this is SimpleTypeMarker && isMarkedNullable()) nullableNothingType() else nothingType()
}
// Any? or Any!
private fun KotlinTypeMarker.isTrivialSuper() = upperBoundIfFlexible().isNullableAny()
// Nothing or Nothing!
private fun KotlinTypeMarker.isTrivialSub() = lowerBoundIfFlexible().isNothing()
}
@@ -0,0 +1,89 @@
/*
* Copyright 2010-2020 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.types
import org.jetbrains.kotlin.types.model.*
open class TypeApproximatorConfiguration {
enum class IntersectionStrategy {
ALLOWED,
TO_FIRST,
TO_COMMON_SUPERTYPE
}
open val flexible: Boolean get() = false // simple flexible types (FlexibleTypeImpl)
open val dynamic: Boolean get() = false // DynamicType
open val rawType: Boolean get() = false // RawTypeImpl
open val errorType: Boolean get() = false
open val integerLiteralType: Boolean = false // IntegerLiteralTypeConstructor
open val definitelyNotNullType: Boolean get() = true
open val intersection: IntersectionStrategy = IntersectionStrategy.TO_COMMON_SUPERTYPE
open val intersectionTypesInContravariantPositions = false
open val typeVariable: (TypeVariableTypeConstructorMarker) -> Boolean = { false }
open fun capturedType(ctx: TypeSystemInferenceExtensionContext, type: CapturedTypeMarker): Boolean =
false // true means that this type we can leave as is
abstract class AllFlexibleSameValue : TypeApproximatorConfiguration() {
abstract val allFlexible: Boolean
override val flexible: Boolean get() = allFlexible
override val dynamic: Boolean get() = allFlexible
override val rawType: Boolean get() = allFlexible
}
object LocalDeclaration : AllFlexibleSameValue() {
override val allFlexible: Boolean get() = true
override val intersection: IntersectionStrategy get() = IntersectionStrategy.ALLOWED
override val errorType: Boolean get() = true
override val integerLiteralType: Boolean get() = true
override val intersectionTypesInContravariantPositions: Boolean get() = true
}
object PublicDeclaration : AllFlexibleSameValue() {
override val allFlexible: Boolean get() = true
override val errorType: Boolean get() = true
override val definitelyNotNullType: Boolean get() = false
override val integerLiteralType: Boolean get() = true
override val intersectionTypesInContravariantPositions: Boolean get() = true
}
abstract class AbstractCapturedTypesApproximation(val approximatedCapturedStatus: CaptureStatus) :
TypeApproximatorConfiguration.AllFlexibleSameValue() {
override val allFlexible: Boolean get() = true
override val errorType: Boolean get() = true
// i.e. will be approximated only approximatedCapturedStatus captured types
override fun capturedType(ctx: TypeSystemInferenceExtensionContext, type: CapturedTypeMarker): Boolean =
type.captureStatus(ctx) != approximatedCapturedStatus
override val intersection: IntersectionStrategy get() = IntersectionStrategy.ALLOWED
override val typeVariable: (TypeVariableTypeConstructorMarker) -> Boolean get() = { true }
}
object IncorporationConfiguration : TypeApproximatorConfiguration.AbstractCapturedTypesApproximation(CaptureStatus.FOR_INCORPORATION)
object SubtypeCapturedTypesApproximation : TypeApproximatorConfiguration.AbstractCapturedTypesApproximation(CaptureStatus.FOR_SUBTYPING)
object InternalTypesApproximation : TypeApproximatorConfiguration.AbstractCapturedTypesApproximation(CaptureStatus.FROM_EXPRESSION) {
override val integerLiteralType: Boolean get() = true
override val intersectionTypesInContravariantPositions: Boolean get() = true
}
object FinalApproximationAfterResolutionAndInference :
TypeApproximatorConfiguration.AbstractCapturedTypesApproximation(CaptureStatus.FROM_EXPRESSION) {
override val integerLiteralType: Boolean get() = true
override val intersectionTypesInContravariantPositions: Boolean get() = true
}
object IntegerLiteralsTypesApproximation : TypeApproximatorConfiguration.AllFlexibleSameValue() {
override val integerLiteralType: Boolean get() = true
override val allFlexible: Boolean get() = true
override val intersection: IntersectionStrategy get() = IntersectionStrategy.ALLOWED
override val typeVariable: (TypeVariableTypeConstructorMarker) -> Boolean get() = { true }
override val errorType: Boolean get() = true
override fun capturedType(ctx: TypeSystemInferenceExtensionContext, type: CapturedTypeMarker): Boolean = true
}
}
@@ -1,5 +1,4 @@
// !LANGUAGE: +NewInference
// IGNORE_BACKEND_FIR: JVM_IR
// KJS_WITH_FULL_RUNTIME
// WITH_RUNTIME
// ISSUE: KT-32462
@@ -13,4 +12,4 @@ fun decodeValue(value: String): Any {
}(value.substring(2))
}
fun box(): String = "OK"
fun box(): String = "OK"
@@ -7,7 +7,7 @@ fun <T: Any> bar(a: Array<T>): Array<T?> = null!!
fun test1(a: Array<out Int>) {
val r: Array<out Int?> = bar(a)
val t = bar(a)
t checkType { _<Array<out Int?>>() }
t checkType { <!INAPPLICABLE_CANDIDATE!>_<!><Array<out Int?>>() }
}
fun <T: Any> foo(l: Array<T>): Array<Array<T?>> = null!!
@@ -15,5 +15,5 @@ fun <T: Any> foo(l: Array<T>): Array<Array<T?>> = null!!
fun test2(a: Array<out Int>) {
val r: Array<out Array<out Int?>> = foo(a)
val t = foo(a)
t checkType { _<Array<out Array<out Int?>>>() }
}
t checkType { <!INAPPLICABLE_CANDIDATE!>_<!><Array<out Array<out Int?>>>() }
}
@@ -187,8 +187,8 @@ fun main() {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction<kotlin.Any?>")!>select(A3(), <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<A3, kotlin.Int, kotlin.Unit>")!>A3::foo1<!>, { a -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>a<!> }, { it -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>it<!> })<!>
// It's OK because `A3::foo2` is from companion of `A3`
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction1<kotlin.Int, kotlin.Any>")!>select(A3(), <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction1<kotlin.Int, kotlin.Unit>")!>A3::foo2<!>, { a -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>a<!> }, { it -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Int, kotlin.Comparable<kotlin.Float & kotlin.String> & java.io.Serializable>")!>select(A4(), { x: Number -> "" })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function2<kotlin.Int, kotlin.Int, kotlin.Comparable<kotlin.Float & kotlin.String> & java.io.Serializable>")!>select(A5<Int, Int>(), { x: Number, y: Int -> "" })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Int, kotlin.Comparable<*> & java.io.Serializable>")!>select(A4(), { x: Number -> "" })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function2<kotlin.Int, kotlin.Int, kotlin.Comparable<*> & java.io.Serializable>")!>select(A5<Int, Int>(), { x: Number, y: Int -> "" })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("A2")!>select(A2(), id { a, b, c -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>a<!>; <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>b<!>; <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>c<!> })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function<kotlin.Any?>")!>select(id(A3()), { <!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: Unresolved name: it"), UNRESOLVED_REFERENCE!>it<!> }, { a -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>a<!> })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction<kotlin.Any>")!>select(A3(), id(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<A3, kotlin.Int, kotlin.Unit>")!>A3::foo1<!>))<!>
@@ -202,7 +202,7 @@ fun main() {
<!DEBUG_INFO_EXPRESSION_TYPE("A4")!>select(A4(), id { x: Number -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>x<!> })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("A5<kotlin.Int, kotlin.Int>")!>select(id(A5<Int, Int>()), id { x: Number, y: Int -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>x<!>;<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>y<!> })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("A5<kotlin.Int, kotlin.Int>")!>select(id(A5<Int, Int>()), id { x, y -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>x<!>;<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>y<!> })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function2<kotlin.Number, kotlin.Int, kotlin.Number & kotlin.Comparable<kotlin.Float & kotlin.Int>>")!>select(id(<!DEBUG_INFO_EXPRESSION_TYPE("A5<kotlin.Number, kotlin.Int>")!>A5()<!>), id { x: Number, y: Int -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>x<!>;<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>y<!> })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function2<kotlin.Number, kotlin.Int, kotlin.Number & kotlin.Comparable<*>>")!>select(id(<!DEBUG_INFO_EXPRESSION_TYPE("A5<kotlin.Number, kotlin.Int>")!>A5()<!>), id { x: Number, y: Int -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>x<!>;<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>y<!> })<!>
val x55: Function2<Number, Int, Float> = select(id(A5()), id { x, y -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>x<!>;<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>y<!>; 1f })
// Diffrerent lambda's parameters with proper CST
@@ -212,11 +212,11 @@ fun main() {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Int, kotlin.Unit>")!>select({ x: Int -> }, id { x: Int, y: Number -> })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Int, kotlin.Unit>")!>select(id { x: Int -> }, id { x: String -> })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Int, kotlin.Unit>")!>select(id { x: Int -> }, id { x: Int, y: Number -> })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Int, kotlin.Comparable<kotlin.Int & kotlin.String> & java.io.Serializable>")!>select({ x: Int -> 1 }, { x: String -> "" })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Int, kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float>>")!>select({ x: Int -> 1 }, { x: Int, y: Number -> 1f })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Int, kotlin.Comparable<*> & java.io.Serializable>")!>select({ x: Int -> 1 }, { x: String -> "" })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Int, kotlin.Number & kotlin.Comparable<*>>")!>select({ x: Int -> 1 }, { x: Int, y: Number -> 1f })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.String, Inv<kotlin.String>>")!>select(id { x: Int -> Inv(10) }, { x: String -> Inv("") })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function<kotlin.Any>")!>select({ x: Int -> TODO() }, id { x: Int, y: Number -> Any() })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Int & kotlin.String, kotlin.String?>")!>select(id { x: Int -> null }, id { x: String -> "" })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<*, kotlin.String?>")!>select(id { x: Int -> null }, id { x: String -> "" })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Int, kotlin.Int>")!>select(id { x: Int -> 10 }, id { x: Int, y: Number -> TODO() })<!>
val x68: String.(String) -> String = select(id { x: String, y: String -> "10" }, id { x: String, y: String -> "TODO()" })
@@ -9,16 +9,16 @@ fun case_1() {
val x = case_1(Out(10), Inv(0.1))
if (x != null) {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Double & kotlin.Int> & kotlin.Number? & kotlin.Comparable<kotlin.Double & kotlin.Int>?")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Double & kotlin.Int> & kotlin.Number? & kotlin.Comparable<kotlin.Double & kotlin.Int>?")!>x<!>.equals(null)
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Double & kotlin.Int> & kotlin.Number? & kotlin.Comparable<kotlin.Double & kotlin.Int>?")!>x<!>.propT
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Double & kotlin.Int> & kotlin.Number? & kotlin.Comparable<kotlin.Double & kotlin.Int>?")!>x<!>.propAny
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Double & kotlin.Int> & kotlin.Number? & kotlin.Comparable<kotlin.Double & kotlin.Int>?")!>x<!>.propNullableT
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Double & kotlin.Int> & kotlin.Number? & kotlin.Comparable<kotlin.Double & kotlin.Int>?")!>x<!>.propNullableAny
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Double & kotlin.Int> & kotlin.Number? & kotlin.Comparable<kotlin.Double & kotlin.Int>?")!>x<!>.funT()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Double & kotlin.Int> & kotlin.Number? & kotlin.Comparable<kotlin.Double & kotlin.Int>?")!>x<!>.funAny()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Double & kotlin.Int> & kotlin.Number? & kotlin.Comparable<kotlin.Double & kotlin.Int>?")!>x<!>.funNullableT()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Double & kotlin.Int> & kotlin.Number? & kotlin.Comparable<kotlin.Double & kotlin.Int>?")!>x<!>.funNullableAny()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number? & kotlin.Comparable<*>?")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number? & kotlin.Comparable<*>?")!>x<!>.equals(null)
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number? & kotlin.Comparable<*>?")!>x<!>.propT
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number? & kotlin.Comparable<*>?")!>x<!>.propAny
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number? & kotlin.Comparable<*>?")!>x<!>.propNullableT
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number? & kotlin.Comparable<*>?")!>x<!>.propNullableAny
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number? & kotlin.Comparable<*>?")!>x<!>.funT()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number? & kotlin.Comparable<*>?")!>x<!>.funAny()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number? & kotlin.Comparable<*>?")!>x<!>.funNullableT()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number? & kotlin.Comparable<*>?")!>x<!>.funNullableAny()
}
}
@@ -29,16 +29,16 @@ fun case_2(y: Int) {
val x = case_2(Out(y), Inv(0.1))
if (x != null) {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Double> & kotlin.Number? & kotlin.Comparable<kotlin.Int & kotlin.Double>?")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Double> & kotlin.Number? & kotlin.Comparable<kotlin.Int & kotlin.Double>?")!>x<!>.equals(null)
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Double> & kotlin.Number? & kotlin.Comparable<kotlin.Int & kotlin.Double>?")!>x<!>.propT
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Double> & kotlin.Number? & kotlin.Comparable<kotlin.Int & kotlin.Double>?")!>x<!>.propAny
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Double> & kotlin.Number? & kotlin.Comparable<kotlin.Int & kotlin.Double>?")!>x<!>.propNullableT
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Double> & kotlin.Number? & kotlin.Comparable<kotlin.Int & kotlin.Double>?")!>x<!>.propNullableAny
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Double> & kotlin.Number? & kotlin.Comparable<kotlin.Int & kotlin.Double>?")!>x<!>.funT()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Double> & kotlin.Number? & kotlin.Comparable<kotlin.Int & kotlin.Double>?")!>x<!>.funAny()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Double> & kotlin.Number? & kotlin.Comparable<kotlin.Int & kotlin.Double>?")!>x<!>.funNullableT()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Double> & kotlin.Number? & kotlin.Comparable<kotlin.Int & kotlin.Double>?")!>x<!>.funNullableAny()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number? & kotlin.Comparable<*>?")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number? & kotlin.Comparable<*>?")!>x<!>.equals(null)
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number? & kotlin.Comparable<*>?")!>x<!>.propT
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number? & kotlin.Comparable<*>?")!>x<!>.propAny
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number? & kotlin.Comparable<*>?")!>x<!>.propNullableT
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number? & kotlin.Comparable<*>?")!>x<!>.propNullableAny
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number? & kotlin.Comparable<*>?")!>x<!>.funT()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number? & kotlin.Comparable<*>?")!>x<!>.funAny()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number? & kotlin.Comparable<*>?")!>x<!>.funNullableT()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number? & kotlin.Comparable<*>?")!>x<!>.funNullableAny()
}
}
@@ -52,32 +52,32 @@ fun case_3(a: Int?, b: Float?, c: Double?, d: Boolean?) {
false -> b
null -> c
}.apply {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number? & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double>?")!>this<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number? & kotlin.Comparable<*>?")!>this<!>
if (this != null) {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double> & kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double>")!>this<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double> & kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double>")!>this<!>.equals(null)
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double> & kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double>")!>this<!>.propT
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double> & kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double>")!>this<!>.propAny
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double> & kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double>")!>this<!>.propNullableT
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double> & kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double>")!>this<!>.propNullableAny
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double> & kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double>")!>this<!>.funT()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double> & kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double>")!>this<!>.funAny()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double> & kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double>")!>this<!>.funNullableT()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double> & kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double>")!>this<!>.funNullableAny()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number & kotlin.Comparable<*>")!>this<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number & kotlin.Comparable<*>")!>this<!>.equals(null)
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number & kotlin.Comparable<*>")!>this<!>.propT
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number & kotlin.Comparable<*>")!>this<!>.propAny
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number & kotlin.Comparable<*>")!>this<!>.propNullableT
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number & kotlin.Comparable<*>")!>this<!>.propNullableAny
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number & kotlin.Comparable<*>")!>this<!>.funT()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number & kotlin.Comparable<*>")!>this<!>.funAny()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number & kotlin.Comparable<*>")!>this<!>.funNullableT()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number & kotlin.Comparable<*>")!>this<!>.funNullableAny()
}
}.let {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number? & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double>?")!>it<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number? & kotlin.Comparable<*>?")!>it<!>
if (it != null) {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double> & kotlin.Number? & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double>?")!>it<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double> & kotlin.Number? & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double>?")!>it<!>.equals(null)
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double> & kotlin.Number? & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double>?")!>it<!>.propT
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double> & kotlin.Number? & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double>?")!>it<!>.propAny
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double> & kotlin.Number? & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double>?")!>it<!>.propNullableT
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double> & kotlin.Number? & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double>?")!>it<!>.propNullableAny
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double> & kotlin.Number? & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double>?")!>it<!>.funT()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double> & kotlin.Number? & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double>?")!>it<!>.funAny()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double> & kotlin.Number? & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double>?")!>it<!>.funNullableT()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double> & kotlin.Number? & kotlin.Comparable<kotlin.Int & kotlin.Float & kotlin.Double>?")!>it<!>.funNullableAny()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number? & kotlin.Comparable<*>?")!>it<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number? & kotlin.Comparable<*>?")!>it<!>.equals(null)
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number? & kotlin.Comparable<*>?")!>it<!>.propT
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number? & kotlin.Comparable<*>?")!>it<!>.propAny
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number? & kotlin.Comparable<*>?")!>it<!>.propNullableT
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number? & kotlin.Comparable<*>?")!>it<!>.propNullableAny
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number? & kotlin.Comparable<*>?")!>it<!>.funT()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number? & kotlin.Comparable<*>?")!>it<!>.funAny()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number? & kotlin.Comparable<*>?")!>it<!>.funNullableT()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*> & kotlin.Number? & kotlin.Comparable<*>?")!>it<!>.funNullableAny()
}
}
}
@@ -90,9 +90,9 @@ fun case_6() {
val x = select(Case6_1<Int>(), Case6_2<Float>(), null)
if (x != null) {
<!DEBUG_INFO_EXPRESSION_TYPE("InterfaceWithTypeParameter1<out InterfaceWithTypeParameter2<out kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float>>> & InterfaceWithTypeParameter2<out InterfaceWithTypeParameter2<out InterfaceWithTypeParameter1<out InterfaceWithTypeParameter2<*>> & InterfaceWithTypeParameter2<*>>> & InterfaceWithTypeParameter1<out InterfaceWithTypeParameter2<out kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float>>>? & InterfaceWithTypeParameter2<out InterfaceWithTypeParameter2<out InterfaceWithTypeParameter1<out InterfaceWithTypeParameter2<*>> & InterfaceWithTypeParameter2<*>>>?")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("InterfaceWithTypeParameter1<out InterfaceWithTypeParameter2<out kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float>>> & InterfaceWithTypeParameter2<out InterfaceWithTypeParameter2<out InterfaceWithTypeParameter1<out InterfaceWithTypeParameter2<*>> & InterfaceWithTypeParameter2<*>>> & InterfaceWithTypeParameter1<out InterfaceWithTypeParameter2<out kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float>>>? & InterfaceWithTypeParameter2<out InterfaceWithTypeParameter2<out InterfaceWithTypeParameter1<out InterfaceWithTypeParameter2<*>> & InterfaceWithTypeParameter2<*>>>?")!>x<!>.ip1test1()
<!DEBUG_INFO_EXPRESSION_TYPE("InterfaceWithTypeParameter1<out InterfaceWithTypeParameter2<out kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float>>> & InterfaceWithTypeParameter2<out InterfaceWithTypeParameter2<out InterfaceWithTypeParameter1<out InterfaceWithTypeParameter2<*>> & InterfaceWithTypeParameter2<*>>> & InterfaceWithTypeParameter1<out InterfaceWithTypeParameter2<out kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float>>>? & InterfaceWithTypeParameter2<out InterfaceWithTypeParameter2<out InterfaceWithTypeParameter1<out InterfaceWithTypeParameter2<*>> & InterfaceWithTypeParameter2<*>>>?")!>x<!>.ip1test2()
<!DEBUG_INFO_EXPRESSION_TYPE("InterfaceWithTypeParameter1<out InterfaceWithTypeParameter2<out kotlin.Number & kotlin.Comparable<*>>> & InterfaceWithTypeParameter2<out InterfaceWithTypeParameter2<out InterfaceWithTypeParameter1<out InterfaceWithTypeParameter2<*>> & InterfaceWithTypeParameter2<*>>> & InterfaceWithTypeParameter1<out InterfaceWithTypeParameter2<out kotlin.Number & kotlin.Comparable<*>>>? & InterfaceWithTypeParameter2<out InterfaceWithTypeParameter2<out InterfaceWithTypeParameter1<out InterfaceWithTypeParameter2<*>> & InterfaceWithTypeParameter2<*>>>?")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("InterfaceWithTypeParameter1<out InterfaceWithTypeParameter2<out kotlin.Number & kotlin.Comparable<*>>> & InterfaceWithTypeParameter2<out InterfaceWithTypeParameter2<out InterfaceWithTypeParameter1<out InterfaceWithTypeParameter2<*>> & InterfaceWithTypeParameter2<*>>> & InterfaceWithTypeParameter1<out InterfaceWithTypeParameter2<out kotlin.Number & kotlin.Comparable<*>>>? & InterfaceWithTypeParameter2<out InterfaceWithTypeParameter2<out InterfaceWithTypeParameter1<out InterfaceWithTypeParameter2<*>> & InterfaceWithTypeParameter2<*>>>?")!>x<!>.ip1test1()
<!DEBUG_INFO_EXPRESSION_TYPE("InterfaceWithTypeParameter1<out InterfaceWithTypeParameter2<out kotlin.Number & kotlin.Comparable<*>>> & InterfaceWithTypeParameter2<out InterfaceWithTypeParameter2<out InterfaceWithTypeParameter1<out InterfaceWithTypeParameter2<*>> & InterfaceWithTypeParameter2<*>>> & InterfaceWithTypeParameter1<out InterfaceWithTypeParameter2<out kotlin.Number & kotlin.Comparable<*>>>? & InterfaceWithTypeParameter2<out InterfaceWithTypeParameter2<out InterfaceWithTypeParameter1<out InterfaceWithTypeParameter2<*>> & InterfaceWithTypeParameter2<*>>>?")!>x<!>.ip1test2()
}
}
@@ -104,8 +104,8 @@ fun case_7() {
val x = select(Case7_1<Int, Float>(), Case7_2<Char, String>(), null)
if (x != null) {
<!DEBUG_INFO_EXPRESSION_TYPE("InterfaceWithTwoTypeParameters<out Inv<out kotlin.Comparable<kotlin.Int & kotlin.String> & java.io.Serializable>, out Inv<out kotlin.Comparable<kotlin.Float & kotlin.Char> & java.io.Serializable>> & InterfaceWithTwoTypeParameters<out Inv<out kotlin.Comparable<kotlin.Int & kotlin.String> & java.io.Serializable>, out Inv<out kotlin.Comparable<kotlin.Float & kotlin.Char> & java.io.Serializable>>?")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("InterfaceWithTwoTypeParameters<out Inv<out kotlin.Comparable<kotlin.Int & kotlin.String> & java.io.Serializable>, out Inv<out kotlin.Comparable<kotlin.Float & kotlin.Char> & java.io.Serializable>> & InterfaceWithTwoTypeParameters<out Inv<out kotlin.Comparable<kotlin.Int & kotlin.String> & java.io.Serializable>, out Inv<out kotlin.Comparable<kotlin.Float & kotlin.Char> & java.io.Serializable>>?")!>x<!>.ip2test()
<!DEBUG_INFO_EXPRESSION_TYPE("InterfaceWithTwoTypeParameters<out Inv<out kotlin.Comparable<*> & java.io.Serializable>, out Inv<out kotlin.Comparable<*> & java.io.Serializable>> & InterfaceWithTwoTypeParameters<out Inv<out kotlin.Comparable<*> & java.io.Serializable>, out Inv<out kotlin.Comparable<*> & java.io.Serializable>>?")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("InterfaceWithTwoTypeParameters<out Inv<out kotlin.Comparable<*> & java.io.Serializable>, out Inv<out kotlin.Comparable<*> & java.io.Serializable>> & InterfaceWithTwoTypeParameters<out Inv<out kotlin.Comparable<*> & java.io.Serializable>, out Inv<out kotlin.Comparable<*> & java.io.Serializable>>?")!>x<!>.ip2test()
}
}
@@ -117,24 +117,24 @@ fun case_8() {
val x = select(Case8_1<Int, Float>(), Case8_2<Char, String>(), null)
if (x != null) {
<!DEBUG_INFO_EXPRESSION_TYPE("ClassWithTwoTypeParameters<out ClassWithTwoTypeParameters<out kotlin.Comparable<kotlin.Int & kotlin.String> & java.io.Serializable, out kotlin.Comparable<kotlin.Float & kotlin.Char> & java.io.Serializable>, out kotlin.Comparable<kotlin.Float & kotlin.Char> & java.io.Serializable> & ClassWithTwoTypeParameters<out ClassWithTwoTypeParameters<out kotlin.Comparable<kotlin.Int & kotlin.String> & java.io.Serializable, out kotlin.Comparable<kotlin.Float & kotlin.Char> & java.io.Serializable>, out kotlin.Comparable<kotlin.Float & kotlin.Char> & java.io.Serializable>?")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("ClassWithTwoTypeParameters<out ClassWithTwoTypeParameters<out kotlin.Comparable<kotlin.Int & kotlin.String> & java.io.Serializable, out kotlin.Comparable<kotlin.Float & kotlin.Char> & java.io.Serializable>, out kotlin.Comparable<kotlin.Float & kotlin.Char> & java.io.Serializable> & ClassWithTwoTypeParameters<out ClassWithTwoTypeParameters<out kotlin.Comparable<kotlin.Int & kotlin.String> & java.io.Serializable, out kotlin.Comparable<kotlin.Float & kotlin.Char> & java.io.Serializable>, out kotlin.Comparable<kotlin.Float & kotlin.Char> & java.io.Serializable>?")!>x<!>.test1()
val y = <!DEBUG_INFO_EXPRESSION_TYPE("ClassWithTwoTypeParameters<out ClassWithTwoTypeParameters<out kotlin.Comparable<kotlin.Int & kotlin.String> & java.io.Serializable, out kotlin.Comparable<kotlin.Float & kotlin.Char> & java.io.Serializable>, out kotlin.Comparable<kotlin.Float & kotlin.Char> & java.io.Serializable> & ClassWithTwoTypeParameters<out ClassWithTwoTypeParameters<out kotlin.Comparable<kotlin.Int & kotlin.String> & java.io.Serializable, out kotlin.Comparable<kotlin.Float & kotlin.Char> & java.io.Serializable>, out kotlin.Comparable<kotlin.Float & kotlin.Char> & java.io.Serializable>?")!>x<!>.test2()
<!DEBUG_INFO_EXPRESSION_TYPE("ClassWithTwoTypeParameters<out ClassWithTwoTypeParameters<out kotlin.Comparable<*> & java.io.Serializable, out kotlin.Comparable<*> & java.io.Serializable>, out kotlin.Comparable<*> & java.io.Serializable> & ClassWithTwoTypeParameters<out ClassWithTwoTypeParameters<out kotlin.Comparable<*> & java.io.Serializable, out kotlin.Comparable<*> & java.io.Serializable>, out kotlin.Comparable<*> & java.io.Serializable>?")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("ClassWithTwoTypeParameters<out ClassWithTwoTypeParameters<out kotlin.Comparable<*> & java.io.Serializable, out kotlin.Comparable<*> & java.io.Serializable>, out kotlin.Comparable<*> & java.io.Serializable> & ClassWithTwoTypeParameters<out ClassWithTwoTypeParameters<out kotlin.Comparable<*> & java.io.Serializable, out kotlin.Comparable<*> & java.io.Serializable>, out kotlin.Comparable<*> & java.io.Serializable>?")!>x<!>.test1()
val y = <!DEBUG_INFO_EXPRESSION_TYPE("ClassWithTwoTypeParameters<out ClassWithTwoTypeParameters<out kotlin.Comparable<*> & java.io.Serializable, out kotlin.Comparable<*> & java.io.Serializable>, out kotlin.Comparable<*> & java.io.Serializable> & ClassWithTwoTypeParameters<out ClassWithTwoTypeParameters<out kotlin.Comparable<*> & java.io.Serializable, out kotlin.Comparable<*> & java.io.Serializable>, out kotlin.Comparable<*> & java.io.Serializable>?")!>x<!>.test2()
if (y != null) {
<!DEBUG_INFO_EXPRESSION_TYPE("ClassWithTwoTypeParameters<out kotlin.Comparable<kotlin.Int & kotlin.String> & java.io.Serializable, out kotlin.Comparable<kotlin.Float & kotlin.Char> & java.io.Serializable> & ClassWithTwoTypeParameters<out kotlin.Comparable<kotlin.Int & kotlin.String> & java.io.Serializable, out kotlin.Comparable<kotlin.Float & kotlin.Char> & java.io.Serializable>?")!>y<!>
<!DEBUG_INFO_EXPRESSION_TYPE("ClassWithTwoTypeParameters<out kotlin.Comparable<kotlin.Int & kotlin.String> & java.io.Serializable, out kotlin.Comparable<kotlin.Float & kotlin.Char> & java.io.Serializable> & ClassWithTwoTypeParameters<out kotlin.Comparable<kotlin.Int & kotlin.String> & java.io.Serializable, out kotlin.Comparable<kotlin.Float & kotlin.Char> & java.io.Serializable>?")!>y<!>.test1()
val z = <!DEBUG_INFO_EXPRESSION_TYPE("ClassWithTwoTypeParameters<out kotlin.Comparable<kotlin.Int & kotlin.String> & java.io.Serializable, out kotlin.Comparable<kotlin.Float & kotlin.Char> & java.io.Serializable> & ClassWithTwoTypeParameters<out kotlin.Comparable<kotlin.Int & kotlin.String> & java.io.Serializable, out kotlin.Comparable<kotlin.Float & kotlin.Char> & java.io.Serializable>?")!>y<!>.test2()
<!DEBUG_INFO_EXPRESSION_TYPE("ClassWithTwoTypeParameters<out kotlin.Comparable<*> & java.io.Serializable, out kotlin.Comparable<*> & java.io.Serializable> & ClassWithTwoTypeParameters<out kotlin.Comparable<*> & java.io.Serializable, out kotlin.Comparable<*> & java.io.Serializable>?")!>y<!>
<!DEBUG_INFO_EXPRESSION_TYPE("ClassWithTwoTypeParameters<out kotlin.Comparable<*> & java.io.Serializable, out kotlin.Comparable<*> & java.io.Serializable> & ClassWithTwoTypeParameters<out kotlin.Comparable<*> & java.io.Serializable, out kotlin.Comparable<*> & java.io.Serializable>?")!>y<!>.test1()
val z = <!DEBUG_INFO_EXPRESSION_TYPE("ClassWithTwoTypeParameters<out kotlin.Comparable<*> & java.io.Serializable, out kotlin.Comparable<*> & java.io.Serializable> & ClassWithTwoTypeParameters<out kotlin.Comparable<*> & java.io.Serializable, out kotlin.Comparable<*> & java.io.Serializable>?")!>y<!>.test2()
if (z != null) {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Comparable<kotlin.Int & kotlin.String> & java.io.Serializable & kotlin.Comparable<kotlin.Int & kotlin.String>? & java.io.Serializable?")!>z<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Comparable<kotlin.Int & kotlin.String> & java.io.Serializable & kotlin.Comparable<kotlin.Int & kotlin.String>? & java.io.Serializable?")!>z<!>.equals(null)
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Comparable<kotlin.Int & kotlin.String> & java.io.Serializable & kotlin.Comparable<kotlin.Int & kotlin.String>? & java.io.Serializable?")!>z<!>.propT
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Comparable<kotlin.Int & kotlin.String> & java.io.Serializable & kotlin.Comparable<kotlin.Int & kotlin.String>? & java.io.Serializable?")!>z<!>.propAny
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Comparable<kotlin.Int & kotlin.String> & java.io.Serializable & kotlin.Comparable<kotlin.Int & kotlin.String>? & java.io.Serializable?")!>z<!>.propNullableT
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Comparable<kotlin.Int & kotlin.String> & java.io.Serializable & kotlin.Comparable<kotlin.Int & kotlin.String>? & java.io.Serializable?")!>z<!>.propNullableAny
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Comparable<kotlin.Int & kotlin.String> & java.io.Serializable & kotlin.Comparable<kotlin.Int & kotlin.String>? & java.io.Serializable?")!>z<!>.funT()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Comparable<kotlin.Int & kotlin.String> & java.io.Serializable & kotlin.Comparable<kotlin.Int & kotlin.String>? & java.io.Serializable?")!>z<!>.funAny()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Comparable<kotlin.Int & kotlin.String> & java.io.Serializable & kotlin.Comparable<kotlin.Int & kotlin.String>? & java.io.Serializable?")!>z<!>.funNullableT()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Comparable<kotlin.Int & kotlin.String> & java.io.Serializable & kotlin.Comparable<kotlin.Int & kotlin.String>? & java.io.Serializable?")!>z<!>.funNullableAny()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Comparable<*> & java.io.Serializable & kotlin.Comparable<*>? & java.io.Serializable?")!>z<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Comparable<*> & java.io.Serializable & kotlin.Comparable<*>? & java.io.Serializable?")!>z<!>.equals(null)
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Comparable<*> & java.io.Serializable & kotlin.Comparable<*>? & java.io.Serializable?")!>z<!>.propT
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Comparable<*> & java.io.Serializable & kotlin.Comparable<*>? & java.io.Serializable?")!>z<!>.propAny
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Comparable<*> & java.io.Serializable & kotlin.Comparable<*>? & java.io.Serializable?")!>z<!>.propNullableT
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Comparable<*> & java.io.Serializable & kotlin.Comparable<*>? & java.io.Serializable?")!>z<!>.propNullableAny
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Comparable<*> & java.io.Serializable & kotlin.Comparable<*>? & java.io.Serializable?")!>z<!>.funT()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Comparable<*> & java.io.Serializable & kotlin.Comparable<*>? & java.io.Serializable?")!>z<!>.funAny()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Comparable<*> & java.io.Serializable & kotlin.Comparable<*>? & java.io.Serializable?")!>z<!>.funNullableT()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Comparable<*> & java.io.Serializable & kotlin.Comparable<*>? & java.io.Serializable?")!>z<!>.funNullableAny()
}
}
}
@@ -134,8 +134,8 @@ fun case_12(z: Any?) {
return@let it as Int
it as? Float ?: 10f
}
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float>")!>y<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float>")!>y<!>.toByte()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*>")!>y<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*>")!>y<!>.toByte()
}
/*
@@ -158,8 +158,8 @@ fun case_14(z: Any?) {
return@run this as Int
this as? Float ?: 10f
}
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float>")!>y<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float>")!>y<!>.toByte()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*>")!>y<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*>")!>y<!>.toByte()
}
/*
@@ -28,6 +28,8 @@ interface TypeVariableTypeConstructorMarker : TypeConstructorMarker
interface CapturedTypeConstructorMarker : TypeConstructorMarker
interface IntersectionTypeConstructorMarker : TypeConstructorMarker
interface TypeSubstitutorMarker
@@ -174,8 +176,12 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui
secondCandidate: KotlinTypeMarker
): KotlinTypeMarker
fun KotlinTypeMarker.isSpecial(): Boolean
fun TypeConstructorMarker.isTypeVariable(): Boolean
fun TypeVariableTypeConstructorMarker.isContainedInInvariantOrContravariantPositions(): Boolean
fun KotlinTypeMarker.isSignedOrUnsignedNumberType(): Boolean
}
@@ -202,6 +208,9 @@ interface TypeSystemContext : TypeSystemOptimizationContext {
fun SimpleTypeMarker.asDefinitelyNotNullType(): DefinitelyNotNullTypeMarker?
fun SimpleTypeMarker.isMarkedNullable(): Boolean
fun KotlinTypeMarker.isMarkedNullable(): Boolean =
this is SimpleTypeMarker && isMarkedNullable()
fun SimpleTypeMarker.withNullability(nullable: Boolean): SimpleTypeMarker
fun SimpleTypeMarker.typeConstructor(): TypeConstructorMarker
@@ -323,7 +332,7 @@ interface TypeSystemContext : TypeSystemOptimizationContext {
fun intersectTypes(types: List<KotlinTypeMarker>): KotlinTypeMarker
fun intersectTypes(types: List<SimpleTypeMarker>): SimpleTypeMarker
fun KotlinTypeMarker.isSimpleType() = asSimpleType() != null
fun KotlinTypeMarker.isSimpleType(): Boolean = asSimpleType() != null
fun prepareType(type: KotlinTypeMarker): KotlinTypeMarker
@@ -23,10 +23,11 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.resolve.scopes.TypeIntersectionScope
import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner
import org.jetbrains.kotlin.types.model.IntersectionTypeConstructorMarker
import org.jetbrains.kotlin.types.refinement.TypeRefinement
import java.util.*
class IntersectionTypeConstructor(typesToIntersect: Collection<KotlinType>) : TypeConstructor {
class IntersectionTypeConstructor(typesToIntersect: Collection<KotlinType>) : TypeConstructor, IntersectionTypeConstructorMarker {
private var alternative: KotlinType? = null
private constructor(
@@ -36,9 +36,6 @@ interface TypeSystemCommonBackendContext : TypeSystemContext {
fun TypeParameterMarker.getRepresentativeUpperBound(): KotlinTypeMarker
fun KotlinTypeMarker.getSubstitutedUnderlyingType(): KotlinTypeMarker?
fun KotlinTypeMarker.isMarkedNullable(): Boolean =
this is SimpleTypeMarker && isMarkedNullable()
fun KotlinTypeMarker.makeNullable(): KotlinTypeMarker =
asSimpleType()?.withNullability(true) ?: this
@@ -6,8 +6,8 @@
package org.jetbrains.kotlin.types.checker
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.StandardNames.FqNames
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.builtins.StandardNames.FqNames
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalTypeOrSubtype
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
import org.jetbrains.kotlin.types.typeUtil.isSignedOrUnsignedNumberType as classicIsSignedOrUnsignedNumberType
interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSystemCommonBackendContext {
override fun TypeConstructorMarker.isDenotable(): Boolean {
@@ -517,6 +518,11 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy
errorSupportedOnlyInTypeInference()
}
override fun KotlinTypeMarker.isSpecial(): Boolean {
require(this is KotlinType)
return this is TypeUtils.SpecialType
}
override fun TypeConstructorMarker.isTypeVariable(): Boolean {
errorSupportedOnlyInTypeInference()
}
@@ -525,6 +531,11 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy
errorSupportedOnlyInTypeInference()
}
override fun KotlinTypeMarker.isSignedOrUnsignedNumberType(): Boolean {
require(this is KotlinType)
return classicIsSignedOrUnsignedNumberType()
}
override fun findCommonIntegerLiteralTypesSuperType(explicitSupertypes: List<SimpleTypeMarker>): SimpleTypeMarker? {
@Suppress("UNCHECKED_CAST")
explicitSupertypes as List<SimpleType>