[NI] Consider intersection type with number type as Nothing

Currently, only for "in": In<in Int & A> == In<in Nothing> == In<*>

 #KT-37302 Fixed
This commit is contained in:
Mikhail Zarechenskiy
2020-03-22 23:25:12 +03:00
parent b23aff4d0d
commit 191fb02bf6
26 changed files with 242 additions and 92 deletions
@@ -94,7 +94,7 @@ fun CallableDescriptor.substituteAndApproximateTypes(
}
}
return substitute(TypeSubstitutor.create(wrappedSubstitution))
return substitute(TypeSubstitutor.create(wrappedSubstitution)) ?: this
}
internal fun <E> MutableList<E>.trimToSize(newSize: Int) = subList(newSize, size).clear()
@@ -149,7 +149,7 @@ class ResultTypeResolver(
return typeApproximator.approximateToSuperType(
commonSuperType,
TypeApproximatorConfiguration.CapturedAndIntegerLiteralsTypesApproximation
TypeApproximatorConfiguration.InternalTypesApproximation
) ?: commonSuperType
}
@@ -202,7 +202,7 @@ class ResultTypeResolver(
return typeApproximator.approximateToSubType(
upperType,
TypeApproximatorConfiguration.CapturedAndIntegerLiteralsTypesApproximation
TypeApproximatorConfiguration.InternalTypesApproximation
) ?: upperType
}
return null
@@ -17,9 +17,6 @@
package org.jetbrains.kotlin.resolve.calls.tower
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.smartcasts.getReceiverValueWithSmartCast
@@ -144,11 +141,11 @@ internal class MemberScopeTowerLevel(
Variance.INVARIANT -> null
Variance.OUT_VARIANCE -> approximator.approximateToSuperType(
topLevelType.unwrap(),
TypeApproximatorConfiguration.CapturedAndIntegerLiteralsTypesApproximation
TypeApproximatorConfiguration.InternalTypesApproximation
)
Variance.IN_VARIANCE -> approximator.approximateToSubType(
topLevelType.unwrap(),
TypeApproximatorConfiguration.CapturedAndIntegerLiteralsTypesApproximation
TypeApproximatorConfiguration.InternalTypesApproximation
)
} ?: topLevelType
}
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.types.TypeApproximatorConfiguration.IntersectionStra
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
@@ -42,6 +43,7 @@ open class TypeApproximatorConfiguration {
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 =
@@ -60,6 +62,7 @@ open class TypeApproximatorConfiguration {
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() {
@@ -67,6 +70,7 @@ open class TypeApproximatorConfiguration {
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) :
@@ -84,13 +88,15 @@ open class TypeApproximatorConfiguration {
object IncorporationConfiguration : TypeApproximatorConfiguration.AbstractCapturedTypesApproximation(FOR_INCORPORATION)
object SubtypeCapturedTypesApproximation : TypeApproximatorConfiguration.AbstractCapturedTypesApproximation(FOR_SUBTYPING)
object CapturedAndIntegerLiteralsTypesApproximation : TypeApproximatorConfiguration.AbstractCapturedTypesApproximation(FROM_EXPRESSION) {
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() {
@@ -279,6 +285,13 @@ abstract class AbstractTypeApproximator(val ctx: TypeSystemInferenceExtensionCon
}
}
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,
@@ -512,6 +525,18 @@ abstract class AbstractTypeApproximator(val ctx: TypeSystemInferenceExtensionCon
} 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)>