FIR: enable useCorrectedNullabilityForFlexibleTypeParameters
It's necessary for correct substitution of `T & Any` with `T = V..V?`.
This commit is contained in:
@@ -143,8 +143,7 @@ private fun ConeKotlinType.enhanceInflexibleType(
|
|||||||
val mergedAttributes = if (shouldAddAttribute) attributes + CompilerConeAttributes.EnhancedNullability else attributes
|
val mergedAttributes = if (shouldAddAttribute) attributes + CompilerConeAttributes.EnhancedNullability else attributes
|
||||||
val enhancedType = enhancedTag.constructType(mergedArguments, enhancedNullability, mergedAttributes)
|
val enhancedType = enhancedTag.constructType(mergedArguments, enhancedNullability, mergedAttributes)
|
||||||
return if (effectiveQualifiers.isNotNullTypeParameter)
|
return if (effectiveQualifiers.isNotNullTypeParameter)
|
||||||
ConeDefinitelyNotNullType.create(enhancedType, session.typeContext, useCorrectedNullabilityForFlexibleTypeParameters = true)
|
ConeDefinitelyNotNullType.create(enhancedType, session.typeContext) ?: enhancedType
|
||||||
?: enhancedType
|
|
||||||
else
|
else
|
||||||
enhancedType
|
enhancedType
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,9 +21,7 @@ import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
|||||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||||
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
||||||
import org.jetbrains.kotlin.resolve.calls.NewCommonSuperTypeCalculator
|
import org.jetbrains.kotlin.resolve.calls.NewCommonSuperTypeCalculator
|
||||||
import org.jetbrains.kotlin.types.AbstractStrictEqualityTypeChecker
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
|
||||||
import org.jetbrains.kotlin.types.TypeApproximatorConfiguration
|
|
||||||
import org.jetbrains.kotlin.types.model.*
|
import org.jetbrains.kotlin.types.model.*
|
||||||
|
|
||||||
fun ConeInferenceContext.commonSuperTypeOrNull(types: List<ConeKotlinType>): ConeKotlinType? {
|
fun ConeInferenceContext.commonSuperTypeOrNull(types: List<ConeKotlinType>): ConeKotlinType? {
|
||||||
@@ -47,20 +45,27 @@ fun ConeInferenceContext.intersectTypesOrNull(types: List<ConeKotlinType>): Cone
|
|||||||
fun TypeCheckerProviderContext.equalTypes(a: ConeKotlinType, b: ConeKotlinType): Boolean =
|
fun TypeCheckerProviderContext.equalTypes(a: ConeKotlinType, b: ConeKotlinType): Boolean =
|
||||||
AbstractTypeChecker.equalTypes(this, a, b)
|
AbstractTypeChecker.equalTypes(this, a, b)
|
||||||
|
|
||||||
|
private fun ConeTypeContext.makesSenseToBeDefinitelyNotNull(type: ConeKotlinType): Boolean = when (type) {
|
||||||
|
is ConeTypeParameterType -> type.isNullableType()
|
||||||
|
// Actually, this branch should work for type parameters as well, but it breaks some cases. See KT-40114.
|
||||||
|
// Basically, if we have `T : X..X?`, then `T <: Any` but we still have `T` != `T & Any`.
|
||||||
|
is ConeTypeVariableType, is ConeCapturedType ->
|
||||||
|
!AbstractNullabilityChecker.isSubtypeOfAny(
|
||||||
|
newTypeCheckerState(errorTypesEqualToAnything = false, stubTypesEqualToAnything = false), type
|
||||||
|
)
|
||||||
|
// For all other types `T & Any` is the same as `T` without a question mark.
|
||||||
|
// TODO: not true for flexible types.
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: leave only one of `create` and `makeConeTypeDefinitelyNotNullOrNotNull`
|
||||||
fun ConeDefinitelyNotNullType.Companion.create(
|
fun ConeDefinitelyNotNullType.Companion.create(
|
||||||
original: ConeKotlinType,
|
original: ConeKotlinType,
|
||||||
typeContext: ConeTypeContext,
|
typeContext: ConeTypeContext
|
||||||
useCorrectedNullabilityForFlexibleTypeParameters: Boolean = false,
|
|
||||||
): ConeDefinitelyNotNullType? {
|
): ConeDefinitelyNotNullType? {
|
||||||
return when {
|
return when {
|
||||||
original is ConeDefinitelyNotNullType -> original
|
original is ConeDefinitelyNotNullType -> original
|
||||||
typeContext
|
typeContext.makesSenseToBeDefinitelyNotNull(original) -> ConeDefinitelyNotNullType(original)
|
||||||
.newTypeCheckerState(errorTypesEqualToAnything = false, stubTypesEqualToAnything = false)
|
|
||||||
.makesSenseToBeDefinitelyNotNull(original, useCorrectedNullabilityForFlexibleTypeParameters) ->
|
|
||||||
|
|
||||||
ConeDefinitelyNotNullType(
|
|
||||||
original.lowerBoundIfFlexible()
|
|
||||||
)
|
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -81,10 +86,7 @@ fun <T : ConeKotlinType> T.withArguments(arguments: Array<out ConeTypeProjection
|
|||||||
return when (this) {
|
return when (this) {
|
||||||
is ConeClassErrorType -> this
|
is ConeClassErrorType -> this
|
||||||
is ConeClassLikeTypeImpl -> ConeClassLikeTypeImpl(lookupTag, arguments, nullability.isNullable) as T
|
is ConeClassLikeTypeImpl -> ConeClassLikeTypeImpl(lookupTag, arguments, nullability.isNullable) as T
|
||||||
is ConeDefinitelyNotNullType -> ConeDefinitelyNotNullType.create(
|
is ConeDefinitelyNotNullType -> ConeDefinitelyNotNullType(original.withArguments(arguments, typeSystemContext)) as T
|
||||||
original.withArguments(arguments, typeSystemContext),
|
|
||||||
typeSystemContext
|
|
||||||
)!! as T
|
|
||||||
else -> error("Not supported: $this: ${this.render()}")
|
else -> error("Not supported: $this: ${this.render()}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,10 +103,7 @@ fun <T : ConeKotlinType> T.withAttributes(attributes: ConeAttributes, typeSystem
|
|||||||
return when (this) {
|
return when (this) {
|
||||||
is ConeClassErrorType -> this
|
is ConeClassErrorType -> this
|
||||||
is ConeClassLikeTypeImpl -> ConeClassLikeTypeImpl(lookupTag, typeArguments, nullability.isNullable, attributes)
|
is ConeClassLikeTypeImpl -> ConeClassLikeTypeImpl(lookupTag, typeArguments, nullability.isNullable, attributes)
|
||||||
is ConeDefinitelyNotNullType -> ConeDefinitelyNotNullType.create(
|
is ConeDefinitelyNotNullType -> ConeDefinitelyNotNullType(original.withAttributes(attributes, typeSystemContext))
|
||||||
original.withAttributes(attributes, typeSystemContext),
|
|
||||||
typeSystemContext
|
|
||||||
)!!
|
|
||||||
is ConeTypeParameterTypeImpl -> ConeTypeParameterTypeImpl(lookupTag, nullability.isNullable, attributes)
|
is ConeTypeParameterTypeImpl -> ConeTypeParameterTypeImpl(lookupTag, nullability.isNullable, attributes)
|
||||||
is ConeFlexibleType -> ConeFlexibleType(
|
is ConeFlexibleType -> ConeFlexibleType(
|
||||||
lowerBound.withAttributes(attributes, typeSystemContext),
|
lowerBound.withAttributes(attributes, typeSystemContext),
|
||||||
|
|||||||
@@ -14,8 +14,6 @@ import org.jetbrains.kotlin.fir.render
|
|||||||
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
|
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.StandardClassIds
|
import org.jetbrains.kotlin.name.StandardClassIds
|
||||||
import org.jetbrains.kotlin.types.AbstractNullabilityChecker
|
|
||||||
import org.jetbrains.kotlin.types.TypeCheckerState
|
|
||||||
import org.jetbrains.kotlin.types.ConstantValueKind
|
import org.jetbrains.kotlin.types.ConstantValueKind
|
||||||
import kotlin.contracts.ExperimentalContracts
|
import kotlin.contracts.ExperimentalContracts
|
||||||
import kotlin.contracts.contract
|
import kotlin.contracts.contract
|
||||||
@@ -151,41 +149,6 @@ fun FirTypeProjection.toConeTypeProjection(): ConeTypeProjection =
|
|||||||
else -> error("!")
|
else -> error("!")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun TypeCheckerState.makesSenseToBeDefinitelyNotNull(
|
|
||||||
type: ConeKotlinType,
|
|
||||||
useCorrectedNullabilityForFlexibleTypeParameters: Boolean
|
|
||||||
): Boolean {
|
|
||||||
if (!type.canHaveUndefinedNullability()) return false
|
|
||||||
|
|
||||||
// Replacing `useCorrectedNullabilityForFlexibleTypeParameters` with true for all call-sites seems to be correct
|
|
||||||
// But it seems that it should be a new feature: KT-28785 would be automatically fixed then
|
|
||||||
// (see the tests org.jetbrains.kotlin.spec.checkers.DiagnosticsTestSpecGenerated.NotLinked.Dfa.Pos.test12/13)
|
|
||||||
// So it should be a language feature, but it's hard correctly identify language version settings for all call sites
|
|
||||||
// Thus, we have non-trivial value at org.jetbrains.kotlin.load.java.typeEnhancement.JavaTypeEnhancement.notNullTypeParameter
|
|
||||||
// that run under related language-feature only
|
|
||||||
if (useCorrectedNullabilityForFlexibleTypeParameters && type is ConeTypeParameterType) {
|
|
||||||
// Effectively checks if the type is flexible or has nullable bound
|
|
||||||
return with(typeSystemContext) {
|
|
||||||
type.isNullableType()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actually, this code should work for type parameters as well, but it breaks some cases
|
|
||||||
// See KT-40114
|
|
||||||
|
|
||||||
return !AbstractNullabilityChecker.isSubtypeOfAny(this, type)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun ConeKotlinType.canHaveUndefinedNullability(): Boolean {
|
|
||||||
return when (this) {
|
|
||||||
is ConeTypeVariableType,
|
|
||||||
is ConeCapturedType,
|
|
||||||
is ConeTypeParameterType
|
|
||||||
-> true
|
|
||||||
else -> false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun ConeTypeParameterType.hasNotNullUpperBound(): Boolean {
|
private fun ConeTypeParameterType.hasNotNullUpperBound(): Boolean {
|
||||||
return lookupTag.typeParameterSymbol.fir.bounds.any {
|
return lookupTag.typeParameterSymbol.fir.bounds.any {
|
||||||
val boundType = it.coneType
|
val boundType = it.coneType
|
||||||
|
|||||||
@@ -82,25 +82,12 @@ FILE fqName:<root> fileName:/AbstractMutableMap.kt
|
|||||||
VALUE_PARAMETER name:p0 index:0 type:K of <root>.MyMap
|
VALUE_PARAMETER name:p0 index:0 type:K of <root>.MyMap
|
||||||
VALUE_PARAMETER name:p1 index:1 type:@[EnhancedNullability] V of <root>.MyMap
|
VALUE_PARAMETER name:p1 index:1 type:@[EnhancedNullability] V of <root>.MyMap
|
||||||
VALUE_PARAMETER name:p2 index:2 type:@[EnhancedNullability] java.util.function.BiFunction<in @[EnhancedNullability] V of <root>.MyMap, in @[EnhancedNullability] V of <root>.MyMap, out V of <root>.MyMap?>
|
VALUE_PARAMETER name:p2 index:2 type:@[EnhancedNullability] java.util.function.BiFunction<in @[EnhancedNullability] V of <root>.MyMap, in @[EnhancedNullability] V of <root>.MyMap, out V of <root>.MyMap?>
|
||||||
FUN FAKE_OVERRIDE name:merge visibility:public modality:OPEN <> ($this:kotlin.collections.MutableMap<K of kotlin.collections.MutableMap, V of kotlin.collections.MutableMap>, p0:@[FlexibleNullability] K of <root>.MyMap?, p1:V of <root>.MyMap, p2:@[EnhancedNullability] java.util.function.BiFunction<in V of <root>.MyMap, in V of <root>.MyMap, out V of <root>.MyMap?>) returnType:V of <root>.MyMap? [fake_override]
|
|
||||||
overridden:
|
|
||||||
public open fun merge (p0: @[FlexibleNullability] K of kotlin.collections.AbstractMutableMap?, p1: V of kotlin.collections.AbstractMutableMap, p2: @[EnhancedNullability] java.util.function.BiFunction<in V of kotlin.collections.AbstractMutableMap, in V of kotlin.collections.AbstractMutableMap, out V of kotlin.collections.AbstractMutableMap?>): V of kotlin.collections.AbstractMutableMap? [fake_override] declared in kotlin.collections.AbstractMutableMap
|
|
||||||
$this: VALUE_PARAMETER name:<this> type:kotlin.collections.MutableMap<K of kotlin.collections.MutableMap, V of kotlin.collections.MutableMap>
|
|
||||||
VALUE_PARAMETER name:p0 index:0 type:@[FlexibleNullability] K of <root>.MyMap?
|
|
||||||
VALUE_PARAMETER name:p1 index:1 type:V of <root>.MyMap
|
|
||||||
VALUE_PARAMETER name:p2 index:2 type:@[EnhancedNullability] java.util.function.BiFunction<in V of <root>.MyMap, in V of <root>.MyMap, out V of <root>.MyMap?>
|
|
||||||
FUN FAKE_OVERRIDE name:computeIfPresent visibility:public modality:OPEN <> ($this:kotlin.collections.MutableMap<K of kotlin.collections.MutableMap, V of kotlin.collections.MutableMap>, p0:K of <root>.MyMap, p1:@[EnhancedNullability] java.util.function.BiFunction<in K of <root>.MyMap, in @[EnhancedNullability] V of <root>.MyMap, out V of <root>.MyMap?>) returnType:V of <root>.MyMap? [fake_override]
|
FUN FAKE_OVERRIDE name:computeIfPresent visibility:public modality:OPEN <> ($this:kotlin.collections.MutableMap<K of kotlin.collections.MutableMap, V of kotlin.collections.MutableMap>, p0:K of <root>.MyMap, p1:@[EnhancedNullability] java.util.function.BiFunction<in K of <root>.MyMap, in @[EnhancedNullability] V of <root>.MyMap, out V of <root>.MyMap?>) returnType:V of <root>.MyMap? [fake_override]
|
||||||
overridden:
|
overridden:
|
||||||
public open fun computeIfPresent (p0: K of kotlin.collections.AbstractMutableMap, p1: @[EnhancedNullability] java.util.function.BiFunction<in K of kotlin.collections.AbstractMutableMap, in @[EnhancedNullability] V of kotlin.collections.AbstractMutableMap, out V of kotlin.collections.AbstractMutableMap?>): V of kotlin.collections.AbstractMutableMap? [fake_override] declared in kotlin.collections.AbstractMutableMap
|
public open fun computeIfPresent (p0: K of kotlin.collections.AbstractMutableMap, p1: @[EnhancedNullability] java.util.function.BiFunction<in K of kotlin.collections.AbstractMutableMap, in @[EnhancedNullability] V of kotlin.collections.AbstractMutableMap, out V of kotlin.collections.AbstractMutableMap?>): V of kotlin.collections.AbstractMutableMap? [fake_override] declared in kotlin.collections.AbstractMutableMap
|
||||||
$this: VALUE_PARAMETER name:<this> type:kotlin.collections.MutableMap<K of kotlin.collections.MutableMap, V of kotlin.collections.MutableMap>
|
$this: VALUE_PARAMETER name:<this> type:kotlin.collections.MutableMap<K of kotlin.collections.MutableMap, V of kotlin.collections.MutableMap>
|
||||||
VALUE_PARAMETER name:p0 index:0 type:K of <root>.MyMap
|
VALUE_PARAMETER name:p0 index:0 type:K of <root>.MyMap
|
||||||
VALUE_PARAMETER name:p1 index:1 type:@[EnhancedNullability] java.util.function.BiFunction<in K of <root>.MyMap, in @[EnhancedNullability] V of <root>.MyMap, out V of <root>.MyMap?>
|
VALUE_PARAMETER name:p1 index:1 type:@[EnhancedNullability] java.util.function.BiFunction<in K of <root>.MyMap, in @[EnhancedNullability] V of <root>.MyMap, out V of <root>.MyMap?>
|
||||||
FUN FAKE_OVERRIDE name:computeIfPresent visibility:public modality:OPEN <> ($this:kotlin.collections.MutableMap<K of kotlin.collections.MutableMap, V of kotlin.collections.MutableMap>, p0:@[FlexibleNullability] K of <root>.MyMap?, p1:@[EnhancedNullability] java.util.function.BiFunction<in @[FlexibleNullability] K of <root>.MyMap?, in V of <root>.MyMap, out V of <root>.MyMap?>) returnType:V of <root>.MyMap? [fake_override]
|
|
||||||
overridden:
|
|
||||||
public open fun computeIfPresent (p0: @[FlexibleNullability] K of kotlin.collections.AbstractMutableMap?, p1: @[EnhancedNullability] java.util.function.BiFunction<in @[FlexibleNullability] K of kotlin.collections.AbstractMutableMap?, in V of kotlin.collections.AbstractMutableMap, out V of kotlin.collections.AbstractMutableMap?>): V of kotlin.collections.AbstractMutableMap? [fake_override] declared in kotlin.collections.AbstractMutableMap
|
|
||||||
$this: VALUE_PARAMETER name:<this> type:kotlin.collections.MutableMap<K of kotlin.collections.MutableMap, V of kotlin.collections.MutableMap>
|
|
||||||
VALUE_PARAMETER name:p0 index:0 type:@[FlexibleNullability] K of <root>.MyMap?
|
|
||||||
VALUE_PARAMETER name:p1 index:1 type:@[EnhancedNullability] java.util.function.BiFunction<in @[FlexibleNullability] K of <root>.MyMap?, in V of <root>.MyMap, out V of <root>.MyMap?>
|
|
||||||
FUN FAKE_OVERRIDE name:putIfAbsent visibility:public modality:OPEN <> ($this:kotlin.collections.MutableMap<K of kotlin.collections.MutableMap, V of kotlin.collections.MutableMap>, p0:K of <root>.MyMap, p1:V of <root>.MyMap) returnType:V of <root>.MyMap? [fake_override]
|
FUN FAKE_OVERRIDE name:putIfAbsent visibility:public modality:OPEN <> ($this:kotlin.collections.MutableMap<K of kotlin.collections.MutableMap, V of kotlin.collections.MutableMap>, p0:K of <root>.MyMap, p1:V of <root>.MyMap) returnType:V of <root>.MyMap? [fake_override]
|
||||||
overridden:
|
overridden:
|
||||||
public open fun putIfAbsent (p0: K of kotlin.collections.AbstractMutableMap, p1: V of kotlin.collections.AbstractMutableMap): V of kotlin.collections.AbstractMutableMap? [fake_override] declared in kotlin.collections.AbstractMutableMap
|
public open fun putIfAbsent (p0: K of kotlin.collections.AbstractMutableMap, p1: V of kotlin.collections.AbstractMutableMap): V of kotlin.collections.AbstractMutableMap? [fake_override] declared in kotlin.collections.AbstractMutableMap
|
||||||
|
|||||||
Reference in New Issue
Block a user