From a8e1a6a2a1a9911cc15df373fc48cdb962666fd4 Mon Sep 17 00:00:00 2001 From: Dmitry Savvinov Date: Thu, 26 Jul 2018 14:58:50 +0300 Subject: [PATCH] Add contract for 'synchronized' ^KT-25962 Fixed --- .../contracts/fromStdlib/synchronize.kt | 11 +++++++++++ .../contracts/fromStdlib/synchronize.txt | 3 +++ .../checkers/DiagnosticsTestWithStdLibGenerated.java | 5 +++++ .../DiagnosticsTestWithStdLibUsingJavacGenerated.java | 5 +++++ libraries/stdlib/js/src/kotlin/concurrent.kt | 9 ++++++++- libraries/stdlib/jvm/src/kotlin/util/Synchronized.kt | 5 +++++ 6 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/synchronize.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/synchronize.txt diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/synchronize.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/synchronize.kt new file mode 100644 index 00000000000..7af925daf1b --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/synchronize.kt @@ -0,0 +1,11 @@ +// !LANGUAGE: +ReadDeserializedContracts +UseCallsInPlaceEffect + +fun test(lock: Any) { + val x: Int + + synchronized(lock) { + x = 42 + } + + x.inc() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/synchronize.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/synchronize.txt new file mode 100644 index 00000000000..68fd635a27b --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/synchronize.txt @@ -0,0 +1,3 @@ +package + +public fun test(/*0*/ lock: kotlin.Any): kotlin.Unit diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java index 849e36d473f..91f4381ddd4 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java @@ -1192,6 +1192,11 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW public void testRequire() throws Exception { runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/require.kt"); } + + @TestMetadata("synchronize.kt") + public void testSynchronize() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/synchronize.kt"); + } } @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts") diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java index 1909266fe2c..f0a0fe95ef6 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java @@ -1192,6 +1192,11 @@ public class DiagnosticsTestWithStdLibUsingJavacGenerated extends AbstractDiagno public void testRequire() throws Exception { runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/require.kt"); } + + @TestMetadata("synchronize.kt") + public void testSynchronize() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/synchronize.kt"); + } } @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts") diff --git a/libraries/stdlib/js/src/kotlin/concurrent.kt b/libraries/stdlib/js/src/kotlin/concurrent.kt index f0fa4220edb..3ecd424bd6a 100644 --- a/libraries/stdlib/js/src/kotlin/concurrent.kt +++ b/libraries/stdlib/js/src/kotlin/concurrent.kt @@ -5,6 +5,8 @@ package kotlin +import kotlin.internal.contracts.* + @Deprecated("Use Synchronized annotation from kotlin.jvm package", ReplaceWith("kotlin.jvm.Synchronized"), level = DeprecationLevel.WARNING) public typealias Synchronized = kotlin.jvm.Synchronized @@ -13,4 +15,9 @@ public typealias Synchronized = kotlin.jvm.Synchronized public typealias Volatile = kotlin.jvm.Volatile @kotlin.internal.InlineOnly -public actual inline fun synchronized(lock: Any, block: () -> R): R = block() +public actual inline fun synchronized(lock: Any, block: () -> R): R { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} diff --git a/libraries/stdlib/jvm/src/kotlin/util/Synchronized.kt b/libraries/stdlib/jvm/src/kotlin/util/Synchronized.kt index 8301c9785cf..ede49dc2008 100644 --- a/libraries/stdlib/jvm/src/kotlin/util/Synchronized.kt +++ b/libraries/stdlib/jvm/src/kotlin/util/Synchronized.kt @@ -7,6 +7,7 @@ @file:kotlin.jvm.JvmName("StandardKt") package kotlin +import kotlin.internal.contracts.* import kotlin.jvm.internal.unsafe.* /** @@ -14,6 +15,10 @@ import kotlin.jvm.internal.unsafe.* */ @kotlin.internal.InlineOnly public actual inline fun synchronized(lock: Any, block: () -> R): R { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + @Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE", "INVISIBLE_MEMBER") monitorEnter(lock) try {