Fix substitution of generic types in contracts

#KT-41078 Fixed
This commit is contained in:
Dmitriy Novozhilov
2021-04-16 13:39:52 +03:00
committed by TeamCityServer
parent 91fedd6a12
commit b530427bb2
8 changed files with 155 additions and 15 deletions
@@ -16,8 +16,10 @@
package org.jetbrains.kotlin.contracts.model
import org.jetbrains.kotlin.contracts.model.structure.ESKotlinType
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.contracts.model.visitors.Reducer
import org.jetbrains.kotlin.resolve.calls.inference.components.EmptySubstitutor
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
/**
* An abstraction of effect-generating nature of some computation.
@@ -43,4 +45,13 @@ abstract class AbstractFunctor : Functor {
): List<ESEffect>
}
typealias ESTypeSubstitution = Map<ESKotlinType, ESKotlinType>
class ESTypeSubstitution(
val substitutor: NewTypeSubstitutor,
val builtIns: KotlinBuiltIns
) {
companion object {
fun empty(builtIns: KotlinBuiltIns): ESTypeSubstitution {
return ESTypeSubstitution(EmptySubstitutor, builtIns)
}
}
}
@@ -17,10 +17,7 @@
package org.jetbrains.kotlin.contracts.model.functors
import org.jetbrains.kotlin.contracts.model.*
import org.jetbrains.kotlin.contracts.model.structure.ESConstants
import org.jetbrains.kotlin.contracts.model.structure.ESIs
import org.jetbrains.kotlin.contracts.model.structure.ESReturns
import org.jetbrains.kotlin.contracts.model.structure.ESType
import org.jetbrains.kotlin.contracts.model.structure.*
import org.jetbrains.kotlin.contracts.model.visitors.Reducer
class IsFunctor(val type: ESType, val isNegated: Boolean) : AbstractFunctor() {
@@ -37,7 +34,9 @@ class IsFunctor(val type: ESType, val isNegated: Boolean) : AbstractFunctor() {
}
private fun invokeWithValue(value: ESValue, typeSubstitution: ESTypeSubstitution): List<ConditionalEffect> {
val substitutedType = typeSubstitution[type] ?: type
val substitutedKotlinType = typeSubstitution.substitutor.safeSubstitute(type.toKotlinType(typeSubstitution.builtIns).unwrap())
val substitutedType = ESKotlinType(substitutedKotlinType)
val trueIs = ESIs(value, IsFunctor(substitutedType, isNegated))
val falseIs = ESIs(value, IsFunctor(substitutedType, isNegated.not()))