From 4e64b077279212a25aca22f35158c2e602598572 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Sun, 17 Feb 2019 12:15:27 +0300 Subject: [PATCH] Add some tests for inference and DFA of `try/catch/finally` --- .../testsWithStdLib/tryCatch/assignTry.kt | 110 ++++++++++++++++++ .../testsWithStdLib/tryCatch/assignTry.txt | 49 ++++++++ .../tryCatch/boundedSmartcasts.kt | 100 ++++++++++++++++ .../tryCatch/boundedSmartcasts.txt | 45 +++++++ .../tryCatch/catchRedeclaration.kt | 53 +++++++++ .../tryCatch/catchRedeclaration.txt | 28 +++++ .../tryCatch/correctSmartcasts.kt | 87 ++++++++++++++ .../tryCatch/correctSmartcasts.txt | 46 ++++++++ .../tryCatch/falseNegativeSmartcasts.kt | 19 +++ .../tryCatch/falseNegativeSmartcasts.txt | 3 + .../tryCatch/falsePositiveSmartcasts.kt | 105 +++++++++++++++++ .../tryCatch/falsePositiveSmartcasts.txt | 46 ++++++++ .../testsWithStdLib/tryCatch/tryExpression.kt | 34 ++++++ .../tryCatch/tryExpression.txt | 44 +++++++ .../DiagnosticsTestWithStdLibGenerated.java | 48 ++++++++ ...ticsTestWithStdLibUsingJavacGenerated.java | 48 ++++++++ 16 files changed, 865 insertions(+) create mode 100644 compiler/testData/diagnostics/testsWithStdLib/tryCatch/assignTry.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/tryCatch/assignTry.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/tryCatch/boundedSmartcasts.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/tryCatch/boundedSmartcasts.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/tryCatch/catchRedeclaration.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/tryCatch/catchRedeclaration.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/tryCatch/correctSmartcasts.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/tryCatch/correctSmartcasts.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/tryCatch/falseNegativeSmartcasts.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/tryCatch/falseNegativeSmartcasts.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/tryCatch/falsePositiveSmartcasts.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/tryCatch/falsePositiveSmartcasts.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/tryCatch/tryExpression.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/tryCatch/tryExpression.txt diff --git a/compiler/testData/diagnostics/testsWithStdLib/tryCatch/assignTry.kt b/compiler/testData/diagnostics/testsWithStdLib/tryCatch/assignTry.kt new file mode 100644 index 00000000000..9c3cf9a5d41 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/tryCatch/assignTry.kt @@ -0,0 +1,110 @@ +// !WITH_NEW_INFERENCE + +class ExcA : Exception() + +class ExcB : Exception() + +fun test2() { + val s: String? = try { + "" + } + catch (e: ExcA) { + null + } + catch (e: ExcB) { + 10 + } + s.length +} + +fun test3() { + val s: String? = try { + "" + } + catch (e: ExcA) { + null + } + catch (e: ExcB) { + return + } + s.length +} + +fun test4() { + val s: String? = try { + "" + } + catch (e: ExcA) { + null + } + finally { + "" + } + s.length +} + +fun test5() { + val s: String? = try { + "" + } + catch (e: ExcA) { + null + } + finally { + return + } + s.length +} + +fun test6() { + val s: String? = try { + "" + } + catch (e: ExcA) { + return + } + catch (e: ExcB) { + return + } + s.length +} + +fun test7() { + val s: String? = try { + "" + } + catch (e: ExcA) { + "" + } + catch (e: ExcB) { + "" + } + s.length +} + +fun test8() { + val s = try { + "" + } catch (e: ExcA) { + null + } + s.length +} + +fun test9() { + val s = try { + "" + } catch (e: ExcA) { + "" + } + s.length +} + +fun test10() { + val x = try { + "" + } finally { + 42 + } + x.length +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/tryCatch/assignTry.txt b/compiler/testData/diagnostics/testsWithStdLib/tryCatch/assignTry.txt new file mode 100644 index 00000000000..5ad037379c9 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/tryCatch/assignTry.txt @@ -0,0 +1,49 @@ +package + +public fun test10(): kotlin.Unit +public fun test2(): kotlin.Unit +public fun test3(): kotlin.Unit +public fun test4(): kotlin.Unit +public fun test5(): kotlin.Unit +public fun test6(): kotlin.Unit +public fun test7(): kotlin.Unit +public fun test8(): kotlin.Unit +public fun test9(): kotlin.Unit + +public final class ExcA : kotlin.Exception /* = java.lang.Exception */ { + public constructor ExcA() + public open override /*1*/ /*fake_override*/ val cause: kotlin.Throwable? + public open override /*1*/ /*fake_override*/ val message: kotlin.String? + public final override /*1*/ /*fake_override*/ fun addSuppressed(/*0*/ exception: kotlin.Throwable!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun fillInStackTrace(): kotlin.Throwable! + public open override /*1*/ /*fake_override*/ fun getLocalizedMessage(): kotlin.String! + public open override /*1*/ /*fake_override*/ fun getStackTrace(): kotlin.Array<(out) java.lang.StackTraceElement!>! + public final override /*1*/ /*fake_override*/ fun getSuppressed(): kotlin.Array<(out) kotlin.Throwable!>! + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun initCause(/*0*/ cause: kotlin.Throwable!): kotlin.Throwable! + public open override /*1*/ /*fake_override*/ fun printStackTrace(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun printStackTrace(/*0*/ s: java.io.PrintStream!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun printStackTrace(/*0*/ s: java.io.PrintWriter!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun setStackTrace(/*0*/ stackTrace: kotlin.Array<(out) java.lang.StackTraceElement!>!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class ExcB : kotlin.Exception /* = java.lang.Exception */ { + public constructor ExcB() + public open override /*1*/ /*fake_override*/ val cause: kotlin.Throwable? + public open override /*1*/ /*fake_override*/ val message: kotlin.String? + public final override /*1*/ /*fake_override*/ fun addSuppressed(/*0*/ exception: kotlin.Throwable!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun fillInStackTrace(): kotlin.Throwable! + public open override /*1*/ /*fake_override*/ fun getLocalizedMessage(): kotlin.String! + public open override /*1*/ /*fake_override*/ fun getStackTrace(): kotlin.Array<(out) java.lang.StackTraceElement!>! + public final override /*1*/ /*fake_override*/ fun getSuppressed(): kotlin.Array<(out) kotlin.Throwable!>! + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun initCause(/*0*/ cause: kotlin.Throwable!): kotlin.Throwable! + public open override /*1*/ /*fake_override*/ fun printStackTrace(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun printStackTrace(/*0*/ s: java.io.PrintStream!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun printStackTrace(/*0*/ s: java.io.PrintWriter!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun setStackTrace(/*0*/ stackTrace: kotlin.Array<(out) java.lang.StackTraceElement!>!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/tryCatch/boundedSmartcasts.kt b/compiler/testData/diagnostics/testsWithStdLib/tryCatch/boundedSmartcasts.kt new file mode 100644 index 00000000000..0f2c04389c1 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/tryCatch/boundedSmartcasts.kt @@ -0,0 +1,100 @@ +// !WTIH_NEW_INFERENCE + +class ExcA : Exception() +class ExcB : Exception() + +fun test0(x: Int?) { + val y = try { + x + } finally { + + } + + if (x != null) { + x.inc() + y.inc() + } + + if (y != null) { + x.inc() + y.inc() + } +} + +fun test1(x: Int?) { + val y = try { + x + } + catch (e: Exception) { + 42 + } + + if (x != null) { + x.inc() + y.inc() + } + + if (y != null) { + x.inc() + y.inc() + } +} + +fun test2(x: Int?) { + val y = try { + x + } + catch (e: Exception) { + x + } + + if (x != null) { + x.inc() + y.inc() + } + + if (y != null) { + x.inc() + y.inc() + } +} + +fun test3(x: Int?) { + val y = try { + x + } catch (e: Exception) { + return + } + + if (x != null) { + x.inc() + y.inc() + } + + if (y != null) { + x.inc() + y.inc() + } +} + +fun test5(x: Int?) { + val y = try { + x + } + catch (e: ExcA) { + return + } + catch (e: ExcB) { + x + } + + if (x != null) { + x.inc() + y.inc() + } + + if (y != null) { + x.inc() + y.inc() + } +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/tryCatch/boundedSmartcasts.txt b/compiler/testData/diagnostics/testsWithStdLib/tryCatch/boundedSmartcasts.txt new file mode 100644 index 00000000000..0a637b835f4 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/tryCatch/boundedSmartcasts.txt @@ -0,0 +1,45 @@ +package + +public fun test0(/*0*/ x: kotlin.Int?): kotlin.Unit +public fun test1(/*0*/ x: kotlin.Int?): kotlin.Unit +public fun test2(/*0*/ x: kotlin.Int?): kotlin.Unit +public fun test3(/*0*/ x: kotlin.Int?): kotlin.Unit +public fun test5(/*0*/ x: kotlin.Int?): kotlin.Unit + +public final class ExcA : kotlin.Exception /* = java.lang.Exception */ { + public constructor ExcA() + public open override /*1*/ /*fake_override*/ val cause: kotlin.Throwable? + public open override /*1*/ /*fake_override*/ val message: kotlin.String? + public final override /*1*/ /*fake_override*/ fun addSuppressed(/*0*/ exception: kotlin.Throwable!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun fillInStackTrace(): kotlin.Throwable! + public open override /*1*/ /*fake_override*/ fun getLocalizedMessage(): kotlin.String! + public open override /*1*/ /*fake_override*/ fun getStackTrace(): kotlin.Array<(out) java.lang.StackTraceElement!>! + public final override /*1*/ /*fake_override*/ fun getSuppressed(): kotlin.Array<(out) kotlin.Throwable!>! + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun initCause(/*0*/ cause: kotlin.Throwable!): kotlin.Throwable! + public open override /*1*/ /*fake_override*/ fun printStackTrace(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun printStackTrace(/*0*/ s: java.io.PrintStream!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun printStackTrace(/*0*/ s: java.io.PrintWriter!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun setStackTrace(/*0*/ stackTrace: kotlin.Array<(out) java.lang.StackTraceElement!>!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class ExcB : kotlin.Exception /* = java.lang.Exception */ { + public constructor ExcB() + public open override /*1*/ /*fake_override*/ val cause: kotlin.Throwable? + public open override /*1*/ /*fake_override*/ val message: kotlin.String? + public final override /*1*/ /*fake_override*/ fun addSuppressed(/*0*/ exception: kotlin.Throwable!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun fillInStackTrace(): kotlin.Throwable! + public open override /*1*/ /*fake_override*/ fun getLocalizedMessage(): kotlin.String! + public open override /*1*/ /*fake_override*/ fun getStackTrace(): kotlin.Array<(out) java.lang.StackTraceElement!>! + public final override /*1*/ /*fake_override*/ fun getSuppressed(): kotlin.Array<(out) kotlin.Throwable!>! + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun initCause(/*0*/ cause: kotlin.Throwable!): kotlin.Throwable! + public open override /*1*/ /*fake_override*/ fun printStackTrace(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun printStackTrace(/*0*/ s: java.io.PrintStream!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun printStackTrace(/*0*/ s: java.io.PrintWriter!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun setStackTrace(/*0*/ stackTrace: kotlin.Array<(out) java.lang.StackTraceElement!>!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/tryCatch/catchRedeclaration.kt b/compiler/testData/diagnostics/testsWithStdLib/tryCatch/catchRedeclaration.kt new file mode 100644 index 00000000000..730ff0e6775 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/tryCatch/catchRedeclaration.kt @@ -0,0 +1,53 @@ +// !WTIH_NEW_INFERENCE + +class MyException : Exception() { + val myField = "field" + + fun myFun() {} +} + +fun test1() { + val e = "something" + try {} + catch (e: Exception) { + e.message + e.length + } +} + +fun test2() { + try {} + catch (e: Exception) { + val e = "something" + e.message + e.length + } +} + +fun test3() { + try {} + catch (e: MyException) { + e.myField + } +} + +fun test4() { + try {} + catch (e: Exception) { + val a = 42 + val a = "foo" + } +} + +fun test5() { + try {} + catch (e: Exception) { + val a: Int = 42 + try {} + catch (e: MyException) { + e.myFun() + val a: String = "" + a.length + } + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/tryCatch/catchRedeclaration.txt b/compiler/testData/diagnostics/testsWithStdLib/tryCatch/catchRedeclaration.txt new file mode 100644 index 00000000000..df5d3dcfa6b --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/tryCatch/catchRedeclaration.txt @@ -0,0 +1,28 @@ +package + +public fun test1(): kotlin.Unit +public fun test2(): kotlin.Unit +public fun test3(): kotlin.Unit +public fun test4(): kotlin.Unit +public fun test5(): kotlin.Unit + +public final class MyException : kotlin.Exception /* = java.lang.Exception */ { + public constructor MyException() + public open override /*1*/ /*fake_override*/ val cause: kotlin.Throwable? + public open override /*1*/ /*fake_override*/ val message: kotlin.String? + public final val myField: kotlin.String = "field" + public final override /*1*/ /*fake_override*/ fun addSuppressed(/*0*/ exception: kotlin.Throwable!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun fillInStackTrace(): kotlin.Throwable! + public open override /*1*/ /*fake_override*/ fun getLocalizedMessage(): kotlin.String! + public open override /*1*/ /*fake_override*/ fun getStackTrace(): kotlin.Array<(out) java.lang.StackTraceElement!>! + public final override /*1*/ /*fake_override*/ fun getSuppressed(): kotlin.Array<(out) kotlin.Throwable!>! + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun initCause(/*0*/ cause: kotlin.Throwable!): kotlin.Throwable! + public final fun myFun(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun printStackTrace(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun printStackTrace(/*0*/ s: java.io.PrintStream!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun printStackTrace(/*0*/ s: java.io.PrintWriter!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun setStackTrace(/*0*/ stackTrace: kotlin.Array<(out) java.lang.StackTraceElement!>!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/tryCatch/correctSmartcasts.kt b/compiler/testData/diagnostics/testsWithStdLib/tryCatch/correctSmartcasts.kt new file mode 100644 index 00000000000..72a5ec3dde4 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/tryCatch/correctSmartcasts.kt @@ -0,0 +1,87 @@ +// !WITH_NEW_INFERENCE +// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_VALUE -VARIABLE_WITH_REDUNDANT_INITIALIZER +// Related issue: KT-28370 + +class ExcA : Exception() +class ExcB : Exception() + +fun test1(s: String?) { + var t2: Boolean? = true + if (t2 != null) { + try { + t2 = null + } + catch (e: Exception) { + requireNotNull(s) + } + t2.not() + s.length + } +} + +fun test2(s: String?) { + var t2: Boolean? = true + if (t2 != null) { + try { + t2 = null + } + finally { + requireNotNull(s) + t2 = true + } + t2.not() + s.length + } +} + +fun test3() { + var s: String? = null + s = "" + try { + + } + catch (e: Exception) { + s = null + return + } + s.length +} + +fun test4() { + var s: String? = null + s = "" + try { + + } + catch (e: ExcA) { + s = null + return + } + catch (e: ExcB) { + + } + s.length +} + +fun test5(s: String?) { + try { + requireNotNull(s) + } + catch (e: ExcA) { + return + } + catch (e: ExcB) { + + } + s.length +} + +fun test6(s: String?) { + try { + requireNotNull(s) + } + catch (e: Exception) { + return + } + s.length +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/tryCatch/correctSmartcasts.txt b/compiler/testData/diagnostics/testsWithStdLib/tryCatch/correctSmartcasts.txt new file mode 100644 index 00000000000..52026a884f5 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/tryCatch/correctSmartcasts.txt @@ -0,0 +1,46 @@ +package + +public fun test1(/*0*/ s: kotlin.String?): kotlin.Unit +public fun test2(/*0*/ s: kotlin.String?): kotlin.Unit +public fun test3(): kotlin.Unit +public fun test4(): kotlin.Unit +public fun test5(/*0*/ s: kotlin.String?): kotlin.Unit +public fun test6(/*0*/ s: kotlin.String?): kotlin.Unit + +public final class ExcA : kotlin.Exception /* = java.lang.Exception */ { + public constructor ExcA() + public open override /*1*/ /*fake_override*/ val cause: kotlin.Throwable? + public open override /*1*/ /*fake_override*/ val message: kotlin.String? + public final override /*1*/ /*fake_override*/ fun addSuppressed(/*0*/ exception: kotlin.Throwable!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun fillInStackTrace(): kotlin.Throwable! + public open override /*1*/ /*fake_override*/ fun getLocalizedMessage(): kotlin.String! + public open override /*1*/ /*fake_override*/ fun getStackTrace(): kotlin.Array<(out) java.lang.StackTraceElement!>! + public final override /*1*/ /*fake_override*/ fun getSuppressed(): kotlin.Array<(out) kotlin.Throwable!>! + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun initCause(/*0*/ cause: kotlin.Throwable!): kotlin.Throwable! + public open override /*1*/ /*fake_override*/ fun printStackTrace(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun printStackTrace(/*0*/ s: java.io.PrintStream!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun printStackTrace(/*0*/ s: java.io.PrintWriter!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun setStackTrace(/*0*/ stackTrace: kotlin.Array<(out) java.lang.StackTraceElement!>!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class ExcB : kotlin.Exception /* = java.lang.Exception */ { + public constructor ExcB() + public open override /*1*/ /*fake_override*/ val cause: kotlin.Throwable? + public open override /*1*/ /*fake_override*/ val message: kotlin.String? + public final override /*1*/ /*fake_override*/ fun addSuppressed(/*0*/ exception: kotlin.Throwable!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun fillInStackTrace(): kotlin.Throwable! + public open override /*1*/ /*fake_override*/ fun getLocalizedMessage(): kotlin.String! + public open override /*1*/ /*fake_override*/ fun getStackTrace(): kotlin.Array<(out) java.lang.StackTraceElement!>! + public final override /*1*/ /*fake_override*/ fun getSuppressed(): kotlin.Array<(out) kotlin.Throwable!>! + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun initCause(/*0*/ cause: kotlin.Throwable!): kotlin.Throwable! + public open override /*1*/ /*fake_override*/ fun printStackTrace(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun printStackTrace(/*0*/ s: java.io.PrintStream!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun printStackTrace(/*0*/ s: java.io.PrintWriter!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun setStackTrace(/*0*/ stackTrace: kotlin.Array<(out) java.lang.StackTraceElement!>!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/tryCatch/falseNegativeSmartcasts.kt b/compiler/testData/diagnostics/testsWithStdLib/tryCatch/falseNegativeSmartcasts.kt new file mode 100644 index 00000000000..9ca17f05112 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/tryCatch/falseNegativeSmartcasts.kt @@ -0,0 +1,19 @@ +// !WITH_NEW_INFERENCE +// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_VALUE -VARIABLE_WITH_REDUNDANT_INITIALIZER +// Related issue: KT-28370 + +fun test1(s1: String?) { + var s: String? = null + s = "" + try { + s = "" + requireNotNull(s1) + } + catch (e: Exception) { + return + } + finally { + s.length + } + s.length +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/tryCatch/falseNegativeSmartcasts.txt b/compiler/testData/diagnostics/testsWithStdLib/tryCatch/falseNegativeSmartcasts.txt new file mode 100644 index 00000000000..f1c7443a56e --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/tryCatch/falseNegativeSmartcasts.txt @@ -0,0 +1,3 @@ +package + +public fun test1(/*0*/ s1: kotlin.String?): kotlin.Unit diff --git a/compiler/testData/diagnostics/testsWithStdLib/tryCatch/falsePositiveSmartcasts.kt b/compiler/testData/diagnostics/testsWithStdLib/tryCatch/falsePositiveSmartcasts.kt new file mode 100644 index 00000000000..de0431eac62 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/tryCatch/falsePositiveSmartcasts.kt @@ -0,0 +1,105 @@ +// !WITH_NEW_INFERENCE +// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_VALUE -VARIABLE_WITH_REDUNDANT_INITIALIZER +// Related issue: KT-28370 + +class ExcA : Exception() +class ExcB : Exception() + +fun test1() { + var x: String? = null + x = "" + + try { + x = null + } catch (e: Exception) { + x.length // smartcast shouldn't be allowed (OOME could happen after `x = null`) + throw e + } + finally { + // smartcast shouldn't be allowed, `x = null` could've happened + x.length + } + // smartcast shouldn't be allowed, `x = null` could've happened + x.length +} + +// With old DFA of try/catch info about unsound smartcasts after try +// removes only if there is at least one catch branch that not returns Nothing +fun test2() { + var x: String? = null + x = "" + + try { + x = null + } catch (e: Exception) { + x.length + } + finally { + x.length + } + x.length +} + +fun test3() { + var t2: Boolean? = true + if (t2 != null) { // or `t2 is Boolean` + try { + throw Exception() + } catch (e: Exception) { + t2 = null + } + t2.not() // wrong smartcast, NPE + } +} + +fun test4() { + var t2: Boolean? = true + if (t2 != null) { // or `t2 is Boolean` + try { + t2 = null + } finally { } + t2.not() // wrong smartcast, NPE + } +} + +fun test5() { + var s1: String? = null + var s2: String? = null + s1 = "" + s2 = "" + try { + TODO() + } + catch (e: ExcA) { + s1 = "" + } + catch (e: ExcB) { + s2 = null + return + } + finally { + s1.length + s2.length + } + s1.length + s2.length +} + +fun test6(s1: String?, s2: String?) { + var s: String? = null + s = "" + try { + s = null + requireNotNull(s1) + } + catch (e: Exception) { + return + } + finally { + s.length + requireNotNull(s2) + } + s.length + s1.length + s2.length +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/tryCatch/falsePositiveSmartcasts.txt b/compiler/testData/diagnostics/testsWithStdLib/tryCatch/falsePositiveSmartcasts.txt new file mode 100644 index 00000000000..eee9a3ef422 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/tryCatch/falsePositiveSmartcasts.txt @@ -0,0 +1,46 @@ +package + +public fun test1(): kotlin.Unit +public fun test2(): kotlin.Unit +public fun test3(): kotlin.Unit +public fun test4(): kotlin.Unit +public fun test5(): kotlin.Unit +public fun test6(/*0*/ s1: kotlin.String?, /*1*/ s2: kotlin.String?): kotlin.Unit + +public final class ExcA : kotlin.Exception /* = java.lang.Exception */ { + public constructor ExcA() + public open override /*1*/ /*fake_override*/ val cause: kotlin.Throwable? + public open override /*1*/ /*fake_override*/ val message: kotlin.String? + public final override /*1*/ /*fake_override*/ fun addSuppressed(/*0*/ exception: kotlin.Throwable!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun fillInStackTrace(): kotlin.Throwable! + public open override /*1*/ /*fake_override*/ fun getLocalizedMessage(): kotlin.String! + public open override /*1*/ /*fake_override*/ fun getStackTrace(): kotlin.Array<(out) java.lang.StackTraceElement!>! + public final override /*1*/ /*fake_override*/ fun getSuppressed(): kotlin.Array<(out) kotlin.Throwable!>! + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun initCause(/*0*/ cause: kotlin.Throwable!): kotlin.Throwable! + public open override /*1*/ /*fake_override*/ fun printStackTrace(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun printStackTrace(/*0*/ s: java.io.PrintStream!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun printStackTrace(/*0*/ s: java.io.PrintWriter!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun setStackTrace(/*0*/ stackTrace: kotlin.Array<(out) java.lang.StackTraceElement!>!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class ExcB : kotlin.Exception /* = java.lang.Exception */ { + public constructor ExcB() + public open override /*1*/ /*fake_override*/ val cause: kotlin.Throwable? + public open override /*1*/ /*fake_override*/ val message: kotlin.String? + public final override /*1*/ /*fake_override*/ fun addSuppressed(/*0*/ exception: kotlin.Throwable!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun fillInStackTrace(): kotlin.Throwable! + public open override /*1*/ /*fake_override*/ fun getLocalizedMessage(): kotlin.String! + public open override /*1*/ /*fake_override*/ fun getStackTrace(): kotlin.Array<(out) java.lang.StackTraceElement!>! + public final override /*1*/ /*fake_override*/ fun getSuppressed(): kotlin.Array<(out) kotlin.Throwable!>! + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun initCause(/*0*/ cause: kotlin.Throwable!): kotlin.Throwable! + public open override /*1*/ /*fake_override*/ fun printStackTrace(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun printStackTrace(/*0*/ s: java.io.PrintStream!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun printStackTrace(/*0*/ s: java.io.PrintWriter!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun setStackTrace(/*0*/ stackTrace: kotlin.Array<(out) java.lang.StackTraceElement!>!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/tryCatch/tryExpression.kt b/compiler/testData/diagnostics/testsWithStdLib/tryCatch/tryExpression.kt new file mode 100644 index 00000000000..f414096b90c --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/tryCatch/tryExpression.kt @@ -0,0 +1,34 @@ +// !WITH_NEW_INFERENCE + +class ExcA : Exception() + +class ExcB(val map: Map) : Exception() + +fun test0(): List = run { + try { + emptyList() + } finally { + "" + fun foo() {} + } +} + +fun test1(): Map = run { + try { + emptyMap() + } catch (e: ExcA) { + emptyMap() + } catch (e: ExcB) { + e.map + } finally { + "" + } +} + +fun test2(): Map = run { + try { + emptyMap() + } catch (e: ExcA) { + mapOf("" to "") + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/tryCatch/tryExpression.txt b/compiler/testData/diagnostics/testsWithStdLib/tryCatch/tryExpression.txt new file mode 100644 index 00000000000..2ce5f9a3352 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/tryCatch/tryExpression.txt @@ -0,0 +1,44 @@ +package + +public fun test0(): kotlin.collections.List +public fun test1(): kotlin.collections.Map +public fun test2(): kotlin.collections.Map + +public final class ExcA : kotlin.Exception /* = java.lang.Exception */ { + public constructor ExcA() + public open override /*1*/ /*fake_override*/ val cause: kotlin.Throwable? + public open override /*1*/ /*fake_override*/ val message: kotlin.String? + public final override /*1*/ /*fake_override*/ fun addSuppressed(/*0*/ exception: kotlin.Throwable!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun fillInStackTrace(): kotlin.Throwable! + public open override /*1*/ /*fake_override*/ fun getLocalizedMessage(): kotlin.String! + public open override /*1*/ /*fake_override*/ fun getStackTrace(): kotlin.Array<(out) java.lang.StackTraceElement!>! + public final override /*1*/ /*fake_override*/ fun getSuppressed(): kotlin.Array<(out) kotlin.Throwable!>! + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun initCause(/*0*/ cause: kotlin.Throwable!): kotlin.Throwable! + public open override /*1*/ /*fake_override*/ fun printStackTrace(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun printStackTrace(/*0*/ s: java.io.PrintStream!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun printStackTrace(/*0*/ s: java.io.PrintWriter!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun setStackTrace(/*0*/ stackTrace: kotlin.Array<(out) java.lang.StackTraceElement!>!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class ExcB : kotlin.Exception /* = java.lang.Exception */ { + public constructor ExcB(/*0*/ map: kotlin.collections.Map) + public open override /*1*/ /*fake_override*/ val cause: kotlin.Throwable? + public final val map: kotlin.collections.Map + public open override /*1*/ /*fake_override*/ val message: kotlin.String? + public final override /*1*/ /*fake_override*/ fun addSuppressed(/*0*/ exception: kotlin.Throwable!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun fillInStackTrace(): kotlin.Throwable! + public open override /*1*/ /*fake_override*/ fun getLocalizedMessage(): kotlin.String! + public open override /*1*/ /*fake_override*/ fun getStackTrace(): kotlin.Array<(out) java.lang.StackTraceElement!>! + public final override /*1*/ /*fake_override*/ fun getSuppressed(): kotlin.Array<(out) kotlin.Throwable!>! + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun initCause(/*0*/ cause: kotlin.Throwable!): kotlin.Throwable! + public open override /*1*/ /*fake_override*/ fun printStackTrace(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun printStackTrace(/*0*/ s: java.io.PrintStream!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun printStackTrace(/*0*/ s: java.io.PrintWriter!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun setStackTrace(/*0*/ stackTrace: kotlin.Array<(out) java.lang.StackTraceElement!>!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java index 8153b531795..7d7b7a1e30d 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java @@ -3234,6 +3234,54 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW } } + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/tryCatch") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class TryCatch extends AbstractDiagnosticsTestWithStdLib { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath); + } + + public void testAllFilesPresentInTryCatch() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/tryCatch"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("assignTry.kt") + public void testAssignTry() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/tryCatch/assignTry.kt"); + } + + @TestMetadata("boundedSmartcasts.kt") + public void testBoundedSmartcasts() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/tryCatch/boundedSmartcasts.kt"); + } + + @TestMetadata("catchRedeclaration.kt") + public void testCatchRedeclaration() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/tryCatch/catchRedeclaration.kt"); + } + + @TestMetadata("correctSmartcasts.kt") + public void testCorrectSmartcasts() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/tryCatch/correctSmartcasts.kt"); + } + + @TestMetadata("falseNegativeSmartcasts.kt") + public void testFalseNegativeSmartcasts() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/tryCatch/falseNegativeSmartcasts.kt"); + } + + @TestMetadata("falsePositiveSmartcasts.kt") + public void testFalsePositiveSmartcasts() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/tryCatch/falsePositiveSmartcasts.kt"); + } + + @TestMetadata("tryExpression.kt") + public void testTryExpression() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/tryCatch/tryExpression.kt"); + } + } + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/typealias") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java index fbc33f73ace..5d0ff885187 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java @@ -3234,6 +3234,54 @@ public class DiagnosticsTestWithStdLibUsingJavacGenerated extends AbstractDiagno } } + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/tryCatch") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class TryCatch extends AbstractDiagnosticsTestWithStdLibUsingJavac { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath); + } + + public void testAllFilesPresentInTryCatch() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/tryCatch"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("assignTry.kt") + public void testAssignTry() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/tryCatch/assignTry.kt"); + } + + @TestMetadata("boundedSmartcasts.kt") + public void testBoundedSmartcasts() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/tryCatch/boundedSmartcasts.kt"); + } + + @TestMetadata("catchRedeclaration.kt") + public void testCatchRedeclaration() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/tryCatch/catchRedeclaration.kt"); + } + + @TestMetadata("correctSmartcasts.kt") + public void testCorrectSmartcasts() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/tryCatch/correctSmartcasts.kt"); + } + + @TestMetadata("falseNegativeSmartcasts.kt") + public void testFalseNegativeSmartcasts() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/tryCatch/falseNegativeSmartcasts.kt"); + } + + @TestMetadata("falsePositiveSmartcasts.kt") + public void testFalsePositiveSmartcasts() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/tryCatch/falsePositiveSmartcasts.kt"); + } + + @TestMetadata("tryExpression.kt") + public void testTryExpression() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/tryCatch/tryExpression.kt"); + } + } + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/typealias") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)