FIR DFA: avoid inverting type statements
By necessity, type statements underapproximate. Therefore, inverting doesn't always produce an equal result. It's best to propagate negations inwards to preserve precision as much as possible.
This commit is contained in:
+2
-11
@@ -17,10 +17,7 @@ data class PersistentTypeStatement(
|
||||
override val variable: RealVariable,
|
||||
override val exactType: PersistentSet<ConeKotlinType>,
|
||||
override val exactNotType: PersistentSet<ConeKotlinType>
|
||||
) : TypeStatement() {
|
||||
override fun invert(): PersistentTypeStatement =
|
||||
PersistentTypeStatement(variable, exactNotType, exactType)
|
||||
}
|
||||
) : TypeStatement()
|
||||
|
||||
typealias PersistentApprovedTypeStatements = PersistentMap<RealVariable, PersistentTypeStatement>
|
||||
typealias PersistentImplications = PersistentMap<DataFlowVariable, PersistentList<Implication>>
|
||||
@@ -397,11 +394,6 @@ private fun TypeStatement.toPersistent(): PersistentTypeStatement = when (this)
|
||||
else -> PersistentTypeStatement(variable, exactType.toPersistentSet(), exactNotType.toPersistentSet())
|
||||
}
|
||||
|
||||
fun TypeStatement.asMutableStatement(): MutableTypeStatement = when (this) {
|
||||
is MutableTypeStatement -> this
|
||||
else -> MutableTypeStatement(variable, exactType.toMutableSet(), exactNotType.toMutableSet())
|
||||
}
|
||||
|
||||
@JvmName("replaceVariableInStatements")
|
||||
private fun PersistentApprovedTypeStatements.replaceVariable(from: RealVariable, to: RealVariable?): PersistentApprovedTypeStatements {
|
||||
val existing = this[from] ?: return this
|
||||
@@ -440,10 +432,9 @@ private fun Implication.replaceVariable(from: RealVariable, to: RealVariable): I
|
||||
else -> this
|
||||
}
|
||||
|
||||
private fun Statement<*>.replaceVariable(from: RealVariable, to: RealVariable): Statement<*> =
|
||||
private fun Statement.replaceVariable(from: RealVariable, to: RealVariable): Statement =
|
||||
if (variable != from) this else when (this) {
|
||||
is OperationStatement -> copy(variable = to)
|
||||
is PersistentTypeStatement -> copy(variable = to)
|
||||
is MutableTypeStatement -> MutableTypeStatement(to, exactType, exactNotType)
|
||||
else -> throw IllegalArgumentException("unknown type of statement $this")
|
||||
}
|
||||
|
||||
@@ -17,14 +17,6 @@ class MutableTypeStatement(
|
||||
override val exactType: MutableSet<ConeKotlinType> = linkedSetOf(),
|
||||
override val exactNotType: MutableSet<ConeKotlinType> = linkedSetOf()
|
||||
) : TypeStatement() {
|
||||
override fun invert(): MutableTypeStatement {
|
||||
return MutableTypeStatement(
|
||||
variable,
|
||||
LinkedHashSet(exactNotType),
|
||||
LinkedHashSet(exactType)
|
||||
)
|
||||
}
|
||||
|
||||
fun copy(): MutableTypeStatement = MutableTypeStatement(variable, LinkedHashSet(exactType), LinkedHashSet(exactNotType))
|
||||
}
|
||||
|
||||
@@ -33,7 +25,6 @@ fun Implication.invertCondition(): Implication = Implication(condition.invert(),
|
||||
// --------------------------------------- Aliases ---------------------------------------
|
||||
|
||||
typealias TypeStatements = Map<RealVariable, TypeStatement>
|
||||
typealias MutableTypeStatements = MutableMap<RealVariable, MutableTypeStatement>
|
||||
|
||||
// --------------------------------------- DSL ---------------------------------------
|
||||
|
||||
@@ -55,7 +46,7 @@ infix fun DataFlowVariable.notEq(constant: Boolean?): OperationStatement {
|
||||
return OperationStatement(this, condition)
|
||||
}
|
||||
|
||||
infix fun OperationStatement.implies(effect: Statement<*>): Implication = Implication(this, effect)
|
||||
infix fun OperationStatement.implies(effect: Statement): Implication = Implication(this, effect)
|
||||
|
||||
infix fun RealVariable.typeEq(type: ConeKotlinType): MutableTypeStatement =
|
||||
MutableTypeStatement(this) andTypeEq type
|
||||
|
||||
@@ -7,8 +7,7 @@ package org.jetbrains.kotlin.fir.resolve.dfa
|
||||
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
|
||||
sealed class Statement<T : Statement<T>> {
|
||||
abstract fun invert(): T
|
||||
sealed class Statement {
|
||||
abstract val variable: DataFlowVariable
|
||||
}
|
||||
|
||||
@@ -19,8 +18,8 @@ sealed class Statement<T : Statement<T>> {
|
||||
* d == True
|
||||
* d == False
|
||||
*/
|
||||
data class OperationStatement(override val variable: DataFlowVariable, val operation: Operation) : Statement<OperationStatement>() {
|
||||
override fun invert(): OperationStatement {
|
||||
data class OperationStatement(override val variable: DataFlowVariable, val operation: Operation) : Statement() {
|
||||
fun invert(): OperationStatement {
|
||||
return OperationStatement(variable, operation.invert())
|
||||
}
|
||||
|
||||
@@ -29,7 +28,7 @@ data class OperationStatement(override val variable: DataFlowVariable, val opera
|
||||
}
|
||||
}
|
||||
|
||||
abstract class TypeStatement : Statement<TypeStatement>() {
|
||||
sealed class TypeStatement : Statement() {
|
||||
abstract override val variable: RealVariable
|
||||
abstract val exactType: Set<ConeKotlinType>
|
||||
abstract val exactNotType: Set<ConeKotlinType>
|
||||
@@ -47,7 +46,7 @@ abstract class TypeStatement : Statement<TypeStatement>() {
|
||||
|
||||
class Implication(
|
||||
val condition: OperationStatement,
|
||||
val effect: Statement<*>
|
||||
val effect: Statement
|
||||
) {
|
||||
override fun toString(): String {
|
||||
return "$condition -> $effect"
|
||||
|
||||
Reference in New Issue
Block a user