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