diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/javaTypeUtils.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/javaTypeUtils.kt index f7d1b110bac..d716b275b32 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/javaTypeUtils.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/javaTypeUtils.kt @@ -143,8 +143,7 @@ private fun ConeKotlinType.enhanceInflexibleType( val mergedAttributes = if (shouldAddAttribute) attributes + CompilerConeAttributes.EnhancedNullability else attributes val enhancedType = enhancedTag.constructType(mergedArguments, enhancedNullability, mergedAttributes) return if (effectiveQualifiers.isNotNullTypeParameter) - ConeDefinitelyNotNullType.create(enhancedType, session.typeContext, useCorrectedNullabilityForFlexibleTypeParameters = true) - ?: enhancedType + ConeDefinitelyNotNullType.create(enhancedType, session.typeContext) ?: enhancedType else enhancedType } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt index f317556ccad..a94bdc07398 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt @@ -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.ConeTypeParameterTypeImpl import org.jetbrains.kotlin.resolve.calls.NewCommonSuperTypeCalculator -import org.jetbrains.kotlin.types.AbstractStrictEqualityTypeChecker -import org.jetbrains.kotlin.types.AbstractTypeChecker -import org.jetbrains.kotlin.types.TypeApproximatorConfiguration +import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.model.* fun ConeInferenceContext.commonSuperTypeOrNull(types: List): ConeKotlinType? { @@ -47,20 +45,27 @@ fun ConeInferenceContext.intersectTypesOrNull(types: List): Cone fun TypeCheckerProviderContext.equalTypes(a: ConeKotlinType, b: ConeKotlinType): Boolean = 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( original: ConeKotlinType, - typeContext: ConeTypeContext, - useCorrectedNullabilityForFlexibleTypeParameters: Boolean = false, + typeContext: ConeTypeContext ): ConeDefinitelyNotNullType? { return when { original is ConeDefinitelyNotNullType -> original - typeContext - .newTypeCheckerState(errorTypesEqualToAnything = false, stubTypesEqualToAnything = false) - .makesSenseToBeDefinitelyNotNull(original, useCorrectedNullabilityForFlexibleTypeParameters) -> - - ConeDefinitelyNotNullType( - original.lowerBoundIfFlexible() - ) + typeContext.makesSenseToBeDefinitelyNotNull(original) -> ConeDefinitelyNotNullType(original) else -> null } } @@ -81,10 +86,7 @@ fun T.withArguments(arguments: Array this is ConeClassLikeTypeImpl -> ConeClassLikeTypeImpl(lookupTag, arguments, nullability.isNullable) as T - is ConeDefinitelyNotNullType -> ConeDefinitelyNotNullType.create( - original.withArguments(arguments, typeSystemContext), - typeSystemContext - )!! as T + is ConeDefinitelyNotNullType -> ConeDefinitelyNotNullType(original.withArguments(arguments, typeSystemContext)) as T else -> error("Not supported: $this: ${this.render()}") } } @@ -101,10 +103,7 @@ fun T.withAttributes(attributes: ConeAttributes, typeSystem return when (this) { is ConeClassErrorType -> this is ConeClassLikeTypeImpl -> ConeClassLikeTypeImpl(lookupTag, typeArguments, nullability.isNullable, attributes) - is ConeDefinitelyNotNullType -> ConeDefinitelyNotNullType.create( - original.withAttributes(attributes, typeSystemContext), - typeSystemContext - )!! + is ConeDefinitelyNotNullType -> ConeDefinitelyNotNullType(original.withAttributes(attributes, typeSystemContext)) is ConeTypeParameterTypeImpl -> ConeTypeParameterTypeImpl(lookupTag, nullability.isNullable, attributes) is ConeFlexibleType -> ConeFlexibleType( lowerBound.withAttributes(attributes, typeSystemContext), diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/FirTypeUtils.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/FirTypeUtils.kt index 7346325d1df..54699ef3368 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/FirTypeUtils.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/FirTypeUtils.kt @@ -14,8 +14,6 @@ import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef import org.jetbrains.kotlin.name.ClassId 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 kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract @@ -151,41 +149,6 @@ fun FirTypeProjection.toConeTypeProjection(): ConeTypeProjection = 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 { return lookupTag.typeParameterSymbol.fir.bounds.any { val boundType = it.coneType diff --git a/compiler/testData/ir/irText/firProblems/AbstractMutableMap.fir.txt b/compiler/testData/ir/irText/firProblems/AbstractMutableMap.fir.txt index 57ff09aa389..f9db8ff2388 100644 --- a/compiler/testData/ir/irText/firProblems/AbstractMutableMap.fir.txt +++ b/compiler/testData/ir/irText/firProblems/AbstractMutableMap.fir.txt @@ -82,25 +82,12 @@ FILE fqName: fileName:/AbstractMutableMap.kt VALUE_PARAMETER name:p0 index:0 type:K of .MyMap VALUE_PARAMETER name:p1 index:1 type:@[EnhancedNullability] V of .MyMap VALUE_PARAMETER name:p2 index:2 type:@[EnhancedNullability] java.util.function.BiFunction.MyMap, in @[EnhancedNullability] V of .MyMap, out V of .MyMap?> - FUN FAKE_OVERRIDE name:merge visibility:public modality:OPEN <> ($this:kotlin.collections.MutableMap, p0:@[FlexibleNullability] K of .MyMap?, p1:V of .MyMap, p2:@[EnhancedNullability] java.util.function.BiFunction.MyMap, in V of .MyMap, out V of .MyMap?>) returnType:V of .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): V of kotlin.collections.AbstractMutableMap? [fake_override] declared in kotlin.collections.AbstractMutableMap - $this: VALUE_PARAMETER name: type:kotlin.collections.MutableMap - VALUE_PARAMETER name:p0 index:0 type:@[FlexibleNullability] K of .MyMap? - VALUE_PARAMETER name:p1 index:1 type:V of .MyMap - VALUE_PARAMETER name:p2 index:2 type:@[EnhancedNullability] java.util.function.BiFunction.MyMap, in V of .MyMap, out V of .MyMap?> FUN FAKE_OVERRIDE name:computeIfPresent visibility:public modality:OPEN <> ($this:kotlin.collections.MutableMap, p0:K of .MyMap, p1:@[EnhancedNullability] java.util.function.BiFunction.MyMap, in @[EnhancedNullability] V of .MyMap, out V of .MyMap?>) returnType:V of .MyMap? [fake_override] overridden: public open fun computeIfPresent (p0: K of kotlin.collections.AbstractMutableMap, p1: @[EnhancedNullability] java.util.function.BiFunction): V of kotlin.collections.AbstractMutableMap? [fake_override] declared in kotlin.collections.AbstractMutableMap $this: VALUE_PARAMETER name: type:kotlin.collections.MutableMap VALUE_PARAMETER name:p0 index:0 type:K of .MyMap VALUE_PARAMETER name:p1 index:1 type:@[EnhancedNullability] java.util.function.BiFunction.MyMap, in @[EnhancedNullability] V of .MyMap, out V of .MyMap?> - FUN FAKE_OVERRIDE name:computeIfPresent visibility:public modality:OPEN <> ($this:kotlin.collections.MutableMap, p0:@[FlexibleNullability] K of .MyMap?, p1:@[EnhancedNullability] java.util.function.BiFunction.MyMap?, in V of .MyMap, out V of .MyMap?>) returnType:V of .MyMap? [fake_override] - overridden: - public open fun computeIfPresent (p0: @[FlexibleNullability] K of kotlin.collections.AbstractMutableMap?, p1: @[EnhancedNullability] java.util.function.BiFunction): V of kotlin.collections.AbstractMutableMap? [fake_override] declared in kotlin.collections.AbstractMutableMap - $this: VALUE_PARAMETER name: type:kotlin.collections.MutableMap - VALUE_PARAMETER name:p0 index:0 type:@[FlexibleNullability] K of .MyMap? - VALUE_PARAMETER name:p1 index:1 type:@[EnhancedNullability] java.util.function.BiFunction.MyMap?, in V of .MyMap, out V of .MyMap?> FUN FAKE_OVERRIDE name:putIfAbsent visibility:public modality:OPEN <> ($this:kotlin.collections.MutableMap, p0:K of .MyMap, p1:V of .MyMap) returnType:V of .MyMap? [fake_override] 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