Relax type parameter constraint for Closeable.use and AutoCloseable.use to allow nullable receiver.
#KT-12894 Fixed
This commit is contained in:
@@ -3,17 +3,17 @@ package kotlin
|
|||||||
|
|
||||||
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
|
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
|
||||||
@kotlin.internal.InlineOnly
|
@kotlin.internal.InlineOnly
|
||||||
public inline fun <T : AutoCloseable, R> T.use(block: (T) -> R): R {
|
public inline fun <T : AutoCloseable?, R> T.use(block: (T) -> R): R {
|
||||||
var closed = false
|
var closed = false
|
||||||
try {
|
try {
|
||||||
return block(this)
|
return block(this)
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
closed = true
|
closed = true
|
||||||
@Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE")
|
@Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE")
|
||||||
closeSuppressed(e)
|
this?.closeSuppressed(e)
|
||||||
throw e
|
throw e
|
||||||
} finally {
|
} finally {
|
||||||
if (!closed) {
|
if (this != null && !closed) {
|
||||||
close()
|
close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,14 @@ package kotlin.jdk7.test
|
|||||||
|
|
||||||
import java.io.*
|
import java.io.*
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
import java.util.*
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
|
|
||||||
|
|
||||||
class TryWithResourcesAutoCloseableTest {
|
class TryWithResourcesAutoCloseableTest {
|
||||||
|
|
||||||
|
@Suppress("HasPlatformType") fun <T> platformNull() = Collections.singletonList(null as T).first()
|
||||||
|
|
||||||
class Resource(val faultyClose: Boolean = false) : AutoCloseable {
|
class Resource(val faultyClose: Boolean = false) : AutoCloseable {
|
||||||
|
|
||||||
var isClosed = false
|
var isClosed = false
|
||||||
@@ -80,7 +83,31 @@ class TryWithResourcesAutoCloseableTest {
|
|||||||
assertEquals("nonLocal", result)
|
assertEquals("nonLocal", result)
|
||||||
assertTrue(resource.isClosed)
|
assertTrue(resource.isClosed)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test fun nullableResourceSuccess() {
|
||||||
|
val resource: Resource? = null
|
||||||
|
val result = resource.use { "ok" }
|
||||||
|
assertEquals("ok", result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test fun nullableResourceOpFails() {
|
||||||
|
val resource: Resource? = null
|
||||||
|
val e = assertFails {
|
||||||
|
resource.use { requireNotNull(it) }
|
||||||
|
}
|
||||||
|
assertTrue(e is IllegalArgumentException)
|
||||||
|
assertTrue(e.suppressed.isEmpty())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test fun platformResourceOpFails() {
|
||||||
|
val resource = platformNull<Resource>()
|
||||||
|
val e = assertFails {
|
||||||
|
resource.use { requireNotNull(it) }
|
||||||
|
}
|
||||||
|
assertTrue(e is IllegalArgumentException)
|
||||||
|
assertTrue(e.suppressed.isEmpty())
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -2,10 +2,13 @@ package kotlin.jdk7.test
|
|||||||
|
|
||||||
import java.io.*
|
import java.io.*
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
import java.util.*
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
|
|
||||||
class TryWithResourcesCloseableTest {
|
class TryWithResourcesCloseableTest {
|
||||||
|
|
||||||
|
@Suppress("HasPlatformType") fun <T> platformNull() = Collections.singletonList(null as T).first()
|
||||||
|
|
||||||
class Resource(val faultyClose: Boolean = false) : Closeable {
|
class Resource(val faultyClose: Boolean = false) : Closeable {
|
||||||
|
|
||||||
var isClosed = false
|
var isClosed = false
|
||||||
@@ -81,4 +84,27 @@ class TryWithResourcesCloseableTest {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test fun nullableResourceSuccess() {
|
||||||
|
val resource: Resource? = null
|
||||||
|
val result = resource.use { "ok" }
|
||||||
|
assertEquals("ok", result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test fun nullableResourceOpFails() {
|
||||||
|
val resource: Resource? = null
|
||||||
|
val e = assertFails {
|
||||||
|
resource.use { requireNotNull(it) }
|
||||||
|
}
|
||||||
|
assertTrue(e is IllegalArgumentException)
|
||||||
|
assertTrue(e.suppressed.isEmpty())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test fun platformResourceOpFails() {
|
||||||
|
val resource = platformNull<Resource>()
|
||||||
|
val e = assertFails {
|
||||||
|
resource.use { requireNotNull(it) }
|
||||||
|
}
|
||||||
|
assertTrue(e is IllegalArgumentException)
|
||||||
|
assertTrue(e.suppressed.isEmpty())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -152,17 +152,17 @@ public fun URL.readBytes(): ByteArray = openStream().use { it.readBytes() }
|
|||||||
* @return the result of [block] function on this closable resource.
|
* @return the result of [block] function on this closable resource.
|
||||||
*/
|
*/
|
||||||
@kotlin.internal.InlineOnly
|
@kotlin.internal.InlineOnly
|
||||||
public inline fun <T : Closeable, R> T.use(block: (T) -> R): R {
|
public inline fun <T : Closeable?, R> T.use(block: (T) -> R): R {
|
||||||
var closed = false
|
var closed = false
|
||||||
try {
|
try {
|
||||||
return block(this)
|
return block(this)
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
closed = true
|
closed = true
|
||||||
@Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE")
|
@Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE")
|
||||||
platformCloseSuppressed(this, e)
|
if (this != null) platformCloseSuppressed(this, e)
|
||||||
throw e
|
throw e
|
||||||
} finally {
|
} finally {
|
||||||
if (!closed) {
|
if (this != null && !closed) {
|
||||||
close()
|
close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -141,6 +141,15 @@ class ReadWriteTest {
|
|||||||
assertEquals(arrayListOf("Hello", "World"), list)
|
assertEquals(arrayListOf("Hello", "World"), list)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test fun testPlatformNullUse() {
|
||||||
|
fun <T> platformNull() = java.util.Collections.singleton(null as T).first()
|
||||||
|
val resource = platformNull<java.io.Closeable>()
|
||||||
|
val result = resource.use {
|
||||||
|
"ok"
|
||||||
|
}
|
||||||
|
assertEquals("ok", result)
|
||||||
|
}
|
||||||
|
|
||||||
@test fun testURL() {
|
@test fun testURL() {
|
||||||
val url = URL("http://kotlinlang.org")
|
val url = URL("http://kotlinlang.org")
|
||||||
val text = url.readText()
|
val text = url.readText()
|
||||||
|
|||||||
Reference in New Issue
Block a user