From 35d433160e0ce6a07af9635488bc27bf4648f0d8 Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Mon, 9 Jan 2017 23:35:46 +0300 Subject: [PATCH] Move more logic of 'use' into 'closeSuppressed', rename the latter to 'closeFinally', that will result in more compact inline call expansions. --- .../stdlib/jre7/src/kotlin/AutoCloseable.kt | 28 +++++++++-------- libraries/stdlib/jre7/src/kotlin/Standard.kt | 2 +- .../internal/PlatformImplementations.kt | 2 +- libraries/stdlib/src/kotlin/io/Closeable.kt | 31 +++++++++++-------- .../reference-public-api/kotlin-stdlib.txt | 2 +- 5 files changed, 36 insertions(+), 29 deletions(-) diff --git a/libraries/stdlib/jre7/src/kotlin/AutoCloseable.kt b/libraries/stdlib/jre7/src/kotlin/AutoCloseable.kt index 8fd4b5636e4..c6ec435e7e6 100644 --- a/libraries/stdlib/jre7/src/kotlin/AutoCloseable.kt +++ b/libraries/stdlib/jre7/src/kotlin/AutoCloseable.kt @@ -31,31 +31,33 @@ package kotlin @Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") @kotlin.internal.InlineOnly public inline fun T.use(block: (T) -> R): R { - var closed = false + var exception: Throwable? = null try { return block(this) } catch (e: Throwable) { - closed = true - this?.closeSuppressed(e) + exception = e throw e } finally { - if (this != null && !closed) { - close() - } + this.closeFinally(exception) } } /** - * Closes this [AutoCloseable] suppressing possible exception or error thrown by [AutoCloseable.close] function. + * Closes this [AutoCloseable], suppressing possible exception or error thrown by [AutoCloseable.close] function when + * it's being closed due to some other [cause] exception occurred. + * * The suppressed exception is added to the list of suppressed exceptions of [cause] exception. */ @SinceKotlin("1.1") @PublishedApi -internal fun AutoCloseable.closeSuppressed(cause: Throwable) { - try { - close() - } catch (closeException: Throwable) { - cause.addSuppressed(closeException) - } +internal fun AutoCloseable?.closeFinally(cause: Throwable?) = when { + this == null -> {} + cause == null -> close() + else -> + try { + close() + } catch (closeException: Throwable) { + cause.addSuppressed(closeException) + } } diff --git a/libraries/stdlib/jre7/src/kotlin/Standard.kt b/libraries/stdlib/jre7/src/kotlin/Standard.kt index 4d7f92462bd..ffb74a5e697 100644 --- a/libraries/stdlib/jre7/src/kotlin/Standard.kt +++ b/libraries/stdlib/jre7/src/kotlin/Standard.kt @@ -6,5 +6,5 @@ package kotlin @PublishedApi @Deprecated("Provided for binary compatibility") @JvmName("closeSuppressed") -internal fun AutoCloseable.closeSuppressedDeprecated(cause: Throwable) = closeSuppressed(cause) +internal fun AutoCloseable.closeSuppressedDeprecated(cause: Throwable) = closeFinally(cause) diff --git a/libraries/stdlib/src/kotlin/internal/PlatformImplementations.kt b/libraries/stdlib/src/kotlin/internal/PlatformImplementations.kt index f13ba7d7d92..2d9ecb3a142 100644 --- a/libraries/stdlib/src/kotlin/internal/PlatformImplementations.kt +++ b/libraries/stdlib/src/kotlin/internal/PlatformImplementations.kt @@ -19,7 +19,7 @@ internal open class PlatformImplementations { @SinceKotlin("1.1") @PublishedApi @Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) -internal fun platformCloseSuppressed(instance: Closeable, cause: Throwable) = instance.closeSuppressed(cause) +internal fun platformCloseSuppressed(instance: Closeable, cause: Throwable) = instance.closeFinally(cause) @JvmField diff --git a/libraries/stdlib/src/kotlin/io/Closeable.kt b/libraries/stdlib/src/kotlin/io/Closeable.kt index 4527e419be6..e0b5aaa30b0 100644 --- a/libraries/stdlib/src/kotlin/io/Closeable.kt +++ b/libraries/stdlib/src/kotlin/io/Closeable.kt @@ -30,27 +30,32 @@ import kotlin.internal.* */ @InlineOnly public inline fun T.use(block: (T) -> R): R { - var closed = false + var exception: Throwable? = null try { return block(this) } catch (e: Throwable) { - closed = true - this?.closeSuppressed(e) + exception = e throw e } finally { - if (this != null && !closed) { - close() - } + this.closeFinally(exception) } } +/** + * Closes this [Closeable], suppressing possible exception or error thrown by [Closeable.close] function when + * it's being closed due to some other [cause] exception occurred. + * + * The suppressed exception is added to the list of suppressed exceptions of [cause] exception, when it's supported. + */ @SinceKotlin("1.1") @PublishedApi -internal fun Closeable.closeSuppressed(cause: Throwable) { - try { - close() - } catch (closeException: Throwable) { - // on Java 7 we should call - IMPLEMENTATIONS.addSuppressed(cause, closeException) - } +internal fun Closeable?.closeFinally(cause: Throwable?) = when { + this == null -> {} + cause == null -> close() + else -> + try { + close() + } catch (closeException: Throwable) { + cause.addSuppressed(closeException) + } } \ No newline at end of file diff --git a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib.txt b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib.txt index ac8da4ed960..5cff91751d1 100644 --- a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib.txt +++ b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib.txt @@ -1758,7 +1758,7 @@ public final class kotlin/io/ByteStreamsKt { } public final class kotlin/io/CloseableKt { - public static final fun closeSuppressed (Ljava/io/Closeable;Ljava/lang/Throwable;)V + public static final fun closeFinally (Ljava/io/Closeable;Ljava/lang/Throwable;)V } public final class kotlin/io/ConsoleKt {