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:
@@ -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
|
||||
|
||||
+4
-23
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user