FIR DFA: do not re-approve statements from LHS of and/or

If the right-hand side is evaluated at all, then in its flow those
statements were already approved. Re-approving them erases the effect of
reassignments.

^KT-28369 tag fixed-in-k2
This commit is contained in:
pyos
2022-11-09 14:10:43 +01:00
committed by teamcity
parent edaca59d83
commit 1506c493c8
7 changed files with 21 additions and 59 deletions
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.resolve.dfa
import org.jetbrains.kotlin.fir.types.ConeKotlinType
abstract class Flow {
abstract val approvedTypeStatements: TypeStatements
abstract fun unwrapVariable(variable: RealVariable): RealVariable
abstract fun getType(variable: RealVariable): Set<ConeKotlinType>?
}
@@ -49,24 +49,7 @@ abstract class LogicSystem<FLOW : Flow>(protected val context: ConeInferenceCont
// ------------------------------- Public TypeStatement util functions -------------------------------
data class InfoForBooleanOperator(
val conditionalFromLeft: Collection<Implication>,
val conditionalFromRight: Collection<Implication>,
val knownFromRight: TypeStatements,
)
abstract fun collectInfoForBooleanOperator(
leftFlow: FLOW,
leftVariable: DataFlowVariable,
rightFlow: FLOW,
rightVariable: DataFlowVariable,
): InfoForBooleanOperator
abstract fun approveOperationStatement(
flow: FLOW,
approvedStatement: OperationStatement,
statementsForVariable: Collection<Implication>?
): TypeStatements
abstract fun approveOperationStatement(flow: FLOW, approvedStatement: OperationStatement): TypeStatements
fun orForTypeStatements(left: TypeStatements, right: TypeStatements): TypeStatements = when {
left.isEmpty() -> left
@@ -23,7 +23,7 @@ typealias PersistentImplications = PersistentMap<DataFlowVariable, PersistentLis
class PersistentFlow : Flow {
val previousFlow: PersistentFlow?
var approvedTypeStatements: PersistentApprovedTypeStatements
override var approvedTypeStatements: PersistentApprovedTypeStatements
var logicStatements: PersistentImplications
val level: Int
@@ -257,7 +257,7 @@ abstract class PersistentLogicSystem(context: ConeInferenceContext) : LogicSyste
}
override fun commitOperationStatement(flow: PersistentFlow, statement: OperationStatement, shouldRemoveSynthetics: Boolean) {
approveOperationStatementsInternal(flow, statement, initialStatements = null, shouldRemoveSynthetics).values.forEach {
approveOperationStatementsInternal(flow, statement, shouldRemoveSynthetics).values.forEach {
addTypeStatement(flow, it)
}
}
@@ -265,21 +265,17 @@ abstract class PersistentLogicSystem(context: ConeInferenceContext) : LogicSyste
private fun approveOperationStatementsInternal(
flow: PersistentFlow,
approvedStatement: OperationStatement,
initialStatements: Collection<Implication>?,
shouldRemoveSynthetics: Boolean
): TypeStatements {
val approvedTypeStatements: ArrayListMultimap<RealVariable, TypeStatement> = ArrayListMultimap.create()
val queue = LinkedList<OperationStatement>().apply { this += approvedStatement }
val approved = mutableSetOf<OperationStatement>()
var firstIteration = true
while (queue.isNotEmpty()) {
val next: OperationStatement = queue.removeFirst()
// Defense from cycles in facts
if (!approved.add(next)) continue
val variable = next.variable
val statements = initialStatements?.takeIf { firstIteration }
?: flow.logicStatements[variable]?.takeIf { it.isNotEmpty() }
?: continue
val statements = flow.logicStatements[variable]?.takeIf { it.isNotEmpty() } ?: continue
if (shouldRemoveSynthetics && variable.isSynthetic()) {
flow.logicStatements -= variable
}
@@ -291,7 +287,6 @@ abstract class PersistentLogicSystem(context: ConeInferenceContext) : LogicSyste
}
}
}
firstIteration = false
}
return approvedTypeStatements.asMap().mapValues { and(it.value) }
}
@@ -299,21 +294,7 @@ abstract class PersistentLogicSystem(context: ConeInferenceContext) : LogicSyste
override fun approveOperationStatement(
flow: PersistentFlow,
approvedStatement: OperationStatement,
statementsForVariable: Collection<Implication>?
): TypeStatements = approveOperationStatementsInternal(flow, approvedStatement, statementsForVariable, shouldRemoveSynthetics = false)
override fun collectInfoForBooleanOperator(
leftFlow: PersistentFlow,
leftVariable: DataFlowVariable,
rightFlow: PersistentFlow,
rightVariable: DataFlowVariable
): InfoForBooleanOperator {
return InfoForBooleanOperator(
leftFlow.logicStatements[leftVariable] ?: emptyList(),
rightFlow.logicStatements[rightVariable] ?: emptyList(),
rightFlow.approvedTypeStatements
)
}
): TypeStatements = approveOperationStatementsInternal(flow, approvedStatement, shouldRemoveSynthetics = false)
override fun getImplicationsWithVariable(flow: PersistentFlow, variable: DataFlowVariable): Collection<Implication> {
return flow.logicStatements[variable] ?: emptyList()