diff --git a/compiler/testData/codegen/boxWithStdlib/casts/isWithMutable.kt b/compiler/testData/codegen/boxWithStdlib/casts/isWithMutable.kt index a41c5eab7ec..28e9619d76a 100644 --- a/compiler/testData/codegen/boxWithStdlib/casts/isWithMutable.kt +++ b/compiler/testData/codegen/boxWithStdlib/casts/isWithMutable.kt @@ -102,5 +102,8 @@ fun box(): String { assert(mentry is MutableMap.MutableEntry<*, *>) { "MME should satisfy 'is MutableMap.MutableEntry'"} assert(hashMapEntry is MutableMap.MutableEntry<*, *>) { "HashMap.Entry should satisfy 'is MutableMap.MutableEntry'"} + assert((mlist as Any) !is MutableSet<*>) { "ML !is MutableSet" } + assert((mlist as Any) !is MutableIterator<*>) { "ML !is MutableIterator" } + return "OK" } \ No newline at end of file diff --git a/compiler/testData/codegen/boxWithStdlib/casts/safeAsWithMutable.kt b/compiler/testData/codegen/boxWithStdlib/casts/safeAsWithMutable.kt index 12c105f47a3..38476d39db4 100644 --- a/compiler/testData/codegen/boxWithStdlib/casts/safeAsWithMutable.kt +++ b/compiler/testData/codegen/boxWithStdlib/casts/safeAsWithMutable.kt @@ -28,23 +28,23 @@ class MME : MutableMap.MutableEntry { override fun setValue(value: String): String = throw UnsupportedOperationException() } -inline fun safeAsReturnsNull(operation: String, block: () -> Any?) { +inline fun safeAsReturnsNull(operation: String, cast: () -> Any?) { try { - val x = block() + val x = cast() assert(x == null) { "$operation: should return null, got $x" } } catch (e: Throwable) { - assert(false) { "$operation: should not throw exceptions, got $e" } + throw AssertionError("$operation: should not throw exceptions, got $e") } } -inline fun safeAsReturnsNonNull(operation: String, block: () -> Any?) { +inline fun safeAsReturnsNonNull(operation: String, cast: () -> Any?) { try { - val x = block() + val x = cast() assert(x != null) { "$operation: should return non-null" } } catch (e: Throwable) { - assert(false) { "$operation: should not throw exceptions, got $e" } + throw AssertionError("$operation: should not throw exceptions, got $e") } } @@ -108,6 +108,7 @@ fun box(): String { safeAsReturnsNull("map as? MutableMap") { map as? MutableMap<*, *> } safeAsReturnsNonNull("mmap as? MutableMap") { mmap as? MutableMap<*, *> } + safeAsReturnsNonNull("hashMap as? MutableMap") { hashMap as? MutableMap<*, *> } val entry = ME() as Any val mentry = MME() @@ -129,5 +130,8 @@ fun box(): String { safeAsReturnsNull("null as? MutableMap") { null as? MutableMap<*, *> } safeAsReturnsNull("null as? MutableMap.MutableEntry") { null as? MutableMap.MutableEntry<*, *> } + safeAsReturnsNull("mlist as? MutableSet") { mlist as? MutableSet<*> } + safeAsReturnsNull("mlist as? MutableIterator") { mlist as? MutableIterator<*> } + return "OK" } \ No newline at end of file diff --git a/compiler/testData/codegen/boxWithStdlib/casts/weirdMutableCasts.kt b/compiler/testData/codegen/boxWithStdlib/casts/weirdMutableCasts.kt new file mode 100644 index 00000000000..aa63dbe74b4 --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/casts/weirdMutableCasts.kt @@ -0,0 +1,138 @@ +fun unsupported(): Nothing = throw UnsupportedOperationException() + +class Weird : Iterator, MutableIterable, MutableMap.MutableEntry { + override fun next(): String = unsupported() + override fun hasNext(): Boolean = unsupported() + override fun getKey(): String = unsupported() + override fun getValue(): String = unsupported() + override fun setValue(value: String): String = unsupported() + override fun iterator(): MutableIterator = unsupported() +} + +inline fun asFailsWithCCE(operation: String, cast: () -> Unit) { + try { + cast() + } + catch (e: java.lang.ClassCastException) { + return + } + catch (e: Throwable) { + throw AssertionError("$operation: should throw ClassCastException, got $e") + } + throw AssertionError("$operation: should throw ClassCastException, no exception thrown") +} + +inline fun asSucceeds(operation: String, cast: () -> Unit) { + try { + cast() + } + catch (e: Throwable) { + throw AssertionError("$operation: should not throw exceptions, got $e") + } +} + +inline fun safeAsReturnsNull(operation: String, cast: () -> Any?) { + try { + val x = cast() + assert(x == null) { "$operation: should return null, got $x" } + } + catch (e: Throwable) { + throw AssertionError("$operation: should not throw exceptions, got $e") + } +} + +inline fun safeAsReturnsNonNull(operation: String, cast: () -> Any?) { + try { + val x = cast() + assert(x != null) { "$operation: should return non-null" } + } + catch (e: Throwable) { + throw AssertionError("$operation: should not throw exceptions, got $e") + } +} + +inline fun reifiedIs(x: Any): Boolean = x is T + +inline fun reifiedIsNot(x: Any): Boolean = x !is T + +inline fun reifiedAsSucceeds(x: Any, operation: String) { + try { + x as T + } + catch (e: Throwable) { + throw AssertionError("$operation: should not throw exceptions, got $e") + } +} + +inline fun reifiedAsFailsWithCCE(x: Any, operation: String) { + try { + x as T + } + catch (e: java.lang.ClassCastException) { + return + } + catch (e: Throwable) { + throw AssertionError("$operation: should throw ClassCastException, got $e") + } + throw AssertionError("$operation: should fail with CCE, no exception thrown") +} + +inline fun reifiedSafeAsReturnsNonNull(x: Any?, operation: String) { + val y = try { + x as? T + } + catch (e: Throwable) { + throw AssertionError("$operation: should not throw exceptions, got $e") + } + if (y == null) { + throw AssertionError("$operation: should return non-null, got null") + } +} + +inline fun reifiedSafeAsReturnsNull(x: Any?, operation: String) { + val y = try { + x as? T + } + catch (e: Throwable) { + throw AssertionError("$operation: should not throw exceptions, got $e") + } + if (y != null) { + throw AssertionError("$operation: should return null, got $y") + } +} + +fun box(): String { + val w: Any = Weird() + + assert(w is Iterator<*>) { "w is Iterator<*>" } + assert(w !is MutableIterator<*>) { "w !is MutableIterator<*>" } + assert(w is MutableIterable<*>) { "w is MutableIterable<*>" } + assert(w is MutableMap.MutableEntry<*, *>) { "w is MutableMap.MutableEntry<*, *>" } + + asSucceeds("w as Iterator<*>") { w as Iterator<*> } + asFailsWithCCE("w as MutableIterator<*>") { w as MutableIterator<*> } + asSucceeds("w as MutableIterable<*>") { w as MutableIterable<*> } + asSucceeds("w as MutableMap.MutableEntry<*, *>") { w as MutableMap.MutableEntry<*, *> } + + safeAsReturnsNonNull("w as Iterator<*>") { w as? Iterator<*> } + safeAsReturnsNull("w as? MutableIterator<*>") { w as? MutableIterator<*> } + safeAsReturnsNonNull("w as? MutableIterable<*>") { w as? MutableIterable<*> } + safeAsReturnsNonNull("w as? MutableMap.MutableEntry<*, *>") { w as? MutableMap.MutableEntry<*, *> } + + assert(reifiedIs>(w)) { "reifiedIs>(w)" } + assert(reifiedIsNot>(w)) { "reifiedIsNot>(w)" } + assert(reifiedIs>(w)) { "reifiedIs>(w)" } + assert(reifiedIs>(w)) { "reifiedIs>(w)" } + + reifiedAsSucceeds>(w, "reified w as Iterator<*>") + reifiedAsFailsWithCCE>(w, "reified w as MutableIterator<*>") + reifiedAsSucceeds>(w, "reified w as MutableIterable<*>") + reifiedAsSucceeds>(w, "reified w as MutableMap.MutableEntry<*, *>") + + reifiedSafeAsReturnsNonNull>(w, "reified w as? Iterator<*>") + reifiedSafeAsReturnsNull>(w, "reified w as? MutableIterator<*>") + reifiedSafeAsReturnsNonNull>(w, "reified w as? MutableIterable<*>") + reifiedSafeAsReturnsNonNull>(w, "reified w as? MutableMap.MutableEntry<*, *>") + + return "OK" +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java index c986b3a4b5b..03b9d4807f7 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java @@ -963,6 +963,12 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/casts/unitAsInt.kt"); doTestWithStdlib(fileName); } + + @TestMetadata("weirdMutableCasts.kt") + public void testWeirdMutableCasts() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/casts/weirdMutableCasts.kt"); + doTestWithStdlib(fileName); + } } @TestMetadata("compiler/testData/codegen/boxWithStdlib/classes")