FIR CFG: ignore exception edges when looking for return values
^KT-54668 Fixed
This commit is contained in:
Vendored
+1
-1
@@ -15,5 +15,5 @@ FILE: lazyValWithElvisToNothingInside.kt
|
||||
}
|
||||
)
|
||||
public get(): R|kotlin/collections/Map<kotlin/String, kotlin/String>| {
|
||||
^ D|/x|.<CS errors: kotlin/getValue>#<R|kotlin/collections/Map<kotlin/String, kotlin/String>|>(Null(null), ::R|/x|)
|
||||
^ D|/x|.R|kotlin/getValue|<R|kotlin/collections/Map<kotlin/String, kotlin/String>|>(Null(null), ::R|/x|)
|
||||
}
|
||||
|
||||
+2
-2
@@ -7,8 +7,8 @@ interface A {
|
||||
|
||||
fun getA(): A? = null
|
||||
|
||||
val x by <!DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE, NEW_INFERENCE_ERROR!>lazy {
|
||||
val x by lazy {
|
||||
(getA() ?: error("error")).list.associateBy {
|
||||
it
|
||||
}
|
||||
}<!>
|
||||
}
|
||||
|
||||
+2
-2
@@ -38,12 +38,12 @@ FILE: kotlinSam.kt
|
||||
}
|
||||
)
|
||||
R|/foo1|(R|<local>/f|)
|
||||
<Inapplicable(INAPPLICABLE): /foo2>#(<L> = foo2@fun <anonymous>(x: R|kotlin/Nothing|): R|kotlin/Nothing| <inline=Unknown> {
|
||||
<Inapplicable(INAPPLICABLE): /foo2>#(<L> = foo2@fun <anonymous>(x: R|kotlin/Nothing|): R|kotlin/Boolean| <inline=Unknown> {
|
||||
^ CMP(>, R|<local>/x|.<Unresolved name: compareTo>#(Int(1)))
|
||||
}
|
||||
)
|
||||
<Inapplicable(INAPPLICABLE): /foo2>#(R|<local>/f|)
|
||||
<Inapplicable(INAPPLICABLE): /foo3>#(<L> = foo3@fun <anonymous>(x: R|kotlin/Nothing|): R|kotlin/Nothing| <inline=Unknown> {
|
||||
<Inapplicable(INAPPLICABLE): /foo3>#(<L> = foo3@fun <anonymous>(x: R|kotlin/Nothing|): R|kotlin/Boolean| <inline=Unknown> {
|
||||
^ CMP(>, R|<local>/x|.<Unresolved name: compareTo>#(Int(1)))
|
||||
}
|
||||
)
|
||||
|
||||
Vendored
+1
-1
@@ -2,7 +2,7 @@ FILE: main.kt
|
||||
public final fun foo(m: R|MyRunnable|): R|kotlin/Unit| {
|
||||
}
|
||||
public final fun main(): R|kotlin/Unit| {
|
||||
Q|JavaUsage|.<Inapplicable(INAPPLICABLE): /JavaUsage.foo>#(<L> = foo@fun <anonymous>(x: R|kotlin/Nothing|): R|kotlin/Nothing| <inline=Unknown> {
|
||||
Q|JavaUsage|.<Inapplicable(INAPPLICABLE): /JavaUsage.foo>#(<L> = foo@fun <anonymous>(x: R|kotlin/Nothing|): R|kotlin/Boolean| <inline=Unknown> {
|
||||
^ CMP(>, R|<local>/x|.<Unresolved name: compareTo>#(Int(1)))
|
||||
}
|
||||
)
|
||||
|
||||
+11
-6
@@ -97,24 +97,29 @@ class ControlFlowGraphBuilder {
|
||||
// ----------------------------------- Public API -----------------------------------
|
||||
|
||||
fun returnExpressionsOfAnonymousFunction(function: FirAnonymousFunction): Collection<FirStatement>? {
|
||||
val exitNode = function.controlFlowGraphReference?.controlFlowGraph?.exitNode
|
||||
?: return null
|
||||
val exitNode = function.controlFlowGraphReference?.controlFlowGraph?.exitNode ?: return null
|
||||
|
||||
fun FirElement.extractArgument(): FirElement = when {
|
||||
this is FirReturnExpression && target.labeledElement.symbol == function.symbol -> result.extractArgument()
|
||||
else -> this
|
||||
}
|
||||
|
||||
fun CFGNode<*>.extractArgument(): FirElement? = when (this) {
|
||||
fun CFGNode<*>.extractArgument(): FirStatement? = when (this) {
|
||||
is FunctionEnterNode, is TryMainBlockEnterNode, is FinallyBlockExitNode, is CatchClauseEnterNode -> null
|
||||
is BlockExitNode -> if (function.isLambda || isDead) firstPreviousNode.extractArgument() else null
|
||||
is StubNode -> firstPreviousNode.extractArgument()
|
||||
else -> fir.extractArgument()
|
||||
else -> fir.extractArgument() as FirStatement?
|
||||
}
|
||||
|
||||
return (nonDirectJumps[exitNode] + exitNode.previousNodes).mapNotNullTo(mutableSetOf()) {
|
||||
it.extractArgument() as FirStatement?
|
||||
val returnValues = exitNode.previousNodes.mapNotNullTo(mutableSetOf()) {
|
||||
val edge = exitNode.incomingEdges.getValue(it)
|
||||
// * NormalPath: last expression = return value
|
||||
// * UncaughtExceptionPath: last expression = whatever threw, *not* a return value
|
||||
// * ReturnPath(this lambda): these go from `finally` blocks, so that's not the return value;
|
||||
// look in `nonDirectJumps` instead.
|
||||
it.takeIf { edge.kind.usedInCfa && edge.label == NormalPath }?.extractArgument()
|
||||
}
|
||||
return nonDirectJumps[exitNode].mapNotNullTo(returnValues) { it.extractArgument() }
|
||||
}
|
||||
|
||||
@OptIn(CfgBuilderInternals::class)
|
||||
|
||||
Reference in New Issue
Block a user