[NI] Refine nullability for CST of types with undefined nullability
This commit is contained in:
+12
-2
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.checker.*
|
||||
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
|
||||
import org.jetbrains.kotlin.types.typeUtil.canHaveUndefinedNullability
|
||||
|
||||
object NewCommonSuperTypeCalculator {
|
||||
|
||||
@@ -61,9 +62,18 @@ object NewCommonSuperTypeCalculator {
|
||||
val notAllNotNull = types.any { !NullabilityChecker.isSubtypeOfAny(it) }
|
||||
val notNullTypes = if (notAllNotNull) types.map { it.makeNullableAsSpecified(false) } else types
|
||||
|
||||
val commonSuperTypes = commonSuperTypeForNotNullTypes(notNullTypes, depth)
|
||||
val commonSuperType = commonSuperTypeForNotNullTypes(notNullTypes, depth)
|
||||
return if (notAllNotNull)
|
||||
refineNullabilityForUndefinedNullability(types, commonSuperType) ?: commonSuperType.makeNullableAsSpecified(true)
|
||||
else
|
||||
commonSuperType
|
||||
}
|
||||
|
||||
return if (notAllNotNull) commonSuperTypes.makeNullableAsSpecified(true) else commonSuperTypes
|
||||
private fun refineNullabilityForUndefinedNullability(types: List<SimpleType>, commonSuperType: SimpleType): SimpleType? {
|
||||
if (!commonSuperType.unwrap().canHaveUndefinedNullability()) return null
|
||||
|
||||
val actuallyNotNull = types.all { NullabilityChecker.hasPathByNotMarkedNullableNodes(it, commonSuperType.constructor) }
|
||||
return if (actuallyNotNull) commonSuperType else null
|
||||
}
|
||||
|
||||
private fun List<SimpleType>.uniquify(): List<SimpleType> {
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
package
|
||||
|
||||
public fun foobar(/*0*/ a: A, /*1*/ b: B): In<kotlin.Nothing>?
|
||||
public fun </*0*/ T> select(/*0*/ x: T, /*1*/ y: T): T?
|
||||
public fun foobar(/*0*/ a: A, /*1*/ b: B): In<kotlin.Nothing>
|
||||
public fun </*0*/ T> select(/*0*/ x: T, /*1*/ y: T): T
|
||||
|
||||
public final class A : In<A> {
|
||||
public constructor A()
|
||||
|
||||
@@ -12,7 +12,7 @@ fun <T> test(v: T): T {
|
||||
v
|
||||
}
|
||||
|
||||
val t: T = <!NI;DEBUG_INFO_SMARTCAST!>a<!>
|
||||
val t: T = a
|
||||
return t
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ fun <T> test3(v: T): T {
|
||||
v
|
||||
}
|
||||
|
||||
val t: T = <!NI;DEBUG_INFO_SMARTCAST!>a<!>
|
||||
val t: T = a
|
||||
return t
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// !DIAGNOSTICS: -NOTHING_TO_INLINE
|
||||
// NI_EXPECTED_FILE
|
||||
|
||||
inline fun <T> foo(t1: T, t2: T) = t1 ?: t2
|
||||
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
package
|
||||
|
||||
public inline fun </*0*/ T> bar(/*0*/ l: (T) -> kotlin.Unit): T
|
||||
public inline fun </*0*/ T> foo(/*0*/ t1: T, /*1*/ t2: T): T?
|
||||
public fun use(): kotlin.Unit
|
||||
@@ -1,5 +1,4 @@
|
||||
// !DIAGNOSTICS: -NOTHING_TO_INLINE
|
||||
// NI_EXPECTED_FILE
|
||||
// See KT-9143: smart cast on a variable nulled inside a lambda argument
|
||||
inline fun <T> foo(t1: T, t2: T) = t1 ?: t2
|
||||
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
package
|
||||
|
||||
public inline fun </*0*/ T> bar(/*0*/ l: (T) -> kotlin.Unit): T
|
||||
public inline fun </*0*/ T> foo(/*0*/ t1: T, /*1*/ t2: T): T?
|
||||
public fun use(): kotlin.Unit
|
||||
@@ -20,9 +20,9 @@ import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
import org.jetbrains.kotlin.types.checker.NewCapturedType
|
||||
import org.jetbrains.kotlin.types.checker.NewTypeVariableConstructor
|
||||
import org.jetbrains.kotlin.types.checker.NullabilityChecker
|
||||
import org.jetbrains.kotlin.types.typeUtil.canHaveUndefinedNullability
|
||||
|
||||
abstract class DelegatingSimpleType : SimpleType() {
|
||||
protected abstract val delegate: SimpleType
|
||||
@@ -82,12 +82,7 @@ class DefinitelyNotNullType private constructor(val original: SimpleType) : Dele
|
||||
}
|
||||
|
||||
fun makesSenseToBeDefinitelyNotNull(type: UnwrappedType): Boolean =
|
||||
canHaveUndefinedNullability(type) && !NullabilityChecker.isSubtypeOfAny(type)
|
||||
|
||||
private fun canHaveUndefinedNullability(type: UnwrappedType): Boolean =
|
||||
type.constructor is NewTypeVariableConstructor ||
|
||||
type.constructor.declarationDescriptor is TypeParameterDescriptor ||
|
||||
type is NewCapturedType
|
||||
type.canHaveUndefinedNullability() && !NullabilityChecker.isSubtypeOfAny(type)
|
||||
}
|
||||
|
||||
override val delegate: SimpleType
|
||||
|
||||
@@ -23,6 +23,8 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.isCaptured
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
import org.jetbrains.kotlin.types.checker.NewCapturedType
|
||||
import org.jetbrains.kotlin.types.checker.NewTypeVariableConstructor
|
||||
import java.util.*
|
||||
|
||||
enum class TypeNullability {
|
||||
@@ -201,3 +203,8 @@ fun KotlinType.containsTypeProjectionsInTopLevelArguments(): Boolean {
|
||||
val possiblyInnerType = buildPossiblyInnerType() ?: return false
|
||||
return possiblyInnerType.arguments.any { it.isStarProjection || it.projectionKind != Variance.INVARIANT }
|
||||
}
|
||||
|
||||
fun UnwrappedType.canHaveUndefinedNullability(): Boolean =
|
||||
constructor is NewTypeVariableConstructor ||
|
||||
constructor.declarationDescriptor is TypeParameterDescriptor ||
|
||||
this is NewCapturedType
|
||||
|
||||
@@ -398,6 +398,9 @@ object NullabilityChecker {
|
||||
fun isSubtypeOfAny(type: UnwrappedType): Boolean =
|
||||
TypeCheckerContext(false).hasNotNullSupertype(type.lowerIfFlexible(), SupertypesPolicy.LowerIfFlexible)
|
||||
|
||||
fun hasPathByNotMarkedNullableNodes(start: SimpleType, end: TypeConstructor) =
|
||||
TypeCheckerContext(false).hasPathByNotMarkedNullableNodes(start, end)
|
||||
|
||||
private fun TypeCheckerContext.runIsPossibleSubtype(subType: SimpleType, superType: SimpleType): Boolean {
|
||||
// it makes for case String? & Any <: String
|
||||
assert(subType.isIntersectionType || subType.isSingleClassifierType || subType.isAllowedTypeVariable) {
|
||||
|
||||
Reference in New Issue
Block a user