KT-1436 Allow break/continue in inlined lambdas
This commit is contained in:
committed by
teamcity
parent
ba7df005a1
commit
8ba80b4b7b
Generated
+4
-1
@@ -8,4 +8,7 @@
|
|||||||
<component name="KotlinCompilerSettings">
|
<component name="KotlinCompilerSettings">
|
||||||
<option name="additionalArguments" value="-version -Xallow-kotlin-package -Xskip-metadata-version-check" />
|
<option name="additionalArguments" value="-version -Xallow-kotlin-package -Xskip-metadata-version-check" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
<component name="KotlinJpsPluginSettings">
|
||||||
|
<option name="version" value="1.8.0-dev-1593" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
+12
@@ -5476,6 +5476,18 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
|
|||||||
runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/breakContinueInTryFinallyInLoop.kt");
|
runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/breakContinueInTryFinallyInLoop.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("breakContinueNoinline.kt")
|
||||||
|
public void testBreakContinueNoinline() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/breakContinueNoinline.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("breakInLambdaPassedToDirectInvoke.kt")
|
||||||
|
public void testBreakInLambdaPassedToDirectInvoke() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/breakInLambdaPassedToDirectInvoke.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("breakInsideLocal.kt")
|
@TestMetadata("breakInsideLocal.kt")
|
||||||
public void testBreakInsideLocal() throws Exception {
|
public void testBreakInsideLocal() throws Exception {
|
||||||
|
|||||||
+12
@@ -5476,6 +5476,18 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
|||||||
runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/breakContinueInTryFinallyInLoop.kt");
|
runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/breakContinueInTryFinallyInLoop.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("breakContinueNoinline.kt")
|
||||||
|
public void testBreakContinueNoinline() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/breakContinueNoinline.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("breakInLambdaPassedToDirectInvoke.kt")
|
||||||
|
public void testBreakInLambdaPassedToDirectInvoke() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/breakInLambdaPassedToDirectInvoke.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("breakInsideLocal.kt")
|
@TestMetadata("breakInsideLocal.kt")
|
||||||
public void testBreakInsideLocal() throws Exception {
|
public void testBreakInsideLocal() throws Exception {
|
||||||
|
|||||||
+12
@@ -5476,6 +5476,18 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
|||||||
runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/breakContinueInTryFinallyInLoop.kt");
|
runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/breakContinueInTryFinallyInLoop.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("breakContinueNoinline.kt")
|
||||||
|
public void testBreakContinueNoinline() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/breakContinueNoinline.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("breakInLambdaPassedToDirectInvoke.kt")
|
||||||
|
public void testBreakInLambdaPassedToDirectInvoke() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/breakInLambdaPassedToDirectInvoke.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("breakInsideLocal.kt")
|
@TestMetadata("breakInsideLocal.kt")
|
||||||
public void testBreakInsideLocal() throws Exception {
|
public void testBreakInsideLocal() throws Exception {
|
||||||
|
|||||||
+28
-2
@@ -5,16 +5,21 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
|
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||||
|
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.FirElement
|
import org.jetbrains.kotlin.fir.FirElement
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.expressions.*
|
import org.jetbrains.kotlin.fir.expressions.*
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
|
||||||
|
import org.jetbrains.kotlin.fir.resolvedSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||||
|
|
||||||
object FirBreakOrContinueJumpsAcrossFunctionBoundaryChecker : FirLoopJumpChecker() {
|
object FirBreakOrContinueJumpsAcrossFunctionBoundaryChecker : FirLoopJumpChecker() {
|
||||||
override fun check(expression: FirLoopJump, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(expression: FirLoopJump, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
val allowInlined = context.languageVersionSettings.supportsFeature(LanguageFeature.BreakContinueInInlineLambdas)
|
||||||
val errorPathElements = ArrayDeque<FirElement>()
|
val errorPathElements = ArrayDeque<FirElement>()
|
||||||
|
|
||||||
fun findPathAndCheck(element: FirElement?): Boolean {
|
fun findPathAndCheck(element: FirElement?): Boolean {
|
||||||
@@ -43,6 +48,7 @@ object FirBreakOrContinueJumpsAcrossFunctionBoundaryChecker : FirLoopJumpChecker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
is FirLoop -> return findPathAndCheck(element.condition) || findPathAndCheck(element.block)
|
||||||
is FirWhenExpression -> {
|
is FirWhenExpression -> {
|
||||||
for (branch in element.branches) {
|
for (branch in element.branches) {
|
||||||
if (findPathAndCheck(branch.result)) {
|
if (findPathAndCheck(branch.result)) {
|
||||||
@@ -52,6 +58,21 @@ object FirBreakOrContinueJumpsAcrossFunctionBoundaryChecker : FirLoopJumpChecker
|
|||||||
}
|
}
|
||||||
is FirVariable -> return findPathAndCheck(element.initializer)
|
is FirVariable -> return findPathAndCheck(element.initializer)
|
||||||
is FirWrappedExpression -> return findPathAndCheck(element.expression)
|
is FirWrappedExpression -> return findPathAndCheck(element.expression)
|
||||||
|
is FirNoReceiverExpression -> return false
|
||||||
|
is FirFunctionCall -> {
|
||||||
|
if (findPathAndCheck(element.extensionReceiver) || findPathAndCheck(element.dispatchReceiver)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
val symbol = if (allowInlined) element.calleeReference.resolvedSymbol as? FirFunctionSymbol else null
|
||||||
|
element.arguments.forEachIndexed { i, argument ->
|
||||||
|
val expressionToCheck =
|
||||||
|
if (symbol?.resolvedStatus?.isInline == true && !symbol.valueParameterSymbols[i].isNoinline) argument.tryInline() else argument
|
||||||
|
if (findPathAndCheck(expressionToCheck)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
is FirCall -> {
|
is FirCall -> {
|
||||||
for (argument in element.arguments) {
|
for (argument in element.arguments) {
|
||||||
if (findPathAndCheck(argument)) {
|
if (findPathAndCheck(argument)) {
|
||||||
@@ -98,4 +119,9 @@ object FirBreakOrContinueJumpsAcrossFunctionBoundaryChecker : FirLoopJumpChecker
|
|||||||
|
|
||||||
findPathAndCheck(expression.target.labeledElement.block)
|
findPathAndCheck(expression.target.labeledElement.block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun FirExpression.tryInline(): FirExpression {
|
||||||
|
val anonymousFunctionExpression = (((this as? FirLambdaArgumentExpression)?.expression) ?: this) as? FirAnonymousFunctionExpression
|
||||||
|
return anonymousFunctionExpression?.anonymousFunction?.body ?: this
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+46
@@ -9033,6 +9033,52 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
|||||||
public void testWhileTrueBreak() throws Exception {
|
public void testWhileTrueBreak() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/whileTrueBreak.kt");
|
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/whileTrueBreak.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class InlinedBreakContinue {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInInlinedBreakContinue() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("inlineFunctionWithMultipleParameters.kt")
|
||||||
|
public void testInlineFunctionWithMultipleParameters() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue/inlineFunctionWithMultipleParameters.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("lambdaPassedToInlineFunction.kt")
|
||||||
|
public void testLambdaPassedToInlineFunction() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue/lambdaPassedToInlineFunction.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("loopWithinInlineFunction.kt")
|
||||||
|
public void testLoopWithinInlineFunction() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue/loopWithinInlineFunction.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("simple.kt")
|
||||||
|
public void testSimple() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue/simple.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("stdlibFunctions.kt")
|
||||||
|
public void testStdlibFunctions() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue/stdlibFunctions.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("withReturnValue.kt")
|
||||||
|
public void testWithReturnValue() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue/withReturnValue.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
|
|||||||
Generated
+18
@@ -1196,6 +1196,12 @@ public class Fir2IrTextTestGenerated extends AbstractFir2IrTextTest {
|
|||||||
runTest("compiler/testData/ir/irText/expressions/badBreakContinue.kt");
|
runTest("compiler/testData/ir/irText/expressions/badBreakContinue.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("badInlinedBreakContinue.kt")
|
||||||
|
public void testBadInlinedBreakContinue() throws Exception {
|
||||||
|
runTest("compiler/testData/ir/irText/expressions/badInlinedBreakContinue.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("bangbang.kt")
|
@TestMetadata("bangbang.kt")
|
||||||
public void testBangbang() throws Exception {
|
public void testBangbang() throws Exception {
|
||||||
@@ -1238,6 +1244,12 @@ public class Fir2IrTextTestGenerated extends AbstractFir2IrTextTest {
|
|||||||
runTest("compiler/testData/ir/irText/expressions/breakContinueInLoopHeader.kt");
|
runTest("compiler/testData/ir/irText/expressions/breakContinueInLoopHeader.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("breakContinueInNoInlineLambda.kt")
|
||||||
|
public void testBreakContinueInNoInlineLambda() throws Exception {
|
||||||
|
runTest("compiler/testData/ir/irText/expressions/breakContinueInNoInlineLambda.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("breakContinueInWhen.kt")
|
@TestMetadata("breakContinueInWhen.kt")
|
||||||
public void testBreakContinueInWhen() throws Exception {
|
public void testBreakContinueInWhen() throws Exception {
|
||||||
@@ -1502,6 +1514,12 @@ public class Fir2IrTextTestGenerated extends AbstractFir2IrTextTest {
|
|||||||
runTest("compiler/testData/ir/irText/expressions/incrementDecrement.kt");
|
runTest("compiler/testData/ir/irText/expressions/incrementDecrement.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("inlinedBreakContinue.kt")
|
||||||
|
public void testInlinedBreakContinue() throws Exception {
|
||||||
|
runTest("compiler/testData/ir/irText/expressions/inlinedBreakContinue.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("interfaceThisRef.kt")
|
@TestMetadata("interfaceThisRef.kt")
|
||||||
public void testInterfaceThisRef() throws Exception {
|
public void testInterfaceThisRef() throws Exception {
|
||||||
|
|||||||
+18
@@ -1196,6 +1196,12 @@ public class LightTreeFir2IrTextTestGenerated extends AbstractLightTreeFir2IrTex
|
|||||||
runTest("compiler/testData/ir/irText/expressions/badBreakContinue.kt");
|
runTest("compiler/testData/ir/irText/expressions/badBreakContinue.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("badInlinedBreakContinue.kt")
|
||||||
|
public void testBadInlinedBreakContinue() throws Exception {
|
||||||
|
runTest("compiler/testData/ir/irText/expressions/badInlinedBreakContinue.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("bangbang.kt")
|
@TestMetadata("bangbang.kt")
|
||||||
public void testBangbang() throws Exception {
|
public void testBangbang() throws Exception {
|
||||||
@@ -1238,6 +1244,12 @@ public class LightTreeFir2IrTextTestGenerated extends AbstractLightTreeFir2IrTex
|
|||||||
runTest("compiler/testData/ir/irText/expressions/breakContinueInLoopHeader.kt");
|
runTest("compiler/testData/ir/irText/expressions/breakContinueInLoopHeader.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("breakContinueInNoInlineLambda.kt")
|
||||||
|
public void testBreakContinueInNoInlineLambda() throws Exception {
|
||||||
|
runTest("compiler/testData/ir/irText/expressions/breakContinueInNoInlineLambda.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("breakContinueInWhen.kt")
|
@TestMetadata("breakContinueInWhen.kt")
|
||||||
public void testBreakContinueInWhen() throws Exception {
|
public void testBreakContinueInWhen() throws Exception {
|
||||||
@@ -1502,6 +1514,12 @@ public class LightTreeFir2IrTextTestGenerated extends AbstractLightTreeFir2IrTex
|
|||||||
runTest("compiler/testData/ir/irText/expressions/incrementDecrement.kt");
|
runTest("compiler/testData/ir/irText/expressions/incrementDecrement.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("inlinedBreakContinue.kt")
|
||||||
|
public void testInlinedBreakContinue() throws Exception {
|
||||||
|
runTest("compiler/testData/ir/irText/expressions/inlinedBreakContinue.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("interfaceThisRef.kt")
|
@TestMetadata("interfaceThisRef.kt")
|
||||||
public void testInterfaceThisRef() throws Exception {
|
public void testInterfaceThisRef() throws Exception {
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.AccessTarget
|
|||||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.InstructionWithValue
|
import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.InstructionWithValue
|
||||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.MagicKind
|
import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.MagicKind
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
|
import org.jetbrains.kotlin.config.LanguageFeature.BreakContinueInInlineLambdas
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature.ProhibitQualifiedAccessToUninitializedEnumEntry
|
import org.jetbrains.kotlin.config.LanguageFeature.ProhibitQualifiedAccessToUninitializedEnumEntry
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||||
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
||||||
@@ -926,9 +927,9 @@ class ControlFlowProcessor(
|
|||||||
|
|
||||||
private fun jumpDoesNotCrossFunctionBoundary(jumpExpression: KtExpressionWithLabel, jumpTarget: KtLoopExpression): Boolean {
|
private fun jumpDoesNotCrossFunctionBoundary(jumpExpression: KtExpressionWithLabel, jumpTarget: KtLoopExpression): Boolean {
|
||||||
val bindingContext = trace.bindingContext
|
val bindingContext = trace.bindingContext
|
||||||
|
val skipInlineFunctions = languageVersionSettings.supportsFeature(BreakContinueInInlineLambdas)
|
||||||
val labelExprEnclosingFunc = getEnclosingFunctionDescriptor(bindingContext, jumpExpression)
|
val labelExprEnclosingFunc = getEnclosingFunctionDescriptor(bindingContext, jumpExpression, skipInlineFunctions)
|
||||||
val labelTargetEnclosingFunc = getEnclosingFunctionDescriptor(bindingContext, jumpTarget)
|
val labelTargetEnclosingFunc = getEnclosingFunctionDescriptor(bindingContext, jumpTarget, skipInlineFunctions)
|
||||||
return if (labelExprEnclosingFunc !== labelTargetEnclosingFunc) {
|
return if (labelExprEnclosingFunc !== labelTargetEnclosingFunc) {
|
||||||
// Check to report only once
|
// Check to report only once
|
||||||
if (builder.getLoopExitPoint(jumpTarget) != null ||
|
if (builder.getLoopExitPoint(jumpTarget) != null ||
|
||||||
|
|||||||
+46
-7
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
|||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.psi.KtPsiUtil.deparenthesizeOnce
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
@@ -32,6 +33,7 @@ import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
|||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
|
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.util.getResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||||
import org.jetbrains.kotlin.resolve.scopes.utils.takeSnapshot
|
import org.jetbrains.kotlin.resolve.scopes.utils.takeSnapshot
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
@@ -154,12 +156,49 @@ fun getEnclosingDescriptor(context: BindingContext, element: KtElement): Declara
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getEnclosingFunctionDescriptor(context: BindingContext, element: KtElement): FunctionDescriptor? {
|
fun getEnclosingFunctionDescriptor(context: BindingContext, element: KtElement, skipInlineFunctionLiterals: Boolean): FunctionDescriptor? {
|
||||||
val functionOrClass = element.getParentOfTypeCodeFragmentAware(KtFunction::class.java, KtClassOrObject::class.java)
|
var current = element
|
||||||
val descriptor = context.get(DECLARATION_TO_DESCRIPTOR, functionOrClass)
|
while (true) {
|
||||||
return if (functionOrClass is KtFunction) {
|
val functionOrClass = current.getParentOfTypeCodeFragmentAware(KtFunction::class.java, KtClassOrObject::class.java)
|
||||||
if (descriptor is FunctionDescriptor) descriptor else null
|
val descriptor = context.get(DECLARATION_TO_DESCRIPTOR, functionOrClass)
|
||||||
} else {
|
if (functionOrClass is KtFunction) {
|
||||||
if (descriptor is ClassDescriptor) descriptor.unsubstitutedPrimaryConstructor else null
|
if (descriptor is FunctionDescriptor) {
|
||||||
|
if (skipInlineFunctionLiterals && isInlineableFunctionLiteral(
|
||||||
|
((functionOrClass as? KtFunctionLiteral)?.parent as? KtExpression) ?: functionOrClass,
|
||||||
|
context
|
||||||
|
)) {
|
||||||
|
current = functionOrClass
|
||||||
|
} else {
|
||||||
|
return descriptor
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return if (descriptor is ClassDescriptor) descriptor.unsubstitutedPrimaryConstructor else null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun isInlineableFunctionLiteral(expression: KtExpression, context: BindingContext): Boolean {
|
||||||
|
if (expression !is KtLambdaExpression && !(expression is KtNamedFunction && expression.name == null)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
var wrapper: PsiElement = expression
|
||||||
|
while (deparenthesizeOnce(wrapper.parent as? KtExpression) == wrapper) {
|
||||||
|
wrapper = wrapper.parent
|
||||||
|
}
|
||||||
|
|
||||||
|
val argument = (wrapper.parent as? KtValueArgument) ?: return false
|
||||||
|
val call = (((argument.parent as? KtValueArgumentList) ?: argument).parent as? KtCallExpression) ?: return false
|
||||||
|
val resolvedCall = call.getResolvedCall(context) ?: return false
|
||||||
|
val descriptor = (resolvedCall.resultingDescriptor as? FunctionDescriptor) ?: return false
|
||||||
|
if (descriptor.isInline) {
|
||||||
|
val parameter = resolvedCall.valueArguments.entries.find { (_, valueArgument) ->
|
||||||
|
valueArgument.arguments.any { it.asElement() == argument }
|
||||||
|
}?.key ?: return false
|
||||||
|
return !parameter.isNoinline
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
+1
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent
|
|||||||
import org.jetbrains.kotlin.ir.declarations.IrTypeParametersContainer
|
import org.jetbrains.kotlin.ir.declarations.IrTypeParametersContainer
|
||||||
import org.jetbrains.kotlin.ir.declarations.copyAttributes
|
import org.jetbrains.kotlin.ir.declarations.copyAttributes
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
|
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrLoop
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall
|
import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
||||||
|
|||||||
+1
-1
@@ -73,7 +73,7 @@ private class DirectInvokeLowering(private val context: JvmBackendContext) : Fil
|
|||||||
return context.createIrBuilder(scope.scopeOwnerSymbol).run {
|
return context.createIrBuilder(scope.scopeOwnerSymbol).run {
|
||||||
at(expression)
|
at(expression)
|
||||||
irBlock {
|
irBlock {
|
||||||
val arguments = function.explicitParameters.withIndex().map { (index, parameter) ->
|
val arguments = function.explicitParameters.mapIndexed { index, parameter ->
|
||||||
val argument = expression.getValueArgument(index)!!
|
val argument = expression.getValueArgument(index)!!
|
||||||
IrVariableImpl(
|
IrVariableImpl(
|
||||||
argument.startOffset, argument.endOffset, IrDeclarationOrigin.DEFINED, IrVariableSymbolImpl(), parameter.name,
|
argument.startOffset, argument.endOffset, IrDeclarationOrigin.DEFINED, IrVariableSymbolImpl(), parameter.name,
|
||||||
|
|||||||
@@ -39,10 +39,15 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
|
|||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||||
|
|
||||||
|
interface LoopResolver {
|
||||||
|
fun getLoop(expression: KtExpression): IrLoop?
|
||||||
|
}
|
||||||
|
|
||||||
class BodyGenerator(
|
class BodyGenerator(
|
||||||
val scopeOwnerSymbol: IrSymbol,
|
val scopeOwnerSymbol: IrSymbol,
|
||||||
override val context: GeneratorContext
|
override val context: GeneratorContext,
|
||||||
) : GeneratorWithScope {
|
private val parentLoopResolver: LoopResolver?
|
||||||
|
) : GeneratorWithScope, LoopResolver {
|
||||||
|
|
||||||
val scopeOwner: DeclarationDescriptor get() = scopeOwnerSymbol.descriptor
|
val scopeOwner: DeclarationDescriptor get() = scopeOwnerSymbol.descriptor
|
||||||
|
|
||||||
@@ -196,8 +201,9 @@ class BodyGenerator(
|
|||||||
loopTable[expression] = irLoop
|
loopTable[expression] = irLoop
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getLoop(expression: KtExpression): IrLoop? =
|
override fun getLoop(expression: KtExpression): IrLoop? {
|
||||||
loopTable[expression]
|
return loopTable[expression] ?: parentLoopResolver?.getLoop(expression)
|
||||||
|
}
|
||||||
|
|
||||||
fun generatePrimaryConstructorBody(ktClassOrObject: KtPureClassOrObject, irConstructor: IrConstructor): IrBody {
|
fun generatePrimaryConstructorBody(ktClassOrObject: KtPureClassOrObject, irConstructor: IrConstructor): IrBody {
|
||||||
val irBlockBody = context.irFactory.createBlockBody(ktClassOrObject.pureStartOffset, ktClassOrObject.pureEndOffset)
|
val irBlockBody = context.irFactory.createBlockBody(ktClassOrObject.pureStartOffset, ktClassOrObject.pureEndOffset)
|
||||||
|
|||||||
+3
-3
@@ -46,7 +46,7 @@ class DeclarationGenerator(override val context: GeneratorContext) : Generator {
|
|||||||
return try {
|
return try {
|
||||||
when (ktDeclaration) {
|
when (ktDeclaration) {
|
||||||
is KtNamedFunction ->
|
is KtNamedFunction ->
|
||||||
FunctionGenerator(this).generateFunctionDeclaration(ktDeclaration)
|
FunctionGenerator(this).generateFunctionDeclaration(ktDeclaration, null)
|
||||||
is KtProperty ->
|
is KtProperty ->
|
||||||
PropertyGenerator(this).generatePropertyDeclaration(ktDeclaration)
|
PropertyGenerator(this).generatePropertyDeclaration(ktDeclaration)
|
||||||
is KtClassOrObject ->
|
is KtClassOrObject ->
|
||||||
@@ -207,5 +207,5 @@ abstract class DeclarationGeneratorExtension(val declarationGenerator: Declarati
|
|||||||
fun KotlinType.toIrType() = with(declarationGenerator) { toIrType() }
|
fun KotlinType.toIrType() = with(declarationGenerator) { toIrType() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Generator.createBodyGenerator(scopeOwnerSymbol: IrSymbol) =
|
fun Generator.createBodyGenerator(scopeOwnerSymbol: IrSymbol, parentLoopResolver: LoopResolver? = null) =
|
||||||
BodyGenerator(scopeOwnerSymbol, context)
|
BodyGenerator(scopeOwnerSymbol, context, parentLoopResolver)
|
||||||
|
|||||||
+8
-4
@@ -40,6 +40,7 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
|
|||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
fun generateFunctionDeclaration(
|
fun generateFunctionDeclaration(
|
||||||
ktFunction: KtNamedFunction,
|
ktFunction: KtNamedFunction,
|
||||||
|
parentLoopResolver: LoopResolver?,
|
||||||
origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED
|
origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED
|
||||||
): IrSimpleFunction =
|
): IrSimpleFunction =
|
||||||
declareSimpleFunction(
|
declareSimpleFunction(
|
||||||
@@ -47,19 +48,21 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
|
|||||||
ktFunction.receiverTypeReference,
|
ktFunction.receiverTypeReference,
|
||||||
ktFunction.contextReceivers.mapNotNull { it.typeReference() },
|
ktFunction.contextReceivers.mapNotNull { it.typeReference() },
|
||||||
origin,
|
origin,
|
||||||
getOrFail(BindingContext.FUNCTION, ktFunction)
|
getOrFail(BindingContext.FUNCTION, ktFunction),
|
||||||
|
parentLoopResolver
|
||||||
) {
|
) {
|
||||||
ktFunction.bodyExpression?.let { generateFunctionBody(it) }
|
ktFunction.bodyExpression?.let { generateFunctionBody(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateLambdaFunctionDeclaration(ktFunction: KtFunctionLiteral): IrSimpleFunction {
|
fun generateLambdaFunctionDeclaration(ktFunction: KtFunctionLiteral, parentLoopResolver: LoopResolver?): IrSimpleFunction {
|
||||||
val lambdaDescriptor = getOrFail(BindingContext.FUNCTION, ktFunction)
|
val lambdaDescriptor = getOrFail(BindingContext.FUNCTION, ktFunction)
|
||||||
return declareSimpleFunction(
|
return declareSimpleFunction(
|
||||||
ktFunction,
|
ktFunction,
|
||||||
null,
|
null,
|
||||||
emptyList(),
|
emptyList(),
|
||||||
IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA,
|
IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA,
|
||||||
lambdaDescriptor
|
lambdaDescriptor,
|
||||||
|
parentLoopResolver
|
||||||
) {
|
) {
|
||||||
generateLambdaBody(ktFunction, lambdaDescriptor)
|
generateLambdaBody(ktFunction, lambdaDescriptor)
|
||||||
}
|
}
|
||||||
@@ -80,11 +83,12 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
|
|||||||
ktContextReceivers: List<KtElement>,
|
ktContextReceivers: List<KtElement>,
|
||||||
origin: IrDeclarationOrigin,
|
origin: IrDeclarationOrigin,
|
||||||
descriptor: FunctionDescriptor,
|
descriptor: FunctionDescriptor,
|
||||||
|
parentLoopResolver: LoopResolver?,
|
||||||
generateBody: BodyGenerator.() -> IrBody?
|
generateBody: BodyGenerator.() -> IrBody?
|
||||||
): IrSimpleFunction =
|
): IrSimpleFunction =
|
||||||
declareSimpleFunctionInner(descriptor, ktFunction, origin).buildWithScope { irFunction ->
|
declareSimpleFunctionInner(descriptor, ktFunction, origin).buildWithScope { irFunction ->
|
||||||
generateFunctionParameterDeclarationsAndReturnType(irFunction, ktFunction, ktReceiver, ktContextReceivers)
|
generateFunctionParameterDeclarationsAndReturnType(irFunction, ktFunction, ktReceiver, ktContextReceivers)
|
||||||
irFunction.body = createBodyGenerator(irFunction.symbol).generateBody()
|
irFunction.body = createBodyGenerator(irFunction.symbol, parentLoopResolver).generateBody()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun declareSimpleFunctionInner(
|
private fun declareSimpleFunctionInner(
|
||||||
|
|||||||
+16
-2
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.psi2ir.generators
|
package org.jetbrains.kotlin.psi2ir.generators
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
||||||
@@ -24,13 +25,19 @@ import org.jetbrains.kotlin.psi.KtLambdaExpression
|
|||||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||||
|
import org.jetbrains.kotlin.resolve.bindingContextUtil.isInlineableFunctionLiteral
|
||||||
|
|
||||||
class LocalFunctionGenerator(statementGenerator: StatementGenerator) : StatementGeneratorExtension(statementGenerator) {
|
class LocalFunctionGenerator(statementGenerator: StatementGenerator) : StatementGeneratorExtension(statementGenerator) {
|
||||||
|
|
||||||
fun generateLambda(ktLambda: KtLambdaExpression): IrStatement {
|
fun generateLambda(ktLambda: KtLambdaExpression): IrStatement {
|
||||||
val ktFun = ktLambda.functionLiteral
|
val ktFun = ktLambda.functionLiteral
|
||||||
val lambdaExpressionType = getTypeInferredByFrontendOrFail(ktLambda).toIrType()
|
val lambdaExpressionType = getTypeInferredByFrontendOrFail(ktLambda).toIrType()
|
||||||
val irLambdaFunction = FunctionGenerator(context).generateLambdaFunctionDeclaration(ktFun)
|
val loopResolver = if (context.languageVersionSettings.supportsFeature(LanguageFeature.BreakContinueInInlineLambdas)
|
||||||
|
&& isInlineableFunctionLiteral(ktLambda, context.bindingContext)
|
||||||
|
)
|
||||||
|
statementGenerator.bodyGenerator
|
||||||
|
else null
|
||||||
|
val irLambdaFunction = FunctionGenerator(context).generateLambdaFunctionDeclaration(ktFun, loopResolver)
|
||||||
|
|
||||||
return IrFunctionExpressionImpl(
|
return IrFunctionExpressionImpl(
|
||||||
ktLambda.startOffset, ktLambda.endOffset,
|
ktLambda.startOffset, ktLambda.endOffset,
|
||||||
@@ -54,5 +61,12 @@ class LocalFunctionGenerator(statementGenerator: StatementGenerator) : Statement
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun generateFunctionDeclaration(ktFun: KtNamedFunction) =
|
private fun generateFunctionDeclaration(ktFun: KtNamedFunction) =
|
||||||
FunctionGenerator(context).generateFunctionDeclaration(ktFun, IrDeclarationOrigin.LOCAL_FUNCTION)
|
FunctionGenerator(context).generateFunctionDeclaration(
|
||||||
|
ktFun,
|
||||||
|
if (context.languageVersionSettings.supportsFeature(LanguageFeature.BreakContinueInInlineLambdas)
|
||||||
|
&& isInlineableFunctionLiteral(ktFun, context.bindingContext)
|
||||||
|
) statementGenerator.bodyGenerator
|
||||||
|
else null,
|
||||||
|
IrDeclarationOrigin.LOCAL_FUNCTION
|
||||||
|
)
|
||||||
}
|
}
|
||||||
@@ -168,7 +168,8 @@ class ScriptGenerator(declarationGenerator: DeclarationGenerator) : DeclarationG
|
|||||||
is KtScriptInitializer -> {
|
is KtScriptInitializer -> {
|
||||||
val irExpressionBody = BodyGenerator(
|
val irExpressionBody = BodyGenerator(
|
||||||
irScript.symbol,
|
irScript.symbol,
|
||||||
context
|
context,
|
||||||
|
null
|
||||||
).generateExpressionBody(d.body!!)
|
).generateExpressionBody(d.body!!)
|
||||||
if (d == ktScript.declarations.last() && descriptor.resultValue != null) {
|
if (d == ktScript.declarations.last() && descriptor.resultValue != null) {
|
||||||
descriptor.resultValue!!.let { resultDescriptor ->
|
descriptor.resultValue!!.let { resultDescriptor ->
|
||||||
@@ -194,7 +195,7 @@ class ScriptGenerator(declarationGenerator: DeclarationGenerator) : DeclarationG
|
|||||||
is KtDestructuringDeclaration -> {
|
is KtDestructuringDeclaration -> {
|
||||||
// copied with modifications from StatementGenerator.visitDestructuringDeclaration
|
// copied with modifications from StatementGenerator.visitDestructuringDeclaration
|
||||||
// TODO: consider code deduplication
|
// TODO: consider code deduplication
|
||||||
val bodyGenerator = BodyGenerator(irScript.symbol, context)
|
val bodyGenerator = BodyGenerator(irScript.symbol, context, null)
|
||||||
val statementGenerator = bodyGenerator.createStatementGenerator()
|
val statementGenerator = bodyGenerator.createStatementGenerator()
|
||||||
val irBlock = IrCompositeImpl(
|
val irBlock = IrCompositeImpl(
|
||||||
d.startOffsetSkippingComments, d.endOffset,
|
d.startOffsetSkippingComments, d.endOffset,
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.ir
|
package org.jetbrains.kotlin.ir
|
||||||
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrLoop
|
|
||||||
import org.jetbrains.kotlin.ir.util.DeepCopyIrTreeWithSymbols
|
import org.jetbrains.kotlin.ir.util.DeepCopyIrTreeWithSymbols
|
||||||
import org.jetbrains.kotlin.ir.util.DeepCopySymbolRemapper
|
import org.jetbrains.kotlin.ir.util.DeepCopySymbolRemapper
|
||||||
import org.jetbrains.kotlin.ir.util.DeepCopyTypeRemapper
|
import org.jetbrains.kotlin.ir.util.DeepCopyTypeRemapper
|
||||||
@@ -19,12 +18,5 @@ fun <T : IrElement> T.deepCopyWithVariables(): T {
|
|||||||
|
|
||||||
val typesRemapper = DeepCopyTypeRemapper(symbolsRemapper)
|
val typesRemapper = DeepCopyTypeRemapper(symbolsRemapper)
|
||||||
|
|
||||||
return this.transform(
|
return this.transform(DeepCopyIrTreeWithSymbols(symbolsRemapper, typesRemapper), null) as T
|
||||||
object : DeepCopyIrTreeWithSymbols(symbolsRemapper, typesRemapper) {
|
|
||||||
override fun getNonTransformedLoop(irLoop: IrLoop): IrLoop {
|
|
||||||
return irLoop
|
|
||||||
}
|
|
||||||
},
|
|
||||||
null
|
|
||||||
) as T
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -738,10 +738,7 @@ open class DeepCopyIrTreeWithSymbols(
|
|||||||
private val transformedLoops = HashMap<IrLoop, IrLoop>()
|
private val transformedLoops = HashMap<IrLoop, IrLoop>()
|
||||||
|
|
||||||
private fun getTransformedLoop(irLoop: IrLoop): IrLoop =
|
private fun getTransformedLoop(irLoop: IrLoop): IrLoop =
|
||||||
transformedLoops.getOrElse(irLoop) { getNonTransformedLoop(irLoop) }
|
transformedLoops.getOrDefault(irLoop, irLoop)
|
||||||
|
|
||||||
protected open fun getNonTransformedLoop(irLoop: IrLoop): IrLoop =
|
|
||||||
throw AssertionError("Outer loop was not transformed: ${irLoop.render()}")
|
|
||||||
|
|
||||||
override fun visitWhileLoop(loop: IrWhileLoop): IrWhileLoop =
|
override fun visitWhileLoop(loop: IrWhileLoop): IrWhileLoop =
|
||||||
IrWhileLoopImpl(loop.startOffset, loop.endOffset, loop.type.remapType(), mapStatementOrigin(loop.origin)).also { newLoop ->
|
IrWhileLoopImpl(loop.startOffset, loop.endOffset, loop.type.remapType(), mapStatementOrigin(loop.origin)).also { newLoop ->
|
||||||
|
|||||||
+35
@@ -0,0 +1,35 @@
|
|||||||
|
// LANGUAGE: +BreakContinueInInlineLambdas
|
||||||
|
// TARGET_BACKEND: JVM_IR
|
||||||
|
// TARGET_BACKEND: JS_IR
|
||||||
|
// TARGET_BACKEND: JS_IR_ES6
|
||||||
|
// TARGET_BACKEND: NATIVE
|
||||||
|
// TARGET_BACKEND: WASM
|
||||||
|
// WITH_STDLIB
|
||||||
|
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
inline fun foo(
|
||||||
|
block1: () -> Unit,
|
||||||
|
noinline block2: () -> Unit,
|
||||||
|
block3: () -> Unit
|
||||||
|
) {
|
||||||
|
block1()
|
||||||
|
block2()
|
||||||
|
block3()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val visited = mutableListOf<Int>()
|
||||||
|
|
||||||
|
for (i in 1..3) {
|
||||||
|
foo(
|
||||||
|
{ visited += 1; if (i == 1) continue },
|
||||||
|
{ visited += 2 },
|
||||||
|
{ visited += 3; if (i == 2) break },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(listOf(1, 1, 2, 3), visited)
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+65
@@ -0,0 +1,65 @@
|
|||||||
|
// LANGUAGE: +BreakContinueInInlineLambdas
|
||||||
|
// TARGET_BACKEND: JVM_IR
|
||||||
|
// TARGET_BACKEND: JS_IR
|
||||||
|
// TARGET_BACKEND: JS_IR_ES6
|
||||||
|
// TARGET_BACKEND: NATIVE
|
||||||
|
// TARGET_BACKEND: WASM
|
||||||
|
// WITH_STDLIB
|
||||||
|
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
@Target(AnnotationTarget.EXPRESSION)
|
||||||
|
@Retention(AnnotationRetention.SOURCE)
|
||||||
|
public annotation class SomeAnnotation
|
||||||
|
|
||||||
|
inline fun foo(block: () -> Unit) = block()
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val visited = mutableListOf<Pair<Int, Int>>()
|
||||||
|
|
||||||
|
var i = 0
|
||||||
|
outer@ while (true) {
|
||||||
|
i += 1
|
||||||
|
inner@ for (j in 1..10) {
|
||||||
|
foo(
|
||||||
|
(@SomeAnnotation
|
||||||
|
fun() {
|
||||||
|
foo(fun() {
|
||||||
|
foo(@SomeAnnotation {
|
||||||
|
foo {
|
||||||
|
if (i == 2) {
|
||||||
|
continue@outer
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == 4) {
|
||||||
|
break@outer
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j == 2) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j == 4) {
|
||||||
|
continue@inner
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j == 6 && i == 1) {
|
||||||
|
break@inner
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j == 6 && i == 3) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
)
|
||||||
|
visited += i to j
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(listOf(1 to 1, 1 to 3, 1 to 5, 3 to 1, 3 to 3, 3 to 5), visited)
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+30
@@ -0,0 +1,30 @@
|
|||||||
|
// LANGUAGE: +BreakContinueInInlineLambdas
|
||||||
|
// TARGET_BACKEND: JVM_IR
|
||||||
|
// TARGET_BACKEND: JS_IR
|
||||||
|
// TARGET_BACKEND: JS_IR_ES6
|
||||||
|
// TARGET_BACKEND: NATIVE
|
||||||
|
// TARGET_BACKEND: WASM
|
||||||
|
// WITH_STDLIB
|
||||||
|
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
inline fun <T> Iterable<T>.myForEach(action: (T) -> Unit): Unit {
|
||||||
|
for (element in this) action(element)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val visited = mutableListOf<Pair<Int, Int>>()
|
||||||
|
|
||||||
|
for (i in 1..3) {
|
||||||
|
(1..3).myForEach { j ->
|
||||||
|
if (j == 3) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
visited += i to j
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(listOf(1 to 1, 1 to 2), visited)
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
// LANGUAGE: +BreakContinueInInlineLambdas
|
||||||
|
// TARGET_BACKEND: JVM_IR
|
||||||
|
// TARGET_BACKEND: JS_IR
|
||||||
|
// TARGET_BACKEND: JS_IR_ES6
|
||||||
|
// TARGET_BACKEND: NATIVE
|
||||||
|
// TARGET_BACKEND: WASM
|
||||||
|
|
||||||
|
inline fun foo(block: () -> Unit) { block() }
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
while (true) {
|
||||||
|
foo { break }
|
||||||
|
return "FAIL"
|
||||||
|
}
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
// LANGUAGE: +BreakContinueInInlineLambdas
|
||||||
|
// TARGET_BACKEND: JVM_IR
|
||||||
|
// TARGET_BACKEND: JS_IR
|
||||||
|
// TARGET_BACKEND: JS_IR_ES6
|
||||||
|
// TARGET_BACKEND: NATIVE
|
||||||
|
// TARGET_BACKEND: WASM
|
||||||
|
// WITH_STDLIB
|
||||||
|
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
inline fun <T> Iterable<T>.myForEach(action: (T) -> Unit): Unit {
|
||||||
|
for (element in this) action(element)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
while (true) {
|
||||||
|
"".let { it.run { break } }
|
||||||
|
}
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
// LANGUAGE: +BreakContinueInInlineLambdas
|
||||||
|
// TARGET_BACKEND: JVM_IR
|
||||||
|
// TARGET_BACKEND: JS_IR
|
||||||
|
// TARGET_BACKEND: JS_IR_ES6
|
||||||
|
// TARGET_BACKEND: NATIVE
|
||||||
|
// TARGET_BACKEND: WASM
|
||||||
|
|
||||||
|
inline fun foo(block: () -> Int): Int = block()
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
var sum = 0
|
||||||
|
|
||||||
|
for (i in 1..10) {
|
||||||
|
sum += foo { if (i == 3) break else i }
|
||||||
|
}
|
||||||
|
|
||||||
|
return if (sum == 3) "OK" else "FAIL"
|
||||||
|
}
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
// LANGUAGE: +BreakContinueInInlineLambdas
|
||||||
|
|
||||||
|
|
||||||
|
inline fun notInlining(noinline block1: () -> Unit, block2: () -> Unit) {
|
||||||
|
block1()
|
||||||
|
block2()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
label@ while(true) {
|
||||||
|
notInlining({ <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> }) {}
|
||||||
|
notInlining({ <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!> }) {}
|
||||||
|
notInlining(fun () { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> }) {}
|
||||||
|
notInlining(fun () { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!> }) {}
|
||||||
|
notInlining({ <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break@label<!> }) {}
|
||||||
|
notInlining({ <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue@label<!> }) {}
|
||||||
|
notInlining(fun () { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break@label<!> }) {}
|
||||||
|
notInlining(fun () { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue@label<!> }) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public inline fun notInlining(/*0*/ noinline block1: () -> kotlin.Unit, /*1*/ block2: () -> kotlin.Unit): kotlin.Unit
|
||||||
|
public fun test(): kotlin.Unit
|
||||||
|
|
||||||
Vendored
+10
@@ -0,0 +1,10 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
// LANGUAGE: +BreakContinueInInlineLambdas
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
while(true) {
|
||||||
|
{block: () -> Unit -> block()}(
|
||||||
|
{<!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!>}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun test(): kotlin.Unit
|
||||||
+100
-23
@@ -1,38 +1,77 @@
|
|||||||
|
// LANGUAGE: +BreakContinueInInlineLambdas
|
||||||
|
|
||||||
|
inline fun <T> foo(block: () -> T): T = block()
|
||||||
|
|
||||||
|
|
||||||
|
@Target(AnnotationTarget.EXPRESSION)
|
||||||
|
@Retention(AnnotationRetention.SOURCE)
|
||||||
|
public annotation class SomeAnnotation
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
while (true) {
|
while (true) {
|
||||||
fun local1() {
|
fun local1(tag: Int) {
|
||||||
<!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!>
|
when(tag) {
|
||||||
|
0 -> <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!>
|
||||||
|
1 -> foo { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> }
|
||||||
|
2 -> foo(@SomeAnnotation { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
||||||
|
3 -> foo(fun () { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
||||||
|
4 -> foo(@SomeAnnotation fun () { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun test2() {
|
fun test2() {
|
||||||
while (true) {
|
while (true) {
|
||||||
{
|
{tag: Int ->
|
||||||
<!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!>
|
when(tag) {
|
||||||
|
0 -> <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!>
|
||||||
|
1 -> foo { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!> }
|
||||||
|
2 -> foo(@SomeAnnotation { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!> })
|
||||||
|
3 -> foo(fun () { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!> })
|
||||||
|
4 -> foo(@SomeAnnotation fun () { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!> })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun test3() {
|
fun test3() {
|
||||||
while (true) {
|
while (true) {
|
||||||
class LocalClass {
|
class LocalClass(val tag: Int) {
|
||||||
init {
|
init {
|
||||||
<!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!>
|
when(tag) {
|
||||||
|
0 -> <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!>
|
||||||
|
1 -> foo { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!> }
|
||||||
|
2 -> foo(@SomeAnnotation { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!> })
|
||||||
|
3 -> foo(fun () { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!> })
|
||||||
|
4 -> foo(@SomeAnnotation fun () { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!> })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun foo() {
|
fun foo() {
|
||||||
<!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!>
|
when(tag) {
|
||||||
|
0 -> <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!>
|
||||||
|
1 -> foo { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> }
|
||||||
|
2 -> foo(@SomeAnnotation { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
||||||
|
3 -> foo(fun () { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
||||||
|
4 -> foo(@SomeAnnotation fun () { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun test4() {
|
fun test4(tag: Int) {
|
||||||
while (true) {
|
while (true) {
|
||||||
object: Any() {
|
object: Any() {
|
||||||
init {
|
init {
|
||||||
<!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!>
|
when(tag) {
|
||||||
|
0 -> <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!>
|
||||||
|
1 -> foo { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> }
|
||||||
|
2 -> foo(@SomeAnnotation { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
||||||
|
3 -> foo(fun () { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
||||||
|
4 -> foo(@SomeAnnotation fun () { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -40,12 +79,15 @@ fun test4() {
|
|||||||
|
|
||||||
fun test5() {
|
fun test5() {
|
||||||
while (true) {
|
while (true) {
|
||||||
class LocalClass(val x: Int) {
|
class LocalClass(val s: String) {
|
||||||
constructor() : this(42) {
|
constructor(tag: Int) : this("") {
|
||||||
<!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!>
|
when(tag) {
|
||||||
}
|
0 -> <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!>
|
||||||
constructor(y: Double) : this(y.toInt()) {
|
1 -> foo { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> }
|
||||||
<!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!>
|
2 -> foo(@SomeAnnotation { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
||||||
|
3 -> foo(fun () { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
||||||
|
4 -> foo(@SomeAnnotation fun () { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -53,12 +95,24 @@ fun test5() {
|
|||||||
|
|
||||||
fun test6() {
|
fun test6() {
|
||||||
while (true) {
|
while (true) {
|
||||||
class LocalClass(val x: Int) {
|
class LocalClass(val tag: Int) {
|
||||||
init {
|
init {
|
||||||
<!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!>
|
when(tag) {
|
||||||
|
0 -> <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!>
|
||||||
|
1 -> foo { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> }
|
||||||
|
2 -> foo(@SomeAnnotation { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
||||||
|
3 -> foo(fun () { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
||||||
|
4 -> foo(@SomeAnnotation fun () { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
init {
|
init {
|
||||||
<!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!>
|
when(tag) {
|
||||||
|
0 -> <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!>
|
||||||
|
1 -> foo { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!> }
|
||||||
|
2 -> foo(@SomeAnnotation { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!> })
|
||||||
|
3 -> foo(fun () { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!> })
|
||||||
|
4 -> foo(@SomeAnnotation fun () { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!> })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -66,12 +120,26 @@ fun test6() {
|
|||||||
|
|
||||||
fun test7() {
|
fun test7() {
|
||||||
while (true) {
|
while (true) {
|
||||||
class LocalClass {
|
class LocalClass(val tag: Int) {
|
||||||
val x: Int = if (true) {
|
val x: Int = if (true) {
|
||||||
<!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!>
|
when(tag) {
|
||||||
|
0 -> <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!>
|
||||||
|
1 -> foo { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> }
|
||||||
|
2 -> foo(@SomeAnnotation { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
||||||
|
3 -> foo(fun (): Int { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
||||||
|
4 -> foo(@SomeAnnotation fun (): Int { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
||||||
|
else -> 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
<!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!>
|
when(tag) {
|
||||||
|
0 -> <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!>
|
||||||
|
1 -> foo { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!> }
|
||||||
|
2 -> foo(@SomeAnnotation { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!> })
|
||||||
|
3 -> foo(fun (): Int { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!> })
|
||||||
|
4 -> foo(@SomeAnnotation fun (): Int { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!> })
|
||||||
|
else -> 2
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -80,7 +148,16 @@ fun test7() {
|
|||||||
fun test8() {
|
fun test8() {
|
||||||
while (true) {
|
while (true) {
|
||||||
class LocalClass(val x: Int) {
|
class LocalClass(val x: Int) {
|
||||||
constructor() : this(if (true) { 42 } else { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
constructor(tag: Int, unused: Boolean) : this(
|
||||||
|
when(tag) {
|
||||||
|
0 -> <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!>
|
||||||
|
1 -> foo { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> }
|
||||||
|
2 -> foo(@SomeAnnotation { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
||||||
|
3 -> foo(fun (): Int { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
||||||
|
4 -> foo(@SomeAnnotation fun (): Int { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
||||||
|
else -> 1
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+99
-22
@@ -1,38 +1,77 @@
|
|||||||
|
// LANGUAGE: +BreakContinueInInlineLambdas
|
||||||
|
|
||||||
|
inline fun <T> foo(block: () -> T): T = block()
|
||||||
|
|
||||||
|
|
||||||
|
@Target(AnnotationTarget.EXPRESSION)
|
||||||
|
@Retention(AnnotationRetention.SOURCE)
|
||||||
|
public annotation class SomeAnnotation
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
while (true) {
|
while (true) {
|
||||||
fun local1() {
|
fun local1(tag: Int) {
|
||||||
<!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!>
|
when(tag) {
|
||||||
|
0 -> <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!>
|
||||||
|
1 -> foo { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> }
|
||||||
|
2 -> foo(@SomeAnnotation { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
||||||
|
3 -> foo(fun () { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
||||||
|
4 -> foo(@SomeAnnotation fun () { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun test2() {
|
fun test2() {
|
||||||
while (true) {
|
while (true) {
|
||||||
<!UNUSED_LAMBDA_EXPRESSION!>{
|
<!UNUSED_LAMBDA_EXPRESSION!>{tag: Int ->
|
||||||
<!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!>
|
when(tag) {
|
||||||
|
0 -> <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!>
|
||||||
|
1 -> foo { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!> }
|
||||||
|
2 -> foo(@SomeAnnotation { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!> })
|
||||||
|
3 -> foo(fun () { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!> })
|
||||||
|
4 -> foo(@SomeAnnotation fun () { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!> })
|
||||||
|
}
|
||||||
}<!>
|
}<!>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun test3() {
|
fun test3() {
|
||||||
while (true) {
|
while (true) {
|
||||||
class LocalClass {
|
class LocalClass(val tag: Int) {
|
||||||
init {
|
init {
|
||||||
<!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!>
|
when(tag) {
|
||||||
|
0 -> <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!>
|
||||||
|
1 -> foo { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!> }
|
||||||
|
2 -> foo(@SomeAnnotation { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!> })
|
||||||
|
3 -> foo(fun () { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!> })
|
||||||
|
4 -> foo(@SomeAnnotation fun () { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!> })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun foo() {
|
fun foo() {
|
||||||
<!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!>
|
when(tag) {
|
||||||
|
0 -> <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!>
|
||||||
|
1 -> foo { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> }
|
||||||
|
2 -> foo(@SomeAnnotation { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
||||||
|
3 -> foo(fun () { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
||||||
|
4 -> foo(@SomeAnnotation fun () { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun test4() {
|
fun test4(tag: Int) {
|
||||||
while (true) {
|
while (true) {
|
||||||
object: Any() {
|
object: Any() {
|
||||||
init {
|
init {
|
||||||
<!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!>
|
when(tag) {
|
||||||
|
0 -> <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!>
|
||||||
|
1 -> foo { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> }
|
||||||
|
2 -> foo(@SomeAnnotation { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
||||||
|
3 -> foo(fun () { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
||||||
|
4 -> foo(@SomeAnnotation fun () { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -40,12 +79,15 @@ fun test4() {
|
|||||||
|
|
||||||
fun test5() {
|
fun test5() {
|
||||||
while (true) {
|
while (true) {
|
||||||
class LocalClass(val x: Int) {
|
class LocalClass(val s: String) {
|
||||||
constructor() : this(42) {
|
constructor(tag: Int) : this("") {
|
||||||
<!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!>
|
when(tag) {
|
||||||
}
|
0 -> <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!>
|
||||||
constructor(y: Double) : this(y.toInt()) {
|
1 -> foo { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> }
|
||||||
<!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!>
|
2 -> foo(@SomeAnnotation { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
||||||
|
3 -> foo(fun () { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
||||||
|
4 -> foo(@SomeAnnotation fun () { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -53,12 +95,24 @@ fun test5() {
|
|||||||
|
|
||||||
fun test6() {
|
fun test6() {
|
||||||
while (true) {
|
while (true) {
|
||||||
class LocalClass(val x: Int) {
|
class LocalClass(val tag: Int) {
|
||||||
init {
|
init {
|
||||||
<!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!>
|
when(tag) {
|
||||||
|
0 -> <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!>
|
||||||
|
1 -> foo { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> }
|
||||||
|
2 -> foo(@SomeAnnotation { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
||||||
|
3 -> foo(fun () { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
||||||
|
4 -> foo(@SomeAnnotation fun () { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
init {
|
init {
|
||||||
<!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!>
|
when(tag) {
|
||||||
|
0 -> <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!>
|
||||||
|
1 -> foo { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!> }
|
||||||
|
2 -> foo(@SomeAnnotation { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!> })
|
||||||
|
3 -> foo(fun () { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!> })
|
||||||
|
4 -> foo(@SomeAnnotation fun () { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!> })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -66,12 +120,26 @@ fun test6() {
|
|||||||
|
|
||||||
fun test7() {
|
fun test7() {
|
||||||
while (true) {
|
while (true) {
|
||||||
class LocalClass {
|
class LocalClass(val tag: Int) {
|
||||||
val x: Int = if (true) {
|
val x: Int = if (true) {
|
||||||
<!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!>
|
when(tag) {
|
||||||
|
0 -> <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!>
|
||||||
|
1 -> foo { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> }
|
||||||
|
2 -> foo(@SomeAnnotation { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
||||||
|
3 -> foo(fun (): Int { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> <!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>}<!>)
|
||||||
|
4 -> foo(@SomeAnnotation fun (): Int { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> <!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>}<!>)
|
||||||
|
else -> 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
<!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!>
|
when(tag) {
|
||||||
|
0 -> <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!>
|
||||||
|
1 -> foo { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!> }
|
||||||
|
2 -> foo(@SomeAnnotation { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!> })
|
||||||
|
3 -> foo(fun (): Int { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!> <!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>}<!>)
|
||||||
|
4 -> foo(@SomeAnnotation fun (): Int { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>continue<!> <!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>}<!>)
|
||||||
|
else -> 2
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -80,7 +148,16 @@ fun test7() {
|
|||||||
fun test8() {
|
fun test8() {
|
||||||
while (true) {
|
while (true) {
|
||||||
class LocalClass(val x: Int) {
|
class LocalClass(val x: Int) {
|
||||||
constructor() : this(if (true) { 42 } else { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
constructor(tag: Int, <!UNUSED_PARAMETER!>unused<!>: Boolean) : this(
|
||||||
|
when(tag) {
|
||||||
|
0 -> <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!>
|
||||||
|
1 -> foo { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> }
|
||||||
|
2 -> foo(@SomeAnnotation { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> })
|
||||||
|
3 -> foo(fun (): Int { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> <!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>}<!>)
|
||||||
|
4 -> foo(@SomeAnnotation fun (): Int { <!BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY!>break<!> <!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>}<!>)
|
||||||
|
else -> 1
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+10
-1
@@ -1,10 +1,19 @@
|
|||||||
package
|
package
|
||||||
|
|
||||||
|
public inline fun </*0*/ T> foo(/*0*/ block: () -> T): T
|
||||||
public fun test(): kotlin.Unit
|
public fun test(): kotlin.Unit
|
||||||
public fun test2(): kotlin.Unit
|
public fun test2(): kotlin.Unit
|
||||||
public fun test3(): kotlin.Unit
|
public fun test3(): kotlin.Unit
|
||||||
public fun test4(): kotlin.Unit
|
public fun test4(/*0*/ tag: kotlin.Int): kotlin.Unit
|
||||||
public fun test5(): kotlin.Unit
|
public fun test5(): kotlin.Unit
|
||||||
public fun test6(): kotlin.Unit
|
public fun test6(): kotlin.Unit
|
||||||
public fun test7(): kotlin.Unit
|
public fun test7(): kotlin.Unit
|
||||||
public fun test8(): kotlin.Unit
|
public fun test8(): kotlin.Unit
|
||||||
|
|
||||||
|
@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.EXPRESSION}) @kotlin.annotation.Retention(value = AnnotationRetention.SOURCE) public final annotation class SomeAnnotation : kotlin.Annotation {
|
||||||
|
public constructor SomeAnnotation()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,344 @@
|
|||||||
|
FILE fqName:<root> fileName:/badInlinedBreakContinue.kt
|
||||||
|
FUN name:foo visibility:public modality:FINAL <> (block:kotlin.Function0<kotlin.Unit>) returnType:kotlin.Unit [inline]
|
||||||
|
VALUE_PARAMETER name:block index:0 type:kotlin.Function0<kotlin.Unit>
|
||||||
|
BLOCK_BODY
|
||||||
|
CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=kotlin.Unit origin=INVOKE
|
||||||
|
$this: GET_VAR 'block: kotlin.Function0<kotlin.Unit> declared in <root>.foo' type=kotlin.Function0<kotlin.Unit> origin=VARIABLE_AS_FUNCTION
|
||||||
|
FUN name:bar visibility:public modality:FINAL <> (block1:kotlin.Function0<kotlin.Unit>, block2:kotlin.Function0<kotlin.Unit>) returnType:kotlin.Unit [inline]
|
||||||
|
VALUE_PARAMETER name:block1 index:0 type:kotlin.Function0<kotlin.Unit>
|
||||||
|
VALUE_PARAMETER name:block2 index:1 type:kotlin.Function0<kotlin.Unit> [noinline]
|
||||||
|
BLOCK_BODY
|
||||||
|
CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=kotlin.Unit origin=INVOKE
|
||||||
|
$this: GET_VAR 'block1: kotlin.Function0<kotlin.Unit> declared in <root>.bar' type=kotlin.Function0<kotlin.Unit> origin=VARIABLE_AS_FUNCTION
|
||||||
|
CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=kotlin.Unit origin=INVOKE
|
||||||
|
$this: GET_VAR 'block2: kotlin.Function0<kotlin.Unit> [noinline] declared in <root>.bar' type=kotlin.Function0<kotlin.Unit> origin=VARIABLE_AS_FUNCTION
|
||||||
|
FUN name:myForEach visibility:public modality:FINAL <T> ($receiver:kotlin.collections.Iterable<T of <root>.myForEach>, action:kotlin.Function1<T of <root>.myForEach, kotlin.Unit>) returnType:kotlin.Unit [inline]
|
||||||
|
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] reified:false
|
||||||
|
$receiver: VALUE_PARAMETER name:<this> type:kotlin.collections.Iterable<T of <root>.myForEach>
|
||||||
|
VALUE_PARAMETER name:action index:0 type:kotlin.Function1<T of <root>.myForEach, kotlin.Unit>
|
||||||
|
BLOCK_BODY
|
||||||
|
BLOCK type=kotlin.Unit origin=FOR_LOOP
|
||||||
|
VAR FOR_LOOP_ITERATOR name:tmp_0 type:kotlin.collections.Iterator<T of <root>.myForEach> [val]
|
||||||
|
CALL 'public abstract fun iterator (): kotlin.collections.Iterator<T of kotlin.collections.Iterable> [operator] declared in kotlin.collections.Iterable' type=kotlin.collections.Iterator<T of <root>.myForEach> origin=FOR_LOOP_ITERATOR
|
||||||
|
$this: GET_VAR '<this>: kotlin.collections.Iterable<T of <root>.myForEach> declared in <root>.myForEach' type=kotlin.collections.Iterable<T of <root>.myForEach> origin=null
|
||||||
|
WHILE label=null origin=FOR_LOOP_INNER_WHILE
|
||||||
|
condition: CALL 'public abstract fun hasNext (): kotlin.Boolean [operator] declared in kotlin.collections.Iterator' type=kotlin.Boolean origin=FOR_LOOP_HAS_NEXT
|
||||||
|
$this: GET_VAR 'val tmp_0: kotlin.collections.Iterator<T of <root>.myForEach> [val] declared in <root>.myForEach' type=kotlin.collections.Iterator<T of <root>.myForEach> origin=null
|
||||||
|
body: BLOCK type=kotlin.Unit origin=FOR_LOOP_INNER_WHILE
|
||||||
|
VAR FOR_LOOP_VARIABLE name:element type:T of <root>.myForEach [val]
|
||||||
|
CALL 'public abstract fun next (): T of kotlin.collections.Iterator [operator] declared in kotlin.collections.Iterator' type=T of <root>.myForEach origin=FOR_LOOP_NEXT
|
||||||
|
$this: GET_VAR 'val tmp_0: kotlin.collections.Iterator<T of <root>.myForEach> [val] declared in <root>.myForEach' type=kotlin.collections.Iterator<T of <root>.myForEach> origin=null
|
||||||
|
CALL 'public abstract fun invoke (p1: P1 of kotlin.Function1): R of kotlin.Function1 [operator] declared in kotlin.Function1' type=kotlin.Unit origin=INVOKE
|
||||||
|
$this: GET_VAR 'action: kotlin.Function1<T of <root>.myForEach, kotlin.Unit> declared in <root>.myForEach' type=kotlin.Function1<T of <root>.myForEach, kotlin.Unit> origin=VARIABLE_AS_FUNCTION
|
||||||
|
p1: GET_VAR 'val element: T of <root>.myForEach [val] declared in <root>.myForEach' type=T of <root>.myForEach origin=null
|
||||||
|
FUN name:test1 visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
ERROR_EXPR '{break}()
|
||||||
|
{continue}()' type=IrErrorType([Error type: Error expression type])
|
||||||
|
CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=kotlin.Unit origin=INVOKE
|
||||||
|
$this: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=ANONYMOUS_FUNCTION
|
||||||
|
FUN LOCAL_FUNCTION name:<no name provided> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
ERROR_EXPR 'Loop not found for break expression: break' type=kotlin.Nothing
|
||||||
|
CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=kotlin.Unit origin=INVOKE
|
||||||
|
$this: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=ANONYMOUS_FUNCTION
|
||||||
|
FUN LOCAL_FUNCTION name:<no name provided> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
ERROR_EXPR 'Loop not found for continue expression: continue' type=kotlin.Nothing
|
||||||
|
CALL 'public final fun foo (block: kotlin.Function0<kotlin.Unit>): kotlin.Unit [inline] declared in <root>' type=kotlin.Unit origin=null
|
||||||
|
block: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=LAMBDA
|
||||||
|
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
ERROR_EXPR 'Loop not found for break expression: break' type=kotlin.Nothing
|
||||||
|
CALL 'public final fun foo (block: kotlin.Function0<kotlin.Unit>): kotlin.Unit [inline] declared in <root>' type=kotlin.Unit origin=null
|
||||||
|
block: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=LAMBDA
|
||||||
|
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
ERROR_EXPR 'Loop not found for continue expression: continue' type=kotlin.Nothing
|
||||||
|
CALL 'public final fun foo (block: kotlin.Function0<kotlin.Unit>): kotlin.Unit [inline] declared in <root>' type=kotlin.Unit origin=null
|
||||||
|
block: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=ANONYMOUS_FUNCTION
|
||||||
|
FUN LOCAL_FUNCTION name:<no name provided> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
ERROR_EXPR 'Loop not found for break expression: break' type=kotlin.Nothing
|
||||||
|
CALL 'public final fun foo (block: kotlin.Function0<kotlin.Unit>): kotlin.Unit [inline] declared in <root>' type=kotlin.Unit origin=null
|
||||||
|
block: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=ANONYMOUS_FUNCTION
|
||||||
|
FUN LOCAL_FUNCTION name:<no name provided> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
ERROR_EXPR 'Loop not found for continue expression: continue' type=kotlin.Nothing
|
||||||
|
FUN name:test2 visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
WHILE label=L1 origin=WHILE_LOOP
|
||||||
|
condition: CONST Boolean type=kotlin.Boolean value=true
|
||||||
|
body: BLOCK type=kotlin.Unit origin=null
|
||||||
|
ERROR_EXPR '{break@ERROR}()
|
||||||
|
{continue@ERROR}()' type=IrErrorType([Error type: Error expression type])
|
||||||
|
CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=kotlin.Unit origin=INVOKE
|
||||||
|
$this: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=ANONYMOUS_FUNCTION
|
||||||
|
FUN LOCAL_FUNCTION name:<no name provided> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
ERROR_EXPR 'Loop not found for break expression: break@ERROR' type=kotlin.Nothing
|
||||||
|
CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=kotlin.Unit origin=INVOKE
|
||||||
|
$this: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=ANONYMOUS_FUNCTION
|
||||||
|
FUN LOCAL_FUNCTION name:<no name provided> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
ERROR_EXPR 'Loop not found for continue expression: continue@ERROR' type=kotlin.Nothing
|
||||||
|
CALL 'public final fun foo (block: kotlin.Function0<kotlin.Unit>): kotlin.Unit [inline] declared in <root>' type=kotlin.Unit origin=null
|
||||||
|
block: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=LAMBDA
|
||||||
|
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
ERROR_EXPR 'Loop not found for break expression: break@ERROR' type=kotlin.Nothing
|
||||||
|
CALL 'public final fun foo (block: kotlin.Function0<kotlin.Unit>): kotlin.Unit [inline] declared in <root>' type=kotlin.Unit origin=null
|
||||||
|
block: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=LAMBDA
|
||||||
|
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
ERROR_EXPR 'Loop not found for continue expression: continue@ERROR' type=kotlin.Nothing
|
||||||
|
CALL 'public final fun foo (block: kotlin.Function0<kotlin.Unit>): kotlin.Unit [inline] declared in <root>' type=kotlin.Unit origin=null
|
||||||
|
block: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=ANONYMOUS_FUNCTION
|
||||||
|
FUN LOCAL_FUNCTION name:<no name provided> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
ERROR_EXPR 'Loop not found for break expression: break@ERROR' type=kotlin.Nothing
|
||||||
|
CALL 'public final fun foo (block: kotlin.Function0<kotlin.Unit>): kotlin.Unit [inline] declared in <root>' type=kotlin.Unit origin=null
|
||||||
|
block: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=ANONYMOUS_FUNCTION
|
||||||
|
FUN LOCAL_FUNCTION name:<no name provided> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
ERROR_EXPR 'Loop not found for continue expression: continue@ERROR' type=kotlin.Nothing
|
||||||
|
FUN name:test3 visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
WHILE label=L1 origin=WHILE_LOOP
|
||||||
|
condition: CONST Boolean type=kotlin.Boolean value=true
|
||||||
|
body: BLOCK type=kotlin.Unit origin=null
|
||||||
|
VAR name:lambda type:kotlin.Function0<kotlin.Unit> [val]
|
||||||
|
FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=LAMBDA
|
||||||
|
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
ERROR_EXPR '{break@L1}()
|
||||||
|
{continue@L1}()' type=IrErrorType([Error type: Error expression type])
|
||||||
|
CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=kotlin.Unit origin=INVOKE
|
||||||
|
$this: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=ANONYMOUS_FUNCTION
|
||||||
|
FUN LOCAL_FUNCTION name:<no name provided> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
ERROR_EXPR 'Loop not found for break expression: break@L1' type=kotlin.Nothing
|
||||||
|
CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=kotlin.Unit origin=INVOKE
|
||||||
|
$this: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=ANONYMOUS_FUNCTION
|
||||||
|
FUN LOCAL_FUNCTION name:<no name provided> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
ERROR_EXPR 'Loop not found for continue expression: continue@L1' type=kotlin.Nothing
|
||||||
|
CALL 'public final fun foo (block: kotlin.Function0<kotlin.Unit>): kotlin.Unit [inline] declared in <root>' type=kotlin.Unit origin=null
|
||||||
|
block: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=LAMBDA
|
||||||
|
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
ERROR_EXPR 'Loop not found for break expression: break@L1' type=kotlin.Nothing
|
||||||
|
CALL 'public final fun foo (block: kotlin.Function0<kotlin.Unit>): kotlin.Unit [inline] declared in <root>' type=kotlin.Unit origin=null
|
||||||
|
block: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=LAMBDA
|
||||||
|
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
ERROR_EXPR 'Loop not found for continue expression: continue@L1' type=kotlin.Nothing
|
||||||
|
CALL 'public final fun foo (block: kotlin.Function0<kotlin.Unit>): kotlin.Unit [inline] declared in <root>' type=kotlin.Unit origin=null
|
||||||
|
block: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=ANONYMOUS_FUNCTION
|
||||||
|
FUN LOCAL_FUNCTION name:<no name provided> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
ERROR_EXPR 'Loop not found for break expression: break@L1' type=kotlin.Nothing
|
||||||
|
CALL 'public final fun foo (block: kotlin.Function0<kotlin.Unit>): kotlin.Unit [inline] declared in <root>' type=kotlin.Unit origin=null
|
||||||
|
block: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=ANONYMOUS_FUNCTION
|
||||||
|
FUN LOCAL_FUNCTION name:<no name provided> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
ERROR_EXPR 'Loop not found for continue expression: continue@L1' type=kotlin.Nothing
|
||||||
|
FUN name:test4 visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
WHILE label=null origin=WHILE_LOOP
|
||||||
|
condition: CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=kotlin.Nothing origin=INVOKE
|
||||||
|
$this: FUN_EXPR type=kotlin.Function0<kotlin.Nothing> origin=LAMBDA
|
||||||
|
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.Nothing
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from='local final fun <anonymous> (): kotlin.Nothing declared in <root>.test4'
|
||||||
|
ERROR_EXPR 'Loop not found for break expression: break' type=kotlin.Nothing
|
||||||
|
body: BLOCK type=kotlin.Unit origin=null
|
||||||
|
WHILE label=null origin=WHILE_LOOP
|
||||||
|
condition: CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=kotlin.Nothing origin=INVOKE
|
||||||
|
$this: FUN_EXPR type=kotlin.Function0<kotlin.Nothing> origin=LAMBDA
|
||||||
|
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.Nothing
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from='local final fun <anonymous> (): kotlin.Nothing declared in <root>.test4'
|
||||||
|
ERROR_EXPR 'Loop not found for continue expression: continue' type=kotlin.Nothing
|
||||||
|
body: BLOCK type=kotlin.Unit origin=null
|
||||||
|
WHILE label=null origin=WHILE_LOOP
|
||||||
|
condition: TYPE_OP type=kotlin.Boolean origin=IMPLICIT_CAST typeOperand=kotlin.Boolean
|
||||||
|
CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=kotlin.Unit origin=INVOKE
|
||||||
|
$this: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=ANONYMOUS_FUNCTION
|
||||||
|
FUN LOCAL_FUNCTION name:<no name provided> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
ERROR_EXPR 'Loop not found for break expression: break' type=kotlin.Nothing
|
||||||
|
body: BLOCK type=kotlin.Unit origin=null
|
||||||
|
WHILE label=null origin=WHILE_LOOP
|
||||||
|
condition: TYPE_OP type=kotlin.Boolean origin=IMPLICIT_CAST typeOperand=kotlin.Boolean
|
||||||
|
CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=kotlin.Unit origin=INVOKE
|
||||||
|
$this: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=ANONYMOUS_FUNCTION
|
||||||
|
FUN LOCAL_FUNCTION name:<no name provided> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
ERROR_EXPR 'Loop not found for continue expression: continue' type=kotlin.Nothing
|
||||||
|
body: BLOCK type=kotlin.Unit origin=null
|
||||||
|
WHILE label=null origin=WHILE_LOOP
|
||||||
|
condition: TYPE_OP type=kotlin.Boolean origin=IMPLICIT_CAST typeOperand=kotlin.Boolean
|
||||||
|
CALL 'public final fun foo (block: kotlin.Function0<kotlin.Unit>): kotlin.Unit [inline] declared in <root>' type=kotlin.Unit origin=null
|
||||||
|
block: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=LAMBDA
|
||||||
|
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
ERROR_EXPR 'Loop not found for break expression: break' type=kotlin.Nothing
|
||||||
|
body: BLOCK type=kotlin.Unit origin=null
|
||||||
|
WHILE label=null origin=WHILE_LOOP
|
||||||
|
condition: TYPE_OP type=kotlin.Boolean origin=IMPLICIT_CAST typeOperand=kotlin.Boolean
|
||||||
|
CALL 'public final fun foo (block: kotlin.Function0<kotlin.Unit>): kotlin.Unit [inline] declared in <root>' type=kotlin.Unit origin=null
|
||||||
|
block: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=LAMBDA
|
||||||
|
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
ERROR_EXPR 'Loop not found for continue expression: continue' type=kotlin.Nothing
|
||||||
|
body: BLOCK type=kotlin.Unit origin=null
|
||||||
|
WHILE label=null origin=WHILE_LOOP
|
||||||
|
condition: TYPE_OP type=kotlin.Boolean origin=IMPLICIT_CAST typeOperand=kotlin.Boolean
|
||||||
|
CALL 'public final fun foo (block: kotlin.Function0<kotlin.Unit>): kotlin.Unit [inline] declared in <root>' type=kotlin.Unit origin=null
|
||||||
|
block: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=ANONYMOUS_FUNCTION
|
||||||
|
FUN LOCAL_FUNCTION name:<no name provided> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
ERROR_EXPR 'Loop not found for break expression: break' type=kotlin.Nothing
|
||||||
|
body: BLOCK type=kotlin.Unit origin=null
|
||||||
|
WHILE label=null origin=WHILE_LOOP
|
||||||
|
condition: TYPE_OP type=kotlin.Boolean origin=IMPLICIT_CAST typeOperand=kotlin.Boolean
|
||||||
|
CALL 'public final fun foo (block: kotlin.Function0<kotlin.Unit>): kotlin.Unit [inline] declared in <root>' type=kotlin.Unit origin=null
|
||||||
|
block: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=ANONYMOUS_FUNCTION
|
||||||
|
FUN LOCAL_FUNCTION name:<no name provided> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
ERROR_EXPR 'Loop not found for continue expression: continue' type=kotlin.Nothing
|
||||||
|
body: BLOCK type=kotlin.Unit origin=null
|
||||||
|
FUN name:test5 visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
CALL 'public final fun forEach <T> (action: kotlin.Function1<T of kotlin.collections.CollectionsKt.forEach, kotlin.Unit>): kotlin.Unit [inline] declared in kotlin.collections.CollectionsKt' type=kotlin.Unit origin=null
|
||||||
|
<T>: kotlin.Int
|
||||||
|
$receiver: CALL 'public final fun listOf <T> (vararg elements: T of kotlin.collections.CollectionsKt.listOf): kotlin.collections.List<T of kotlin.collections.CollectionsKt.listOf> declared in kotlin.collections.CollectionsKt' type=kotlin.collections.List<kotlin.Int> origin=null
|
||||||
|
<T>: kotlin.Int
|
||||||
|
elements: VARARG type=kotlin.Array<out kotlin.Int> varargElementType=kotlin.Int
|
||||||
|
CONST Int type=kotlin.Int value=1
|
||||||
|
CONST Int type=kotlin.Int value=2
|
||||||
|
CONST Int type=kotlin.Int value=3
|
||||||
|
action: FUN_EXPR type=kotlin.Function1<kotlin.Int, kotlin.Unit> origin=LAMBDA
|
||||||
|
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> (i:kotlin.Int) returnType:kotlin.Unit
|
||||||
|
VALUE_PARAMETER name:i index:0 type:kotlin.Int
|
||||||
|
BLOCK_BODY
|
||||||
|
WHEN type=kotlin.Unit origin=IF
|
||||||
|
BRANCH
|
||||||
|
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
|
||||||
|
arg0: GET_VAR 'i: kotlin.Int declared in <root>.test5.<anonymous>' type=kotlin.Int origin=null
|
||||||
|
arg1: CONST Int type=kotlin.Int value=2
|
||||||
|
then: ERROR_EXPR 'Loop not found for break expression: break' type=kotlin.Nothing
|
||||||
|
CALL 'public final fun forEach <T> (action: kotlin.Function1<T of kotlin.collections.CollectionsKt.forEach, kotlin.Unit>): kotlin.Unit [inline] declared in kotlin.collections.CollectionsKt' type=kotlin.Unit origin=null
|
||||||
|
<T>: kotlin.Int
|
||||||
|
$receiver: CALL 'public final fun listOf <T> (vararg elements: T of kotlin.collections.CollectionsKt.listOf): kotlin.collections.List<T of kotlin.collections.CollectionsKt.listOf> declared in kotlin.collections.CollectionsKt' type=kotlin.collections.List<kotlin.Int> origin=null
|
||||||
|
<T>: kotlin.Int
|
||||||
|
elements: VARARG type=kotlin.Array<out kotlin.Int> varargElementType=kotlin.Int
|
||||||
|
CONST Int type=kotlin.Int value=1
|
||||||
|
CONST Int type=kotlin.Int value=2
|
||||||
|
CONST Int type=kotlin.Int value=3
|
||||||
|
action: FUN_EXPR type=kotlin.Function1<kotlin.Int, kotlin.Unit> origin=LAMBDA
|
||||||
|
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> (i:kotlin.Int) returnType:kotlin.Unit
|
||||||
|
VALUE_PARAMETER name:i index:0 type:kotlin.Int
|
||||||
|
BLOCK_BODY
|
||||||
|
WHEN type=kotlin.Unit origin=IF
|
||||||
|
BRANCH
|
||||||
|
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
|
||||||
|
arg0: GET_VAR 'i: kotlin.Int declared in <root>.test5.<anonymous>' type=kotlin.Int origin=null
|
||||||
|
arg1: CONST Int type=kotlin.Int value=2
|
||||||
|
then: ERROR_EXPR 'Loop not found for continue expression: continue' type=kotlin.Nothing
|
||||||
|
CALL 'public final fun forEach <T> (action: kotlin.Function1<T of kotlin.collections.CollectionsKt.forEach, kotlin.Unit>): kotlin.Unit [inline] declared in kotlin.collections.CollectionsKt' type=kotlin.Unit origin=null
|
||||||
|
<T>: kotlin.Int
|
||||||
|
$receiver: CALL 'public final fun listOf <T> (vararg elements: T of kotlin.collections.CollectionsKt.listOf): kotlin.collections.List<T of kotlin.collections.CollectionsKt.listOf> declared in kotlin.collections.CollectionsKt' type=kotlin.collections.List<kotlin.Int> origin=null
|
||||||
|
<T>: kotlin.Int
|
||||||
|
elements: VARARG type=kotlin.Array<out kotlin.Int> varargElementType=kotlin.Int
|
||||||
|
CONST Int type=kotlin.Int value=1
|
||||||
|
CONST Int type=kotlin.Int value=2
|
||||||
|
CONST Int type=kotlin.Int value=3
|
||||||
|
action: FUN_EXPR type=kotlin.Function1<kotlin.Int, kotlin.Unit> origin=ANONYMOUS_FUNCTION
|
||||||
|
FUN LOCAL_FUNCTION name:<no name provided> visibility:local modality:FINAL <> (i:kotlin.Int) returnType:kotlin.Unit
|
||||||
|
VALUE_PARAMETER name:i index:0 type:kotlin.Int
|
||||||
|
BLOCK_BODY
|
||||||
|
WHEN type=kotlin.Unit origin=IF
|
||||||
|
BRANCH
|
||||||
|
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
|
||||||
|
arg0: GET_VAR 'i: kotlin.Int declared in <root>.test5.<no name provided>' type=kotlin.Int origin=null
|
||||||
|
arg1: CONST Int type=kotlin.Int value=2
|
||||||
|
then: ERROR_EXPR 'Loop not found for break expression: break' type=kotlin.Nothing
|
||||||
|
CALL 'public final fun forEach <T> (action: kotlin.Function1<T of kotlin.collections.CollectionsKt.forEach, kotlin.Unit>): kotlin.Unit [inline] declared in kotlin.collections.CollectionsKt' type=kotlin.Unit origin=null
|
||||||
|
<T>: kotlin.Int
|
||||||
|
$receiver: CALL 'public final fun listOf <T> (vararg elements: T of kotlin.collections.CollectionsKt.listOf): kotlin.collections.List<T of kotlin.collections.CollectionsKt.listOf> declared in kotlin.collections.CollectionsKt' type=kotlin.collections.List<kotlin.Int> origin=null
|
||||||
|
<T>: kotlin.Int
|
||||||
|
elements: VARARG type=kotlin.Array<out kotlin.Int> varargElementType=kotlin.Int
|
||||||
|
CONST Int type=kotlin.Int value=1
|
||||||
|
CONST Int type=kotlin.Int value=2
|
||||||
|
CONST Int type=kotlin.Int value=3
|
||||||
|
action: FUN_EXPR type=kotlin.Function1<kotlin.Int, kotlin.Unit> origin=ANONYMOUS_FUNCTION
|
||||||
|
FUN LOCAL_FUNCTION name:<no name provided> visibility:local modality:FINAL <> (i:kotlin.Int) returnType:kotlin.Unit
|
||||||
|
VALUE_PARAMETER name:i index:0 type:kotlin.Int
|
||||||
|
BLOCK_BODY
|
||||||
|
WHEN type=kotlin.Unit origin=IF
|
||||||
|
BRANCH
|
||||||
|
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
|
||||||
|
arg0: GET_VAR 'i: kotlin.Int declared in <root>.test5.<no name provided>' type=kotlin.Int origin=null
|
||||||
|
arg1: CONST Int type=kotlin.Int value=2
|
||||||
|
then: ERROR_EXPR 'Loop not found for continue expression: continue' type=kotlin.Nothing
|
||||||
|
FUN name:test6 visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
WHILE label=null origin=WHILE_LOOP
|
||||||
|
condition: CONST Boolean type=kotlin.Boolean value=true
|
||||||
|
body: BLOCK type=kotlin.Unit origin=null
|
||||||
|
CALL 'public final fun bar (block1: kotlin.Function0<kotlin.Unit>, block2: kotlin.Function0<kotlin.Unit>): kotlin.Unit [inline] declared in <root>' type=kotlin.Unit origin=null
|
||||||
|
block1: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=LAMBDA
|
||||||
|
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from='local final fun <anonymous> (): kotlin.Unit declared in <root>.test6'
|
||||||
|
GET_OBJECT 'CLASS IR_EXTERNAL_DECLARATION_STUB OBJECT name:Unit modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.Unit
|
||||||
|
block2: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=LAMBDA
|
||||||
|
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
ERROR_EXPR 'Loop not found for break expression: break' type=kotlin.Nothing
|
||||||
|
CALL 'public final fun bar (block1: kotlin.Function0<kotlin.Unit>, block2: kotlin.Function0<kotlin.Unit>): kotlin.Unit [inline] declared in <root>' type=kotlin.Unit origin=null
|
||||||
|
block1: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=LAMBDA
|
||||||
|
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from='local final fun <anonymous> (): kotlin.Unit declared in <root>.test6'
|
||||||
|
GET_OBJECT 'CLASS IR_EXTERNAL_DECLARATION_STUB OBJECT name:Unit modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.Unit
|
||||||
|
block2: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=LAMBDA
|
||||||
|
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
ERROR_EXPR 'Loop not found for continue expression: continue' type=kotlin.Nothing
|
||||||
|
CALL 'public final fun bar (block1: kotlin.Function0<kotlin.Unit>, block2: kotlin.Function0<kotlin.Unit>): kotlin.Unit [inline] declared in <root>' type=kotlin.Unit origin=null
|
||||||
|
block1: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=ANONYMOUS_FUNCTION
|
||||||
|
FUN LOCAL_FUNCTION name:<no name provided> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
block2: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=ANONYMOUS_FUNCTION
|
||||||
|
FUN LOCAL_FUNCTION name:<no name provided> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
ERROR_EXPR 'Loop not found for break expression: break' type=kotlin.Nothing
|
||||||
|
CALL 'public final fun bar (block1: kotlin.Function0<kotlin.Unit>, block2: kotlin.Function0<kotlin.Unit>): kotlin.Unit [inline] declared in <root>' type=kotlin.Unit origin=null
|
||||||
|
block1: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=ANONYMOUS_FUNCTION
|
||||||
|
FUN LOCAL_FUNCTION name:<no name provided> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
block2: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=ANONYMOUS_FUNCTION
|
||||||
|
FUN LOCAL_FUNCTION name:<no name provided> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
ERROR_EXPR 'Loop not found for continue expression: continue' type=kotlin.Nothing
|
||||||
|
FUN name:test7 visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
CALL 'public final fun myForEach <T> (action: kotlin.Function1<T of <root>.myForEach, kotlin.Unit>): kotlin.Unit [inline] declared in <root>' type=kotlin.Unit origin=null
|
||||||
|
<T>: kotlin.Int
|
||||||
|
$receiver: CALL 'public final fun rangeTo (other: kotlin.Int): kotlin.ranges.IntRange [operator] declared in kotlin.Int' type=kotlin.ranges.IntRange origin=RANGE
|
||||||
|
$this: CONST Int type=kotlin.Int value=1
|
||||||
|
other: CONST Int type=kotlin.Int value=3
|
||||||
|
action: FUN_EXPR type=kotlin.Function1<kotlin.Int, kotlin.Unit> origin=LAMBDA
|
||||||
|
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> (i:kotlin.Int) returnType:kotlin.Unit
|
||||||
|
VALUE_PARAMETER name:i index:0 type:kotlin.Int
|
||||||
|
BLOCK_BODY
|
||||||
|
WHEN type=kotlin.Unit origin=IF
|
||||||
|
BRANCH
|
||||||
|
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
|
||||||
|
arg0: GET_VAR 'i: kotlin.Int declared in <root>.test7.<anonymous>' type=kotlin.Int origin=null
|
||||||
|
arg1: CONST Int type=kotlin.Int value=2
|
||||||
|
then: BLOCK type=kotlin.Unit origin=null
|
||||||
|
ERROR_EXPR 'Loop not found for break expression: break' type=kotlin.Nothing
|
||||||
@@ -0,0 +1,111 @@
|
|||||||
|
// LANGUAGE: +BreakContinueInInlineLambdas
|
||||||
|
// TARGET_BACKEND: JVM_IR
|
||||||
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
|
// !IGNORE_ERRORS
|
||||||
|
// WITH_STDLIB
|
||||||
|
|
||||||
|
inline fun foo(block: () -> Unit) { block() }
|
||||||
|
|
||||||
|
inline fun bar(block1: () -> Unit, noinline block2: () -> Unit) {
|
||||||
|
block1()
|
||||||
|
block2()
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <T> Iterable<T>.myForEach(action: (T) -> Unit): Unit {
|
||||||
|
for (element in this) action(element)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test1() {
|
||||||
|
{break}()
|
||||||
|
{continue}()
|
||||||
|
|
||||||
|
(fun () {break})()
|
||||||
|
(fun () {continue})()
|
||||||
|
|
||||||
|
foo {break}
|
||||||
|
foo {continue}
|
||||||
|
|
||||||
|
foo(fun () {break})
|
||||||
|
foo(fun () {continue})
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test2() {
|
||||||
|
L1@ while (true) {
|
||||||
|
{break@ERROR}()
|
||||||
|
{continue@ERROR}()
|
||||||
|
|
||||||
|
(fun () {break@ERROR})()
|
||||||
|
(fun () {continue@ERROR})()
|
||||||
|
|
||||||
|
foo {break@ERROR}
|
||||||
|
foo {continue@ERROR}
|
||||||
|
|
||||||
|
foo(fun () {break@ERROR})
|
||||||
|
foo(fun () {continue@ERROR})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test3() {
|
||||||
|
L1@ while (true) {
|
||||||
|
val lambda = {
|
||||||
|
{break@L1}()
|
||||||
|
{continue@L1}()
|
||||||
|
|
||||||
|
(fun () {break@L1})()
|
||||||
|
(fun () {continue@L1})()
|
||||||
|
|
||||||
|
foo {break@L1}
|
||||||
|
foo {continue@L1}
|
||||||
|
|
||||||
|
foo(fun () {break@L1})
|
||||||
|
foo(fun () {continue@L1})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test4() {
|
||||||
|
while ({ break }()) {
|
||||||
|
}
|
||||||
|
while ({ continue }()) {
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((fun() { break })()) {
|
||||||
|
}
|
||||||
|
while ((fun() { continue })()) {
|
||||||
|
}
|
||||||
|
|
||||||
|
while (foo { break }) {
|
||||||
|
}
|
||||||
|
while (foo { continue }) {
|
||||||
|
}
|
||||||
|
|
||||||
|
while (foo(fun() { break })) {
|
||||||
|
}
|
||||||
|
while (foo(fun() { continue })) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test5() {
|
||||||
|
listOf(1, 2, 3).forEach { i -> if (i == 2) break }
|
||||||
|
listOf(1, 2, 3).forEach { i -> if (i == 2) continue }
|
||||||
|
listOf(1, 2, 3).forEach(fun (i: Int) { if (i == 2) break })
|
||||||
|
listOf(1, 2, 3).forEach(fun (i: Int) { if (i == 2) continue })
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test6() {
|
||||||
|
while (true) {
|
||||||
|
bar({}, {break})
|
||||||
|
bar({}, {continue})
|
||||||
|
|
||||||
|
bar(fun () {}, fun () {break})
|
||||||
|
bar(fun () {}, fun () {continue})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test7() {
|
||||||
|
(1..3).myForEach { i ->
|
||||||
|
if (i == 2) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,222 @@
|
|||||||
|
inline fun foo(block: Function0<Unit>) {
|
||||||
|
block.invoke()
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun bar(block1: Function0<Unit>, noinline block2: Function0<Unit>) {
|
||||||
|
block1.invoke()
|
||||||
|
block2.invoke()
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <T : Any?> Iterable<T>.myForEach(action: Function1<T, Unit>) {
|
||||||
|
{ // BLOCK
|
||||||
|
val tmp0_iterator: Iterator<T> = <this>.iterator()
|
||||||
|
while (tmp0_iterator.hasNext()) { // BLOCK
|
||||||
|
val element: T = tmp0_iterator.next()
|
||||||
|
action.invoke(p1 = element)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test1() {
|
||||||
|
error("") /* ErrorExpression */
|
||||||
|
local fun <no name provided>() {
|
||||||
|
error("") /* ErrorExpression */
|
||||||
|
}
|
||||||
|
.invoke()
|
||||||
|
local fun <no name provided>() {
|
||||||
|
error("") /* ErrorExpression */
|
||||||
|
}
|
||||||
|
.invoke()
|
||||||
|
foo(block = local fun <anonymous>() {
|
||||||
|
error("") /* ErrorExpression */
|
||||||
|
}
|
||||||
|
)
|
||||||
|
foo(block = local fun <anonymous>() {
|
||||||
|
error("") /* ErrorExpression */
|
||||||
|
}
|
||||||
|
)
|
||||||
|
foo(block = local fun <no name provided>() {
|
||||||
|
error("") /* ErrorExpression */
|
||||||
|
}
|
||||||
|
)
|
||||||
|
foo(block = local fun <no name provided>() {
|
||||||
|
error("") /* ErrorExpression */
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test2() {
|
||||||
|
L1@ while (true) { // BLOCK
|
||||||
|
error("") /* ErrorExpression */
|
||||||
|
local fun <no name provided>() {
|
||||||
|
error("") /* ErrorExpression */
|
||||||
|
}
|
||||||
|
.invoke()
|
||||||
|
local fun <no name provided>() {
|
||||||
|
error("") /* ErrorExpression */
|
||||||
|
}
|
||||||
|
.invoke()
|
||||||
|
foo(block = local fun <anonymous>() {
|
||||||
|
error("") /* ErrorExpression */
|
||||||
|
}
|
||||||
|
)
|
||||||
|
foo(block = local fun <anonymous>() {
|
||||||
|
error("") /* ErrorExpression */
|
||||||
|
}
|
||||||
|
)
|
||||||
|
foo(block = local fun <no name provided>() {
|
||||||
|
error("") /* ErrorExpression */
|
||||||
|
}
|
||||||
|
)
|
||||||
|
foo(block = local fun <no name provided>() {
|
||||||
|
error("") /* ErrorExpression */
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test3() {
|
||||||
|
L1@ while (true) { // BLOCK
|
||||||
|
val lambda: Function0<Unit> = local fun <anonymous>() {
|
||||||
|
error("") /* ErrorExpression */
|
||||||
|
local fun <no name provided>() {
|
||||||
|
error("") /* ErrorExpression */
|
||||||
|
}
|
||||||
|
.invoke()
|
||||||
|
local fun <no name provided>() {
|
||||||
|
error("") /* ErrorExpression */
|
||||||
|
}
|
||||||
|
.invoke()
|
||||||
|
foo(block = local fun <anonymous>() {
|
||||||
|
error("") /* ErrorExpression */
|
||||||
|
}
|
||||||
|
)
|
||||||
|
foo(block = local fun <anonymous>() {
|
||||||
|
error("") /* ErrorExpression */
|
||||||
|
}
|
||||||
|
)
|
||||||
|
foo(block = local fun <no name provided>() {
|
||||||
|
error("") /* ErrorExpression */
|
||||||
|
}
|
||||||
|
)
|
||||||
|
foo(block = local fun <no name provided>() {
|
||||||
|
error("") /* ErrorExpression */
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test4() {
|
||||||
|
while (local fun <anonymous>(): Nothing {
|
||||||
|
return error("") /* ErrorExpression */
|
||||||
|
}
|
||||||
|
.invoke()) { // BLOCK
|
||||||
|
}
|
||||||
|
while (local fun <anonymous>(): Nothing {
|
||||||
|
return error("") /* ErrorExpression */
|
||||||
|
}
|
||||||
|
.invoke()) { // BLOCK
|
||||||
|
}
|
||||||
|
while (local fun <no name provided>() {
|
||||||
|
error("") /* ErrorExpression */
|
||||||
|
}
|
||||||
|
.invoke() /*as Boolean */) { // BLOCK
|
||||||
|
}
|
||||||
|
while (local fun <no name provided>() {
|
||||||
|
error("") /* ErrorExpression */
|
||||||
|
}
|
||||||
|
.invoke() /*as Boolean */) { // BLOCK
|
||||||
|
}
|
||||||
|
while (foo(block = local fun <anonymous>() {
|
||||||
|
error("") /* ErrorExpression */
|
||||||
|
}
|
||||||
|
) /*as Boolean */) { // BLOCK
|
||||||
|
}
|
||||||
|
while (foo(block = local fun <anonymous>() {
|
||||||
|
error("") /* ErrorExpression */
|
||||||
|
}
|
||||||
|
) /*as Boolean */) { // BLOCK
|
||||||
|
}
|
||||||
|
while (foo(block = local fun <no name provided>() {
|
||||||
|
error("") /* ErrorExpression */
|
||||||
|
}
|
||||||
|
) /*as Boolean */) { // BLOCK
|
||||||
|
}
|
||||||
|
while (foo(block = local fun <no name provided>() {
|
||||||
|
error("") /* ErrorExpression */
|
||||||
|
}
|
||||||
|
) /*as Boolean */) { // BLOCK
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test5() {
|
||||||
|
listOf<Int>(elements = [1, 2, 3]).forEach<Int>(action = local fun <anonymous>(i: Int) {
|
||||||
|
when {
|
||||||
|
EQEQ(arg0 = i, arg1 = 2) -> error("") /* ErrorExpression */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
listOf<Int>(elements = [1, 2, 3]).forEach<Int>(action = local fun <anonymous>(i: Int) {
|
||||||
|
when {
|
||||||
|
EQEQ(arg0 = i, arg1 = 2) -> error("") /* ErrorExpression */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
listOf<Int>(elements = [1, 2, 3]).forEach<Int>(action = local fun <no name provided>(i: Int) {
|
||||||
|
when {
|
||||||
|
EQEQ(arg0 = i, arg1 = 2) -> error("") /* ErrorExpression */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
listOf<Int>(elements = [1, 2, 3]).forEach<Int>(action = local fun <no name provided>(i: Int) {
|
||||||
|
when {
|
||||||
|
EQEQ(arg0 = i, arg1 = 2) -> error("") /* ErrorExpression */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test6() {
|
||||||
|
while (true) { // BLOCK
|
||||||
|
bar(block1 = local fun <anonymous>() {
|
||||||
|
return Unit
|
||||||
|
}
|
||||||
|
, block2 = local fun <anonymous>() {
|
||||||
|
error("") /* ErrorExpression */
|
||||||
|
}
|
||||||
|
)
|
||||||
|
bar(block1 = local fun <anonymous>() {
|
||||||
|
return Unit
|
||||||
|
}
|
||||||
|
, block2 = local fun <anonymous>() {
|
||||||
|
error("") /* ErrorExpression */
|
||||||
|
}
|
||||||
|
)
|
||||||
|
bar(block1 = local fun <no name provided>() {
|
||||||
|
}
|
||||||
|
, block2 = local fun <no name provided>() {
|
||||||
|
error("") /* ErrorExpression */
|
||||||
|
}
|
||||||
|
)
|
||||||
|
bar(block1 = local fun <no name provided>() {
|
||||||
|
}
|
||||||
|
, block2 = local fun <no name provided>() {
|
||||||
|
error("") /* ErrorExpression */
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test7() {
|
||||||
|
1.rangeTo(other = 3).myForEach<Int>(action = local fun <anonymous>(i: Int) {
|
||||||
|
when {
|
||||||
|
EQEQ(arg0 = i, arg1 = 2) -> { // BLOCK
|
||||||
|
error("") /* ErrorExpression */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
FILE fqName:<root> fileName:/breakContinueInNoInlineLambda.kt
|
||||||
|
FUN name:foo visibility:public modality:FINAL <> (block:kotlin.Function0<kotlin.Unit>) returnType:kotlin.Unit [inline]
|
||||||
|
VALUE_PARAMETER name:block index:0 type:kotlin.Function0<kotlin.Unit> [noinline]
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from='public final fun foo (block: kotlin.Function0<kotlin.Unit>): kotlin.Unit [inline] declared in <root>'
|
||||||
|
CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=kotlin.Unit origin=INVOKE
|
||||||
|
$this: GET_VAR 'block: kotlin.Function0<kotlin.Unit> [noinline] declared in <root>.foo' type=kotlin.Function0<kotlin.Unit> origin=VARIABLE_AS_FUNCTION
|
||||||
|
FUN name:test1 visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
WHILE label=L1 origin=WHILE_LOOP
|
||||||
|
condition: CONST Boolean type=kotlin.Boolean value=true
|
||||||
|
body: BLOCK type=kotlin.Unit origin=null
|
||||||
|
CALL 'public final fun foo (block: kotlin.Function0<kotlin.Unit>): kotlin.Unit [inline] declared in <root>' type=kotlin.Unit origin=null
|
||||||
|
block: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=LAMBDA
|
||||||
|
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
ERROR_EXPR 'Loop not found for break expression: break' type=kotlin.Nothing
|
||||||
|
CALL 'public final fun foo (block: kotlin.Function0<kotlin.Unit>): kotlin.Unit [inline] declared in <root>' type=kotlin.Unit origin=null
|
||||||
|
block: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=LAMBDA
|
||||||
|
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
ERROR_EXPR 'Loop not found for break expression: break@L1' type=kotlin.Nothing
|
||||||
|
CALL 'public final fun foo (block: kotlin.Function0<kotlin.Unit>): kotlin.Unit [inline] declared in <root>' type=kotlin.Unit origin=null
|
||||||
|
block: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=LAMBDA
|
||||||
|
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
ERROR_EXPR 'Loop not found for continue expression: continue' type=kotlin.Nothing
|
||||||
|
CALL 'public final fun foo (block: kotlin.Function0<kotlin.Unit>): kotlin.Unit [inline] declared in <root>' type=kotlin.Unit origin=null
|
||||||
|
block: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=LAMBDA
|
||||||
|
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
ERROR_EXPR 'Loop not found for continue expression: continue@L1' type=kotlin.Nothing
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
// LANGUAGE: +BreakContinueInInlineLambdas
|
||||||
|
// TARGET_BACKEND: JVM_IR
|
||||||
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
|
// !IGNORE_ERRORS
|
||||||
|
|
||||||
|
|
||||||
|
inline fun foo(noinline block: () -> Unit) = block()
|
||||||
|
|
||||||
|
|
||||||
|
fun test1() {
|
||||||
|
L1@ while (true) {
|
||||||
|
foo { break }
|
||||||
|
|
||||||
|
foo { break@L1 }
|
||||||
|
|
||||||
|
foo { continue }
|
||||||
|
|
||||||
|
foo { continue@L1 }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
inline fun foo(noinline block: Function0<Unit>) {
|
||||||
|
return block.invoke()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test1() {
|
||||||
|
L1@ while (true) { // BLOCK
|
||||||
|
foo(block = local fun <anonymous>() {
|
||||||
|
error("") /* ErrorExpression */
|
||||||
|
}
|
||||||
|
)
|
||||||
|
foo(block = local fun <anonymous>() {
|
||||||
|
error("") /* ErrorExpression */
|
||||||
|
}
|
||||||
|
)
|
||||||
|
foo(block = local fun <anonymous>() {
|
||||||
|
error("") /* ErrorExpression */
|
||||||
|
}
|
||||||
|
)
|
||||||
|
foo(block = local fun <anonymous>() {
|
||||||
|
error("") /* ErrorExpression */
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
FILE fqName:<root> fileName:/inlinedBreakContinue.kt
|
||||||
|
FUN name:foo visibility:public modality:FINAL <> (block:kotlin.Function0<kotlin.Unit>) returnType:kotlin.Unit [inline]
|
||||||
|
VALUE_PARAMETER name:block index:0 type:kotlin.Function0<kotlin.Unit>
|
||||||
|
BLOCK_BODY
|
||||||
|
CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=kotlin.Unit origin=INVOKE
|
||||||
|
$this: GET_VAR 'block: kotlin.Function0<kotlin.Unit> declared in <root>.foo' type=kotlin.Function0<kotlin.Unit> origin=VARIABLE_AS_FUNCTION
|
||||||
|
FUN name:bar visibility:public modality:FINAL <> (block1:kotlin.Function0<kotlin.Unit>, block2:kotlin.Function0<kotlin.Unit>) returnType:kotlin.Unit [inline]
|
||||||
|
VALUE_PARAMETER name:block1 index:0 type:kotlin.Function0<kotlin.Unit>
|
||||||
|
VALUE_PARAMETER name:block2 index:1 type:kotlin.Function0<kotlin.Unit> [noinline]
|
||||||
|
BLOCK_BODY
|
||||||
|
CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=kotlin.Unit origin=INVOKE
|
||||||
|
$this: GET_VAR 'block1: kotlin.Function0<kotlin.Unit> declared in <root>.bar' type=kotlin.Function0<kotlin.Unit> origin=VARIABLE_AS_FUNCTION
|
||||||
|
CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=kotlin.Unit origin=INVOKE
|
||||||
|
$this: GET_VAR 'block2: kotlin.Function0<kotlin.Unit> [noinline] declared in <root>.bar' type=kotlin.Function0<kotlin.Unit> origin=VARIABLE_AS_FUNCTION
|
||||||
|
FUN name:test1 visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
WHILE label=null origin=WHILE_LOOP
|
||||||
|
condition: CONST Boolean type=kotlin.Boolean value=true
|
||||||
|
body: BLOCK type=kotlin.Unit origin=null
|
||||||
|
CALL 'public final fun foo (block: kotlin.Function0<kotlin.Unit>): kotlin.Unit [inline] declared in <root>' type=kotlin.Unit origin=null
|
||||||
|
block: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=LAMBDA
|
||||||
|
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
BREAK label=null loop.label=null
|
||||||
|
CALL 'public final fun foo (block: kotlin.Function0<kotlin.Unit>): kotlin.Unit [inline] declared in <root>' type=kotlin.Unit origin=null
|
||||||
|
block: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=LAMBDA
|
||||||
|
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
CONTINUE label=null loop.label=null
|
||||||
|
CALL 'public final fun foo (block: kotlin.Function0<kotlin.Unit>): kotlin.Unit [inline] declared in <root>' type=kotlin.Unit origin=null
|
||||||
|
block: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=ANONYMOUS_FUNCTION
|
||||||
|
FUN LOCAL_FUNCTION name:<no name provided> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
BREAK label=null loop.label=null
|
||||||
|
CALL 'public final fun foo (block: kotlin.Function0<kotlin.Unit>): kotlin.Unit [inline] declared in <root>' type=kotlin.Unit origin=null
|
||||||
|
block: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=ANONYMOUS_FUNCTION
|
||||||
|
FUN LOCAL_FUNCTION name:<no name provided> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
CONTINUE label=null loop.label=null
|
||||||
|
FUN name:test2 visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
WHILE label=null origin=WHILE_LOOP
|
||||||
|
condition: CONST Boolean type=kotlin.Boolean value=true
|
||||||
|
body: BLOCK type=kotlin.Unit origin=null
|
||||||
|
CALL 'public final fun bar (block1: kotlin.Function0<kotlin.Unit>, block2: kotlin.Function0<kotlin.Unit>): kotlin.Unit [inline] declared in <root>' type=kotlin.Unit origin=null
|
||||||
|
block1: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=LAMBDA
|
||||||
|
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
BREAK label=null loop.label=null
|
||||||
|
block2: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=LAMBDA
|
||||||
|
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from='local final fun <anonymous> (): kotlin.Unit declared in <root>.test2'
|
||||||
|
GET_OBJECT 'CLASS IR_EXTERNAL_DECLARATION_STUB OBJECT name:Unit modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.Unit
|
||||||
|
CALL 'public final fun bar (block1: kotlin.Function0<kotlin.Unit>, block2: kotlin.Function0<kotlin.Unit>): kotlin.Unit [inline] declared in <root>' type=kotlin.Unit origin=null
|
||||||
|
block1: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=LAMBDA
|
||||||
|
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
CONTINUE label=null loop.label=null
|
||||||
|
block2: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=LAMBDA
|
||||||
|
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from='local final fun <anonymous> (): kotlin.Unit declared in <root>.test2'
|
||||||
|
GET_OBJECT 'CLASS IR_EXTERNAL_DECLARATION_STUB OBJECT name:Unit modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.Unit
|
||||||
|
CALL 'public final fun bar (block1: kotlin.Function0<kotlin.Unit>, block2: kotlin.Function0<kotlin.Unit>): kotlin.Unit [inline] declared in <root>' type=kotlin.Unit origin=null
|
||||||
|
block1: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=ANONYMOUS_FUNCTION
|
||||||
|
FUN LOCAL_FUNCTION name:<no name provided> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
BREAK label=null loop.label=null
|
||||||
|
block2: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=ANONYMOUS_FUNCTION
|
||||||
|
FUN LOCAL_FUNCTION name:<no name provided> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
CALL 'public final fun bar (block1: kotlin.Function0<kotlin.Unit>, block2: kotlin.Function0<kotlin.Unit>): kotlin.Unit [inline] declared in <root>' type=kotlin.Unit origin=null
|
||||||
|
block1: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=ANONYMOUS_FUNCTION
|
||||||
|
FUN LOCAL_FUNCTION name:<no name provided> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
CONTINUE label=null loop.label=null
|
||||||
|
block2: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=ANONYMOUS_FUNCTION
|
||||||
|
FUN LOCAL_FUNCTION name:<no name provided> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
// LANGUAGE: +BreakContinueInInlineLambdas
|
||||||
|
// TARGET_BACKEND: JVM_IR
|
||||||
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
|
// !IGNORE_ERRORS
|
||||||
|
// WITH_STDLIB
|
||||||
|
|
||||||
|
inline fun foo(block: () -> Unit) { block() }
|
||||||
|
|
||||||
|
inline fun bar(block1: () -> Unit, noinline block2: () -> Unit) {
|
||||||
|
block1()
|
||||||
|
block2()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test1() {
|
||||||
|
while (true) {
|
||||||
|
foo { break }
|
||||||
|
foo { continue }
|
||||||
|
foo(fun () { break })
|
||||||
|
foo(fun () { continue })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test2() {
|
||||||
|
while (true) {
|
||||||
|
bar({break}, {})
|
||||||
|
bar({continue}, {})
|
||||||
|
|
||||||
|
bar(fun () {break}, fun () {})
|
||||||
|
bar(fun () {continue}, fun () {})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
inline fun foo(block: Function0<Unit>) {
|
||||||
|
block.invoke()
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun bar(block1: Function0<Unit>, noinline block2: Function0<Unit>) {
|
||||||
|
block1.invoke()
|
||||||
|
block2.invoke()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test1() {
|
||||||
|
while (true) { // BLOCK
|
||||||
|
foo(block = local fun <anonymous>() {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
)
|
||||||
|
foo(block = local fun <anonymous>() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
)
|
||||||
|
foo(block = local fun <no name provided>() {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
)
|
||||||
|
foo(block = local fun <no name provided>() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test2() {
|
||||||
|
while (true) { // BLOCK
|
||||||
|
bar(block1 = local fun <anonymous>() {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
, block2 = local fun <anonymous>() {
|
||||||
|
return Unit
|
||||||
|
}
|
||||||
|
)
|
||||||
|
bar(block1 = local fun <anonymous>() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
, block2 = local fun <anonymous>() {
|
||||||
|
return Unit
|
||||||
|
}
|
||||||
|
)
|
||||||
|
bar(block1 = local fun <no name provided>() {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
, block2 = local fun <no name provided>() {
|
||||||
|
}
|
||||||
|
)
|
||||||
|
bar(block1 = local fun <no name provided>() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
, block2 = local fun <no name provided>() {
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
Generated
+12
@@ -5482,6 +5482,18 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
|||||||
runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/breakContinueInTryFinallyInLoop.kt");
|
runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/breakContinueInTryFinallyInLoop.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("breakContinueNoinline.kt")
|
||||||
|
public void testBreakContinueNoinline() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/breakContinueNoinline.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("breakInLambdaPassedToDirectInvoke.kt")
|
||||||
|
public void testBreakInLambdaPassedToDirectInvoke() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/breakInLambdaPassedToDirectInvoke.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("breakInsideLocal.kt")
|
@TestMetadata("breakInsideLocal.kt")
|
||||||
public void testBreakInsideLocal() throws Exception {
|
public void testBreakInsideLocal() throws Exception {
|
||||||
|
|||||||
+10
@@ -8913,6 +8913,16 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
public void testWhileTrueBreak() throws Exception {
|
public void testWhileTrueBreak() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/whileTrueBreak.kt");
|
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/whileTrueBreak.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class InlinedBreakContinue {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInInlinedBreakContinue() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
|
|||||||
+46
@@ -9033,6 +9033,52 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
public void testWhileTrueBreak() throws Exception {
|
public void testWhileTrueBreak() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/whileTrueBreak.kt");
|
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/whileTrueBreak.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class InlinedBreakContinue {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInInlinedBreakContinue() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("inlineFunctionWithMultipleParameters.kt")
|
||||||
|
public void testInlineFunctionWithMultipleParameters() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue/inlineFunctionWithMultipleParameters.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("lambdaPassedToInlineFunction.kt")
|
||||||
|
public void testLambdaPassedToInlineFunction() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue/lambdaPassedToInlineFunction.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("loopWithinInlineFunction.kt")
|
||||||
|
public void testLoopWithinInlineFunction() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue/loopWithinInlineFunction.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("simple.kt")
|
||||||
|
public void testSimple() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue/simple.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("stdlibFunctions.kt")
|
||||||
|
public void testStdlibFunctions() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue/stdlibFunctions.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("withReturnValue.kt")
|
||||||
|
public void testWithReturnValue() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue/withReturnValue.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
|
|||||||
Generated
+18
@@ -1196,6 +1196,12 @@ public class IrTextTestGenerated extends AbstractIrTextTest {
|
|||||||
runTest("compiler/testData/ir/irText/expressions/badBreakContinue.kt");
|
runTest("compiler/testData/ir/irText/expressions/badBreakContinue.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("badInlinedBreakContinue.kt")
|
||||||
|
public void testBadInlinedBreakContinue() throws Exception {
|
||||||
|
runTest("compiler/testData/ir/irText/expressions/badInlinedBreakContinue.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("bangbang.kt")
|
@TestMetadata("bangbang.kt")
|
||||||
public void testBangbang() throws Exception {
|
public void testBangbang() throws Exception {
|
||||||
@@ -1238,6 +1244,12 @@ public class IrTextTestGenerated extends AbstractIrTextTest {
|
|||||||
runTest("compiler/testData/ir/irText/expressions/breakContinueInLoopHeader.kt");
|
runTest("compiler/testData/ir/irText/expressions/breakContinueInLoopHeader.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("breakContinueInNoInlineLambda.kt")
|
||||||
|
public void testBreakContinueInNoInlineLambda() throws Exception {
|
||||||
|
runTest("compiler/testData/ir/irText/expressions/breakContinueInNoInlineLambda.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("breakContinueInWhen.kt")
|
@TestMetadata("breakContinueInWhen.kt")
|
||||||
public void testBreakContinueInWhen() throws Exception {
|
public void testBreakContinueInWhen() throws Exception {
|
||||||
@@ -1502,6 +1514,12 @@ public class IrTextTestGenerated extends AbstractIrTextTest {
|
|||||||
runTest("compiler/testData/ir/irText/expressions/incrementDecrement.kt");
|
runTest("compiler/testData/ir/irText/expressions/incrementDecrement.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("inlinedBreakContinue.kt")
|
||||||
|
public void testInlinedBreakContinue() throws Exception {
|
||||||
|
runTest("compiler/testData/ir/irText/expressions/inlinedBreakContinue.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("interfaceThisRef.kt")
|
@TestMetadata("interfaceThisRef.kt")
|
||||||
public void testInterfaceThisRef() throws Exception {
|
public void testInterfaceThisRef() throws Exception {
|
||||||
|
|||||||
+13
@@ -6892,6 +6892,19 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
public void testWhileTrueBreak() throws Exception {
|
public void testWhileTrueBreak() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/whileTrueBreak.kt");
|
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/whileTrueBreak.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class InlinedBreakContinue extends AbstractLightAnalysisModeTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInInlinedBreakContinue() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/controlStructures/forInArray")
|
@TestMetadata("compiler/testData/codegen/box/controlStructures/forInArray")
|
||||||
|
|||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// LANGUAGE: -BreakContinueInInlineLambdas
|
||||||
// !OPT_IN: kotlin.contracts.ExperimentalContracts
|
// !OPT_IN: kotlin.contracts.ExperimentalContracts
|
||||||
// SKIP_TXT
|
// SKIP_TXT
|
||||||
|
|
||||||
|
|||||||
@@ -282,6 +282,7 @@ enum class LanguageFeature(
|
|||||||
ForbidInferringPostponedTypeVariableIntoDeclaredUpperBound(KOTLIN_1_9, kind = BUG_FIX), // KT-47986
|
ForbidInferringPostponedTypeVariableIntoDeclaredUpperBound(KOTLIN_1_9, kind = BUG_FIX), // KT-47986
|
||||||
SkipStandaloneScriptsInSourceRoots(KOTLIN_1_9, kind = OTHER), // KT-52525
|
SkipStandaloneScriptsInSourceRoots(KOTLIN_1_9, kind = OTHER), // KT-52525
|
||||||
ModifierNonBuiltinSuspendFunError(KOTLIN_1_9),
|
ModifierNonBuiltinSuspendFunError(KOTLIN_1_9),
|
||||||
|
BreakContinueInInlineLambdas(KOTLIN_1_9, defaultState = State.ENABLED), // KT-1436
|
||||||
|
|
||||||
// Disabled for indefinite time. See KT-48535 and related discussion
|
// Disabled for indefinite time. See KT-48535 and related discussion
|
||||||
ApproximateIntegerLiteralTypesInReceiverPosition(sinceVersion = null),
|
ApproximateIntegerLiteralTypesInReceiverPosition(sinceVersion = null),
|
||||||
|
|||||||
+10
@@ -6077,6 +6077,16 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
public void testWhileTrueBreak() throws Exception {
|
public void testWhileTrueBreak() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/whileTrueBreak.kt");
|
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/whileTrueBreak.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class InlinedBreakContinue {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInInlinedBreakContinue() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
|
|||||||
+46
@@ -6125,6 +6125,52 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
|||||||
public void testWhileTrueBreak() throws Exception {
|
public void testWhileTrueBreak() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/whileTrueBreak.kt");
|
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/whileTrueBreak.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class InlinedBreakContinue {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInInlinedBreakContinue() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("inlineFunctionWithMultipleParameters.kt")
|
||||||
|
public void testInlineFunctionWithMultipleParameters() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue/inlineFunctionWithMultipleParameters.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("lambdaPassedToInlineFunction.kt")
|
||||||
|
public void testLambdaPassedToInlineFunction() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue/lambdaPassedToInlineFunction.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("loopWithinInlineFunction.kt")
|
||||||
|
public void testLoopWithinInlineFunction() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue/loopWithinInlineFunction.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("simple.kt")
|
||||||
|
public void testSimple() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue/simple.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("stdlibFunctions.kt")
|
||||||
|
public void testStdlibFunctions() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue/stdlibFunctions.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("withReturnValue.kt")
|
||||||
|
public void testWithReturnValue() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue/withReturnValue.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
|
|||||||
+43
@@ -5392,6 +5392,49 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
|
|||||||
public void testWhileTrueBreak() throws Exception {
|
public void testWhileTrueBreak() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/whileTrueBreak.kt");
|
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/whileTrueBreak.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class InlinedBreakContinue extends AbstractIrCodegenBoxWasmTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInInlinedBreakContinue() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inlineFunctionWithMultipleParameters.kt")
|
||||||
|
public void testInlineFunctionWithMultipleParameters() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue/inlineFunctionWithMultipleParameters.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("lambdaPassedToInlineFunction.kt")
|
||||||
|
public void testLambdaPassedToInlineFunction() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue/lambdaPassedToInlineFunction.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("loopWithinInlineFunction.kt")
|
||||||
|
public void testLoopWithinInlineFunction() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue/loopWithinInlineFunction.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("simple.kt")
|
||||||
|
public void testSimple() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue/simple.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("stdlibFunctions.kt")
|
||||||
|
public void testStdlibFunctions() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue/stdlibFunctions.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("withReturnValue.kt")
|
||||||
|
public void testWithReturnValue() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue/withReturnValue.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/controlStructures/forInArray")
|
@TestMetadata("compiler/testData/codegen/box/controlStructures/forInArray")
|
||||||
|
|||||||
+48
@@ -6965,6 +6965,54 @@ public class NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTest
|
|||||||
public void testWhileTrueBreak() throws Exception {
|
public void testWhileTrueBreak() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/whileTrueBreak.kt");
|
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/whileTrueBreak.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@Tag("codegen")
|
||||||
|
@UseExtTestCaseGroupProvider()
|
||||||
|
public class InlinedBreakContinue {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInInlinedBreakContinue() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.NATIVE, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("inlineFunctionWithMultipleParameters.kt")
|
||||||
|
public void testInlineFunctionWithMultipleParameters() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue/inlineFunctionWithMultipleParameters.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("lambdaPassedToInlineFunction.kt")
|
||||||
|
public void testLambdaPassedToInlineFunction() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue/lambdaPassedToInlineFunction.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("loopWithinInlineFunction.kt")
|
||||||
|
public void testLoopWithinInlineFunction() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue/loopWithinInlineFunction.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("simple.kt")
|
||||||
|
public void testSimple() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue/simple.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("stdlibFunctions.kt")
|
||||||
|
public void testStdlibFunctions() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue/stdlibFunctions.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("withReturnValue.kt")
|
||||||
|
public void testWithReturnValue() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/inlinedBreakContinue/withReturnValue.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
|
|||||||
Reference in New Issue
Block a user