[FIR] Fix false positive "return required" for if/else with inlined return in branch
^KT-49289 Fixed
This commit is contained in:
committed by
TeamCityServer
parent
5b10396f48
commit
744191099c
+6
@@ -15843,6 +15843,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
|
||||
runTest("compiler/testData/diagnostics/tests/inline/inlineReified.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inlinedReturnInBranch.kt")
|
||||
public void testInlinedReturnInBranch() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inline/inlinedReturnInBranch.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("invoke.kt")
|
||||
public void testInvoke() throws Exception {
|
||||
|
||||
+6
@@ -15843,6 +15843,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
runTest("compiler/testData/diagnostics/tests/inline/inlineReified.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inlinedReturnInBranch.kt")
|
||||
public void testInlinedReturnInBranch() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inline/inlinedReturnInBranch.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("invoke.kt")
|
||||
public void testInvoke() throws Exception {
|
||||
|
||||
+6
@@ -15843,6 +15843,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
runTest("compiler/testData/diagnostics/tests/inline/inlineReified.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inlinedReturnInBranch.kt")
|
||||
public void testInlinedReturnInBranch() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inline/inlinedReturnInBranch.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("invoke.kt")
|
||||
public void testInvoke() throws Exception {
|
||||
|
||||
+6
-3
@@ -641,6 +641,7 @@ class ControlFlowGraphBuilder {
|
||||
addNewSimpleNode(node)
|
||||
whenExitNodes.push(createWhenExitNode(whenExpression))
|
||||
whenBranchIndices.push(whenExpression.branches.mapIndexed { index, branch -> branch to index }.toMap())
|
||||
notCompletedFunctionCalls.push(mutableListOf())
|
||||
levelCounter++
|
||||
return node
|
||||
}
|
||||
@@ -676,6 +677,7 @@ class ControlFlowGraphBuilder {
|
||||
val whenExitNode = whenExitNodes.pop()
|
||||
// exit from last condition node still on stack
|
||||
// we should remove it
|
||||
notCompletedFunctionCalls.pop().forEach(::completeFunctionCall)
|
||||
val lastWhenConditionExit = lastNodes.pop()
|
||||
val syntheticElseBranchNode = if (!whenExpression.isProperlyExhaustive) {
|
||||
createWhenSyntheticElseBranchNode(whenExpression).apply {
|
||||
@@ -985,7 +987,7 @@ class ControlFlowGraphBuilder {
|
||||
catchNodeStorages.pop()
|
||||
val catchExitNodes = catchExitNodeStorages.pop()
|
||||
val tryMainExitNode = tryMainExitNodes.pop()
|
||||
|
||||
|
||||
notCompletedFunctionCalls.pop().forEach(::completeFunctionCall)
|
||||
|
||||
val node = tryExitNodes.pop()
|
||||
@@ -1396,14 +1398,15 @@ class ControlFlowGraphBuilder {
|
||||
tryExitNodes.top().fir.finallyBlock == null -> {
|
||||
// (3)... without finally ...(4)
|
||||
// Either in try-main or catch.
|
||||
if (tryMainExitNodes.top().followingNodes.isNotEmpty()) {
|
||||
val tryMainExitNode = tryMainExitNodes.top()
|
||||
if (tryMainExitNode.followingNodes.isNotEmpty()) {
|
||||
// (4)... in catch, i.e., re-throw.
|
||||
exitTargetsForTry.top()
|
||||
} else {
|
||||
// (4)... in try-main. Route to exit of try main block.
|
||||
// We already have edges from the exit of try main block to each catch clause.
|
||||
// This edge makes the remaining part of try main block, e.g., following `when` branches, marked as dead.
|
||||
tryMainExitNodes.top()
|
||||
tryMainExitNode
|
||||
}
|
||||
}
|
||||
// (3)... within finally.
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
// FIR_IDENTICAL
|
||||
// https://youtrack.jetbrains.com/issue/KT-49289
|
||||
|
||||
inline fun <T> myRun(f: () -> T): T = f()
|
||||
|
||||
fun foo(): Int {
|
||||
myRun {
|
||||
return 24
|
||||
}
|
||||
}
|
||||
|
||||
fun bar(arg: Boolean): Int {
|
||||
if (arg) {
|
||||
return 42
|
||||
} else {
|
||||
myRun {
|
||||
return 24
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package
|
||||
|
||||
public fun bar(/*0*/ arg: kotlin.Boolean): kotlin.Int
|
||||
public fun foo(): kotlin.Int
|
||||
public inline fun </*0*/ T> myRun(/*0*/ f: () -> T): T
|
||||
Generated
+6
@@ -15849,6 +15849,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
||||
runTest("compiler/testData/diagnostics/tests/inline/inlineReified.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inlinedReturnInBranch.kt")
|
||||
public void testInlinedReturnInBranch() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inline/inlinedReturnInBranch.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("invoke.kt")
|
||||
public void testInvoke() throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user