From 941de655c4686cae53136f4b95794f09d80230f6 Mon Sep 17 00:00:00 2001 From: Toshiaki Kameyama Date: Fri, 20 Dec 2019 09:52:00 +0900 Subject: [PATCH] Add contract for 'use' #KT-35216 Fixed --- libraries/stdlib/jdk7/build.gradle | 3 ++- .../stdlib/jdk7/src/kotlin/AutoCloseable.kt | 5 ++++ .../jdk7/test/AutoCloseableContractsTest.kt | 25 +++++++++++++++++++ .../stdlib/jvm/src/kotlin/io/Closeable.kt | 4 +++ libraries/stdlib/jvm/test/io/Closeable.kt | 20 +++++++++++++++ 5 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 libraries/stdlib/jdk7/test/AutoCloseableContractsTest.kt create mode 100644 libraries/stdlib/jvm/test/io/Closeable.kt diff --git a/libraries/stdlib/jdk7/build.gradle b/libraries/stdlib/jdk7/build.gradle index 4bffbd69b73..a081d3fff2f 100644 --- a/libraries/stdlib/jdk7/build.gradle +++ b/libraries/stdlib/jdk7/build.gradle @@ -82,7 +82,8 @@ compileKotlin { "-Xallow-kotlin-package", "-Xmultifile-parts-inherit", "-Xnormalize-constructor-calls=enable", - "-module-name", project.name + "-module-name", project.name, + "-Xuse-experimental=kotlin.contracts.ExperimentalContracts", ] } diff --git a/libraries/stdlib/jdk7/src/kotlin/AutoCloseable.kt b/libraries/stdlib/jdk7/src/kotlin/AutoCloseable.kt index 31770fab79a..3c9fc678a20 100644 --- a/libraries/stdlib/jdk7/src/kotlin/AutoCloseable.kt +++ b/libraries/stdlib/jdk7/src/kotlin/AutoCloseable.kt @@ -19,6 +19,8 @@ @file:kotlin.jvm.JvmPackageName("kotlin.jdk7") package kotlin +import kotlin.contracts.* + /** * Executes the given [block] function on this resource and then closes it down correctly whether an exception * is thrown or not. @@ -32,6 +34,9 @@ package kotlin @SinceKotlin("1.2") @kotlin.internal.InlineOnly public inline fun T.use(block: (T) -> R): R { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } var exception: Throwable? = null try { return block(this) diff --git a/libraries/stdlib/jdk7/test/AutoCloseableContractsTest.kt b/libraries/stdlib/jdk7/test/AutoCloseableContractsTest.kt new file mode 100644 index 00000000000..ef5440c0550 --- /dev/null +++ b/libraries/stdlib/jdk7/test/AutoCloseableContractsTest.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.jdk7.test + +import org.junit.Test +import kotlin.test.assertEquals + +class AutoCloseableContractsTest { + @Test + fun shouldHaveBlockExactlyOnceContract() { + class TestAutoCloseable : AutoCloseable { + override fun close() { + } + } + + val i: Int + TestAutoCloseable().use { + i = 1 + } + assertEquals(1, i) + } +} diff --git a/libraries/stdlib/jvm/src/kotlin/io/Closeable.kt b/libraries/stdlib/jvm/src/kotlin/io/Closeable.kt index a2e477fcb2c..e41fe2637aa 100644 --- a/libraries/stdlib/jvm/src/kotlin/io/Closeable.kt +++ b/libraries/stdlib/jvm/src/kotlin/io/Closeable.kt @@ -7,6 +7,7 @@ package kotlin.io import java.io.Closeable +import kotlin.contracts.* import kotlin.internal.* /** @@ -19,6 +20,9 @@ import kotlin.internal.* @InlineOnly @RequireKotlin("1.2", versionKind = RequireKotlinVersionKind.COMPILER_VERSION, message = "Requires newer compiler version to be inlined correctly.") public inline fun T.use(block: (T) -> R): R { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } var exception: Throwable? = null try { return block(this) diff --git a/libraries/stdlib/jvm/test/io/Closeable.kt b/libraries/stdlib/jvm/test/io/Closeable.kt new file mode 100644 index 00000000000..c81a8155dd8 --- /dev/null +++ b/libraries/stdlib/jvm/test/io/Closeable.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package test.io + +import org.junit.Test +import kotlin.test.assertEquals + +class CloseableTest { + @Test + fun shouldHaveBlockExactlyOnceContract() { + val i: Int + "".byteInputStream().use { + i = 1 + } + assertEquals(1, i) + } +}