diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ConeInferenceContext.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ConeInferenceContext.kt index eaa70dc091a..addf9b1c587 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ConeInferenceContext.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ConeInferenceContext.kt @@ -202,19 +202,12 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo override fun KotlinTypeMarker.makeDefinitelyNotNullOrNotNull(): KotlinTypeMarker { require(this is ConeKotlinType) - return makeDefinitelyNotNullOrNotNull() + return makeConeTypeDefinitelyNotNullOrNotNull() } override fun SimpleTypeMarker.makeSimpleTypeDefinitelyNotNullOrNotNull(): SimpleTypeMarker { require(this is ConeKotlinType) - return makeDefinitelyNotNullOrNotNull() as SimpleTypeMarker - } - - private fun ConeKotlinType.makeDefinitelyNotNullOrNotNull(): ConeKotlinType { - if (this is ConeIntersectionType) { - return ConeIntersectionType(intersectedTypes.map { it.makeDefinitelyNotNullOrNotNull() }) - } - return ConeDefinitelyNotNullType.create(this) ?: this.withNullability(false) as ConeKotlinType + return makeConeTypeDefinitelyNotNullOrNotNull() as SimpleTypeMarker } override fun createCapturedType( diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/substitution/Substitutors.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/substitution/Substitutors.kt index 97fed82b9c7..b4de2249773 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/substitution/Substitutors.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/substitution/Substitutors.kt @@ -38,6 +38,9 @@ abstract class AbstractConeSubstitutor : ConeSubstitutor() { override fun substituteOrNull(type: ConeKotlinType): ConeKotlinType? { val newType = substituteType(type) + if (newType != null && type is ConeDefinitelyNotNullType) { + return newType.makeConeTypeDefinitelyNotNullOrNotNull() + } return (newType ?: type.substituteRecursive()) } 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 d391f207244..0fa7b16f5ab 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 @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.fir.types import org.jetbrains.kotlin.fir.resolve.calls.ConeInferenceContext +import org.jetbrains.kotlin.fir.resolve.withNullability import org.jetbrains.kotlin.resolve.calls.NewCommonSuperTypeCalculator import org.jetbrains.kotlin.resolve.calls.NewCommonSuperTypeCalculator.commonSuperType import org.jetbrains.kotlin.types.AbstractNullabilityChecker @@ -42,7 +43,8 @@ fun ConeInferenceContext.intersectTypesOrNull(types: List): Cone fun ConeDefinitelyNotNullType.Companion.create(original: ConeKotlinType): ConeDefinitelyNotNullType? { return when { original is ConeDefinitelyNotNullType -> original - makesSenseToBeDefinitelyNotNull(original) -> ConeDefinitelyNotNullType(original.lowerBoundIfFlexible()) + makesSenseToBeDefinitelyNotNull(original) -> + ConeDefinitelyNotNullType(original.lowerBoundIfFlexible()) else -> null } } @@ -50,7 +52,30 @@ fun ConeDefinitelyNotNullType.Companion.create(original: ConeKotlinType): ConeDe fun makesSenseToBeDefinitelyNotNull(type: ConeKotlinType): Boolean = type.canHaveUndefinedNullability() // TODO: also check nullability -fun ConeKotlinType.canHaveUndefinedNullability(): Boolean = - this is ConeTypeVariableType || - this is ConeTypeParameterType || - this is ConeCapturedType +fun ConeKotlinType.canHaveUndefinedNullability(): Boolean { + return when (this) { + is ConeTypeVariableType, + is ConeCapturedType + -> true + is ConeTypeParameterType -> type.isMarkedNullable || !hasNotNullUpperBound() + else -> false + } +} + +private fun ConeTypeParameterType.hasNotNullUpperBound(): Boolean { + return lookupTag.typeParameterSymbol.fir.bounds.any { + val boundType = it.coneTypeUnsafe() + if (boundType is ConeTypeParameterType) { + boundType.hasNotNullUpperBound() + } else { + boundType.nullability == ConeNullability.NOT_NULL + } + } +} + +fun ConeKotlinType.makeConeTypeDefinitelyNotNullOrNotNull(): ConeKotlinType { + if (this is ConeIntersectionType) { + return ConeIntersectionType(intersectedTypes.map { it.makeConeTypeDefinitelyNotNullOrNotNull() }) + } + return ConeDefinitelyNotNullType.create(this) ?: this.withNullability(ConeNullability.NOT_NULL) +} \ No newline at end of file diff --git a/compiler/fir/resolve/testData/resolve/expresssions/genericDiagnostic.txt b/compiler/fir/resolve/testData/resolve/expresssions/genericDiagnostic.txt index 2d125c19844..1e490e2a819 100644 --- a/compiler/fir/resolve/testData/resolve/expresssions/genericDiagnostic.txt +++ b/compiler/fir/resolve/testData/resolve/expresssions/genericDiagnostic.txt @@ -10,7 +10,7 @@ FILE: test.kt R|/Fix.Fix|(R|/element|) } public final fun createGeneric(d: R|Diagnostic|): R|kotlin/Unit| { - lval element: R|DE!!| = R|/d|.R|/Diagnostic.element| + lval element: R|DE| = R|/d|.R|/Diagnostic.element| R|/Fix.Fix|(R|/element|) } private final val DERIVED_FACTORY: R|DiagnosticFactory0| = R|/DiagnosticFactory0.DiagnosticFactory0|() diff --git a/compiler/fir/resolve/testData/resolve/problems/definetelyNotNullForTypeParameter.kt b/compiler/fir/resolve/testData/resolve/problems/definetelyNotNullForTypeParameter.kt index 518989b5ca6..ce312e56336 100644 --- a/compiler/fir/resolve/testData/resolve/problems/definetelyNotNullForTypeParameter.kt +++ b/compiler/fir/resolve/testData/resolve/problems/definetelyNotNullForTypeParameter.kt @@ -5,8 +5,5 @@ fun id(x: Out): Out = TODO() fun foo(computable: Out) fun bar(computable: Out) { - // Should be resolved but fails during inference - // Failed incorporated constraint: T? <: Any (from T? <: X!! and X!! <: F and F <: Any) - // Hypothesis: DefinetelyNotNull(T?) = should just remove "?" while it actually gets created - foo(id(computable)) + foo(id(computable)) } diff --git a/compiler/fir/resolve/testData/resolve/problems/definetelyNotNullForTypeParameter.txt b/compiler/fir/resolve/testData/resolve/problems/definetelyNotNullForTypeParameter.txt index 7414e4607cc..a98d52191d6 100644 --- a/compiler/fir/resolve/testData/resolve/problems/definetelyNotNullForTypeParameter.txt +++ b/compiler/fir/resolve/testData/resolve/problems/definetelyNotNullForTypeParameter.txt @@ -6,5 +6,5 @@ FILE: definetelyNotNullForTypeParameter.kt } public final fun foo(computable: R|Out|): R|kotlin/Unit| public final fun bar(computable: R|Out|): R|kotlin/Unit| { - #(R|/id|(R|/computable|)) + R|/foo|(R|/id|(R|/computable|)) }