[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:
Mikhail Zarechenskiy
2018-11-21 16:07:00 +03:00
parent aa224558bd
commit c6712ff861
8 changed files with 124 additions and 7 deletions
@@ -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())
}
}