FIR DFA: copy logic statements to aliases before removing variables
^KT-54744 Fixed
This commit is contained in:
@@ -1243,7 +1243,6 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
|||||||
)
|
)
|
||||||
val isAssignment = assignment != null
|
val isAssignment = assignment != null
|
||||||
if (isAssignment) {
|
if (isAssignment) {
|
||||||
logicSystem.removeLocalVariableAlias(flow, propertyVariable)
|
|
||||||
logicSystem.removeAllAboutVariable(flow, propertyVariable)
|
logicSystem.removeAllAboutVariable(flow, propertyVariable)
|
||||||
logicSystem.recordNewAssignment(flow, propertyVariable, context.newAssignmentIndex())
|
logicSystem.recordNewAssignment(flow, propertyVariable, context.newAssignmentIndex())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,13 +24,13 @@ abstract class LogicSystem<FLOW : Flow>(protected val context: ConeInferenceCont
|
|||||||
|
|
||||||
fun removeAllAboutVariable(flow: FLOW, variable: RealVariable?) {
|
fun removeAllAboutVariable(flow: FLOW, variable: RealVariable?) {
|
||||||
if (variable == null) return
|
if (variable == null) return
|
||||||
|
removeAliasInformationAboutVariable(flow, variable)
|
||||||
removeTypeStatementsAboutVariable(flow, variable)
|
removeTypeStatementsAboutVariable(flow, variable)
|
||||||
removeLogicStatementsAboutVariable(flow, variable)
|
removeLogicStatementsAboutVariable(flow, variable)
|
||||||
removeAliasInformationAboutVariable(flow, variable)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract fun removeTypeStatementsAboutVariable(flow: FLOW, variable: RealVariable)
|
abstract fun removeTypeStatementsAboutVariable(flow: FLOW, variable: RealVariable)
|
||||||
abstract fun removeLogicStatementsAboutVariable(flow: FLOW, variable: DataFlowVariable)
|
abstract fun removeLogicStatementsAboutVariable(flow: FLOW, variable: RealVariable)
|
||||||
abstract fun removeAliasInformationAboutVariable(flow: FLOW, variable: RealVariable)
|
abstract fun removeAliasInformationAboutVariable(flow: FLOW, variable: RealVariable)
|
||||||
|
|
||||||
abstract fun translateVariableFromConditionInStatements(
|
abstract fun translateVariableFromConditionInStatements(
|
||||||
|
|||||||
+14
-27
@@ -243,8 +243,12 @@ abstract class PersistentLogicSystem(context: ConeInferenceContext) : LogicSyste
|
|||||||
val original = flow.directAliasMap[alias]?.variable
|
val original = flow.directAliasMap[alias]?.variable
|
||||||
if (original != null) {
|
if (original != null) {
|
||||||
flow.directAliasMap = flow.directAliasMap.remove(alias)
|
flow.directAliasMap = flow.directAliasMap.remove(alias)
|
||||||
val variables = flow.backwardsAliasMap.getValue(original)
|
val updatedBackwardsAliasList = flow.backwardsAliasMap.getValue(original).remove(alias)
|
||||||
flow.backwardsAliasMap = flow.backwardsAliasMap.put(original, variables - alias)
|
flow.backwardsAliasMap = if (updatedBackwardsAliasList.isEmpty()) {
|
||||||
|
flow.backwardsAliasMap.remove(original)
|
||||||
|
} else {
|
||||||
|
flow.backwardsAliasMap.put(original, updatedBackwardsAliasList)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
flow.backwardsAliasMap = flow.backwardsAliasMap.remove(alias)
|
flow.backwardsAliasMap = flow.backwardsAliasMap.remove(alias)
|
||||||
for (backAlias in backAliases) {
|
for (backAlias in backAliases) {
|
||||||
@@ -312,32 +316,22 @@ abstract class PersistentLogicSystem(context: ConeInferenceContext) : LogicSyste
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun removeTypeStatementsAboutVariable(flow: PersistentFlow, variable: RealVariable) {
|
override fun removeTypeStatementsAboutVariable(flow: PersistentFlow, variable: RealVariable) {
|
||||||
flow.approvedTypeStatements -= variable
|
|
||||||
flow.approvedTypeStatementsDiff -= variable
|
|
||||||
variable.forEachTransitiveDependentVariable {
|
variable.forEachTransitiveDependentVariable {
|
||||||
flow.approvedTypeStatements -= it
|
flow.approvedTypeStatements -= it
|
||||||
flow.approvedTypeStatementsDiff -= it
|
flow.approvedTypeStatementsDiff -= it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun removeLogicStatementsAboutVariable(flow: PersistentFlow, variable: DataFlowVariable) {
|
override fun removeLogicStatementsAboutVariable(flow: PersistentFlow, variable: RealVariable) {
|
||||||
flow.logicStatements -= variable
|
variable.forEachTransitiveDependentVariable {
|
||||||
val realVariable = variable as? RealVariable
|
|
||||||
realVariable?.forEachTransitiveDependentVariable {
|
|
||||||
flow.logicStatements -= it
|
flow.logicStatements -= it
|
||||||
}
|
}
|
||||||
var newLogicStatements = flow.logicStatements
|
var newLogicStatements = flow.logicStatements
|
||||||
for ((key, implications) in flow.logicStatements) {
|
for ((key, implications) in flow.logicStatements) {
|
||||||
val implicationsToDelete = mutableListOf<Implication>()
|
val implicationsToDelete = mutableListOf<Implication>()
|
||||||
implications.forEach { implication ->
|
variable.forEachTransitiveDependentVariable {
|
||||||
val implicationVariable = implication.effect.variable
|
implications.filterTo(implicationsToDelete) { implication ->
|
||||||
if (implicationVariable == variable) {
|
implication.effect.variable == it
|
||||||
implicationsToDelete += implication
|
|
||||||
}
|
|
||||||
realVariable?.forEachTransitiveDependentVariable {
|
|
||||||
if (implicationVariable == it) {
|
|
||||||
implicationsToDelete += implication
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (implicationsToDelete.isEmpty()) continue
|
if (implicationsToDelete.isEmpty()) continue
|
||||||
@@ -352,22 +346,15 @@ abstract class PersistentLogicSystem(context: ConeInferenceContext) : LogicSyste
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun removeAliasInformationAboutVariable(flow: PersistentFlow, variable: RealVariable) {
|
override fun removeAliasInformationAboutVariable(flow: PersistentFlow, variable: RealVariable) {
|
||||||
val existedAlias = flow.directAliasMap[variable]?.variable
|
variable.forEachTransitiveDependentVariable {
|
||||||
if (existedAlias != null) {
|
removeLocalVariableAlias(flow, it)
|
||||||
flow.directAliasMap = flow.directAliasMap.remove(variable)
|
|
||||||
val updatedBackwardsAliasList = flow.backwardsAliasMap.getValue(existedAlias).remove(variable)
|
|
||||||
flow.backwardsAliasMap = if (updatedBackwardsAliasList.isEmpty()) {
|
|
||||||
flow.backwardsAliasMap.remove(existedAlias)
|
|
||||||
} else {
|
|
||||||
flow.backwardsAliasMap.put(existedAlias, updatedBackwardsAliasList)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun RealVariable.forEachTransitiveDependentVariable(action: (RealVariable) -> Unit) {
|
private fun RealVariable.forEachTransitiveDependentVariable(action: (RealVariable) -> Unit) {
|
||||||
|
action(this)
|
||||||
dependentVariables.forEach {
|
dependentVariables.forEach {
|
||||||
it.forEachTransitiveDependentVariable(action)
|
it.forEachTransitiveDependentVariable(action)
|
||||||
action(it)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -9,7 +9,7 @@ fun test1() {
|
|||||||
x.length // ok
|
x.length // ok
|
||||||
c.x.length // ok
|
c.x.length // ok
|
||||||
c = C(null)
|
c = C(null)
|
||||||
x<!UNSAFE_CALL!>.<!>length // ok
|
x.length // ok
|
||||||
c.x<!UNSAFE_CALL!>.<!>length // bad
|
c.x<!UNSAFE_CALL!>.<!>length // bad
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -18,10 +18,10 @@ fun test2() {
|
|||||||
val x = c.x
|
val x = c.x
|
||||||
if (x == null) return
|
if (x == null) return
|
||||||
while (true) {
|
while (true) {
|
||||||
x<!UNSAFE_CALL!>.<!>length // ok
|
x.length // ok
|
||||||
c.x<!UNSAFE_CALL!>.<!>length // bad
|
c.x<!UNSAFE_CALL!>.<!>length // bad
|
||||||
c = C(null)
|
c = C(null)
|
||||||
x<!UNSAFE_CALL!>.<!>length // ok
|
x.length // ok
|
||||||
c.x<!UNSAFE_CALL!>.<!>length // bad
|
c.x<!UNSAFE_CALL!>.<!>length // bad
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user