From 3b5706972ed397f0bc3e187e8dd4efe884b28498 Mon Sep 17 00:00:00 2001 From: Ilmir Usmanov Date: Sun, 11 Oct 2020 20:07:05 +0200 Subject: [PATCH] Extract effect from lambda argument if it is in parentheses Otherwise, contracts on the parameter have no effect. #KT-42044 Fixed #KT-26229 Fixed --- .../ir/FirBlackBoxCodegenTestGenerated.java | 5 ++++ .../contracts/EffectsExtractingVisitor.kt | 5 +++- .../box/contracts/fieldInConstructorParens.kt | 27 +++++++++++++++++++ .../controlFlow/initialization/neg/5.kt | 17 ++++-------- .../controlFlow/initialization/neg/6.fir.kt | 16 ----------- .../controlFlow/initialization/neg/6.kt | 27 ------------------- .../controlFlow/initialization/pos/6.kt | 18 ++++++------- .../DiagnosticsTestSpecGenerated.java | 5 ---- .../FirDiagnosticsTestSpecGenerated.java | 5 ---- .../codegen/BlackBoxCodegenTestGenerated.java | 5 ++++ .../LightAnalysisModeTestGenerated.java | 5 ++++ .../ir/IrBlackBoxCodegenTestGenerated.java | 5 ++++ .../IrJsCodegenBoxES6TestGenerated.java | 5 ++++ .../IrJsCodegenBoxTestGenerated.java | 5 ++++ .../semantics/JsCodegenBoxTestGenerated.java | 5 ++++ 15 files changed, 79 insertions(+), 76 deletions(-) create mode 100644 compiler/testData/codegen/box/contracts/fieldInConstructorParens.kt delete mode 100644 compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/neg/6.fir.kt delete mode 100644 compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/neg/6.kt diff --git a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java index 984a9c53698..18d70957a04 100644 --- a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java @@ -5324,6 +5324,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/contracts/exception.kt"); } + @TestMetadata("fieldInConstructorParens.kt") + public void testFieldInConstructorParens() throws Exception { + runTest("compiler/testData/codegen/box/contracts/fieldInConstructorParens.kt"); + } + @TestMetadata("fieldReadInConstructor.kt") public void testFieldReadInConstructor() throws Exception { runTest("compiler/testData/codegen/box/contracts/fieldReadInConstructor.kt"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/contracts/EffectsExtractingVisitor.kt b/compiler/frontend/src/org/jetbrains/kotlin/contracts/EffectsExtractingVisitor.kt index 6a83e670ffa..1cf8aaa8f29 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/contracts/EffectsExtractingVisitor.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/contracts/EffectsExtractingVisitor.kt @@ -242,7 +242,10 @@ class EffectsExtractingVisitor( private fun ValueArgument.toComputation(): Computation? { return when (this) { is KtLambdaArgument -> getLambdaExpression()?.let { ESLambda(it) } - is KtValueArgument -> getArgumentExpression()?.let { extractOrGetCached(it) } + is KtValueArgument -> getArgumentExpression()?.let { + if (it is KtLambdaExpression) ESLambda(it) + else extractOrGetCached(it) + } else -> null } } diff --git a/compiler/testData/codegen/box/contracts/fieldInConstructorParens.kt b/compiler/testData/codegen/box/contracts/fieldInConstructorParens.kt new file mode 100644 index 00000000000..c704f80699b --- /dev/null +++ b/compiler/testData/codegen/box/contracts/fieldInConstructorParens.kt @@ -0,0 +1,27 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts +// IGNORE_BACKEND: NATIVE +// WITH_RUNTIME +// KJS_WITH_FULL_RUNTIME + +import kotlin.contracts.* + +class Smth { + val whatever: Int + + init { + calculate({ whatever = it }) + } + + @OptIn(ExperimentalContracts::class) + private inline fun calculate(block: (Int) -> Unit) { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + block(42) + } +} + +fun box(): String { + val smth = Smth() + return if (smth.whatever == 42) "OK" else "FAIL ${smth.whatever}" +} \ No newline at end of file diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/neg/5.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/neg/5.kt index 88df1048fe5..ccf1dd3da16 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/neg/5.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/neg/5.kt @@ -12,15 +12,16 @@ // TESTCASE NUMBER: 1 fun case_1() { - val value_1: Int - funWithExactlyOnceCallsInPlace({ value_1 = 10 }) + var value_1: Int + val l = { value_1 = 10 } + funWithAtLeastOnceCallsInPlace(l) value_1.inc() } // TESTCASE NUMBER: 2 fun case_2() { var value_1: Int - val l = { value_1 = 10 } + val l = fun () { value_1 = 10 } funWithAtLeastOnceCallsInPlace(l) value_1.inc() } @@ -28,20 +29,12 @@ fun case_2() { // TESTCASE NUMBER: 3 fun case_3() { var value_1: Int - val l = fun () { value_1 = 10 } - funWithAtLeastOnceCallsInPlace(l) + funWithAtLeastOnceCallsInPlace(fun () { value_1 = 10 }) value_1.inc() } // TESTCASE NUMBER: 4 fun case_4() { - var value_1: Int - funWithAtLeastOnceCallsInPlace(fun () { value_1 = 10 }) - value_1.inc() -} - -// TESTCASE NUMBER: 5 -fun case_5() { val value_1: Int val o = object { fun l() { value_1 = 10 } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/neg/6.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/neg/6.fir.kt deleted file mode 100644 index ab4d419989d..00000000000 --- a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/neg/6.fir.kt +++ /dev/null @@ -1,16 +0,0 @@ -// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts -// SKIP_TXT - -// TESTCASE NUMBER: 1 -fun case_1() { - val value_1: Int - funWithExactlyOnceCallsInPlace({ value_1 = 11 }) - value_1.inc() -} - -// TESTCASE NUMBER: 2 -fun case_2() { - var value_1: Int - funWithAtLeastOnceCallsInPlace({ value_1 = 11 }) - value_1.inc() -} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/neg/6.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/neg/6.kt deleted file mode 100644 index a5144d533cf..00000000000 --- a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/neg/6.kt +++ /dev/null @@ -1,27 +0,0 @@ -// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts -// SKIP_TXT - -/* - * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) - * - * SECTIONS: contracts, analysis, controlFlow, initialization - * NUMBER: 6 - * DESCRIPTION: Check the lack of CallsInPlace effect on the lambda in the parentheses. - * UNEXPECTED BEHAVIOUR - * ISSUES: KT-26229 - * HELPERS: contractFunctions - */ - -// TESTCASE NUMBER: 1 -fun case_1() { - val value_1: Int - funWithExactlyOnceCallsInPlace({ value_1 = 11 }) - value_1.inc() -} - -// TESTCASE NUMBER: 2 -fun case_2() { - var value_1: Int - funWithAtLeastOnceCallsInPlace({ value_1 = 11 }) - value_1.inc() -} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/pos/6.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/pos/6.kt index 3d8a52ee6d0..3c99ce6354e 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/pos/6.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/pos/6.kt @@ -5,9 +5,7 @@ * * SECTIONS: contracts, analysis, controlFlow, initialization * NUMBER: 6 - * DESCRIPTION: Check the lack of CallsInPlace effect on the lambda in the parentheses. - * UNEXPECTED BEHAVIOUR - * ISSUES: KT-26229 + * DESCRIPTION: Check the presence of CallsInPlace effect on the lambda in the parentheses. * HELPERS: contractFunctions */ @@ -37,15 +35,15 @@ import contracts.* // TESTCASE NUMBER: 1 fun case_1() { val value_1: Int - funWithExactlyOnceCallsInPlace({ value_1 = 11 }) - value_1.inc() + funWithExactlyOnceCallsInPlace({ value_1 = 11 }) + value_1.inc() } // TESTCASE NUMBER: 2 fun case_2() { var value_1: Int funWithAtLeastOnceCallsInPlace({ value_1 = 11 }) - value_1.inc() + value_1.inc() } // TESTCASE NUMBER: 3 @@ -53,8 +51,8 @@ fun case_3() { val value_1: Int var value_2: Int val value_3: Int - contracts.case_3({ value_1 = 1 }, { value_2 = 2 }, { value_3 = 3 }) - value_1.inc() - value_2.inc() - value_3.inc() + contracts.case_3({ value_1 = 1 }, { value_2 = 2 }, { value_3 = 3 }) + value_1.inc() + value_2.inc() + value_3.inc() } diff --git a/compiler/tests-spec/tests/org/jetbrains/kotlin/spec/checkers/DiagnosticsTestSpecGenerated.java b/compiler/tests-spec/tests/org/jetbrains/kotlin/spec/checkers/DiagnosticsTestSpecGenerated.java index ae25fbd5383..e7bd2bdf4c2 100644 --- a/compiler/tests-spec/tests/org/jetbrains/kotlin/spec/checkers/DiagnosticsTestSpecGenerated.java +++ b/compiler/tests-spec/tests/org/jetbrains/kotlin/spec/checkers/DiagnosticsTestSpecGenerated.java @@ -6527,11 +6527,6 @@ public class DiagnosticsTestSpecGenerated extends AbstractDiagnosticsTestSpec { runTest("compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/neg/5.kt"); } - @TestMetadata("6.kt") - public void test6() throws Exception { - runTest("compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/neg/6.kt"); - } - public void testAllFilesPresentInNeg() throws Exception { KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/neg"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true); } diff --git a/compiler/tests-spec/tests/org/jetbrains/kotlin/spec/checkers/FirDiagnosticsTestSpecGenerated.java b/compiler/tests-spec/tests/org/jetbrains/kotlin/spec/checkers/FirDiagnosticsTestSpecGenerated.java index 0dcda97c33a..47b5b6cb458 100644 --- a/compiler/tests-spec/tests/org/jetbrains/kotlin/spec/checkers/FirDiagnosticsTestSpecGenerated.java +++ b/compiler/tests-spec/tests/org/jetbrains/kotlin/spec/checkers/FirDiagnosticsTestSpecGenerated.java @@ -6527,11 +6527,6 @@ public class FirDiagnosticsTestSpecGenerated extends AbstractFirDiagnosticsTestS runTest("compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/neg/5.kt"); } - @TestMetadata("6.kt") - public void test6() throws Exception { - runTest("compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/neg/6.kt"); - } - public void testAllFilesPresentInNeg() throws Exception { KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/neg"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true); } diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 8dcdf239622..78208c95a36 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -5354,6 +5354,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/contracts/exception.kt"); } + @TestMetadata("fieldInConstructorParens.kt") + public void testFieldInConstructorParens() throws Exception { + runTest("compiler/testData/codegen/box/contracts/fieldInConstructorParens.kt"); + } + @TestMetadata("fieldReadInConstructor.kt") public void testFieldReadInConstructor() throws Exception { runTest("compiler/testData/codegen/box/contracts/fieldReadInConstructor.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 8213a0f61ab..514a1d249d8 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -5354,6 +5354,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/contracts/exception.kt"); } + @TestMetadata("fieldInConstructorParens.kt") + public void testFieldInConstructorParens() throws Exception { + runTest("compiler/testData/codegen/box/contracts/fieldInConstructorParens.kt"); + } + @TestMetadata("fieldReadInConstructor.kt") public void testFieldReadInConstructor() throws Exception { runTest("compiler/testData/codegen/box/contracts/fieldReadInConstructor.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 2cf0c9c0f07..f931ca78313 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -5324,6 +5324,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/contracts/exception.kt"); } + @TestMetadata("fieldInConstructorParens.kt") + public void testFieldInConstructorParens() throws Exception { + runTest("compiler/testData/codegen/box/contracts/fieldInConstructorParens.kt"); + } + @TestMetadata("fieldReadInConstructor.kt") public void testFieldReadInConstructor() throws Exception { runTest("compiler/testData/codegen/box/contracts/fieldReadInConstructor.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java index 16caaf78470..62c5b3c760d 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java @@ -4239,6 +4239,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes runTest("compiler/testData/codegen/box/contracts/exception.kt"); } + @TestMetadata("fieldInConstructorParens.kt") + public void testFieldInConstructorParens() throws Exception { + runTest("compiler/testData/codegen/box/contracts/fieldInConstructorParens.kt"); + } + @TestMetadata("fieldReadInConstructor.kt") public void testFieldReadInConstructor() throws Exception { runTest("compiler/testData/codegen/box/contracts/fieldReadInConstructor.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index 45275b48f87..0ffd7405ba5 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -4239,6 +4239,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/contracts/exception.kt"); } + @TestMetadata("fieldInConstructorParens.kt") + public void testFieldInConstructorParens() throws Exception { + runTest("compiler/testData/codegen/box/contracts/fieldInConstructorParens.kt"); + } + @TestMetadata("fieldReadInConstructor.kt") public void testFieldReadInConstructor() throws Exception { runTest("compiler/testData/codegen/box/contracts/fieldReadInConstructor.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 90b220a5a91..97f6242fecc 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -4239,6 +4239,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/contracts/exception.kt"); } + @TestMetadata("fieldInConstructorParens.kt") + public void testFieldInConstructorParens() throws Exception { + runTest("compiler/testData/codegen/box/contracts/fieldInConstructorParens.kt"); + } + @TestMetadata("fieldReadInConstructor.kt") public void testFieldReadInConstructor() throws Exception { runTest("compiler/testData/codegen/box/contracts/fieldReadInConstructor.kt");