FIR DFA: don't erase statements when entering non-call-in-place lambda
Instead, rely on the variable assignment analyzer to properly restrict smart casts. This makes error messages more consistent, but otherwise should have no effect.
This commit is contained in:
+10
-12
@@ -154,9 +154,8 @@ abstract class FirDataFlowAnalyzer(
|
|||||||
}
|
}
|
||||||
localFunctionNode?.mergeIncomingFlow()
|
localFunctionNode?.mergeIncomingFlow()
|
||||||
functionEnterNode.mergeIncomingFlow {
|
functionEnterNode.mergeIncomingFlow {
|
||||||
// TODO: ||?
|
if (function is FirAnonymousFunction && function.invocationKind?.canBeRevisited() == true) {
|
||||||
if (function is FirAnonymousFunction && function.invocationKind?.canBeRevisited() != false) {
|
enterRepeatableStatement(it, function)
|
||||||
enterCapturingStatement(it, function)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
context.variableAssignmentAnalyzer.enterFunction(function)
|
context.variableAssignmentAnalyzer.enterFunction(function)
|
||||||
@@ -166,9 +165,8 @@ abstract class FirDataFlowAnalyzer(
|
|||||||
if (function is FirDefaultPropertyAccessor) return null
|
if (function is FirDefaultPropertyAccessor) return null
|
||||||
|
|
||||||
context.variableAssignmentAnalyzer.exitFunction()
|
context.variableAssignmentAnalyzer.exitFunction()
|
||||||
// TODO: ||?
|
if (function is FirAnonymousFunction && function.invocationKind?.canBeRevisited() == true) {
|
||||||
if (function is FirAnonymousFunction && function.invocationKind?.canBeRevisited() != false) {
|
exitRepeatableStatement(function)
|
||||||
exitCapturingStatement(function)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (function is FirAnonymousFunction) {
|
if (function is FirAnonymousFunction) {
|
||||||
@@ -596,7 +594,7 @@ abstract class FirDataFlowAnalyzer(
|
|||||||
fun enterWhileLoop(loop: FirLoop) {
|
fun enterWhileLoop(loop: FirLoop) {
|
||||||
val (loopEnterNode, loopConditionEnterNode) = graphBuilder.enterWhileLoop(loop)
|
val (loopEnterNode, loopConditionEnterNode) = graphBuilder.enterWhileLoop(loop)
|
||||||
loopEnterNode.mergeIncomingFlow()
|
loopEnterNode.mergeIncomingFlow()
|
||||||
loopConditionEnterNode.mergeIncomingFlow { flow -> enterCapturingStatement(flow, loop) }
|
loopConditionEnterNode.mergeIncomingFlow { flow -> enterRepeatableStatement(flow, loop) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun exitWhileLoopCondition(loop: FirLoop) {
|
fun exitWhileLoopCondition(loop: FirLoop) {
|
||||||
@@ -620,7 +618,7 @@ abstract class FirDataFlowAnalyzer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun processWhileLoopExit(flow: MutableFlow, node: LoopExitNode, conditionEnterNode: LoopConditionEnterNode) {
|
private fun processWhileLoopExit(flow: MutableFlow, node: LoopExitNode, conditionEnterNode: LoopConditionEnterNode) {
|
||||||
val possiblyChangedVariables = exitCapturingStatement(node.fir)
|
val possiblyChangedVariables = exitRepeatableStatement(node.fir)
|
||||||
if (possiblyChangedVariables.isNullOrEmpty()) return
|
if (possiblyChangedVariables.isNullOrEmpty()) return
|
||||||
// While analyzing the loop we might have added some backwards jumps to `conditionEnterNode` which weren't
|
// While analyzing the loop we might have added some backwards jumps to `conditionEnterNode` which weren't
|
||||||
// there at the time its flow was computed - which is why we erased all information about `possiblyChangedVariables`
|
// there at the time its flow was computed - which is why we erased all information about `possiblyChangedVariables`
|
||||||
@@ -653,7 +651,7 @@ abstract class FirDataFlowAnalyzer(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun enterCapturingStatement(flow: MutableFlow, statement: FirStatement) {
|
private fun enterRepeatableStatement(flow: MutableFlow, statement: FirStatement) {
|
||||||
val reassignedNames = context.preliminaryLoopVisitor.enterCapturingStatement(statement)
|
val reassignedNames = context.preliminaryLoopVisitor.enterCapturingStatement(statement)
|
||||||
if (reassignedNames.isEmpty()) return
|
if (reassignedNames.isEmpty()) return
|
||||||
// TODO: only choose the innermost variable for each name
|
// TODO: only choose the innermost variable for each name
|
||||||
@@ -670,7 +668,7 @@ abstract class FirDataFlowAnalyzer(
|
|||||||
context.variablesClearedBeforeLoop.push(possiblyChangedVariables)
|
context.variablesClearedBeforeLoop.push(possiblyChangedVariables)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun exitCapturingStatement(statement: FirStatement): List<RealVariable>? {
|
private fun exitRepeatableStatement(statement: FirStatement): List<RealVariable>? {
|
||||||
if (context.preliminaryLoopVisitor.exitCapturingStatement(statement).isEmpty()) return null
|
if (context.preliminaryLoopVisitor.exitCapturingStatement(statement).isEmpty()) return null
|
||||||
return context.variablesClearedBeforeLoop.pop()
|
return context.variablesClearedBeforeLoop.pop()
|
||||||
}
|
}
|
||||||
@@ -679,7 +677,7 @@ abstract class FirDataFlowAnalyzer(
|
|||||||
|
|
||||||
fun enterDoWhileLoop(loop: FirLoop) {
|
fun enterDoWhileLoop(loop: FirLoop) {
|
||||||
val (loopEnterNode, loopBlockEnterNode) = graphBuilder.enterDoWhileLoop(loop)
|
val (loopEnterNode, loopBlockEnterNode) = graphBuilder.enterDoWhileLoop(loop)
|
||||||
loopEnterNode.mergeIncomingFlow { flow -> enterCapturingStatement(flow, loop) }
|
loopEnterNode.mergeIncomingFlow { flow -> enterRepeatableStatement(flow, loop) }
|
||||||
loopBlockEnterNode.mergeIncomingFlow()
|
loopBlockEnterNode.mergeIncomingFlow()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -693,7 +691,7 @@ abstract class FirDataFlowAnalyzer(
|
|||||||
val (loopConditionExitNode, loopExitNode) = graphBuilder.exitDoWhileLoop(loop)
|
val (loopConditionExitNode, loopExitNode) = graphBuilder.exitDoWhileLoop(loop)
|
||||||
loopConditionExitNode.mergeIncomingFlow()
|
loopConditionExitNode.mergeIncomingFlow()
|
||||||
loopExitNode.mergeIncomingFlow { processLoopExit(it, loopExitNode, loopConditionExitNode) }
|
loopExitNode.mergeIncomingFlow { processLoopExit(it, loopExitNode, loopConditionExitNode) }
|
||||||
exitCapturingStatement(loop)
|
exitRepeatableStatement(loop)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------- Try-catch-finally -----------------------------------
|
// ----------------------------------- Try-catch-finally -----------------------------------
|
||||||
|
|||||||
Vendored
+2
-2
@@ -30,7 +30,7 @@ fun baz(s: String?) {
|
|||||||
<!SMARTCAST_IMPOSSIBLE!>x<!>.hashCode()
|
<!SMARTCAST_IMPOSSIBLE!>x<!>.hashCode()
|
||||||
}
|
}
|
||||||
run {
|
run {
|
||||||
x<!UNSAFE_CALL!>.<!>hashCode()
|
<!SMARTCAST_IMPOSSIBLE!>x<!>.hashCode()
|
||||||
x = null
|
x = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -40,7 +40,7 @@ fun gaz(s: String?) {
|
|||||||
var x = s
|
var x = s
|
||||||
if (x != null) {
|
if (x != null) {
|
||||||
run {
|
run {
|
||||||
x<!UNSAFE_CALL!>.<!>hashCode()
|
<!SMARTCAST_IMPOSSIBLE!>x<!>.hashCode()
|
||||||
x = null
|
x = null
|
||||||
}
|
}
|
||||||
run {
|
run {
|
||||||
|
|||||||
Reference in New Issue
Block a user