diff --git a/compiler/resolution/src/org/jetbrains/kotlin/types/TypeApproximator.kt b/compiler/resolution/src/org/jetbrains/kotlin/types/TypeApproximator.kt index 6b1e9ffd88e..39ac42353ca 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/types/TypeApproximator.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/types/TypeApproximator.kt @@ -203,7 +203,25 @@ class TypeApproximator { val baseSuperType = when (supertypes.size) { 0 -> type.builtIns.nullableAnyType // Let C = in Int, then superType for C and C? is Any? 1 -> supertypes.single() - else -> intersectTypes(supertypes) + + // Consider the following example: + // A.getA()::class.java, where `getA()` returns some class from Java + // From `::class` we are getting type KClass>, where Cap 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`, because { Any & (A..A?) } = A, + // but in old inference type was equal to `KClass`. + + // Important note that from the point of type system first type is more specific: + // Here, approximation of KClass> is a type KClass such that KClass> <: KClass => + // 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` + + // Once NI will be more stabilized, we'll use more specific type + + else -> type.constructor.projection.type.unwrap() } val baseSubType = type.lowerType ?: type.builtIns.nothingType