diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/BaseExpressionCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/BaseExpressionCodegen.kt index e5acd00721c..7d3f01ec4b9 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/BaseExpressionCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/BaseExpressionCodegen.kt @@ -47,7 +47,7 @@ interface BaseExpressionCodegen { functionReferenceReceiver: StackValue? ) - fun markLineNumberAfterInlineIfNeeded() + fun markLineNumberAfterInlineIfNeeded(registerLineNumberAfterwards: Boolean) fun consumeReifiedOperationMarker(typeParameter: TypeParameterMarker) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index 5a8295b8a83..aa0651709ee 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -1499,10 +1499,9 @@ public class ExpressionCodegen extends KtVisitor impleme v.visitLineNumber(lineNumber, label); } - //we should generate additional linenumber info after inline call only if it used as argument @Override - public void markLineNumberAfterInlineIfNeeded() { - if (!shouldMarkLineNumbers) { + public void markLineNumberAfterInlineIfNeeded(boolean registerLineNumberAfterwards) { + if (!shouldMarkLineNumbers || registerLineNumberAfterwards) { //if it used as general argument if (myLastLineNumber > -1) { Label label = new Label(); @@ -1510,7 +1509,6 @@ public class ExpressionCodegen extends KtVisitor impleme v.visitLineNumber(myLastLineNumber, label); } } else { - //if it used as argument of infix call (in this case lineNumber for simple inlineCall also would be reset) resetLastLineNumber(); } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt index b3f25b8d7b9..ea369419f42 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt @@ -118,28 +118,29 @@ abstract class InlineCodegen( AsmUtil.genThrow(codegen.v, "java/lang/UnsupportedOperationException", message) } - protected fun endCall(result: InlineResult) { + protected fun endCall(result: InlineResult, registerLineNumberAfterwards: Boolean) { leaveTemps() codegen.propagateChildReifiedTypeParametersUsages(result.reifiedTypeParametersUsages) state.factory.removeClasses(result.calcClassesToRemove()) - codegen.markLineNumberAfterInlineIfNeeded() + codegen.markLineNumberAfterInlineIfNeeded(registerLineNumberAfterwards) } fun performInline( typeArguments: List?, inlineDefaultLambdas: Boolean, mapDefaultSignature: Boolean, - typeSystem: TypeSystemCommonBackendContext + typeSystem: TypeSystemCommonBackendContext, + registerLineNumberAfterwards: Boolean ) { var nodeAndSmap: SMAPAndMethodNode? = null try { nodeAndSmap = createInlineMethodNode( functionDescriptor, methodOwner, jvmSignature, mapDefaultSignature, typeArguments, typeSystem, state, sourceCompiler ) - endCall(inlineCall(nodeAndSmap, inlineDefaultLambdas)) + endCall(inlineCall(nodeAndSmap, inlineDefaultLambdas), registerLineNumberAfterwards) } catch (e: CompilationException) { throw e } catch (e: InlineException) { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiInlineCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiInlineCodegen.kt index 2ab8b66df9a..df0f924ccb5 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiInlineCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiInlineCodegen.kt @@ -14,7 +14,10 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.psi.KtCallableReferenceExpression import org.jetbrains.kotlin.psi.KtExpression +import org.jetbrains.kotlin.psi.KtIfExpression import org.jetbrains.kotlin.psi.KtPsiUtil +import org.jetbrains.kotlin.psi.psiUtil.getParentOfType +import org.jetbrains.kotlin.psi.psiUtil.isAncestor import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.inline.InlineUtil @@ -66,12 +69,19 @@ class PsiInlineCodegen( return } try { - performInline(resolvedCall?.typeArguments?.keys?.toList(), callDefault, callDefault, codegen.typeSystem) + val registerLineNumber = registerLineNumberAfterwards(resolvedCall) + performInline(resolvedCall?.typeArguments?.keys?.toList(), callDefault, callDefault, codegen.typeSystem, registerLineNumber) } finally { state.globalInlineContext.exitFromInliningOf(inlineCall) } } + private fun registerLineNumberAfterwards(resolvedCall: ResolvedCall<*>?): Boolean { + val callElement = resolvedCall?.call?.callElement ?: return false + val parentIfCondition = callElement.getParentOfType(true)?.condition ?: return false + return parentIfCondition.isAncestor(callElement, false) + } + override fun processAndPutHiddenParameters(justProcess: Boolean) { if (getMethodAsmFlags(functionDescriptor, sourceCompiler.contextKind, state) and Opcodes.ACC_STATIC == 0) { invocationParamBuilder.addNextParameter(methodOwner, false, actualDispatchReceiver) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt index 74e689dd571..0f7acd23ac2 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt @@ -1119,7 +1119,7 @@ class ExpressionCodegen( //TODO } - override fun markLineNumberAfterInlineIfNeeded() { + override fun markLineNumberAfterInlineIfNeeded(registerLineNumberAfterwards: Boolean) { // Inline function has its own line number which is in a separate instance of codegen, // therefore we need to reset lastLineNumber to force a line number generation after visiting inline function. lastLineNumber = -1 diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt index c2cf9be8fc0..930f8d5510e 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.ir.types.toKotlinType import org.jetbrains.kotlin.ir.util.dump import org.jetbrains.kotlin.ir.util.getArgumentsWithIr import org.jetbrains.kotlin.ir.util.isSuspend +import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.resolve.jvm.AsmTypes import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature @@ -187,7 +188,8 @@ class IrInlineCodegen( expression.symbol.owner.typeParameters.map { it.symbol }, function.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER, false, - codegen.typeMapper.typeSystem + codegen.typeMapper.typeSystem, + false ) } finally { state.globalInlineContext.exitFromInliningOf(inlineCall) diff --git a/compiler/testData/codegen/bytecodeText/lineNumbers/inlineCondition.kt b/compiler/testData/codegen/bytecodeText/lineNumbers/inlineCondition.kt new file mode 100644 index 00000000000..4abd4ae5805 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/lineNumbers/inlineCondition.kt @@ -0,0 +1,17 @@ +//FILE: test.kt +// IGNORE_BACKEND: JVM_IR + +fun box() { + if (listOf(1, 2, 3).myAny { it > 2 }) { + println("foo") + } +} + +public inline fun Iterable.myAny(predicate: (T) -> Boolean): Boolean { + for (element in this) { + if (predicate(element)) return true + } + return false +} + +// 3 LINENUMBER 5 \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/lineNumbers/inlineCondition2.kt b/compiler/testData/codegen/bytecodeText/lineNumbers/inlineCondition2.kt new file mode 100644 index 00000000000..902a94d2767 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/lineNumbers/inlineCondition2.kt @@ -0,0 +1,16 @@ +//FILE: test.kt + +fun box() { + if (listOf(1, 2, 3).myAny { it > 2 } == true) { + println("foo") + } +} + +public inline fun Iterable.myAny(predicate: (T) -> Boolean): Boolean { + for (element in this) { + if (predicate(element)) return true + } + return false +} + +// 3 LINENUMBER 4 \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java index bf67a54a256..c17d56f4788 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java @@ -3253,6 +3253,16 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { runTest("compiler/testData/codegen/bytecodeText/lineNumbers/ifTrueElse.kt"); } + @TestMetadata("inlineCondition.kt") + public void testInlineCondition() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/lineNumbers/inlineCondition.kt"); + } + + @TestMetadata("inlineCondition2.kt") + public void testInlineCondition2() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/lineNumbers/inlineCondition2.kt"); + } + @TestMetadata("singleThen.kt") public void testSingleThen() throws Exception { runTest("compiler/testData/codegen/bytecodeText/lineNumbers/singleThen.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java index 20129099942..1fefea29ab3 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java @@ -3298,6 +3298,16 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest { runTest("compiler/testData/codegen/bytecodeText/lineNumbers/ifTrueElse.kt"); } + @TestMetadata("inlineCondition.kt") + public void testInlineCondition() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/lineNumbers/inlineCondition.kt"); + } + + @TestMetadata("inlineCondition2.kt") + public void testInlineCondition2() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/lineNumbers/inlineCondition2.kt"); + } + @TestMetadata("singleThen.kt") public void testSingleThen() throws Exception { runTest("compiler/testData/codegen/bytecodeText/lineNumbers/singleThen.kt");