[NI] Get rid of FE 1.0 types in AbstractTypeApproximator
This commit is contained in:
+2
-2
@@ -13,8 +13,8 @@ FILE: withInInitializer.kt
|
|||||||
super<R|kotlin/Any|>()
|
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 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<it(kotlin/String & kotlin/Int)> & java/io/Serializable)>|
|
public get(): R|kotlin/collections/List<it(kotlin/Comparable<*> & java/io/Serializable)>|
|
||||||
|
|
||||||
public final val data: R|First| = R|/First.First|(Int(42))
|
public final val data: R|First| = R|/First.First|(Int(42))
|
||||||
public get(): R|First|
|
public get(): R|First|
|
||||||
|
|||||||
@@ -235,7 +235,7 @@ class ConeRawType(lowerBound: ConeKotlinType, upperBound: ConeKotlinType) : Cone
|
|||||||
*/
|
*/
|
||||||
class ConeIntersectionType(
|
class ConeIntersectionType(
|
||||||
val intersectedTypes: Collection<ConeKotlinType>
|
val intersectedTypes: Collection<ConeKotlinType>
|
||||||
) : ConeSimpleKotlinType(), TypeConstructorMarker {
|
) : ConeSimpleKotlinType(), IntersectionTypeConstructorMarker {
|
||||||
override val typeArguments: Array<out ConeTypeProjection>
|
override val typeArguments: Array<out ConeTypeProjection>
|
||||||
get() = emptyArray()
|
get() = emptyArray()
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.fir.types
|
package org.jetbrains.kotlin.fir.types
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.diagnostics.ConeIntermediateDiagnostic
|
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.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.NoSubstitutor
|
import org.jetbrains.kotlin.fir.resolve.calls.NoSubstitutor
|
||||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
||||||
@@ -316,6 +317,11 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
|
|||||||
return this.defaultType
|
return this.defaultType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun KotlinTypeMarker.isSpecial(): Boolean {
|
||||||
|
// TODO
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
override fun TypeConstructorMarker.isTypeVariable(): Boolean {
|
override fun TypeConstructorMarker.isTypeVariable(): Boolean {
|
||||||
return this is ConeTypeVariableTypeConstructor
|
return this is ConeTypeVariableTypeConstructor
|
||||||
}
|
}
|
||||||
@@ -362,4 +368,10 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
|
|||||||
require(this is ConeIntegerLiteralType)
|
require(this is ConeIntegerLiteralType)
|
||||||
return this.getApproximatedType()
|
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
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
|
||||||
object PrimitiveTypes {
|
object PrimitiveTypes {
|
||||||
val Boolean = StandardClassIds.Boolean.createType()
|
val Boolean: ConeClassLikeType = StandardClassIds.Boolean.createType()
|
||||||
val Char = StandardClassIds.Char.createType()
|
val Char: ConeClassLikeType = StandardClassIds.Char.createType()
|
||||||
val Byte = StandardClassIds.Byte.createType()
|
val Byte: ConeClassLikeType = StandardClassIds.Byte.createType()
|
||||||
val Short = StandardClassIds.Short.createType()
|
val Short: ConeClassLikeType = StandardClassIds.Short.createType()
|
||||||
val Int = StandardClassIds.Int.createType()
|
val Int: ConeClassLikeType = StandardClassIds.Int.createType()
|
||||||
val Long = StandardClassIds.Long.createType()
|
val Long: ConeClassLikeType = StandardClassIds.Long.createType()
|
||||||
val Float = StandardClassIds.Float.createType()
|
val Float: ConeClassLikeType = StandardClassIds.Float.createType()
|
||||||
val Double = StandardClassIds.Double.createType()
|
val Double: ConeClassLikeType = StandardClassIds.Double.createType()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ClassId.createType(): ConeClassLikeType =
|
private fun ClassId.createType(): ConeClassLikeType =
|
||||||
ConeClassLikeTypeImpl(ConeClassLikeLookupTagImpl(this), emptyArray(), isNullable = false)
|
ConeClassLikeTypeImpl(ConeClassLikeLookupTagImpl(this), emptyArray(), isNullable = false)
|
||||||
|
|
||||||
fun ConeClassLikeType.isDouble() = lookupTag.classId == StandardClassIds.Double
|
fun ConeClassLikeType.isDouble(): Boolean = lookupTag.classId == StandardClassIds.Double
|
||||||
fun ConeClassLikeType.isFloat() = lookupTag.classId == StandardClassIds.Float
|
fun ConeClassLikeType.isFloat(): Boolean = lookupTag.classId == StandardClassIds.Float
|
||||||
fun ConeClassLikeType.isLong() = lookupTag.classId == StandardClassIds.Long
|
fun ConeClassLikeType.isLong(): Boolean = lookupTag.classId == StandardClassIds.Long
|
||||||
fun ConeClassLikeType.isInt() = lookupTag.classId == StandardClassIds.Int
|
fun ConeClassLikeType.isInt(): Boolean = lookupTag.classId == StandardClassIds.Int
|
||||||
fun ConeClassLikeType.isShort() = lookupTag.classId == StandardClassIds.Short
|
fun ConeClassLikeType.isShort(): Boolean = lookupTag.classId == StandardClassIds.Short
|
||||||
fun ConeClassLikeType.isByte() = lookupTag.classId == StandardClassIds.Byte
|
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.Double, StandardClassIds.Float, StandardClassIds.Long, StandardClassIds.Int,
|
||||||
StandardClassIds.Short, StandardClassIds.Byte
|
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
|
||||||
|
)
|
||||||
|
|||||||
+2
-1
@@ -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.components.CreateFreshVariablesSubstitutor.shouldBeFlexible
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.*
|
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.types.model.*
|
||||||
import org.jetbrains.kotlin.utils.SmartList
|
import org.jetbrains.kotlin.utils.SmartList
|
||||||
import org.jetbrains.kotlin.utils.SmartSet
|
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.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
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.resolve.calls.components.ClassicTypeSystemContextForCS
|
||||||
import org.jetbrains.kotlin.types.TypeApproximatorConfiguration.IntersectionStrategy.*
|
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class TypeApproximator(builtIns: KotlinBuiltIns) : AbstractTypeApproximator(ClassicTypeSystemContextForCS(builtIns)) {
|
class TypeApproximator(builtIns: KotlinBuiltIns) : AbstractTypeApproximator(ClassicTypeSystemContextForCS(builtIns)) {
|
||||||
fun approximateDeclarationType(baseType: KotlinType, local: Boolean, languageVersionSettings: LanguageVersionSettings): UnwrappedType {
|
fun approximateDeclarationType(baseType: KotlinType, local: Boolean, languageVersionSettings: LanguageVersionSettings): UnwrappedType {
|
||||||
@@ -128,524 +39,9 @@ class TypeApproximator(builtIns: KotlinBuiltIns) : AbstractTypeApproximator(Clas
|
|||||||
// resultType <: type
|
// resultType <: type
|
||||||
fun approximateToSubType(type: UnwrappedType, conf: TypeApproximatorConfiguration): UnwrappedType? =
|
fun approximateToSubType(type: UnwrappedType, conf: TypeApproximatorConfiguration): UnwrappedType? =
|
||||||
super.approximateToSubType(type, conf) as 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
|
// !LANGUAGE: +NewInference
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
// KJS_WITH_FULL_RUNTIME
|
// KJS_WITH_FULL_RUNTIME
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// ISSUE: KT-32462
|
// ISSUE: KT-32462
|
||||||
@@ -13,4 +12,4 @@ fun decodeValue(value: String): Any {
|
|||||||
}(value.substring(2))
|
}(value.substring(2))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun box(): String = "OK"
|
fun box(): String = "OK"
|
||||||
|
|||||||
+3
-3
@@ -7,7 +7,7 @@ fun <T: Any> bar(a: Array<T>): Array<T?> = null!!
|
|||||||
fun test1(a: Array<out Int>) {
|
fun test1(a: Array<out Int>) {
|
||||||
val r: Array<out Int?> = bar(a)
|
val r: Array<out Int?> = bar(a)
|
||||||
val t = 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!!
|
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>) {
|
fun test2(a: Array<out Int>) {
|
||||||
val r: Array<out Array<out Int?>> = foo(a)
|
val r: Array<out Array<out Int?>> = foo(a)
|
||||||
val t = foo(a)
|
val t = foo(a)
|
||||||
t checkType { _<Array<out Array<out Int?>>>() }
|
t checkType { <!INAPPLICABLE_CANDIDATE!>_<!><Array<out Array<out Int?>>>() }
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+6
-6
@@ -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<!> })<!>
|
<!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`
|
// 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.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.Function1<kotlin.Int, kotlin.Comparable<*> & 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.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("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.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<!>))<!>
|
<!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("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: 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("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 })
|
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
|
// 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({ 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: 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.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.Comparable<*> & 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.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.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.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() })<!>
|
<!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()" })
|
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))
|
val x = case_1(Out(10), Inv(0.1))
|
||||||
|
|
||||||
if (x != null) {
|
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.Number? & kotlin.Comparable<*>?")!>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.Number? & kotlin.Comparable<*>?")!>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.Number? & kotlin.Comparable<*>?")!>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.Number? & kotlin.Comparable<*>?")!>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.Number? & kotlin.Comparable<*>?")!>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.Number? & kotlin.Comparable<*>?")!>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.Number? & kotlin.Comparable<*>?")!>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.Number? & kotlin.Comparable<*>?")!>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.Number? & kotlin.Comparable<*>?")!>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<!>.funNullableAny()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,16 +29,16 @@ fun case_2(y: Int) {
|
|||||||
val x = case_2(Out(y), Inv(0.1))
|
val x = case_2(Out(y), Inv(0.1))
|
||||||
|
|
||||||
if (x != null) {
|
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.Number? & kotlin.Comparable<*>?")!>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.Number? & kotlin.Comparable<*>?")!>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.Number? & kotlin.Comparable<*>?")!>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.Number? & kotlin.Comparable<*>?")!>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.Number? & kotlin.Comparable<*>?")!>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.Number? & kotlin.Comparable<*>?")!>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.Number? & kotlin.Comparable<*>?")!>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.Number? & kotlin.Comparable<*>?")!>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.Number? & kotlin.Comparable<*>?")!>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<!>.funNullableAny()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,32 +52,32 @@ fun case_3(a: Int?, b: Float?, c: Double?, d: Boolean?) {
|
|||||||
false -> b
|
false -> b
|
||||||
null -> c
|
null -> c
|
||||||
}.apply {
|
}.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) {
|
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.Number & kotlin.Comparable<*>")!>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.Number & kotlin.Comparable<*>")!>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.Number & kotlin.Comparable<*>")!>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.Number & kotlin.Comparable<*>")!>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.Number & kotlin.Comparable<*>")!>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.Number & kotlin.Comparable<*>")!>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.Number & kotlin.Comparable<*>")!>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.Number & kotlin.Comparable<*>")!>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.Number & kotlin.Comparable<*>")!>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<!>.funNullableAny()
|
||||||
}
|
}
|
||||||
}.let {
|
}.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) {
|
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.Number? & kotlin.Comparable<*>?")!>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.Number? & kotlin.Comparable<*>?")!>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.Number? & kotlin.Comparable<*>?")!>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.Number? & kotlin.Comparable<*>?")!>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.Number? & kotlin.Comparable<*>?")!>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.Number? & kotlin.Comparable<*>?")!>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.Number? & kotlin.Comparable<*>?")!>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.Number? & kotlin.Comparable<*>?")!>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.Number? & kotlin.Comparable<*>?")!>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<!>.funNullableAny()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,9 +90,9 @@ fun case_6() {
|
|||||||
val x = select(Case6_1<Int>(), Case6_2<Float>(), null)
|
val x = select(Case6_1<Int>(), Case6_2<Float>(), null)
|
||||||
|
|
||||||
if (x != 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<*>>> & 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<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<*>>> & 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<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<!>.ip1test2()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,8 +104,8 @@ fun case_7() {
|
|||||||
val x = select(Case7_1<Int, Float>(), Case7_2<Char, String>(), null)
|
val x = select(Case7_1<Int, Float>(), Case7_2<Char, String>(), null)
|
||||||
|
|
||||||
if (x != 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<*> & 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<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<!>.ip2test()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,24 +117,24 @@ fun case_8() {
|
|||||||
val x = select(Case8_1<Int, Float>(), Case8_2<Char, String>(), null)
|
val x = select(Case8_1<Int, Float>(), Case8_2<Char, String>(), null)
|
||||||
|
|
||||||
if (x != 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<*> & 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<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()
|
<!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<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()
|
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) {
|
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<*> & 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<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()
|
<!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<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()
|
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) {
|
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<*> & java.io.Serializable & kotlin.Comparable<*>? & 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<*> & java.io.Serializable & kotlin.Comparable<*>? & 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<*> & java.io.Serializable & kotlin.Comparable<*>? & 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<*> & java.io.Serializable & kotlin.Comparable<*>? & 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<*> & java.io.Serializable & kotlin.Comparable<*>? & 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<*> & java.io.Serializable & kotlin.Comparable<*>? & 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<*> & java.io.Serializable & kotlin.Comparable<*>? & 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<*> & java.io.Serializable & kotlin.Comparable<*>? & 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<*> & java.io.Serializable & kotlin.Comparable<*>? & 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<!>.funNullableAny()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -134,8 +134,8 @@ fun case_12(z: Any?) {
|
|||||||
return@let it as Int
|
return@let it as Int
|
||||||
it as? Float ?: 10f
|
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<*>")!>y<!>
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float>")!>y<!>.toByte()
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*>")!>y<!>.toByte()
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -158,8 +158,8 @@ fun case_14(z: Any?) {
|
|||||||
return@run this as Int
|
return@run this as Int
|
||||||
this as? Float ?: 10f
|
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<*>")!>y<!>
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<kotlin.Int & kotlin.Float>")!>y<!>.toByte()
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*>")!>y<!>.toByte()
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ interface TypeVariableTypeConstructorMarker : TypeConstructorMarker
|
|||||||
|
|
||||||
interface CapturedTypeConstructorMarker : TypeConstructorMarker
|
interface CapturedTypeConstructorMarker : TypeConstructorMarker
|
||||||
|
|
||||||
|
interface IntersectionTypeConstructorMarker : TypeConstructorMarker
|
||||||
|
|
||||||
interface TypeSubstitutorMarker
|
interface TypeSubstitutorMarker
|
||||||
|
|
||||||
|
|
||||||
@@ -174,8 +176,12 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui
|
|||||||
secondCandidate: KotlinTypeMarker
|
secondCandidate: KotlinTypeMarker
|
||||||
): KotlinTypeMarker
|
): KotlinTypeMarker
|
||||||
|
|
||||||
|
fun KotlinTypeMarker.isSpecial(): Boolean
|
||||||
|
|
||||||
fun TypeConstructorMarker.isTypeVariable(): Boolean
|
fun TypeConstructorMarker.isTypeVariable(): Boolean
|
||||||
fun TypeVariableTypeConstructorMarker.isContainedInInvariantOrContravariantPositions(): Boolean
|
fun TypeVariableTypeConstructorMarker.isContainedInInvariantOrContravariantPositions(): Boolean
|
||||||
|
|
||||||
|
fun KotlinTypeMarker.isSignedOrUnsignedNumberType(): Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -202,6 +208,9 @@ interface TypeSystemContext : TypeSystemOptimizationContext {
|
|||||||
|
|
||||||
fun SimpleTypeMarker.asDefinitelyNotNullType(): DefinitelyNotNullTypeMarker?
|
fun SimpleTypeMarker.asDefinitelyNotNullType(): DefinitelyNotNullTypeMarker?
|
||||||
fun SimpleTypeMarker.isMarkedNullable(): Boolean
|
fun SimpleTypeMarker.isMarkedNullable(): Boolean
|
||||||
|
fun KotlinTypeMarker.isMarkedNullable(): Boolean =
|
||||||
|
this is SimpleTypeMarker && isMarkedNullable()
|
||||||
|
|
||||||
fun SimpleTypeMarker.withNullability(nullable: Boolean): SimpleTypeMarker
|
fun SimpleTypeMarker.withNullability(nullable: Boolean): SimpleTypeMarker
|
||||||
fun SimpleTypeMarker.typeConstructor(): TypeConstructorMarker
|
fun SimpleTypeMarker.typeConstructor(): TypeConstructorMarker
|
||||||
|
|
||||||
@@ -323,7 +332,7 @@ interface TypeSystemContext : TypeSystemOptimizationContext {
|
|||||||
fun intersectTypes(types: List<KotlinTypeMarker>): KotlinTypeMarker
|
fun intersectTypes(types: List<KotlinTypeMarker>): KotlinTypeMarker
|
||||||
fun intersectTypes(types: List<SimpleTypeMarker>): SimpleTypeMarker
|
fun intersectTypes(types: List<SimpleTypeMarker>): SimpleTypeMarker
|
||||||
|
|
||||||
fun KotlinTypeMarker.isSimpleType() = asSimpleType() != null
|
fun KotlinTypeMarker.isSimpleType(): Boolean = asSimpleType() != null
|
||||||
|
|
||||||
fun prepareType(type: KotlinTypeMarker): KotlinTypeMarker
|
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.MemberScope
|
||||||
import org.jetbrains.kotlin.resolve.scopes.TypeIntersectionScope
|
import org.jetbrains.kotlin.resolve.scopes.TypeIntersectionScope
|
||||||
import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner
|
import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner
|
||||||
|
import org.jetbrains.kotlin.types.model.IntersectionTypeConstructorMarker
|
||||||
import org.jetbrains.kotlin.types.refinement.TypeRefinement
|
import org.jetbrains.kotlin.types.refinement.TypeRefinement
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class IntersectionTypeConstructor(typesToIntersect: Collection<KotlinType>) : TypeConstructor {
|
class IntersectionTypeConstructor(typesToIntersect: Collection<KotlinType>) : TypeConstructor, IntersectionTypeConstructorMarker {
|
||||||
private var alternative: KotlinType? = null
|
private var alternative: KotlinType? = null
|
||||||
|
|
||||||
private constructor(
|
private constructor(
|
||||||
|
|||||||
@@ -36,9 +36,6 @@ interface TypeSystemCommonBackendContext : TypeSystemContext {
|
|||||||
fun TypeParameterMarker.getRepresentativeUpperBound(): KotlinTypeMarker
|
fun TypeParameterMarker.getRepresentativeUpperBound(): KotlinTypeMarker
|
||||||
fun KotlinTypeMarker.getSubstitutedUnderlyingType(): KotlinTypeMarker?
|
fun KotlinTypeMarker.getSubstitutedUnderlyingType(): KotlinTypeMarker?
|
||||||
|
|
||||||
fun KotlinTypeMarker.isMarkedNullable(): Boolean =
|
|
||||||
this is SimpleTypeMarker && isMarkedNullable()
|
|
||||||
|
|
||||||
fun KotlinTypeMarker.makeNullable(): KotlinTypeMarker =
|
fun KotlinTypeMarker.makeNullable(): KotlinTypeMarker =
|
||||||
asSimpleType()?.withNullability(true) ?: this
|
asSimpleType()?.withNullability(true) ?: this
|
||||||
|
|
||||||
|
|||||||
+12
-1
@@ -6,8 +6,8 @@
|
|||||||
package org.jetbrains.kotlin.types.checker
|
package org.jetbrains.kotlin.types.checker
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.builtins.StandardNames.FqNames
|
|
||||||
import org.jetbrains.kotlin.builtins.PrimitiveType
|
import org.jetbrains.kotlin.builtins.PrimitiveType
|
||||||
|
import org.jetbrains.kotlin.builtins.StandardNames.FqNames
|
||||||
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalTypeOrSubtype
|
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalTypeOrSubtype
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
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 org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
import kotlin.contracts.ExperimentalContracts
|
import kotlin.contracts.ExperimentalContracts
|
||||||
import kotlin.contracts.contract
|
import kotlin.contracts.contract
|
||||||
|
import org.jetbrains.kotlin.types.typeUtil.isSignedOrUnsignedNumberType as classicIsSignedOrUnsignedNumberType
|
||||||
|
|
||||||
interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSystemCommonBackendContext {
|
interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSystemCommonBackendContext {
|
||||||
override fun TypeConstructorMarker.isDenotable(): Boolean {
|
override fun TypeConstructorMarker.isDenotable(): Boolean {
|
||||||
@@ -517,6 +518,11 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy
|
|||||||
errorSupportedOnlyInTypeInference()
|
errorSupportedOnlyInTypeInference()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun KotlinTypeMarker.isSpecial(): Boolean {
|
||||||
|
require(this is KotlinType)
|
||||||
|
return this is TypeUtils.SpecialType
|
||||||
|
}
|
||||||
|
|
||||||
override fun TypeConstructorMarker.isTypeVariable(): Boolean {
|
override fun TypeConstructorMarker.isTypeVariable(): Boolean {
|
||||||
errorSupportedOnlyInTypeInference()
|
errorSupportedOnlyInTypeInference()
|
||||||
}
|
}
|
||||||
@@ -525,6 +531,11 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy
|
|||||||
errorSupportedOnlyInTypeInference()
|
errorSupportedOnlyInTypeInference()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun KotlinTypeMarker.isSignedOrUnsignedNumberType(): Boolean {
|
||||||
|
require(this is KotlinType)
|
||||||
|
return classicIsSignedOrUnsignedNumberType()
|
||||||
|
}
|
||||||
|
|
||||||
override fun findCommonIntegerLiteralTypesSuperType(explicitSupertypes: List<SimpleTypeMarker>): SimpleTypeMarker? {
|
override fun findCommonIntegerLiteralTypesSuperType(explicitSupertypes: List<SimpleTypeMarker>): SimpleTypeMarker? {
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
explicitSupertypes as List<SimpleType>
|
explicitSupertypes as List<SimpleType>
|
||||||
|
|||||||
Reference in New Issue
Block a user