[FE] Determine intersection type emptiness by looking at supertypes properly: substitute their type arguments
This commit is contained in:
committed by
teamcity
parent
a0260292ec
commit
20a8e5d742
@@ -343,33 +343,61 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui
|
||||
return EmptyIntersectionTypeKind.NOT_EMPTY_INTERSECTION
|
||||
}
|
||||
|
||||
fun createSubstitutorForSuperTypes(baseType: KotlinTypeMarker): TypeSubstitutorMarker?
|
||||
|
||||
private fun areIncompatibleSuperTypes(firstType: KotlinTypeMarker, secondType: KotlinTypeMarker): Boolean =
|
||||
firstType.typeConstructor() == secondType.typeConstructor()
|
||||
&& !AbstractTypeChecker.equalTypes(context = this, firstType, secondType)
|
||||
|
||||
// interface A<T>
|
||||
// interface B : A<Int>
|
||||
// interface C : A<String>
|
||||
// => B and C have incompatible supertypes
|
||||
private fun hasIncompatibleSuperTypes(firstType: KotlinTypeMarker, secondType: KotlinTypeMarker): Boolean {
|
||||
val superTypesOfFirst = firstType.typeConstructor().supertypes()
|
||||
val firstTypeSubstitutor = createSubstitutorForSuperTypes(firstType)
|
||||
val superTypesOfSecond = secondType.typeConstructor().supertypes()
|
||||
val secondTypeSubstitutor = createSubstitutorForSuperTypes(secondType)
|
||||
|
||||
for (superTypeOfFirst in superTypesOfFirst) {
|
||||
@Suppress("NAME_SHADOWING")
|
||||
val superTypeOfFirst = firstTypeSubstitutor?.safeSubstitute(superTypeOfFirst) ?: superTypeOfFirst
|
||||
|
||||
if (areIncompatibleSuperTypes(superTypeOfFirst, secondType))
|
||||
return true
|
||||
|
||||
for (superTypeOfSecond in superTypesOfSecond) {
|
||||
@Suppress("NAME_SHADOWING")
|
||||
val superTypeOfSecond = secondTypeSubstitutor?.safeSubstitute(superTypeOfSecond) ?: superTypeOfSecond
|
||||
|
||||
if (
|
||||
areIncompatibleSuperTypes(firstType, superTypeOfSecond)
|
||||
|| areIncompatibleSuperTypes(superTypeOfFirst, superTypeOfSecond)
|
||||
) return true
|
||||
|
||||
if (hasIncompatibleSuperTypes(superTypeOfFirst, superTypeOfSecond))
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private fun canHaveCommonSubtypeWithInterface(firstType: KotlinTypeMarker, secondType: KotlinTypeMarker): Boolean {
|
||||
require(firstType.typeConstructor().isInterface() || secondType.typeConstructor().isInterface()) {
|
||||
"One of the passed type should be an interface"
|
||||
}
|
||||
@Suppress("NAME_SHADOWING")
|
||||
val firstType = firstType.withNullability(false)
|
||||
val firstType = firstType.withNullability(false).eraseContainingTypeParameters()
|
||||
|
||||
@Suppress("NAME_SHADOWING")
|
||||
val secondType = secondType.withNullability(false)
|
||||
val secondType = secondType.withNullability(false).eraseContainingTypeParameters()
|
||||
|
||||
// interface A<K>
|
||||
// interface B: A<String>
|
||||
// interface C: A<Int>
|
||||
// B & C can't have common subtype due to having incompatible supertypes: A<String> and A<Int>
|
||||
val haveIncompatibleSupertypes = firstType.anySuperTypeConstructor { superTypeOfFirst ->
|
||||
secondType.anySuperTypeConstructor { superTypeOfSecond ->
|
||||
val erasedSuperTypeOfSecond by lazy { superTypeOfSecond.eraseContainingTypeParameters() }
|
||||
superTypeOfFirst.typeConstructor() == superTypeOfSecond.typeConstructor()
|
||||
&& !AbstractTypeChecker.equalTypes(
|
||||
context = this,
|
||||
superTypeOfFirst.eraseContainingTypeParameters(),
|
||||
erasedSuperTypeOfSecond
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return !haveIncompatibleSupertypes
|
||||
return !hasIncompatibleSuperTypes(firstType, secondType)
|
||||
}
|
||||
|
||||
private fun canHaveCommonSubtype(first: KotlinTypeMarker, second: KotlinTypeMarker): Boolean {
|
||||
|
||||
@@ -30,8 +30,7 @@ import org.jetbrains.kotlin.utils.sure
|
||||
import java.util.*
|
||||
|
||||
class SubstitutingScope(private val workerScope: MemberScope, givenSubstitutor: TypeSubstitutor) : MemberScope {
|
||||
|
||||
private val substitutor = givenSubstitutor.substitution.wrapWithCapturingSubstitution().buildSubstitutor()
|
||||
val substitutor = givenSubstitutor.substitution.wrapWithCapturingSubstitution().buildSubstitutor()
|
||||
|
||||
private var substitutedDescriptors: MutableMap<DeclarationDescriptor, DeclarationDescriptor>? = null
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.CapturedType
|
||||
import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.*
|
||||
import org.jetbrains.kotlin.resolve.scopes.SubstitutingScope
|
||||
import org.jetbrains.kotlin.resolve.substitutedUnderlyingType
|
||||
import org.jetbrains.kotlin.resolve.unsubstitutedUnderlyingType
|
||||
import org.jetbrains.kotlin.types.*
|
||||
@@ -870,6 +871,11 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy
|
||||
return getKFunctionDescriptor(builtIns, parametersNumber, isSuspend).typeConstructor
|
||||
}
|
||||
|
||||
override fun createSubstitutorForSuperTypes(baseType: KotlinTypeMarker): TypeSubstitutorMarker? {
|
||||
require(baseType is KotlinType, baseType::errorMessage)
|
||||
return (baseType.memberScope as? SubstitutingScope)?.substitutor
|
||||
}
|
||||
|
||||
override fun SimpleTypeMarker.createConstraintPartForLowerBoundAndFlexibleTypeVariable(): KotlinTypeMarker =
|
||||
if (this.isMarkedNullable()) {
|
||||
this
|
||||
|
||||
Reference in New Issue
Block a user