[NI] Correctly compute definitely not null type for intersection one
{ T : Any? & Foo & Bar? }!! -> { T!! & Foo & Bar }
Also, fix bug with loosing non-representative number type.
For example, for type { Byte & SomeType } we lost type `Byte` because
`getDefaultPrimitiveNumberType` returns null for it
Fixes #KT-28334 for NI
This commit is contained in:
+6
-2
@@ -128,8 +128,12 @@ class ResultTypeResolver(
|
||||
newSupertypes.add(supertype)
|
||||
}
|
||||
|
||||
TypeUtils.getDefaultPrimitiveNumberType(numberSupertypes)?.let {
|
||||
newSupertypes.add(it.unwrap())
|
||||
|
||||
val representativeNumberType = TypeUtils.getDefaultPrimitiveNumberType(numberSupertypes)
|
||||
if (representativeNumberType != null) {
|
||||
newSupertypes.add(representativeNumberType.unwrap())
|
||||
} else {
|
||||
newSupertypes.addAll(numberSupertypes.map { it.unwrap() })
|
||||
}
|
||||
|
||||
intersectTypes(newSupertypes).makeNullableAsSpecified(commonSuperType.isMarkedNullable)
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
// !LANGUAGE: +NewInference
|
||||
|
||||
fun simpleTypeAndNumberType(b: Comparable<*>?) {
|
||||
if (b is Byte?) {
|
||||
<!DEBUG_INFO_SMARTCAST!>b<!>!!.dec()
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> typeParmeterAndNumberType(b: T?) {
|
||||
if (b is Byte?) {
|
||||
b!!.dec()
|
||||
}
|
||||
}
|
||||
|
||||
fun anyAndNumberType(b: Any?) {
|
||||
if (b is Byte?) {
|
||||
<!DEBUG_INFO_SMARTCAST!>b<!>!!.dec()
|
||||
}
|
||||
}
|
||||
|
||||
fun comparableAndNumberType(b: Comparable<Byte>?) {
|
||||
if (b is Byte?) {
|
||||
<!DEBUG_INFO_SMARTCAST!>b<!>!!.dec()
|
||||
}
|
||||
}
|
||||
|
||||
object SeparateTypes {
|
||||
interface A
|
||||
interface B {
|
||||
fun foo() {}
|
||||
}
|
||||
|
||||
fun separate(a: A?) {
|
||||
if (a is B?) {
|
||||
a!!.foo()
|
||||
}
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package
|
||||
|
||||
public fun anyAndNumberType(/*0*/ b: kotlin.Any?): kotlin.Unit
|
||||
public fun comparableAndNumberType(/*0*/ b: kotlin.Comparable<kotlin.Byte>?): kotlin.Unit
|
||||
public fun simpleTypeAndNumberType(/*0*/ b: kotlin.Comparable<*>?): kotlin.Unit
|
||||
public fun </*0*/ T> typeParmeterAndNumberType(/*0*/ b: T?): kotlin.Unit
|
||||
|
||||
public object SeparateTypes {
|
||||
private constructor SeparateTypes()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public final fun separate(/*0*/ a: SeparateTypes.A?): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
public interface A {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface B {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open fun foo(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
}
|
||||
@@ -8420,6 +8420,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
runTest("compiler/testData/diagnostics/tests/generics/nullability/functionalBound.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inferNotNullTypeFromIntersectionOfNullableTypes.kt")
|
||||
public void testInferNotNullTypeFromIntersectionOfNullableTypes() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/generics/nullability/inferNotNullTypeFromIntersectionOfNullableTypes.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nullToGeneric.kt")
|
||||
public void testNullToGeneric() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/generics/nullability/nullToGeneric.kt");
|
||||
|
||||
Generated
+5
@@ -8420,6 +8420,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
|
||||
runTest("compiler/testData/diagnostics/tests/generics/nullability/functionalBound.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inferNotNullTypeFromIntersectionOfNullableTypes.kt")
|
||||
public void testInferNotNullTypeFromIntersectionOfNullableTypes() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/generics/nullability/inferNotNullTypeFromIntersectionOfNullableTypes.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nullToGeneric.kt")
|
||||
public void testNullToGeneric() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/generics/nullability/nullToGeneric.kt");
|
||||
|
||||
@@ -21,7 +21,6 @@ import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.TypeIntersectionScope
|
||||
|
||||
import java.util.*
|
||||
|
||||
class IntersectionTypeConstructor(typesToIntersect: Collection<KotlinType>) : TypeConstructor {
|
||||
@@ -63,3 +62,22 @@ class IntersectionTypeConstructor(typesToIntersect: Collection<KotlinType>) : Ty
|
||||
|
||||
override fun hashCode(): Int = hashCode
|
||||
}
|
||||
|
||||
inline fun IntersectionTypeConstructor.transformComponents(
|
||||
predicate: (KotlinType) -> Boolean = { true },
|
||||
transform: (KotlinType) -> KotlinType
|
||||
): IntersectionTypeConstructor? {
|
||||
var changed = false
|
||||
val newSupertypes = supertypes.map {
|
||||
if (predicate(it)) {
|
||||
changed = true
|
||||
transform(it)
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}
|
||||
|
||||
if (!changed) return null
|
||||
|
||||
return IntersectionTypeConstructor(newSupertypes)
|
||||
}
|
||||
@@ -111,7 +111,28 @@ val KotlinType.isDefinitelyNotNullType: Boolean
|
||||
get() = unwrap() is DefinitelyNotNullType
|
||||
|
||||
fun SimpleType.makeSimpleTypeDefinitelyNotNullOrNotNull(): SimpleType =
|
||||
DefinitelyNotNullType.makeDefinitelyNotNull(this) ?: makeNullableAsSpecified(false)
|
||||
DefinitelyNotNullType.makeDefinitelyNotNull(this)
|
||||
?: makeIntersectionTypeDefinitelyNotNullOrNotNull()
|
||||
?: makeNullableAsSpecified(false)
|
||||
|
||||
fun UnwrappedType.makeDefinitelyNotNullOrNotNull(): UnwrappedType =
|
||||
DefinitelyNotNullType.makeDefinitelyNotNull(this) ?: makeNullableAsSpecified(false)
|
||||
DefinitelyNotNullType.makeDefinitelyNotNull(this)
|
||||
?: makeIntersectionTypeDefinitelyNotNullOrNotNull()
|
||||
?: makeNullableAsSpecified(false)
|
||||
|
||||
private fun KotlinType.makeIntersectionTypeDefinitelyNotNullOrNotNull(): SimpleType? {
|
||||
val typeConstructor = constructor as? IntersectionTypeConstructor ?: return null
|
||||
val definitelyNotNullConstructor = typeConstructor.makeDefinitelyNotNullOrNotNull() ?: return null
|
||||
|
||||
return KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope(
|
||||
annotations,
|
||||
definitelyNotNullConstructor,
|
||||
listOf(),
|
||||
false,
|
||||
definitelyNotNullConstructor.createScopeForKotlinType()
|
||||
)
|
||||
}
|
||||
|
||||
private fun IntersectionTypeConstructor.makeDefinitelyNotNullOrNotNull(): IntersectionTypeConstructor? {
|
||||
return transformComponents({ TypeUtils.isNullableType(it) }, { it.unwrap().makeDefinitelyNotNullOrNotNull() })
|
||||
}
|
||||
|
||||
@@ -153,8 +153,7 @@ object NewKotlinTypeChecker : KotlinTypeChecker {
|
||||
}
|
||||
|
||||
is IntersectionTypeConstructor -> if (type.isMarkedNullable) {
|
||||
val newSuperTypes = constructor.supertypes.map { it.makeNullable() }
|
||||
val newConstructor = IntersectionTypeConstructor(newSuperTypes)
|
||||
val newConstructor = constructor.transformComponents(transform = { it.makeNullable() }) ?: constructor
|
||||
return KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope(type.annotations, newConstructor, listOf(), false, newConstructor.createScopeForKotlinType())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user