[NI] Simplify code that capture types from expression

This commit is contained in:
Mikhail Zarechenskiy
2019-09-16 19:26:21 +03:00
parent 6327f657a5
commit 7e8784dca1
@@ -28,88 +28,73 @@ import org.jetbrains.kotlin.types.model.CapturedTypeMarker
import org.jetbrains.kotlin.types.refinement.TypeRefinement
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
import org.jetbrains.kotlin.types.typeUtil.builtIns
import org.jetbrains.kotlin.utils.DO_NOTHING_2
// if input type is capturedType, then we approximate it to UpperBound
// null means that type should be leaved as is
fun prepareArgumentTypeRegardingCaptureTypes(argumentType: UnwrappedType): UnwrappedType? {
val simpleType = NewKotlinTypeChecker.Default.transformToNewType(argumentType.lowerIfFlexible())
if (simpleType.constructor is IntersectionTypeConstructor) {
var changed = false
val preparedSuperTypes = simpleType.constructor.supertypes.map {
prepareArgumentTypeRegardingCaptureTypes(it.unwrap())?.apply { changed = true } ?: it.unwrap()
}
if (!changed) return null
return intersectTypes(preparedSuperTypes).makeNullableAsSpecified(simpleType.isMarkedNullable)
}
if (simpleType is NewCapturedType) {
// todo may be we should respect flexible/definitelyNotNull captured types also...
return simpleType.constructor.supertypes.takeIf { it.isNotEmpty() }?.let {
intersectTypes(it).makeNullableAsSpecified(simpleType.isMarkedNullable)
} ?: argumentType.builtIns.nullableAnyType
}
return captureFromExpression(simpleType)
return if (argumentType is NewCapturedType) null else captureFromExpression(argumentType)
}
fun captureFromExpression(type: UnwrappedType): UnwrappedType? = when (type) {
is SimpleType -> captureFromExpression(type)
// i.e. if there is nothing to capture -- no changes, if there is something -- use lowerBound as base type
is FlexibleType -> captureFromExpression(type.lowerBound)
}
fun captureFromExpression(type: UnwrappedType): UnwrappedType? =
captureFromExpression(type.lowerIfFlexible())
fun captureFromExpression(type: SimpleType): UnwrappedType? {
private fun captureFromExpression(type: SimpleType): UnwrappedType? {
val typeConstructor = type.constructor
if (typeConstructor is IntersectionTypeConstructor) {
var changed = false
val capturedSupertypes = typeConstructor.supertypes.map {
captureFromExpression(it.unwrap())?.apply { changed = true } ?: it.unwrap()
val capturedSupertypes = typeConstructor.supertypes.map { supertype ->
val unwrapped = supertype.unwrap()
captureFromExpression(unwrapped)?.apply { changed = true } ?: unwrapped
}
if (!changed) return null
return intersectTypes(capturedSupertypes).makeNullableAsSpecified(type.isMarkedNullable)
}
return captureFromArguments(type, CaptureStatus.FROM_EXPRESSION)
}
// this function suppose that input type is simple classifier type
fun captureFromArguments(
internal fun captureFromArguments(
type: SimpleType,
status: CaptureStatus,
acceptNewCapturedType: ((argumentIndex: Int, NewCapturedType) -> Unit) = DO_NOTHING_2
status: CaptureStatus
): SimpleType? {
if (type.arguments.size != type.constructor.parameters.size) return null
val arguments = type.arguments
if (arguments.all { it.projectionKind == Variance.INVARIANT }) return null
val newArguments = arguments.map { projection ->
val capturedArguments = arguments.map { projection ->
if (projection.projectionKind == Variance.INVARIANT) return@map projection
val lowerType = if (!projection.isStarProjection && projection.projectionKind == Variance.IN_VARIANCE) {
projection.type.unwrap()
} else null
val lowerType =
if (!projection.isStarProjection && projection.projectionKind == Variance.IN_VARIANCE) {
projection.type.unwrap()
} else {
null
}
NewCapturedType(status, lowerType, projection).asTypeProjection() // todo optimization: do not create type projection
}
val substitutor = TypeConstructorSubstitution.create(type.constructor, newArguments).buildSubstitutor()
val substitutor = TypeConstructorSubstitution.create(type.constructor, capturedArguments).buildSubstitutor()
for (index in arguments.indices) {
val oldProjection = arguments[index]
val newProjection = newArguments[index]
val newProjection = capturedArguments[index]
if (oldProjection.projectionKind == Variance.INVARIANT) continue
var upperBounds = type.constructor.parameters[index].upperBounds.map {
val capturedTypeSupertypes = type.constructor.parameters[index].upperBounds.mapTo(mutableListOf()) {
NewKotlinTypeChecker.Default.transformToNewType(substitutor.safeSubstitute(it, Variance.INVARIANT).unwrap())
}
if (!oldProjection.isStarProjection && oldProjection.projectionKind == Variance.OUT_VARIANCE) {
upperBounds += NewKotlinTypeChecker.Default.transformToNewType(oldProjection.type.unwrap())
capturedTypeSupertypes += NewKotlinTypeChecker.Default.transformToNewType(oldProjection.type.unwrap())
}
val capturedType = newProjection.type as NewCapturedType
capturedType.constructor.initializeSupertypes(upperBounds)
acceptNewCapturedType(index, capturedType)
capturedType.constructor.initializeSupertypes(capturedTypeSupertypes)
}
return KotlinTypeFactory.simpleType(type.annotations, type.constructor, newArguments, type.isMarkedNullable)
return KotlinTypeFactory.simpleType(type.annotations, type.constructor, capturedArguments, type.isMarkedNullable)
}
/**