Native: improve ClassCastException message for local classes

Previously it was like "null cannot be cast to MyObject" or
"MyObject cannot be cast to null", because `KClass.qualifiedName` is
`null` for local classes (including anonymous ones).

Use `KClass.toString()` instead, for both object actual dynamic type
and cast target type. This string representation is generally more
meaningful for such cases, and contains useful details for local
classes.
This commit is contained in:
Svyatoslav Scherbina
2022-03-18 17:50:57 +03:00
committed by Space
parent 5c612078e5
commit cf581738c3
13 changed files with 191 additions and 1 deletions
@@ -5048,6 +5048,16 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/casts/mutableCollections/weirdMutableCasts.kt");
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/casts/nativeCCEMessage")
@TestDataPath("$PROJECT_ROOT")
public class NativeCCEMessage {
@Test
public void testAllFilesPresentInNativeCCEMessage() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/casts/nativeCCEMessage"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
}
}
@Nested
@@ -0,0 +1,19 @@
// TARGET_BACKEND: NATIVE
class MyObject
// Test infrastructure can move declarations to a package. So we need a prefix for class names in exception messages:
val p = MyObject::class.qualifiedName!!.removeSuffix("MyObject")
fun box(): String {
try {
object {} as MyObject
} catch (e: Throwable) {
if (e !is ClassCastException) return "fail 1: $e"
if (e.message != "class ${p}box$1 cannot be cast to class ${p}MyObject") return "fail 2: ${e.message}"
return "OK"
}
return "fail 3"
}
@@ -0,0 +1,19 @@
// TARGET_BACKEND: NATIVE
class MyObject
// Test infrastructure can move declarations to a package. So we need a prefix for class names in exception messages:
val p = MyObject::class.qualifiedName!!.removeSuffix("MyObject")
fun box(): String {
try {
MyObject() as String
} catch (e: Throwable) {
if (e !is ClassCastException) return "fail 1: $e"
if (e.message != "class ${p}MyObject cannot be cast to class kotlin.String") return "fail 2: ${e.message}"
return "OK"
}
return "fail 3"
}
@@ -0,0 +1,20 @@
// TARGET_BACKEND: NATIVE
class MyObject
// Test infrastructure can move declarations to a package. So we need a prefix for class names in exception messages:
val p = MyObject::class.qualifiedName!!.removeSuffix("MyObject")
fun box(): String {
class MyLocalObject
try {
MyLocalObject() as MyObject
} catch (e: Throwable) {
if (e !is ClassCastException) return "fail 1: $e"
if (e.message != "class ${p}box\$MyLocalObject cannot be cast to class ${p}MyObject") return "fail 2: ${e.message}"
return "OK"
}
return "fail 3"
}
@@ -0,0 +1,20 @@
// TARGET_BACKEND: NATIVE
class MyObject
// Test infrastructure can move declarations to a package. So we need a prefix for class names in exception messages:
val p = MyObject::class.qualifiedName!!.removeSuffix("MyObject")
fun box(): String {
class MyLocalObject
try {
MyObject() as MyLocalObject
} catch (e: Throwable) {
if (e !is ClassCastException) return "fail 1: $e"
if (e.message != "class ${p}MyObject cannot be cast to class ${p}box\$MyLocalObject") return "fail 2: ${e.message}"
return "OK"
}
return "fail 3"
}
@@ -4928,6 +4928,16 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/casts/mutableCollections/weirdMutableCasts.kt");
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/casts/nativeCCEMessage")
@TestDataPath("$PROJECT_ROOT")
public class NativeCCEMessage {
@Test
public void testAllFilesPresentInNativeCCEMessage() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/casts/nativeCCEMessage"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
}
}
@Nested
@@ -5048,6 +5048,16 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/casts/mutableCollections/weirdMutableCasts.kt");
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/casts/nativeCCEMessage")
@TestDataPath("$PROJECT_ROOT")
public class NativeCCEMessage {
@Test
public void testAllFilesPresentInNativeCCEMessage() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/casts/nativeCCEMessage"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
}
}
@Nested
@@ -4307,6 +4307,19 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/casts/mutableCollections/weirdMutableCasts.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/casts/nativeCCEMessage")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class NativeCCEMessage extends AbstractLightAnalysisModeTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
}
public void testAllFilesPresentInNativeCCEMessage() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/casts/nativeCCEMessage"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
}
}
@TestMetadata("compiler/testData/codegen/box/checkcastOptimization")
@@ -3614,6 +3614,16 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/casts/mutableCollections/weirdMutableCasts.kt");
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/casts/nativeCCEMessage")
@TestDataPath("$PROJECT_ROOT")
public class NativeCCEMessage {
@Test
public void testAllFilesPresentInNativeCCEMessage() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/casts/nativeCCEMessage"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true);
}
}
}
@Nested
@@ -3656,6 +3656,16 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/casts/mutableCollections/weirdMutableCasts.kt");
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/casts/nativeCCEMessage")
@TestDataPath("$PROJECT_ROOT")
public class NativeCCEMessage {
@Test
public void testAllFilesPresentInNativeCCEMessage() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/casts/nativeCCEMessage"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
}
}
}
@Nested
@@ -3237,6 +3237,19 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
runTest("compiler/testData/codegen/box/casts/mutableCollections/weirdMutableCasts.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/casts/nativeCCEMessage")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class NativeCCEMessage extends AbstractIrCodegenBoxWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public void testAllFilesPresentInNativeCCEMessage() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/casts/nativeCCEMessage"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
}
}
}
@TestMetadata("compiler/testData/codegen/box/checkcastOptimization")
@@ -28,7 +28,7 @@ internal fun ThrowArrayIndexOutOfBoundsException(): Nothing {
@ExportForCppRuntime
fun ThrowClassCastException(instance: Any, typeInfo: NativePtr): Nothing {
val clazz = KClassImpl<Any>(typeInfo)
throw ClassCastException("${instance::class.qualifiedName} cannot be cast to ${clazz.qualifiedName}")
throw ClassCastException("${instance::class} cannot be cast to $clazz")
}
@ExportForCppRuntime
@@ -3738,6 +3738,42 @@ public class NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTest
runTest("compiler/testData/codegen/box/casts/mutableCollections/weirdMutableCasts.kt");
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/casts/nativeCCEMessage")
@TestDataPath("$PROJECT_ROOT")
@Tag("codegen")
@UseExtTestCaseGroupProvider()
public class NativeCCEMessage {
@Test
public void testAllFilesPresentInNativeCCEMessage() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/casts/nativeCCEMessage"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.NATIVE, true);
}
@Test
@TestMetadata("castAnonymousClass.kt")
public void testCastAnonymousClass() throws Exception {
runTest("compiler/testData/codegen/box/casts/nativeCCEMessage/castAnonymousClass.kt");
}
@Test
@TestMetadata("castGlobalClass.kt")
public void testCastGlobalClass() throws Exception {
runTest("compiler/testData/codegen/box/casts/nativeCCEMessage/castGlobalClass.kt");
}
@Test
@TestMetadata("castLocalClass.kt")
public void testCastLocalClass() throws Exception {
runTest("compiler/testData/codegen/box/casts/nativeCCEMessage/castLocalClass.kt");
}
@Test
@TestMetadata("castToLocalClass.kt")
public void testCastToLocalClass() throws Exception {
runTest("compiler/testData/codegen/box/casts/nativeCCEMessage/castToLocalClass.kt");
}
}
}
@Nested