diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/common/neg/1.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/common/neg/1.fir.kt new file mode 100644 index 00000000000..56fa753c21a --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/common/neg/1.fir.kt @@ -0,0 +1,84 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts +// !WITH_NEW_INFERENCE + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, analysis, common + * NUMBER: 1 + * DESCRIPTION: Analysis by contracts with mixed CallsInPlace and Returns effects. + */ + +// FILE: contracts.kt + +package contracts + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +inline fun case_1(value_1: Int?, block: () -> Unit): Boolean { + contract { + callsInPlace(block, InvocationKind.AT_MOST_ONCE) + returns(true) implies (value_1 != null) + } + + block() + + return value_1 != null +} + +// TESTCASE NUMBER: 2 +inline fun T?.case_2(value_1: Int?, value_2: Any?, block: () -> Unit): Boolean? { + contract { + callsInPlace(block, InvocationKind.AT_MOST_ONCE) + returns(true) implies (value_1 == null && this@case_2 == null && value_2 !is Boolean?) + returns(false) implies (value_2 is Boolean?) + returns(null) implies ((value_1 != null || this@case_2 != null) && value_2 !is Boolean?) + } + + block() + + if (value_1 != null && this != null && value_2 is Boolean?) return true + if (value_2 !is Boolean?) return false + + return null +} + +// FILE: main.kt + +import contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(value_1: Int?) { + val value_2: Int + if (contracts.case_1(value_1) { value_2 = 10 }) { + println(value_2) + } else { + value_1.inv() + println(value_2) + } +} + +// TESTCASE NUMBER: 2 +fun case_2(value_1: Int?, value_2: Int?, value_3: Any?) { + val value_4: Int + when (value_1.case_2(value_2, value_3) { value_4 = 10 }) { + true -> { + println(value_3?.xor(true)) + println(value_4) + println(value_1.inv()) + println(value_2.inv()) + } + false -> { + println(value_4) + println(value_1) + println(value_2) + } + null -> { + println(value_3?.xor(true)) + println(value_4) + println(value_1) + println(value_2) + } + } +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/common/pos/1.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/common/pos/1.fir.kt new file mode 100644 index 00000000000..3f7ba7e3d08 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/common/pos/1.fir.kt @@ -0,0 +1,79 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (POSITIVE) + * + * SECTIONS: contracts, analysis, common + * NUMBER: 1 + * DESCRIPTION: Analysis by contracts with mixed CallsInPlace and Returns effects. + */ + +// FILE: contracts.kt + +package contracts + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +inline fun case_1(value_1: Int?, block: () -> Unit): Boolean { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + returns(true) implies (value_1 != null) + } + block() + return value_1 != null +} + +// TESTCASE NUMBER: 2 +inline fun T?.case_2(value_1: Int?, value_2: Any?, block: () -> Unit): Boolean? { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + returns(true) implies (value_1 != null && this@case_2 != null && value_2 is Boolean?) + returns(false) implies (value_2 !is Boolean?) + returns(null) implies ((value_1 == null || this@case_2 == null) && value_2 is Boolean?) + } + block() + if (value_1 != null && this != null && value_2 is Boolean?) return true + if (value_2 !is Boolean?) return false + return null +} + +// FILE: main.kt + +import contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(value_1: Int?) { + val value_3: Int + if (contracts.case_1(value_1) { value_3 = 10 }) { + value_1.inv() + println(value_3) + } else { + println(value_3) + } +} + +// TESTCASE NUMBER: 2 +fun case_2(value_1: Int?, value_2: Int?, value_3: Any?) { + val value_4: Int + when (value_1.case_2(value_2, value_3) { value_4 = 10 }) { + true -> { + println(value_3?.xor(true)) + println(value_4) + println(value_1.inv()) + println(value_2.inv()) + } + false -> { + println(value_4) + println(value_1) + println(value_2) + } + null -> { + println(value_3?.xor(true)) + println(value_4) + println(value_1) + println(value_2) + } + } + println(value_4) +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/neg/1.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/neg/1.fir.kt new file mode 100644 index 00000000000..569a098f78d --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/neg/1.fir.kt @@ -0,0 +1,84 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts +// SKIP_TXT + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, analysis, controlFlow, initialization + * NUMBER: 1 + * DESCRIPTION: val/var reassignment and/or uninitialized variable usages based on CallsInPlace effect with wrong invocation kind + * HELPERS: contractFunctions + */ + +// TESTCASE NUMBER: 1 +fun case_1() { + val value_1: Int + funWithAtLeastOnceCallsInPlace { value_1 = 10 } + value_1.inc() +} + +// TESTCASE NUMBER: 2 +fun case_2() { + val value_1: Int + funWithAtMostOnceCallsInPlace { value_1 = 10 } + value_1.inc() +} + +// TESTCASE NUMBER: 3 +fun case_3() { + val value_1: Int + funWithUnknownCallsInPlace { value_1 = 10 } + value_1.inc() +} + +// TESTCASE NUMBER: 4 +fun case_4() { + var value_1: Int + var value_2: Int + funWithAtMostOnceCallsInPlace { value_1 = 10 } + funWithUnknownCallsInPlace { value_2 = 10 } + value_1.dec() + value_2.div(10) +} + +// TESTCASE NUMBER: 5 +class case_5 { + val value_1: Int + val value_2: Int + val value_3: Int + var value_4: Int + var value_5: Int + init { + funWithAtMostOnceCallsInPlace { value_1 = 1 } + funWithUnknownCallsInPlace { value_2 = 1 } + funWithAtLeastOnceCallsInPlace { value_3 = 1 } + funWithAtMostOnceCallsInPlace { value_4 = 2 } + funWithUnknownCallsInPlace { value_5 = 3 } + } +} + +// TESTCASE NUMBER: 6 +fun case_6() { + val value_1: Int + for (i in 0..1) + funWithExactlyOnceCallsInPlace { value_1 = 10 } + value_1.dec() +} + +// TESTCASE NUMBER: 7 +fun case_7() { + var value_1: Int + var i = 0 + while (i < 10) { + funWithExactlyOnceCallsInPlace { value_1 = 10 } + i++ + } + value_1.dec() +} + +// TESTCASE NUMBER: 8 +fun case_8() { + var value_1: Int + if (true) funWithAtLeastOnceCallsInPlace { value_1 = 10 } + value_1.dec() +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/neg/2.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/neg/2.fir.kt new file mode 100644 index 00000000000..8a4f01c8b3f --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/neg/2.fir.kt @@ -0,0 +1,86 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts +// SKIP_TXT + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, analysis, controlFlow, initialization + * NUMBER: 2 + * DESCRIPTION: val/var reassignment and/or uninitialized variable usages based on nested CallsInPlace effects with wrong invocation kind + * HELPERS: contractFunctions + */ + +// TESTCASE NUMBER: 1 +fun case_1() { + val value_1: Int + funWithAtLeastOnceCallsInPlace { + funWithAtMostOnceCallsInPlace { + value_1 = 1 + funWithExactlyOnceCallsInPlace { + value_1.inc() + } + } + funWithExactlyOnceCallsInPlace { + value_1.inc() + } + value_1.inc() + } + value_1.inc() +} + +// TESTCASE NUMBER: 2 +fun case_2() { + val value_1: Int + funWithAtMostOnceCallsInPlace { + funWithAtMostOnceCallsInPlace { + value_1 = 1 + } + funWithAtLeastOnceCallsInPlace { + value_1.inc() + } + funWithUnknownCallsInPlace { + value_1.inc() + } + value_1.inc() + } + value_1.inc() +} + +// TESTCASE NUMBER: 3 +fun case_3() { + var value_1: Int + funWithAtLeastOnceCallsInPlace { + funWithAtMostOnceCallsInPlace { + value_1 = 1 + funWithExactlyOnceCallsInPlace { + value_1.inc() + } + } + funWithExactlyOnceCallsInPlace { + value_1.inc() + } + value_1.inc() + } + value_1.inc() +} + +// TESTCASE NUMBER: 4 +fun case_4() { + var value_1: Int + funWithAtLeastOnceCallsInPlace { + funWithUnknownCallsInPlace { + value_1 = 1 + } + funWithAtLeastOnceCallsInPlace { + value_1.inc() + } + funWithUnknownCallsInPlace { + value_1.inc() + } + funWithExactlyOnceCallsInPlace { + value_1.inc() + } + value_1.inc() + } + value_1.inc() +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/neg/3.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/neg/3.fir.kt new file mode 100644 index 00000000000..6deabc66df3 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/neg/3.fir.kt @@ -0,0 +1,169 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts +// SKIP_TXT + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, analysis, controlFlow, initialization + * NUMBER: 3 + * DESCRIPTION: val/var reassignment and/or uninitialized variable usages with compelx control flow inside/outside lambda of contract function with CallsInPlace effect + * HELPERS: enumClasses, contractFunctions + */ + +// TESTCASE NUMBER: 1 +fun case_1(value_1: EnumClass?) { + val value_2: Int + + when (value_1) { + EnumClass.NORTH -> funWithExactlyOnceCallsInPlace { value_2 = 1 } + EnumClass.SOUTH -> funWithExactlyOnceCallsInPlace { value_2 = 2 } + EnumClass.EAST -> funWithExactlyOnceCallsInPlace { value_2 = 4 } + null -> funWithExactlyOnceCallsInPlace { value_2 = 5 } + } + + value_2.inc() +} + +// TESTCASE NUMBER: 2 +fun case_2(value_1: Any?) { + val value_2: Int + + funWithAtMostOnceCallsInPlace { + if (value_1 is String) { + value_2 = 0 + } else if (value_1 == null) { + value_2 = 1 + } else { + funWithAtMostOnceCallsInPlace { value_2 = 2 } + } + value_2.dec() + } + value_2.dec() +} + +// TESTCASE NUMBER: 3 +class case_3(value_1: Any?) { + var value_2: Int + + init { + if (value_1 is String) { + funWithUnknownCallsInPlace { value_2 = 0 } + value_2.div(10) + } else if (value_1 == null) { + funWithAtLeastOnceCallsInPlace { value_2 = 1 } + value_2.div(10) + } else { + value_2 = 2 + } + + value_2.div(10) + } +} + +// TESTCASE NUMBER: 4 +fun case_4(value_1: EnumClassSingle?) { + var value_2: Int + + funWithAtMostOnceCallsInPlace { + when (value_1) { + EnumClassSingle.EVERYTHING -> { + funWithExactlyOnceCallsInPlace { value_2 = 1 } + ++value_2 + } + null -> { + funWithUnknownCallsInPlace { value_2 = 2 } + } + } + value_2.minus(5) + } + value_2.minus(5) +} + +// TESTCASE NUMBER: 5 +fun case_5() { + var value_2: Int + + try { + funWithAtLeastOnceCallsInPlace { value_2 = 10 } + } catch (e: Exception) { + funWithAtMostOnceCallsInPlace { value_2 = 1 } + } + + value_2++ +} + +// TESTCASE NUMBER: 6 +fun case_6() { + var value_2: Int + + try { + funWithAtLeastOnceCallsInPlace { value_2 = 10 } + } catch (e: Exception) { + throw Exception() + } finally { + println(value_2.inc()) + } + + value_2++ +} + +// TESTCASE NUMBER: 7 +fun case_7() { + var value_1: Int + + try { + funWithAtLeastOnceCallsInPlace { value_1 = 10 } + } catch (e: Exception) { + try { + funWithAtLeastOnceCallsInPlace { value_1 = 10 } + } catch (e: Exception) { + funWithAtMostOnceCallsInPlace { value_1 = 10 } + } + } + + println(value_1.inc()) +} + +// TESTCASE NUMBER: 8 +fun case_8() { + val x: Int + funWithExactlyOnceCallsInPlace outer@ { + funWithAtMostOnceCallsInPlace { + funWithUnknownCallsInPlace { + x = 42 + } + return@outer + } + throw Exception() + } + println(x.inc()) +} + +// TESTCASE NUMBER: 9 +fun case_9() { + val x: Int + funWithExactlyOnceCallsInPlace outer@ { + funWithAtMostOnceCallsInPlace { + x = 42 + return@outer + } + } + println(x.inc()) +} + +// TESTCASE NUMBER: 10 +fun case_10() { + var x: Int + funWithAtLeastOnceCallsInPlace outer@ { + funWithAtMostOnceCallsInPlace { + x = 41 + return@outer + } + funWithUnknownCallsInPlace { + x = 42 + return@outer + } + return@outer + } + println(x.inc()) +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/neg/4.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/neg/4.fir.kt new file mode 100644 index 00000000000..aeed27bd4b4 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/neg/4.fir.kt @@ -0,0 +1,94 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts +// SKIP_TXT + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, analysis, controlFlow, initialization + * NUMBER: 4 + * DESCRIPTION: CallsInPlace contract functions with name shadowing and wrong invocation kind + * HELPERS: contractFunctions + */ + +// TESTCASE NUMBER: 1 +fun case_1() { + val value_1: Int + funWithExactlyOnceCallsInPlace { + val value_1 = 10 + value_1.inc() + } + value_1.inc() +} + +// TESTCASE NUMBER: 2 +fun case_2() { + val value_1: Int + funWithExactlyOnceCallsInPlace { + val value_1: Int + funWithExactlyOnceCallsInPlace { + value_1 = 10 + } + funWithAtLeastOnceCallsInPlace { + value_1.inc() + } + value_1.inc() + } + value_1.inc() +} + +// TESTCASE NUMBER: 3 +fun case_3() { + val value_1: Int + funWithAtLeastOnceCallsInPlace { + val value_1: Int + funWithAtMostOnceCallsInPlace { + value_1 = 10 + } + funWithAtMostOnceCallsInPlace { + value_1.inc() + } + value_1.inc() + } + funWithAtMostOnceCallsInPlace { + value_1 = 10 + } + value_1.inc() +} + +// TESTCASE NUMBER: 4 +fun case_4() { + var value_1: Int + funWithAtLeastOnceCallsInPlace { + val value_1: Int + funWithExactlyOnceCallsInPlace { + value_1 = 10 + } + funWithAtMostOnceCallsInPlace { + value_1.inc() + } + value_1.inc() + } + funWithAtMostOnceCallsInPlace { + value_1 = 1 + } + value_1.dec() +} + +// TESTCASE NUMBER: 5 +fun case_5() { + val value_1: Int + funWithUnknownCallsInPlace { + var value_1: Int + funWithAtLeastOnceCallsInPlace { + value_1 = 10 + } + funWithUnknownCallsInPlace { + value_1.inc() + } + value_1.inc() + } + funWithUnknownCallsInPlace { + value_1 = 1 + } + value_1.dec() +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/neg/5.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/neg/5.fir.kt new file mode 100644 index 00000000000..ffcc358e0f6 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/neg/5.fir.kt @@ -0,0 +1,51 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts +// SKIP_TXT + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, analysis, controlFlow, initialization + * NUMBER: 5 + * DESCRIPTION: CallsInPlace contract functions with invalid lambda passing to function parameter. + * HELPERS: contractFunctions + */ + +// TESTCASE NUMBER: 1 +fun case_1() { + val value_1: Int + funWithExactlyOnceCallsInPlace({ value_1 = 10 }) + value_1.inc() +} + +// TESTCASE NUMBER: 2 +fun case_2() { + var value_1: Int + val l = { value_1 = 10 } + funWithAtLeastOnceCallsInPlace(l) + value_1.inc() +} + +// TESTCASE NUMBER: 3 +fun case_3() { + var value_1: Int + val l = fun () { value_1 = 10 } + funWithAtLeastOnceCallsInPlace(l) + value_1.inc() +} + +// TESTCASE NUMBER: 4 +fun case_4() { + var value_1: Int + funWithAtLeastOnceCallsInPlace(fun () { value_1 = 10 }) + value_1.inc() +} + +// TESTCASE NUMBER: 5 +fun case_5() { + val value_1: Int + val o = object { + fun l() { value_1 = 10 } + } + funWithExactlyOnceCallsInPlace(o::l) + value_1.inc() +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/neg/6.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/neg/6.fir.kt new file mode 100644 index 00000000000..c26ef0cc6a3 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/neg/6.fir.kt @@ -0,0 +1,27 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts +// SKIP_TXT + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, analysis, controlFlow, initialization + * NUMBER: 6 + * DESCRIPTION: Check the lack of CallsInPlace effect on the lambda in the parentheses. + * UNEXPECTED BEHAVIOUR + * ISSUES: KT-26229 + * HELPERS: contractFunctions + */ + +// TESTCASE NUMBER: 1 +fun case_1() { + val value_1: Int + funWithExactlyOnceCallsInPlace({ value_1 = 11 }) + value_1.inc() +} + +// TESTCASE NUMBER: 2 +fun case_2() { + var value_1: Int + funWithAtLeastOnceCallsInPlace({ value_1 = 11 }) + value_1.inc() +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/pos/3.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/pos/3.fir.kt new file mode 100644 index 00000000000..43adc67c4d1 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/pos/3.fir.kt @@ -0,0 +1,189 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts +// SKIP_TXT + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (POSITIVE) + * + * SECTIONS: contracts, analysis, controlFlow, initialization + * NUMBER: 3 + * DESCRIPTION: val/var assignments or subsequent usages with compelx control flow inside/outside lambda of contract function with CallsInPlace effect + * HELPERS: enumClasses, contractFunctions + */ + +// TESTCASE NUMBER: 1 +fun case_1(value_1: EnumClass?) { + val value_2: Int + + when (value_1) { + EnumClass.NORTH -> funWithExactlyOnceCallsInPlace { value_2 = 1 } + EnumClass.SOUTH -> funWithExactlyOnceCallsInPlace { value_2 = 2 } + EnumClass.WEST -> funWithExactlyOnceCallsInPlace { value_2 = 3 } + EnumClass.EAST -> funWithExactlyOnceCallsInPlace { value_2 = 4 } + null -> funWithExactlyOnceCallsInPlace { value_2 = 5 } + } + + value_2.inc() +} + +// TESTCASE NUMBER: 2 +fun case_2(value_1: Any?) { + val value_2: Int + + funWithAtMostOnceCallsInPlace { + if (value_1 is String) { + value_2 = 0 + } else if (value_1 == null) { + value_2 = 1 + } else { + funWithExactlyOnceCallsInPlace { value_2 = 2 } + value_2.dec() + } + value_2.dec() + } +} + +// TESTCASE NUMBER: 3 +class case_3(value_1: Any?) { + var value_2: Int + + init { + if (value_1 is String) { + funWithExactlyOnceCallsInPlace { value_2 = 0 } + value_2.div(10) + } else if (value_1 == null) { + funWithAtLeastOnceCallsInPlace { value_2 = 1 } + value_2.div(10) + } else { + value_2 = 2 + } + + value_2.div(10) + } +} + +// TESTCASE NUMBER: 4 +fun case_4(value_1: EnumClassSingle?) { + var value_2: Int + + funWithAtMostOnceCallsInPlace { + when (value_1) { + EnumClassSingle.EVERYTHING -> { + funWithExactlyOnceCallsInPlace { value_2 = 1 } + ++value_2 + } + null -> { + funWithAtLeastOnceCallsInPlace { value_2 = 2 } + --value_2 + } + } + value_2.minus(5) + } +} + +// TESTCASE NUMBER: 5 +fun case_5() { + var value_2: Int + + try { + funWithAtLeastOnceCallsInPlace { value_2 = 10 } + } catch (e: Exception) { + funWithExactlyOnceCallsInPlace { value_2 = 1 } + } + + value_2++ +} + +// TESTCASE NUMBER: 6 +fun case_6() { + var value_2: Int + + try { + funWithAtLeastOnceCallsInPlace { value_2 = 10 } + } catch (e: Exception) { + throw Exception() + } finally { + funWithAtLeastOnceCallsInPlace { value_2 = 10 } + } + + value_2++ +} + +// TESTCASE NUMBER: 7 +fun case_7() { + var value_1: Int + + try { + funWithAtLeastOnceCallsInPlace { value_1 = 10 } + } catch (e: Exception) { + try { + funWithAtLeastOnceCallsInPlace { value_1 = 10 } + } catch (e: Exception) { + throw Exception() + } + } finally { + funWithAtLeastOnceCallsInPlace { value_1 = 10 } + } + + println(value_1.inc()) +} + +// TESTCASE NUMBER: 8 +fun case_8() { + var value_1: Int + + try { + funWithAtLeastOnceCallsInPlace { value_1 = 10 } + } catch (e: Exception) { + try { + funWithAtLeastOnceCallsInPlace { value_1 = 10 } + } catch (e: Exception) { + funWithAtLeastOnceCallsInPlace { value_1 = 10 } + } + } + + println(value_1.inc()) +} + +// TESTCASE NUMBER: 9 +fun case_9() { + val x: Int + funWithExactlyOnceCallsInPlace outer@ { + funWithAtMostOnceCallsInPlace { + funWithUnknownCallsInPlace { + x = 42 + return@outer + } + } + throw Exception() + } + println(x.inc()) +} + +// TESTCASE NUMBER: 10 +fun case_10() { + val x: Int + funWithExactlyOnceCallsInPlace outer@ { + funWithAtLeastOnceCallsInPlace { + x = 42 + return@outer + } + } + println(x.inc()) +} + +// TESTCASE NUMBER: 11 +fun case_11() { + var x: Int + funWithAtLeastOnceCallsInPlace outer@ { + funWithAtMostOnceCallsInPlace { + x = 41 + return@outer + } + funWithUnknownCallsInPlace { + x = 42 + return@outer + } + return@case_11 + } + println(x.inc()) +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/pos/4.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/pos/4.fir.kt new file mode 100644 index 00000000000..65ac9f897e0 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/pos/4.fir.kt @@ -0,0 +1,140 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts +// SKIP_TXT + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (POSITIVE) + * + * SECTIONS: contracts, analysis, controlFlow, initialization + * NUMBER: 4 + * DESCRIPTION: CallsInPlace contract functions with name shadowing + * HELPERS: contractFunctions + */ + +// TESTCASE NUMBER: 1 +fun case_1() { + val value_1: Int + funWithExactlyOnceCallsInPlace { + val value_1 = 10 + value_1.inc() + } +} + +// TESTCASE NUMBER: 2 +fun case_2() { + val value_1: Int + funWithExactlyOnceCallsInPlace { + val value_1: Int + funWithExactlyOnceCallsInPlace { + value_1 = 10 + } + funWithAtLeastOnceCallsInPlace { + value_1.inc() + } + value_1.inc() + } +} + +// TESTCASE NUMBER: 3 +fun case_3() { + val value_1: Int + funWithAtLeastOnceCallsInPlace { + val value_1: Int + funWithExactlyOnceCallsInPlace { + value_1 = 10 + } + funWithAtMostOnceCallsInPlace { + value_1.inc() + } + value_1.inc() + } + funWithExactlyOnceCallsInPlace { + value_1 = 10 + } + value_1.inc() +} + +// TESTCASE NUMBER: 4 +fun case_4() { + val value_1: Int + funWithAtMostOnceCallsInPlace { + val value_1: Int + funWithExactlyOnceCallsInPlace { + value_1 = 10 + } + funWithUnknownCallsInPlace { + value_1.inc() + } + value_1.inc() + } + funWithExactlyOnceCallsInPlace { + value_1 = 10 + } + value_1.inc() +} + +// TESTCASE NUMBER: 5 +fun case_5() { + val value_1: Int + funWithUnknownCallsInPlace { + val value_1: Int + funWithExactlyOnceCallsInPlace { + value_1 = 10 + } + funWithAtMostOnceCallsInPlace { + value_1.inc() + } + } + funWithExactlyOnceCallsInPlace { + value_1 = 10 + } + value_1.inc() +} + +// TESTCASE NUMBER: 6 +fun case_6() { + var value_1: Int + funWithAtLeastOnceCallsInPlace { + val value_1: Int + funWithExactlyOnceCallsInPlace { + value_1 = 10 + } + funWithAtMostOnceCallsInPlace { + value_1.inc() + } + value_1.inc() + } + funWithAtLeastOnceCallsInPlace { value_1 = 1 } + value_1.dec() +} + +// TESTCASE NUMBER: 7 +fun case_7() { + val value_1: Int + funWithAtLeastOnceCallsInPlace { + var value_1: Int + funWithAtLeastOnceCallsInPlace { value_1 = 10 } + funWithUnknownCallsInPlace { value_1.inc() } + value_1.inc() + } + funWithExactlyOnceCallsInPlace { value_1 = 1 } + value_1.dec() +} + +// TESTCASE NUMBER: 8 +fun case_8() { + var value_1: Int + funWithAtLeastOnceCallsInPlace { + var value_1: Int + funWithAtLeastOnceCallsInPlace { + value_1 = 10 + } + funWithAtLeastOnceCallsInPlace { + value_1.inc() + } + value_1++ + } + funWithAtLeastOnceCallsInPlace { + value_1 = 1 + } + value_1-- +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/pos/6.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/pos/6.fir.kt new file mode 100644 index 00000000000..1ce167821a0 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/pos/6.fir.kt @@ -0,0 +1,60 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (POSITIVE) + * + * SECTIONS: contracts, analysis, controlFlow, initialization + * NUMBER: 6 + * DESCRIPTION: Check the lack of CallsInPlace effect on the lambda in the parentheses. + * UNEXPECTED BEHAVIOUR + * ISSUES: KT-26229 + * HELPERS: contractFunctions + */ + +// FILE: contracts.kt + +package contracts + +import kotlin.contracts.* + +// TESTCASE NUMBER: 3 +inline fun case_3(block1: () -> Unit, block2: () -> Unit, block3: () -> Unit) { + contract { + callsInPlace(block1, InvocationKind.EXACTLY_ONCE) + callsInPlace(block2, InvocationKind.AT_LEAST_ONCE) + callsInPlace(block3, InvocationKind.EXACTLY_ONCE) + } + block1() + block2() + block2() + block3() +} + +// FILE: main.kt + +import contracts.* + +// TESTCASE NUMBER: 1 +fun case_1() { + val value_1: Int + funWithExactlyOnceCallsInPlace({ value_1 = 11 }) + value_1.inc() +} + +// TESTCASE NUMBER: 2 +fun case_2() { + var value_1: Int + funWithAtLeastOnceCallsInPlace({ value_1 = 11 }) + value_1.inc() +} + +// TESTCASE NUMBER: 3 +fun case_3() { + val value_1: Int + var value_2: Int + val value_3: Int + contracts.case_3({ value_1 = 1 }, { value_2 = 2 }, { value_3 = 3 }) + value_1.inc() + value_2.inc() + value_3.inc() +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/unreachableCode/neg/1.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/unreachableCode/neg/1.fir.kt new file mode 100644 index 00000000000..e66912046a2 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/unreachableCode/neg/1.fir.kt @@ -0,0 +1,45 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts +// SKIP_TXT + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, analysis, controlFlow, unreachableCode + * NUMBER: 1 + * DESCRIPTION: Using not allowed break and continue inside lambda of contract function + * HELPERS: contractFunctions + */ + +// TESTCASE NUMBER: 1 +fun case_1(value_1: Boolean) { + while (value_1) { + funWithExactlyOnceCallsInPlace { + break + } + println("1") + } + + loop@ for (i in 0..10) { + funWithExactlyOnceCallsInPlace { + break@loop + } + println("1") + } +} + +// TESTCASE NUMBER: 2 +fun case_2(value_1: Boolean) { + for (i in 0..10) { + funWithExactlyOnceCallsInPlace { + continue + } + println("1") + } + + loop@ while (value_1) { + funWithExactlyOnceCallsInPlace { + continue@loop + } + println("1") + } +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/unreachableCode/pos/1.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/unreachableCode/pos/1.fir.kt new file mode 100644 index 00000000000..cca0c5f17cd --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/unreachableCode/pos/1.fir.kt @@ -0,0 +1,113 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts +// SKIP_TXT + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (POSITIVE) + * + * SECTIONS: contracts, analysis, controlFlow, unreachableCode + * NUMBER: 1 + * DESCRIPTION: Unreachable code detection using contract function with CallsInPlace effect + * HELPERS: contractFunctions + */ + +// TESTCASE NUMBER: 1 +fun case_1() { + funWithExactlyOnceCallsInPlace { + throw Exception() + } + println("1") +} + +// TESTCASE NUMBER: 2 +fun case_2() { + funWithAtLeastOnceCallsInPlace { + throw Exception() + } + println("1") +} + +// TESTCASE NUMBER: 3 +fun case_3() { + funWithExactlyOnceCallsInPlace { + return + } + println("1") +} + +// TESTCASE NUMBER: 4 +fun case_4() { + funWithAtLeastOnceCallsInPlace { + return + } + println("1") +} + +// TESTCASE NUMBER: 5 +fun case_5(args: Array) { + fun nestedFun_1() { + funWithAtLeastOnceCallsInPlace { + return@nestedFun_1 + } + println("1") + } + fun nestedFun_2() { + args.forEach { + funWithAtLeastOnceCallsInPlace { + return@forEach + } + println("1") + } + } + fun nestedFun_3() { + fun nestedFun_4() { + funWithAtLeastOnceCallsInPlace { + return@nestedFun_4 + } + println("1") + } + println("1") + } +} + +// TESTCASE NUMBER: 6 +fun case_6(args: Array) { + args.forEach { + funWithExactlyOnceCallsInPlace { + return@forEach + } + println("1") + } + args.forEach { + fun nestedFun_1() { + funWithExactlyOnceCallsInPlace { + return@nestedFun_1 + } + println("1") + } + } + args.forEach { + fun nestedFun_2() { + funWithExactlyOnceCallsInPlace { + return + } + println("1") + } + } +} + +// TESTCASE NUMBER: 7 +fun case_7() { + val value_1 = funWithExactlyOnceCallsInPlace { + throw Exception() + println(1) + } + println(value_1) +} + + +// TESTCASE NUMBER: 8 +fun case_8() { + println(funWithExactlyOnceCallsInPlace { return; println(1) }) + return +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/unreachableCode/pos/3.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/unreachableCode/pos/3.fir.kt new file mode 100644 index 00000000000..bdf299bcb0b --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/unreachableCode/pos/3.fir.kt @@ -0,0 +1,96 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts +// SKIP_TXT + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (POSITIVE) + * + * SECTIONS: contracts, analysis, controlFlow, unreachableCode + * NUMBER: 3 + * DESCRIPTION: Unreachable code detection using local functions or labdas combined with contract functions with CallsInPlace effect + * HELPERS: contractFunctions + */ + +// TESTCASE NUMBER: 1 +fun case_1() { + funWithExactlyOnceCallsInPlace { + throw Exception() + } + println("1") +} + +// TESTCASE NUMBER: 2 +fun case_2() { + funWithAtLeastOnceCallsInPlace { + throw Exception() + } + println("1") +} + +// TESTCASE NUMBER: 3 +fun case_3() { + funWithExactlyOnceCallsInPlace { + return + } + println("1") +} + +// TESTCASE NUMBER: 4 +fun case_4() { + funWithAtLeastOnceCallsInPlace { + return + } + println("1") +} + +// TESTCASE NUMBER: 5 +fun case_5(args: Array) { + fun nestedFun_1() { + funWithAtLeastOnceCallsInPlace { + return@nestedFun_1 + } + println("1") + } + fun nestedFun_2() { + args.forEach { + funWithAtLeastOnceCallsInPlace { + return@forEach + } + println("1") + } + } + fun nestedFun_3() { + fun nestedFun_4() { + funWithAtLeastOnceCallsInPlace { + return@nestedFun_4 + } + println("1") + } + println("1") + } +} + +// TESTCASE NUMBER: 6 +fun case_6(args: Array) { + args.forEach { + funWithExactlyOnceCallsInPlace { + return@forEach + } + println("1") + } + args.forEach { + fun nestedFun_1() { + funWithExactlyOnceCallsInPlace { + return@nestedFun_1 + } + println("1") + } + } + args.forEach { + fun nestedFun_2() { + funWithExactlyOnceCallsInPlace { + return + } + println("1") + } + } +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/unreachableCode/pos/4.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/unreachableCode/pos/4.fir.kt new file mode 100644 index 00000000000..4effef15e21 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/unreachableCode/pos/4.fir.kt @@ -0,0 +1,56 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts +// SKIP_TXT + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (POSITIVE) + * + * SECTIONS: contracts, analysis, controlFlow, unreachableCode + * NUMBER: 4 + * DESCRIPTION: Unreachable code detection using nested contract functions with CallsInPlace effect + * HELPERS: contractFunctions + */ + +// TESTCASE NUMBER: 1 +fun case_1() { + funWithExactlyOnceCallsInPlace { + funWithExactlyOnceCallsInPlace { + funWithExactlyOnceCallsInPlace { + throw Exception() + } + println("1") + } + println("2") + } + println("3") +} + +// TESTCASE NUMBER: 2 +fun case_2() { + funWithAtLeastOnceCallsInPlace { + funWithAtLeastOnceCallsInPlace label_1@ { + funWithAtLeastOnceCallsInPlace { + return@label_1 + } + println("1") + } + println("2") + } + funWithAtLeastOnceCallsInPlace { + return + } + println("3") +} + +// TESTCASE NUMBER: 3 +fun case_3() { + funWithExactlyOnceCallsInPlace { + funWithExactlyOnceCallsInPlace { + funWithExactlyOnceCallsInPlace { + return@funWithExactlyOnceCallsInPlace + } + println("1") + } + println("2") + } + println("3") +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/unreachableCode/pos/5.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/unreachableCode/pos/5.fir.kt new file mode 100644 index 00000000000..441b0fdf0da --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/unreachableCode/pos/5.fir.kt @@ -0,0 +1,60 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts +// SKIP_TXT + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (POSITIVE) + * + * SECTIONS: contracts, analysis, controlFlow, unreachableCode + * NUMBER: 5 + * DESCRIPTION: Unreachable code detection using contract functions with complex control flow inside + * HELPERS: contractFunctions + */ + +// TESTCASE NUMBER: 1 +fun case_1(b: Boolean?) { + funWithExactlyOnceCallsInPlace { + if (b == null) return + + when (b) { + true -> { + println(1) + return + } + false -> { + println(2) + throw Exception() + } + } + println(3) + } + println(3) +} + +// TESTCASE NUMBER: 2 +fun case_2(b: Boolean?, c: Boolean) { + funWithAtLeastOnceCallsInPlace { + when (b) { + true -> { + println(1) + return + } + else -> { + if (b == null) { + funWithExactlyOnceCallsInPlace { + when { + c == true -> throw Exception() + else -> funWithAtLeastOnceCallsInPlace { return } + } + println(3) + } + println(3) + } else { + throw Exception() + } + println(3) + } + } + println(3) + } + println(3) +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/unreachableCode/pos/6.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/unreachableCode/pos/6.fir.kt new file mode 100644 index 00000000000..3476bf64327 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/unreachableCode/pos/6.fir.kt @@ -0,0 +1,68 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts +// SKIP_TXT + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (POSITIVE) + * + * SECTIONS: contracts, analysis, controlFlow, unreachableCode + * NUMBER: 6 + * DESCRIPTION: Check for lack of unreachable code report when in complex control flow of contract function lambda not all branches are doing non-local return + * HELPERS: contractFunctions + */ + +// TESTCASE NUMBER: 1 +fun case_1(b: Boolean?, c: Boolean) { + funWithExactlyOnceCallsInPlace { + if (b == null) return + + try { + when (b) { + true -> { + println(1) + return + } + false -> { + println(2) + throw Exception() + } + } + } catch (e: Exception) { + if (c) { + return@funWithExactlyOnceCallsInPlace + } else { + return + } + } + println(3) + } + println(3) +} + +// TESTCASE NUMBER: 2 +fun case_2(b: Boolean?, c: Boolean) { + funWithAtLeastOnceCallsInPlace { + when (b) { + true -> { + println(1) + return + } + else -> { + if (b == null) { + funWithExactlyOnceCallsInPlace { + when { + c == true -> throw Exception() + else -> funWithAtMostOnceCallsInPlace { return } + } + println(3) + } + println(3) + } else { + throw Exception() + } + println(3) + } + } + println(3) + } + println(3) +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/unreachableCode/pos/7.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/unreachableCode/pos/7.fir.kt new file mode 100644 index 00000000000..307c3e2ccf5 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/unreachableCode/pos/7.fir.kt @@ -0,0 +1,32 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (POSITIVE) + * + * SECTIONS: contracts, analysis, controlFlow, unreachableCode + * NUMBER: 7 + * DESCRIPTION: Smart initialization with correspond contract function with default value before lambda. + * ISSUES: KT-26444 + */ + +// FILE: contracts.kt + +package contracts + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(x: Double = 1.0, block: () -> Unit): Double { + contract { callsInPlace(block, InvocationKind.AT_LEAST_ONCE) } + return x +} + +// FILE: main.kt + +import contracts.* + +// TESTCASE NUMBER: 1 +fun case_1() { + contracts.case_1 { throw Exception() } + println(1) +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/1.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/1.fir.kt new file mode 100644 index 00000000000..bf2b762ffe7 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/1.fir.kt @@ -0,0 +1,105 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts +// !WITH_NEW_INFERENCE +// SKIP_TXT + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, analysis, smartcasts + * NUMBER: 1 + * DESCRIPTION: Smartcasts using Returns effects with simple type checking, not-null conditions and custom condition (condition for smartcast outside contract). + * HELPERS: contractFunctions + */ + +// TESTCASE NUMBER: 1 +fun case_1(value_1: Any?) { + funWithReturns(value_1 !is String) + println(value_1.length) +} + +// TESTCASE NUMBER: 2 +fun case_2(value_1: Int?) { + funWithReturnsAndInvertCondition(value_1 != null) + println(value_1.inc()) +} + +// TESTCASE NUMBER: 3 +fun case_3(value_1: Int?) { + funWithReturns(value_1 == null) + println(value_1.inc()) +} + +// TESTCASE NUMBER: 4 +fun case_4(value_1: Any?) { + funWithReturnsAndInvertTypeCheck(value_1) + println(value_1.length) +} + +// TESTCASE NUMBER: 5 +fun case_5(value_1: String?) { + funWithReturnsAndNullCheck(value_1) + println(value_1.length) +} + +// TESTCASE NUMBER: 6 +fun case_6(value_1: String?) { + funWithReturnsAndNullCheck(value_1) + println(value_1.length) +} + +// TESTCASE NUMBER: 7 +object case_7_object { + val prop_1: Int? = 10 +} +fun case_7() { + funWithReturns(case_7_object.prop_1 == null) + case_7_object.prop_1.inc() +} + +// TESTCASE NUMBER: 8 +fun case_8(value_1: Any?) { + if (!funWithReturnsTrue(value_1 is String)) println(value_1.length) + if (!funWithReturnsTrueAndInvertCondition(value_1 !is String)) println(value_1.length) + if (funWithReturnsFalse(value_1 is String)) println(value_1.length) + if (funWithReturnsFalseAndInvertCondition(value_1 !is String)) println(value_1.length) + if (funWithReturnsNotNull(value_1 is String) == null) println(value_1.length) + if (!(funWithReturnsNotNull(value_1 is String) != null)) println(value_1.length) + if (!(funWithReturnsNull(value_1 is String) == null)) println(value_1.length) + if (funWithReturnsNull(value_1 is String) != null) println(value_1.length) +} + +// TESTCASE NUMBER: 9 +fun case_9(value_1: String?) { + if (!funWithReturnsTrue(value_1 != null)) println(value_1.length) + if (!funWithReturnsTrueAndInvertCondition(value_1 == null)) println(value_1.length) + if (funWithReturnsFalse(value_1 != null)) println(value_1.length) + if (funWithReturnsFalseAndInvertCondition(value_1 == null)) println(value_1.length) + if (funWithReturnsNotNull(value_1 != null) == null) println(value_1.length) + if (funWithReturnsNotNullAndInvertCondition(value_1 == null) == null) println(value_1.length) + if (funWithReturnsNull(value_1 != null) != null) println(value_1.length) + if (funWithReturnsNullAndInvertCondition(value_1 == null) != null) println(value_1.length) +} + +// TESTCASE NUMBER: 10 +fun case_10(value_1: Any?) { + if (!funWithReturnsTrueAndTypeCheck(value_1)) println(value_1.length) + if (!!funWithReturnsFalseAndTypeCheck(value_1)) println(value_1.length) + if (!(funWithReturnsNotNullAndTypeCheck(value_1) != null)) println(value_1.length) + if (!!(funWithReturnsNotNullAndTypeCheck(value_1) == null)) println(value_1.length) + if (!!(funWithReturnsNullAndTypeCheck(value_1) != null)) println(value_1.length) + if (!(funWithReturnsNullAndTypeCheck(value_1) == null)) println(value_1.length) +} + +// TESTCASE NUMBER: 11 +fun case_11(value_1: Number?) { + if (!funWithReturnsTrueAndNotNullCheck(value_1)) println(value_1.toByte()) + if (!funWithReturnsTrueAndNullCheck(value_1)) println(value_1) + if (funWithReturnsFalseAndNotNullCheck(value_1)) println(value_1.toByte()) + if (funWithReturnsFalseAndNullCheck(value_1)) println(value_1) + if ((funWithReturnsNotNullAndNotNullCheck(value_1) == null)) println(value_1.toByte()) + if (!!!(funWithReturnsNotNullAndNotNullCheck(value_1) != null)) println(value_1.toByte()) + if (!!(funWithReturnsNotNullAndNullCheck(value_1) == null)) println(value_1) + if (!(funWithReturnsNullAndNotNullCheck(value_1) == null)) println(value_1.toByte()) + if (!!(funWithReturnsNullAndNotNullCheck(value_1) != null)) println(value_1.toByte()) + if (!!!(funWithReturnsNullAndNullCheck(value_1) == null)) println(value_1) +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/10.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/10.fir.kt new file mode 100644 index 00000000000..00f8921d0fc --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/10.fir.kt @@ -0,0 +1,533 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts +// !WITH_NEW_INFERENCE + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, analysis, smartcasts + * NUMBER: 10 + * DESCRIPTION: Check smartcasts using double negation (returnsFalse/invert type checking/not operator). + * ISSUES: KT-26176 + * HELPERS: contractFunctions + */ + +// FILE: contracts.kt + +package contracts + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(x: Any?): Boolean { + contract { returns(true) implies (x !is Number) } + return x !is Number +} + +// TESTCASE NUMBER: 2 +fun case_2(x: Any?): Boolean { + contract { returns(true) implies (x !is Number?) } + return x !is Number? +} + +// TESTCASE NUMBER: 15 +fun case_15_1(value_1: Any?, value_2: Any?): Boolean { + contract { returns(true) implies (value_1 !is String || value_2 !is Number) } + return value_1 !is String || value_2 !is Number +} +fun case_15_2(value_1: Any?, value_2: Any?): Boolean { + contract { returns(false) implies (value_1 !is String || value_2 !is Number) } + return !(value_1 !is String || value_2 !is Number) +} +fun case_15_3(value_1: Any?, value_2: Any?): Boolean? { + contract { returnsNotNull() implies (value_1 !is String || value_2 !is Number) } + return if (value_1 !is String || value_2 !is Number) true else null +} +fun case_15_4(value_1: Any?, value_2: Any?): Boolean? { + contract { returns(null) implies (value_1 !is String || value_2 !is Number) } + return if (value_1 !is String || value_2 !is Number) null else true +} + +// TESTCASE NUMBER: 16 +fun case_16_1(value_1: Any?, value_2: Any?): Boolean { + contract { returns(true) implies (value_1 !is String || value_2 != null) } + return value_1 !is String || value_2 != null +} +fun case_16_2(value_1: Any?, value_2: Any?): Boolean { + contract { returns(false) implies (value_1 !is String || value_2 != null) } + return !(value_1 !is String || value_2 != null) +} +fun case_16_3(value_1: Any?, value_2: Any?): Boolean? { + contract { returnsNotNull() implies (value_1 !is String || value_2 != null) } + return if (value_1 !is String || value_2 != null) true else null +} +fun case_16_4(value_1: Any?, value_2: Any?): Boolean? { + contract { returns(null) implies (value_1 !is String || value_2 != null) } + return if (value_1 !is String || value_2 != null) null else true +} + +// TESTCASE NUMBER: 17 +fun case_17_1(value_1: Any?, value_2: Any?, value_3: Any?, value_4: Any?): Boolean { + contract { returns(true) implies (value_1 !is Float? || value_1 == null || value_2 == null || value_3 == null || value_4 == null) } + return value_1 !is Float? || value_1 == null || value_2 == null || value_3 == null || value_4 == null +} +fun case_17_2(value_1: Any?, value_2: Any?, value_3: Any?, value_4: Any?): Boolean { + contract { returns(false) implies (value_1 !is Float? || value_1 == null || value_2 == null || value_3 == null || value_4 == null) } + return !(value_1 !is Float? || value_1 == null || value_2 == null || value_3 == null || value_4 == null) +} +fun case_17_3(value_1: Any?, value_2: Any?, value_3: Any?, value_4: Any?): Boolean? { + contract { returnsNotNull() implies (value_1 !is Float? || value_1 == null || value_2 == null || value_3 == null || value_4 == null) } + return if (value_1 !is Float? || value_1 == null || value_2 == null || value_3 == null || value_4 == null) true else null +} +fun case_17_4(value_1: Any?, value_2: Any?, value_3: Any?, value_4: Any?): Boolean? { + contract { returns(null) implies (value_1 !is Float? || value_1 == null || value_2 == null || value_3 == null || value_4 == null) } + return if (value_1 !is Float? || value_1 == null || value_2 == null || value_3 == null || value_4 == null) null else true +} + +// TESTCASE NUMBER: 18 +fun T.case_18_1(): Boolean { + contract { returns(true) implies (this@case_18_1 !is String) } + return this@case_18_1 !is String +} +fun T.case_18_2(): Boolean { + contract { returns(false) implies (this@case_18_2 is String) } + return !(this@case_18_2 is String) +} +fun T.case_18_3(): Boolean? { + contract { returnsNotNull() implies (this@case_18_3 is String) } + return if (this@case_18_3 is String) true else null +} +fun T.case_18_4(): Boolean? { + contract { returns(null) implies (this@case_18_4 is String) } + return if (this@case_18_4 is String) null else true +} + +// TESTCASE NUMBER: 19 +fun T.case_19_1(): Boolean { + contract { returns(true) implies (this@case_19_1 !is Int) } + return this@case_19_1 !is Int +} +fun T.case_19_2(): Boolean { + contract { returns(false) implies (this@case_19_2 is Int) } + return !(this@case_19_2 is Int) +} +fun T.case_19_3(): Boolean? { + contract { returnsNotNull() implies (this@case_19_3 is Int) } + return if (this@case_19_3 is Int) true else null +} +fun T.case_19_4(): Boolean? { + contract { returns(null) implies (this@case_19_4 is Int) } + return if (this@case_19_4 is Int) null else true +} + +// TESTCASE NUMBER: 20 +fun T?.case_20_1(): Boolean { + contract { returns(true) implies (this@case_20_1 != null) } + return this@case_20_1 != null +} +fun T?.case_20_2(): Boolean { + contract { returns(true) implies (this@case_20_2 == null) } + return this@case_20_2 == null +} +fun T?.case_20_3(): Boolean { + contract { returns(false) implies (this@case_20_3 != null) } + return !(this@case_20_3 != null) +} + +// TESTCASE NUMBER: 21 +fun T.case_21_1(): Boolean { + contract { returns(true) implies (this@case_21_1 != null) } + return this@case_21_1 != null +} +fun T.case_21_2(): Boolean { + contract { returns(true) implies (this@case_21_2 == null) } + return this@case_21_2 == null +} +fun T?.case_21_5(): Boolean? { + contract { returnsNotNull() implies (this@case_21_5 != null) } + return if (this@case_21_5 != null) true else null +} +fun T?.case_21_7(): Boolean? { + contract { returns(null) implies (this@case_21_7 != null) } + return if (this@case_21_7 != null) null else true +} + +// TESTCASE NUMBER: 22 +fun T?.case_22_1(): Boolean { + contract { returns(false) implies (this@case_22_1 == null || this@case_22_1 !is String) } + return !(this@case_22_1 == null || this@case_22_1 !is String) +} +fun T?.case_22_2(): Boolean? { + contract { returnsNotNull() implies (this@case_22_2 == null || this@case_22_2 !is String) } + return if (this@case_22_2 == null || this@case_22_2 !is String) true else null +} +fun T?.case_22_3(): Boolean? { + contract { returns(null) implies (this@case_22_3 == null || this@case_22_3 !is String) } + return if (this@case_22_3 == null || this@case_22_3 !is String) null else true +} + +// TESTCASE NUMBER: 23 +fun T.case_23_1(): Boolean { + contract { returns(false) implies (this@case_23_1 !is Int || this@case_23_1 == null) } + return !(this@case_23_1 !is Int || this@case_23_1 == null) +} +fun T.case_23_2(): Boolean? { + contract { returnsNotNull() implies (this@case_23_2 !is Int || this@case_23_2 == null) } + return if (this@case_23_2 !is Int || this@case_23_2 == null) true else null +} +fun T.case_23_3(): Boolean? { + contract { returns(null) implies (this@case_23_3 !is Int || this@case_23_3 == null) } + return if (this@case_23_3 !is Int || this@case_23_3 == null) null else true +} + +// TESTCASE NUMBER: 24 +inline fun T?.case_24_1(): Boolean { + contract { returns(false) implies (this@case_24_1 !is Number || this@case_24_1 !is Int || this@case_24_1 == null) } + return !(this@case_24_1 !is Number || this@case_24_1 !is Int || this@case_24_1 == null) +} +inline fun T?.case_24_2(): Boolean? { + contract { returnsNotNull() implies (this@case_24_2 !is Number || this@case_24_2 !is Int || this@case_24_2 == null) } + return if (this@case_24_2 !is Number || this@case_24_2 !is Int || this@case_24_2 == null) true else null +} +inline fun T?.case_24_3(): Boolean? { + contract { returns(null) implies (this@case_24_3 !is Number || this@case_24_3 !is Int || this@case_24_3 == null) } + return if (this@case_24_3 !is Number || this@case_24_3 !is Int || this@case_24_3 == null) null else true +} + +// TESTCASE NUMBER: 25 +fun T?.case_25_1(value_1: Int?): Boolean { + contract { returns(false) implies (this@case_25_1 == null || this@case_25_1 !is String || value_1 == null) } + return !(this@case_25_1 == null || this@case_25_1 !is String || value_1 == null) +} +fun T?.case_25_2(value_1: Int?): Boolean? { + contract { returnsNotNull() implies (this@case_25_2 == null || this@case_25_2 !is String || value_1 == null) } + return if (this@case_25_2 == null || this@case_25_2 !is String || value_1 == null) true else null +} +fun T?.case_25_3(value_1: Int?): Boolean? { + contract { returns(null) implies (this@case_25_3 == null || this@case_25_3 !is String || value_1 == null) } + return if (this@case_25_3 == null || this@case_25_3 !is String || value_1 == null) null else true +} + +// FILE: main.kt + +import contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(value_1: Any?) { + if (!contracts.case_1(value_1)) println(value_1.toByte()) +} + +// TESTCASE NUMBER: 2 +fun case_2(value_1: Any?) { + if (!contracts.case_2(value_1)) println(value_1?.toByte()) +} + +// TESTCASE NUMBER: 3 +fun case_3(number: Int?) { + if (!funWithReturnsTrueAndNullCheck(number)) number.inc() +} + +// TESTCASE NUMBER: 4 +fun case_4(value_1: Any?) { + if (!funWithReturnsTrue(value_1 !is String)) println(value_1.length) +} + +// TESTCASE NUMBER: 5 +fun case_5(value_1: Any?) { + if (!funWithReturnsTrueAndInvertCondition(value_1 is String)) println(value_1.length) + if (funWithReturnsFalse(value_1 !is String)) println(value_1.length) + if (funWithReturnsFalseAndInvertCondition(value_1 is String)) println(value_1.length) + if (!(funWithReturnsNotNullAndInvertCondition(value_1 !is String) != null)) println(value_1.length) + if (!(funWithReturnsNullAndInvertCondition(value_1 !is String) == null)) println(value_1.length) +} + +// TESTCASE NUMBER: 6 +fun case_6(value_1: Any?) { + if (!funWithReturnsTrue(value_1 == null)) println(value_1.length) +} + +// TESTCASE NUMBER: 7 +fun case_7(value_1: Any?) { + if (!funWithReturnsTrueAndInvertCondition(value_1 != null)) println(value_1.length) + if (funWithReturnsFalse(value_1 == null)) println(value_1.length) + if (funWithReturnsFalseAndInvertCondition(value_1 != null)) println(value_1.length) +} + +// TESTCASE NUMBER: 8 +fun case_8(value_1: Any?) { + if (!funWithReturnsTrueAndInvertTypeCheck(value_1)) println(value_1.length) + if (funWithReturnsFalseAndInvertTypeCheck(value_1)) println(value_1.length) +} + +// TESTCASE NUMBER: 9 +fun case_9(value_1: Number?) { + if (!funWithReturnsTrueAndNullCheck(value_1)) println(value_1.toByte()) + if (funWithReturnsFalseAndNullCheck(value_1)) println(value_1.toByte()) + if (funWithReturnsFalseAndNotNullCheck(value_1)) println(value_1) + if (!(funWithReturnsNotNullAndNullCheck(value_1) != null)) println(value_1) + if (!(funWithReturnsNullAndNullCheck(value_1) == null)) println(value_1) +} + +// TESTCASE NUMBER: 10 +fun case_10(value_1: Any?, value_2: Any?) { + if (!funWithReturnsTrueAndInvertCondition(value_1 is String && value_2 is Number)) { + println(value_1.length) + println(value_2.toByte()) + } +} + +// TESTCASE NUMBER: 11 +fun case_11(value_1: Any?, value_2: Any?) { + if (!funWithReturnsTrue(value_1 !is String || value_2 !is Number)) { + println(value_1.length) + println(value_2.toByte()) + } + if (funWithReturnsFalse(value_1 !is String || value_2 !is Number)) { + println(value_1.length) + println(value_2.toByte()) + } +} + +// TESTCASE NUMBER: 12 +fun case_12(value_1: Any?, value_2: Any?) { + if (!funWithReturnsTrue(value_1 !is String || value_2 != null)) { + println(value_1.length) + println(value_2?.toByte()) + } + if (funWithReturnsFalse(value_1 !is Float? || value_1 == null || value_2 == null)) { + println(value_1.dec()) + println(value_2?.toByte()) + } + if (funWithReturnsNotNull(value_1 !is String || value_2 !is Number) == null) { + println(value_1.length) + println(value_2.toByte()) + } + if (funWithReturnsNull(value_1 !is String || value_2 !is Number) != null) { + println(value_1.length) + println(value_2.toByte()) + } +} + +// TESTCASE NUMBER: 13 +fun case_13(value_1: Any?, value_2: Any?) { + if (!funWithReturnsTrueAndInvertCondition(value_1 is Float? && value_1 != null && value_2 != null)) { + println(value_1.dec()) + println(value_2?.toByte()) + } + if (funWithReturnsFalseAndInvertCondition(value_1 is String && value_2 is Number)) { + println(value_1.length) + println(value_2.toByte()) + } + if (funWithReturnsFalseAndInvertCondition(value_1 is String && value_2 == null)) { + println(value_1.length) + println(value_2?.toByte()) + } + if (funWithReturnsNotNullAndInvertCondition(value_1 is String && value_2 is Number) == null) { + println(value_1.length) + println(value_2.toByte()) + } + if (funWithReturnsNotNullAndInvertCondition(value_1 is String && value_2 == null) == null) { + println(value_1.length) + println(value_2?.toByte()) + } + if (funWithReturnsNotNull(value_1 is Float? && value_1 != null && value_2 != null) == null) { + println(value_1.dec()) + println(value_2?.toByte()) + } + if (funWithReturnsNullAndInvertCondition(value_1 is String && value_2 is Number) != null) { + println(value_1.length) + println(value_2.toByte()) + } + if (funWithReturnsNullAndInvertCondition(value_1 is String && value_2 == null) != null) { + println(value_1.length) + println(value_2?.toByte()) + } + if (funWithReturnsNull(value_1 is Float? && value_1 != null && value_2 != null) != null) { + println(value_1.dec()) + println(value_2?.toByte()) + } +} + +// TESTCASE NUMBER: 14 +class case_14_class { + val prop_1: Int? = 10 + + fun case_14(value_1: Any?, value_2: Number?) { + val o = case_14_class() + if (!funWithReturnsTrueAndInvertCondition(value_1 is Float? && value_1 != null && value_2 != null && o.prop_1 != null)) { + println(value_1.dec()) + println(value_2?.toByte()) + println(o.prop_1.plus(3)) + } + if (funWithReturnsFalse(value_1 !is Float? || value_1 == null || value_2 == null || o.prop_1 == null || this.prop_1 == null)) { + println(value_1.dec()) + println(value_2?.toByte()) + println(o.prop_1.plus(3)) + } + if (funWithReturnsNotNull(value_1 !is Float? || value_1 == null || value_2 == null || o.prop_1 == null || this.prop_1 == null) == null) { + println(value_1.dec()) + println(value_2?.toByte()) + println(o.prop_1.plus(3)) + } + if (funWithReturnsNull(value_1 !is Float? || value_1 == null || value_2 == null || o.prop_1 == null || this.prop_1 == null) != null) { + println(value_1.dec()) + println(value_2?.toByte()) + println(o.prop_1.plus(3)) + } + } +} + +// TESTCASE NUMBER: 15 +fun case_15(value_1: Any?, value_2: Any?) { + if (!contracts.case_15_1(value_1, value_2)) { + println(value_1.length) + println(value_2.toByte()) + } + if (contracts.case_15_2(value_1, value_2)) { + println(value_1.length) + println(value_2.toByte()) + } + if (!(contracts.case_15_3(value_1, value_2) != null)) { + println(value_1.length) + println(value_2.toByte()) + } + if (!(contracts.case_15_4(value_1, value_2) == null)) { + println(value_1.length) + println(value_2.toByte()) + } +} + +// TESTCASE NUMBER: 16 +fun case_16(value_1: Any?, value_2: Any?) { + if (!contracts.case_16_1(value_1, value_2)) { + println(value_1.length) + println(value_2?.toByte()) + } + if (contracts.case_16_2(value_1, value_2)) { + println(value_1.length) + println(value_2?.toByte()) + } + if (contracts.case_16_3(value_1, value_2) == null) { + println(value_1.length) + println(value_2?.toByte()) + } + if (contracts.case_16_4(value_1, value_2) != null) { + println(value_1.length) + println(value_2?.toByte()) + } +} + +// TESTCASE NUMBER: 17 +class case_17_class { + val prop_1: Int? = 10 + + fun case_17(value_1: Any?, value_2: Number?) { + val o = case_17_class() + if (contracts.case_17_1(value_1, value_2, o.prop_1, this.prop_1)) { + println(value_1.dec()) + println(value_2?.toByte()) + println(o.prop_1.plus(3)) + println(this.prop_1.plus(3)) + } + if (contracts.case_17_2(value_1, value_2, o.prop_1, this.prop_1)) { + println(value_1.dec()) + println(value_2?.toByte()) + println(o.prop_1.plus(3)) + println(this.prop_1.plus(3)) + } + if (contracts.case_17_3(value_1, value_2, o.prop_1, this.prop_1) == null) { + println(value_1.dec()) + println(value_2?.toByte()) + println(o.prop_1.plus(3)) + println(this.prop_1.plus(3)) + } + if (contracts.case_17_4(value_1, value_2, o.prop_1, this.prop_1) != null) { + println(value_1.dec()) + println(value_2?.toByte()) + println(o.prop_1.plus(3)) + println(this.prop_1.plus(3)) + } + } +} + +// TESTCASE NUMBER: 18 +fun case_18(value_1: Any?) { + if (!value_1.case_18_1()) println(value_1.length) + if (value_1.case_18_2()) println(value_1.length) + if (value_1.case_18_3() == null) println(value_1.length) + if (value_1.case_18_4() != null) println(value_1.length) +} + +// TESTCASE NUMBER: 19 +fun case_19(value_1: Number) { + when { !value_1.case_19_1() -> println(value_1.inv()) } + when { value_1.case_19_2() -> println(value_1.inv()) } + when { value_1.case_19_3() == null -> println(value_1.inv()) } + when { value_1.case_19_4() != null -> println(value_1.inv()) } +} + +// TESTCASE NUMBER: 20 +fun case_20(value_1: String?, value_2: String?, value_3: String?, value_4: String?) { + if (!value_1.case_20_1()) println(value_1) + if (!value_2.case_20_2()) println(value_2.length) + when (value_3.case_20_3()) { + true -> println(value_4.length) + false -> println(value_3) + } +} + +// TESTCASE NUMBER: 21 +fun case_21(value_1: String?) { + when { !value_1.case_21_1() -> println(value_1) } + when { !value_1.case_21_2() -> println(value_1.length) } + when { + value_1.case_21_5() == null -> println(value_1.length) + value_1.case_21_5() != null -> println(value_1) + } + when { + value_1.case_21_7() != null -> println(value_1.length) + value_1.case_21_7() == null -> println(value_1) + } +} + +// TESTCASE NUMBER: 22 +fun case_22(value_1: Any?, value_2: Any?) { + when { value_1.case_22_1() -> println(value_1.length) } + when { value_2.case_22_2() == null -> println(value_2.length) } + when { value_2.case_22_3() != null -> println(value_2.length) } +} + +// TESTCASE NUMBER: 23 +fun case_23(value_1: Number?, value_2: Number?) { + if (value_1.case_23_1()) println(value_1.inv()) + if (value_2.case_23_2() == null) println(value_2.inv()) + if (value_2.case_23_3() != null) println(value_2.inv()) +} + +// TESTCASE NUMBER: 24 +fun case_24(value_1: Any?, value_2: Any?) { + if (value_1.case_24_1()) println(value_1.inv()) + if (value_2.case_24_2() != null) println(value_2.inv()) + if (value_2.case_24_3() == null) println(value_2.inv()) +} + +// TESTCASE NUMBER: 25 +fun case_25(value_1: Any?, value_2: Int?, value_3: Any?, value_4: Int?) { + when { + value_1.case_25_1(value_2) -> { + println(value_1.length) + println(value_2.inv()) + } + } + when { + value_3.case_25_2(value_4) == null -> { + println(value_3.length) + println(value_4.inv()) + } + } + when { + value_3.case_25_3(value_4) != null -> { + println(value_3.length) + println(value_4.inv()) + } + } +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/11.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/11.fir.kt new file mode 100644 index 00000000000..df1d8e61a18 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/11.fir.kt @@ -0,0 +1,57 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, analysis, smartcasts + * NUMBER: 11 + * DESCRIPTION: Smartcast using many of the various Returns effects on the same values. + * HELPERS: contractFunctions + */ + +// FILE: contracts.kt + +package contracts + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +fun T?.case_1_1(): Boolean { + contract { returns(false) implies (this@case_1_1 != null) } + return !(this@case_1_1 != null) +} +fun T?.case_1_2(): Boolean? { + contract { returns(null) implies (this@case_1_2 is String) } + return if (this@case_1_2 is String) null else true +} + +// TESTCASE NUMBER: 2 +fun T.case_2_1(): Boolean? { + contract { returnsNotNull() implies (this@case_2_1 != null) } + return if (this@case_2_1 != null) true else null +} +fun T.case_2_2(): Boolean? { + contract { returns(null) implies (this@case_2_2 != null) } + return if (this@case_2_2 != null) null else true +} + +// FILE: main.kt + +import contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(value_1: Any?) { + if (!(value_1.case_1_1() || value_1.case_1_2() == null)) { + println(value_1.length) + } +} + +/* + * TESTCASE NUMBER: 2 + * DISCUSSION: maybe make the code unreachable in the second condition? + * UNEXPECTED BEHAVIOUR + */ +fun case_2(value_1: Number?) { + if (value_1?.case_2_1() != null) println(value_1.toByte()) + if (value_1?.case_2_2() != null) println(value_1.toByte()) +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/12.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/12.fir.kt new file mode 100644 index 00000000000..2d4868b0be4 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/12.fir.kt @@ -0,0 +1,45 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, analysis, smartcasts + * NUMBER: 12 + * DESCRIPTION: Check smartcast to upper bound of the types in disjunction. + * UNEXPECTED BEHAVIOUR + * ISSUES: KT-1982 + */ + +// FILE: contracts.kt + +package contracts + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +fun T?.case_1() { + contract { returns() implies (this@case_1 is Number || this@case_1 is Int) } + if (!(this@case_1 is Number || this@case_1 is Int)) throw Exception() +} + +// TESTCASE NUMBER: 2 +inline fun T?.case_2(value_2: Number, value_3: Any?, value_4: String?) { + contract { returns() implies ((this@case_2 is Number || this@case_2 is Int) && value_2 is Int && value_3 != null && value_3 is Number && value_4 != null) } + if (!((this is Number || this is Int) && value_2 is Int && value_3 != null && value_3 is Number && value_4 != null)) throw Exception() +} + +// FILE: main.kt + +import contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(value_1: Any?) { + value_1.case_1() + println(value_1.toByte()) +} + +// TESTCASE NUMBER: 2 +fun case_2(value_1: Any?, value_2: Number, value_3: Any?, value_4: String?) { + value_1.case_2(value_2, value_3, value_4) + println(value_1.toByte()) +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/13.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/13.fir.kt new file mode 100644 index 00000000000..3fdb9ff3278 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/13.fir.kt @@ -0,0 +1,58 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, analysis, smartcasts + * NUMBER: 13 + * DESCRIPTION: Smartcast using many of the various Returns effects on the same values. + * HELPERS: contractFunctions + */ + +// FILE: contracts.kt + +package contracts + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +fun T?.case_1_1(): Boolean { + contract { returns(false) implies (this@case_1_1 != null) } + return !(this@case_1_1 != null) +} +fun T?.case_1_2(): Boolean? { + contract { returns(null) implies (this@case_1_2 is String) } + return if (this@case_1_2 is String) null else true +} + +// TESTCASE NUMBER: 2 +fun T?.case_2_1(): Boolean { + contract { returns(true) implies (this@case_2_1 is Float) } + return this@case_2_1 is Float +} +fun T?.case_2_2(): Boolean { + contract { returns(false) implies (this@case_2_2 is Double) } + return !(this@case_2_2 is Double) +} + +// FILE: main.kt + +import contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(value_1: Any?) { + if (!(value_1.case_1_1() || value_1.case_1_2() == null)) { + println(value_1.length) + } +} + +/* + * TESTCASE NUMBER: 2 + * UNEXPECTED BEHAVIOUR + * ISSUES: KT-1982 + */ +fun case_2(value_1: Any?) { + if (value_1.case_2_1() || !value_1.case_2_2()) { + println(value_1.toByte()) + } +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/14.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/14.fir.kt new file mode 100644 index 00000000000..4537a17f544 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/14.fir.kt @@ -0,0 +1,58 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, analysis, smartcasts + * NUMBER: 14 + * DESCRIPTION: Smartcast using many of the various Returns effects on the same values. + * HELPERS: contractFunctions + */ + +// FILE: contracts.kt + +package contracts + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +fun T?.case_1_1(): Boolean { + contract { returns(false) implies (this@case_1_1 != null) } + return !(this@case_1_1 != null) +} +fun T?.case_1_2(): Boolean? { + contract { returns(null) implies (this@case_1_2 is String) } + return if (this@case_1_2 is String) null else true +} + +// TESTCASE NUMBER: 2 +fun T?.case_2_1(): Boolean { + contract { returns(true) implies (this@case_2_1 is Float) } + return this@case_2_1 is Float +} +fun T?.case_2_2(): Boolean { + contract { returns(false) implies (this@case_2_2 is Double) } + return !(this@case_2_2 is Double) +} + +// FILE: main.kt + +import contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(value_1: Any?) { + if (!(value_1.case_1_1() || value_1.case_1_2() == null)) { + println(value_1.length) + } +} + +/* + * TESTCASE NUMBER: 2 + * UNEXPECTED BEHAVIOUR + * ISSUES: KT-1982 + */ +fun case_2(value_1: Any?) { + if (value_1.case_2_1() || !value_1.case_2_2()) { + println(value_1.toByte()) + } +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/15.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/15.fir.kt new file mode 100644 index 00000000000..959e1a77f56 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/15.fir.kt @@ -0,0 +1,59 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts +// !WITH_NEW_INFERENCE + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, analysis, smartcasts + * NUMBER: 15 + * DESCRIPTION: Check smartcasts working if type checking for contract function is used + * ISSUES: KT-27241 + * HELPERS: contractFunctions + */ + +// FILE: contracts.kt + +package contracts + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +fun case_1_1(cond: Boolean): Any { + contract { returns(true) implies cond } + return cond +} +fun case_1_2(value: Any): Boolean { + contract { returns(true) implies (value is Boolean) } + return value is Boolean +} + +// TESTCASE NUMBER: 2 +fun case_2(cond: Boolean): Any { + contract { returns(true) implies cond } + return cond +} + +// FILE: main.kt + +import contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(value: Any) { + if (contracts.case_1_2(contracts.case_1_1(value is Char))) { + println(value.category) + } +} + +// TESTCASE NUMBER: 2 +fun case_2(value: Any) { + if (contracts.case_2(value is Char) is Boolean) { + println(value.category) + } +} + +// TESTCASE NUMBER: 3 +fun case_3(value: String?) { + if (!value.isNullOrEmpty() is Boolean) { + value.length + } +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/2.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/2.fir.kt new file mode 100644 index 00000000000..802716a7f07 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/2.fir.kt @@ -0,0 +1,169 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts +// !WITH_NEW_INFERENCE +// SKIP_TXT + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, analysis, smartcasts + * NUMBER: 2 + * DESCRIPTION: Smartcasts using Returns effects with complex (conjunction/disjunction) type checking and not-null conditions outside contract (custom condition). + * HELPERS: contractFunctions + */ + +// TESTCASE NUMBER: 1 +fun case_1(value_1: Any?, value_2: Any?) { + funWithReturns(value_1 !is String || value_2 !is Number) + println(value_1.length) + println(value_2.toByte()) +} + +// TESTCASE NUMBER: 2 +fun case_2(value_1: Any?, value_2: Any?) { + funWithReturnsAndInvertCondition(value_1 is String && value_2 is Number) + println(value_1.length) + println(value_2.toByte()) +} + +// TESTCASE NUMBER: 3 +fun case_3(value_1: Any?, value_2: Any?) { + funWithReturnsAndInvertCondition(value_1 is String && value_2 == null) + println(value_1.length) + println(value_2?.toByte()) +} + +// TESTCASE NUMBER: 4 +fun case_4(value_1: Any?, value_2: Number?) { + funWithReturns(value_1 !is Float? || value_1 == null || value_2 == null) + println(value_1.dec()) + println(value_2?.toByte()) +} + +// TESTCASE NUMBER: 5 +class case_5_class { + val prop_1: Int? = 10 + fun case_5(value_1: Any?, value_2: Number?) { + val o = case_5_class() + funWithReturns(value_1 !is Float? || value_1 == null || value_2 == null || o.prop_1 == null) + println(value_1.dec()) + println(value_2?.toByte()) + println(o.prop_1.plus(3)) + } +} + +// TESTCASE NUMBER: 6 +fun case_6(value_1: Any?, value_2: Any) { + if (funWithReturnsTrue(value_1 !is String || value_2 !is Number)) { + println(value_1.length) + println(value_2.toByte()) + } + if (!funWithReturnsFalse(value_1 !is String || value_2 !is Number)) { + println(value_1.length) + println(value_2.toByte()) + } + if (funWithReturnsNotNull(value_1 !is String || value_2 !is Number) != null) { + println(value_1.length) + println(value_2.toByte()) + } + if (funWithReturnsNull(value_1 !is String || value_2 !is Number) == null) { + println(value_1.length) + println(value_2.toByte()) + } +} + +// TESTCASE NUMBER: 7 +fun case_7(value_1: Any?, value_2: Any?) { + if (funWithReturnsTrueAndInvertCondition(value_1 is String && value_2 is Number)) { + println(value_1.length) + println(value_2.toByte()) + } + if (!funWithReturnsFalseAndInvertCondition(value_1 is String && value_2 is Number)) { + println(value_1.length) + println(value_2.toByte()) + } + if (funWithReturnsNotNullAndInvertCondition(value_1 is String && value_2 is Number) != null) { + println(value_1.length) + println(value_2.toByte()) + } + if (funWithReturnsNullAndInvertCondition(value_1 is String && value_2 is Number) == null) { + println(value_1.length) + println(value_2.toByte()) + } +} + +// TESTCASE NUMBER: 8 +fun case_8(value_1: Any?, value_2: Any?) { + if (funWithReturnsTrueAndInvertCondition(value_1 is String && value_2 == null)) { + println(value_1.length) + println(value_2?.toByte()) + } + if (!funWithReturnsFalseAndInvertCondition(value_1 is String && value_2 == null)) { + println(value_1.length) + println(value_2?.toByte()) + } + if (funWithReturnsNotNullAndInvertCondition(value_1 is String && value_2 == null) != null) { + println(value_1.length) + println(value_2?.toByte()) + } + if (funWithReturnsNullAndInvertCondition(value_1 is String && value_2 == null) == null) { + println(value_1.length) + println(value_2?.toByte()) + } +} + +// TESTCASE NUMBER: 9 +fun case_9(value_1: Any?, value_2: Number?) { + if (funWithReturnsTrue(value_1 !is Float? || value_1 == null || value_2 == null)) { + println(value_1.dec()) + println(value_2?.toByte()) + } + if (!funWithReturnsFalse(value_1 !is Float? || value_1 == null || value_2 == null)) { + println(value_1.dec()) + println(value_2?.toByte()) + } + if (funWithReturnsNotNull(value_1 is Float? && value_1 != null && value_2 != null) == null) { + println(value_1.dec()) + println(value_2?.toByte()) + } + if (funWithReturnsNull(value_1 is Float? && value_1 != null && value_2 != null) != null) { + println(value_1.dec()) + println(value_2?.toByte()) + } +} + +// TESTCASE NUMBER: 10 +class case_10_class { + val prop_1: Int? = 10 + + fun case_10(value_1: Any?, value_2: Number?) { + val o = case_10_class() + if (funWithReturnsTrue(value_1 !is Float? || value_1 == null || value_2 == null || o.prop_1 == null || this.prop_1 == null)) { + println(value_1.dec()) + println(value_2?.toByte()) + println(o.prop_1.plus(3)) + } + if (!funWithReturnsFalse(value_1 !is Float? || value_1 == null || value_2 == null || o.prop_1 == null || this.prop_1 == null)) { + println(value_1.dec()) + println(value_2?.toByte()) + println(o.prop_1.plus(3)) + } + if (funWithReturnsNotNull(value_1 !is Float? || value_1 == null || value_2 == null || o.prop_1 == null || this.prop_1 == null) != null) { + println(value_1.dec()) + println(value_2?.toByte()) + println(o.prop_1.plus(3)) + } + if (funWithReturnsNull(value_1 !is Float? || value_1 == null || value_2 == null || o.prop_1 == null || this.prop_1 == null) == null) { + println(value_1.dec()) + println(value_2?.toByte()) + println(o.prop_1.plus(3)) + } + } +} + +// TESTCASE NUMBER: 11 +fun case_11(value_1: Any?, value_2: Any?, value_3: Any?) { + funWithReturnsAndInvertCondition(value_1 !is String? || value_2 !is Number && value_3 !is Float) + println(value_1!!.length) + println(value_2.toByte()) + println(value_3.dec()) +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/3.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/3.fir.kt new file mode 100644 index 00000000000..796aba3859a --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/3.fir.kt @@ -0,0 +1,187 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, analysis, smartcasts + * NUMBER: 3 + * DESCRIPTION: Smartcasts using Returns effects with complex (conjunction/disjunction) type checking and not-null conditions inside contract. + */ + +// FILE: contracts.kt + +package contracts + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(value_1: Any?, value_2: Any?) { + contract { returns() implies (value_1 !is String || value_2 !is Number) } + if (!(value_1 !is String || value_2 !is Number)) throw Exception() +} + +// TESTCASE NUMBER: 2 +fun case_2(value_1: Any?, value_2: Any?) { + contract { returns() implies (value_1 !is String || value_2 != null) } + if (!(value_1 !is String || value_2 != null)) throw Exception() +} + +// TESTCASE NUMBER: 3 +fun case_3(value_1: Any?, value_2: Any?, value_3: Any?, value_4: Any?) { + contract { returns() implies (value_1 !is Float? || value_1 == null || value_2 == null || value_3 == null || value_4 == null) } + if (!(value_1 !is Float? || value_1 == null || value_2 == null || value_3 == null || value_4 == null)) throw Exception() +} + +// TESTCASE NUMBER: 4 +fun case_4_1(value_1: Any?, value_2: Any?): Boolean { + contract { returns(true) implies (value_1 !is String || value_2 !is Number) } + return value_1 !is String || value_2 !is Number +} +fun case_4_2(value_1: Any?, value_2: Any?): Boolean { + contract { returns(false) implies (value_1 !is String || value_2 !is Number) } + return !(value_1 !is String || value_2 !is Number) +} +fun case_4_3(value_1: Any?, value_2: Any?): Boolean? { + contract { returnsNotNull() implies (value_1 !is String || value_2 !is Number) } + return if (value_1 !is String || value_2 !is Number) true else null +} +fun case_4_4(value_1: Any?, value_2: Any?): Boolean? { + contract { returns(null) implies (value_1 !is String || value_2 !is Number) } + return if (value_1 !is String || value_2 !is Number) null else true +} + +// TESTCASE NUMBER: 5 +fun case_5_1(value_1: Any?, value_2: Any?): Boolean { + contract { returns(true) implies (value_1 !is String || value_2 != null) } + return value_1 !is String || value_2 != null +} +fun case_5_2(value_1: Any?, value_2: Any?): Boolean { + contract { returns(false) implies (value_1 !is String || value_2 != null) } + return !(value_1 !is String || value_2 != null) +} +fun case_5_3(value_1: Any?, value_2: Any?): Boolean? { + contract { returnsNotNull() implies (value_1 is String && value_2 == null) } + return if (value_1 is String && value_2 == null) true else null +} +fun case_5_4(value_1: Any?, value_2: Any?): Boolean? { + contract { returns(null) implies (value_1 is String && value_2 == null) } + return if (value_1 is String && value_2 == null) null else true +} + +// TESTCASE NUMBER: 6 +fun case_6_1(value_1: Any?, value_2: Any?, value_3: Any?, value_4: Any?): Boolean { + contract { returns(true) implies (value_1 !is Float? || value_1 == null || value_2 == null || value_3 == null || value_4 == null) } + return value_1 !is Float? || value_1 == null || value_2 == null || value_3 == null || value_4 == null +} +fun case_6_2(value_1: Any?, value_2: Any?, value_3: Any?, value_4: Any?): Boolean { + contract { returns(false) implies (value_1 !is Float? || value_1 == null || value_2 == null || value_3 == null || value_4 == null) } + return !(value_1 !is Float? || value_1 == null || value_2 == null || value_3 == null || value_4 == null) +} +fun case_6_3(value_1: Any?, value_2: Any?, value_3: Any?, value_4: Any?): Boolean? { + contract { returnsNotNull() implies (value_1 is Float? && value_1 != null && value_2 != null && value_3 != null && value_4 != null) } + return if (value_1 is Float? && value_1 != null && value_2 != null && value_3 != null && value_4 != null) true else null +} +fun case_6_4(value_1: Any?, value_2: Any?, value_3: Any?, value_4: Any?): Boolean? { + contract { returns(null) implies (value_1 is Float? && value_1 != null && value_2 != null && value_3 != null && value_4 != null) } + return if (value_1 is Float? && value_1 != null && value_2 != null && value_3 != null && value_4 != null) null else true +} + +// FILE: main.kt + +import contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(value_1: Any?, value_2: Any?) { + contracts.case_1(value_1, value_2) + println(value_1.length) + println(value_2.toByte()) +} + +// TESTCASE NUMBER: 2 +fun case_2(value_1: Any?, value_2: Any?) { + contracts.case_2(value_1, value_2) + println(value_1.length) + println(value_2?.toByte()) +} + +// TESTCASE NUMBER: 3 +class case_3_class { + val prop_1: Int? = 10 + + fun case_3(value_1: Any?, value_2: Number?) { + val o = case_3_class() + contracts.case_3(value_1, value_2, o.prop_1, this.prop_1) + println(value_1.dec()) + println(value_2?.toByte()) + println(o.prop_1.plus(3)) + } +} + +// TESTCASE NUMBER: 4 +fun case_4(value_1: Any?, value_2: Any?) { + if (contracts.case_4_1(value_1, value_2)) { + println(value_1.length) + println(value_2.toByte()) + } + if (!contracts.case_4_2(value_1, value_2)) { + println(value_1.length) + println(value_2.toByte()) + } + if (contracts.case_4_3(value_1, value_2) != null) { + println(value_1.length) + println(value_2.toByte()) + } + if (contracts.case_4_4(value_1, value_2) == null) { + println(value_1.length) + println(value_2.toByte()) + } +} + +// TESTCASE NUMBER: 5 +fun case_5(value_1: Any?, value_2: Any?) { + if (contracts.case_5_1(value_1, value_2)) { + println(value_1.length) + println(value_2?.toByte()) + } + if (!contracts.case_5_2(value_1, value_2)) { + println(value_1.length) + println(value_2?.toByte()) + } + if (contracts.case_5_3(value_1, value_2) == null) { + println(value_1.length) + println(value_2?.toByte()) + } + if (contracts.case_5_4(value_1, value_2) != null) { + println(value_1.length) + println(value_2?.toByte()) + } +} + +// TESTCASE NUMBER: 6 +class case_6_class { + val prop_1: Int? = 10 + + fun case_6(value_1: Any?, value_2: Number?) { + val o = case_6_class() + if (contracts.case_6_1(value_1, value_2, o.prop_1, this.prop_1)) { + println(value_1.dec()) + println(value_2?.toByte()) + println(o.prop_1.plus(3)) + } + if (!contracts.case_6_2(value_1, value_2, o.prop_1, this.prop_1)) { + println(value_1.dec()) + println(value_2?.toByte()) + println(o.prop_1.plus(3)) + } + if (contracts.case_6_3(value_1, value_2, o.prop_1, this.prop_1) == null) { + println(value_1.dec()) + println(value_2?.toByte()) + println(o.prop_1.plus(3)) + } + if (contracts.case_6_4(value_1, value_2, o.prop_1, this.prop_1) != null) { + println(value_1.dec()) + println(value_2?.toByte()) + println(o.prop_1.plus(3)) + } + } +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/4.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/4.fir.kt new file mode 100644 index 00000000000..e22836792f2 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/4.fir.kt @@ -0,0 +1,237 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts +// !WITH_NEW_INFERENCE + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, analysis, smartcasts + * NUMBER: 4 + * DESCRIPTION: Smartcasts using Returns effects with simple type checking and not-null conditions on receiver inside contract. + */ + +// FILE: contracts.kt + +package contracts + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +fun T.case_1() { + contract { returns() implies (this@case_1 !is String) } + if (!(this@case_1 !is String)) throw Exception() +} + +// TESTCASE NUMBER: 2 +fun T.case_2() { + contract { returns() implies (this@case_2 !is Int) } + if (!(this@case_2 !is Int)) throw Exception() +} + +// TESTCASE NUMBER: 3 +fun T?.case_3_1() { + contract { returns() implies (this@case_3_1 == null) } + if (!(this@case_3_1 == null)) throw Exception() +} +fun T?.case_3_2() { + contract { returns() implies (this@case_3_2 != null) } + if (!(this@case_3_2 != null)) throw Exception() +} + +// TESTCASE NUMBER: 4 +fun T.case_4_1() { + contract { returns() implies (this@case_4_1 == null) } + if (!(this@case_4_1 == null)) throw Exception() +} +fun T.case_4_2() { + contract { returns() implies (this@case_4_2 != null) } + if (!(this@case_4_2 != null)) throw Exception() +} + +// TESTCASE NUMBER: 5 +fun T.case_5_1(): Boolean { + contract { returns(true) implies (this@case_5_1 !is String) } + return this@case_5_1 !is String +} +fun T.case_5_2(): Boolean { + contract { returns(false) implies (this@case_5_2 !is String) } + return !(this@case_5_2 !is String) +} +fun T.case_5_3(): Boolean? { + contract { returnsNotNull() implies (this@case_5_3 !is String) } + return if (this@case_5_3 !is String) true else null +} +fun T.case_5_4(): Boolean? { + contract { returns(null) implies (this@case_5_4 !is String) } + return if (this@case_5_4 !is String) null else true +} + +// TESTCASE NUMBER: 6 +fun T.case_6_1(): Boolean { + contract { returns(true) implies (this@case_6_1 !is Int) } + return this@case_6_1 !is Int +} +fun T.case_6_2(): Boolean { + contract { returns(false) implies (this@case_6_2 !is Int) } + return !(this@case_6_2 !is Int) +} +fun T.case_6_3(): Boolean? { + contract { returnsNotNull() implies (this@case_6_3 !is Int) } + return if (this@case_6_3 !is Int) true else null +} +fun T.case_6_4(): Boolean? { + contract { returns(null) implies (this@case_6_4 !is Int) } + return if (this@case_6_4 !is Int) null else true +} + +// TESTCASE NUMBER: 7 +fun T?.case_7_1(): Boolean { + contract { returns(true) implies (this@case_7_1 == null) } + return this@case_7_1 == null +} +fun T?.case_7_2(): Boolean { + contract { returns(false) implies (this@case_7_2 != null) } + return !(this@case_7_2 != null) +} +fun T?.case_7_3(): Boolean? { + contract { returnsNotNull() implies (this@case_7_3 != null) } + return if (this@case_7_3 != null) true else null +} +fun T?.case_7_4(): Boolean? { + contract { returns(null) implies (this@case_7_4 != null) } + return if (this@case_7_4 != null) null else true +} + +// TESTCASE NUMBER: 8 +fun T.case_8_1(): Boolean { + contract { returns(true) implies (this@case_8_1 == null) } + return this@case_8_1 == null +} +fun T.case_8_2(): Boolean { + contract { returns(false) implies (this@case_8_2 != null) } + return !(this@case_8_2 != null) +} +fun T.case_8_3(): Boolean? { + contract { returnsNotNull() implies (this@case_8_3 != null) } + return if (this@case_8_3 != null) true else null +} +fun T.case_8_4(): Boolean? { + contract { returns(null) implies (this@case_8_4 != null) } + return if (this@case_8_4 != null) null else true +} + +// TESTCASE NUMBER: 9 +fun T.case_9(): Boolean? { + contract { returnsNotNull() implies (this@case_9 != null) } + return if (this@case_9 != null) true else null +} + +// TESTCASE NUMBER: 10 +fun T.case_10(): Boolean? { + contract { returnsNotNull() implies (this@case_10 == null) } + return if (this@case_10 == null) true else null +} + +// TESTCASE NUMBER: 11 +fun T.case_11_1(): Boolean? { + contract { returns(null) implies (this@case_11_1 != null) } + return if (this@case_11_1 != null) null else true +} +fun T.case_11_2(): Boolean? { + contract { returns(null) implies (this@case_11_2 != null) } + return if (this@case_11_2 != null) null else true +} + +// FILE: main.kt + +import contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(value_1: Any?) { + value_1.case_1() + println(value_1.length) +} + +// TESTCASE NUMBER: 2 +fun case_2(value_1: Number) { + value_1.case_2() + println(value_1.inv()) +} + +// TESTCASE NUMBER: 3 +fun case_3(value_1: String?, value_2: String?) { + value_1.case_3_1() + println(value_1.length) + value_2.case_3_2() + println(value_2) +} + +// TESTCASE NUMBER: 4 +fun case_4(value_1: String?, value_2: String?) { + value_1.case_4_1() + println(value_1.length) + value_2.case_4_2() + println(value_2) +} + +// TESTCASE NUMBER: 5 +fun case_5(value_1: Any?) { + if (value_1.case_5_1()) println(value_1.length) + if (!value_1.case_5_2()) println(value_1.length) + if (value_1.case_5_3() != null) println(value_1.length) + if (value_1.case_5_4() == null) println(value_1.length) +} + +// TESTCASE NUMBER: 6 +fun case_6(value_1: Number) { + when { value_1.case_6_1() -> println(value_1.inv()) } + when { !value_1.case_6_2() -> println(value_1.inv()) } + when { value_1.case_6_3() != null -> println(value_1.inv()) } + when { value_1.case_6_4() != null -> println(value_1.inv()) } +} + +// TESTCASE NUMBER: 7 +fun case_7(value_1: String?, value_2: String?) { + if (value_1.case_7_1()) println(value_1.length) + if (value_2.case_7_2()) println(value_2) + if (!(value_2.case_7_3() == null)) println(value_2) + if (value_2.case_7_3() == null) println(value_2) +} + +// TESTCASE NUMBER: 8 +fun case_8(value_1: String?, value_2: String?) { + when { value_1.case_8_1() -> println(value_1.length) } + when { value_2.case_8_2() -> println(value_2) } + when { !(value_2.case_8_3() == null) -> println(value_2) } + when { value_2.case_8_3() == null -> println(value_2) } +} + +// TESTCASE NUMBER: 9 +fun case_9(value_1: Number?) { + if (value_1?.case_9() == null) println(value_1.toByte()) +} + +// TESTCASE NUMBER: 10 +fun case_10(value_1: Number?) { + if (value_1?.case_10() == null) { + println(value_1.toByte()) + } else { + println(value_1.toByte()) + } +} + +/* + * TESTCASE NUMBER: 11 + * ISSUES: KT-26382 + */ +fun case_11(value_1: Number?, value_2: Number?) { + if (value_1?.case_11_1() == null) { + println(value_1.toByte()) + } else { + println(value_1.toByte()) + } + if (value_2?.case_11_2() != null) { + println(value_2.toByte()) + } else { + println(value_2.toByte()) + } +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/5.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/5.fir.kt new file mode 100644 index 00000000000..fbf445ad1ab --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/5.fir.kt @@ -0,0 +1,134 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts +// !WITH_NEW_INFERENCE + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, analysis, smartcasts + * NUMBER: 5 + * DESCRIPTION: Smartcasts using Returns effects with complex (conjunction/disjunction) type checking and not-null conditions on receiver inside contract. + */ + +// FILE: contracts.kt + +package contracts + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +fun T?.case_1() { + contract { returns() implies (this@case_1 == null || this@case_1 !is String) } + if (!(this@case_1 == null || this@case_1 !is String)) throw Exception() +} + +// TESTCASE NUMBER: 2 +fun T.case_2() { + contract { returns() implies (this@case_2 !is Int || this@case_2 == null) } + if (!(this@case_2 !is Int || this@case_2 == null)) throw Exception() +} + +// TESTCASE NUMBER: 3 +inline fun T?.case_3() { + contract { returns() implies (this@case_3 !is Number || this@case_3 !is Int || this@case_3 == null) } + if (!(this@case_3 !is Number || this@case_3 !is Int || this@case_3 == null)) throw Exception() +} + +// TESTCASE NUMBER: 4 +fun T?.case_4_1(): Boolean { + contract { returns(true) implies (this@case_4_1 == null || this@case_4_1 !is String) } + return this@case_4_1 == null || this@case_4_1 !is String +} +fun T?.case_4_2(): Boolean { + contract { returns(false) implies (this@case_4_2 == null || this@case_4_2 !is String) } + return !(this@case_4_2 == null || this@case_4_2 !is String) +} +fun T?.case_4_3(): Boolean? { + contract { returnsNotNull() implies (this@case_4_3 == null || this@case_4_3 !is String) } + return if (this@case_4_3 == null || this@case_4_3 !is String) true else null +} +fun T?.case_4_4(): Boolean? { + contract { returns(null) implies (this@case_4_4 == null || this@case_4_4 !is String) } + return if (this@case_4_4 == null || this@case_4_4 !is String) null else true +} + +// TESTCASE NUMBER: 5 +fun T.case_5_1(): Boolean { + contract { returns(true) implies (this@case_5_1 !is Int || this@case_5_1 == null) } + return this@case_5_1 !is Int || this@case_5_1 == null +} +fun T.case_5_2(): Boolean { + contract { returns(false) implies (this@case_5_2 !is Int || this@case_5_2 == null) } + return !(this@case_5_2 !is Int || this@case_5_2 == null) +} +fun T.case_5_3(): Boolean? { + contract { returnsNotNull() implies (this@case_5_3 !is Int || this@case_5_3 == null) } + return if (this@case_5_3 !is Int || this@case_5_3 == null) true else null +} +fun T.case_5_4(): Boolean? { + contract { returns(null) implies (this@case_5_4 !is Int || this@case_5_4 == null) } + return if (this@case_5_4 !is Int || this@case_5_4 == null) null else true +} + +// TESTCASE NUMBER: 6 +inline fun T?.case_6_1(): Boolean { + contract { returns(true) implies (this@case_6_1 !is Number || this@case_6_1 !is Int || this@case_6_1 == null) } + return this@case_6_1 !is Number || this@case_6_1 !is Int || this@case_6_1 == null +} +inline fun T?.case_6_2(): Boolean { + contract { returns(false) implies (this@case_6_2 !is Number || this@case_6_2 !is Int || this@case_6_2 == null) } + return !(this@case_6_2 !is Number || this@case_6_2 !is Int || this@case_6_2 == null) +} +inline fun T?.case_6_3(): Boolean? { + contract { returnsNotNull() implies (this@case_6_3 is Number && this@case_6_3 is Int && this@case_6_3 != null) } + return if (this@case_6_3 is Number && this@case_6_3 is Int && this@case_6_3 != null) true else null +} +inline fun T?.case_6_4(): Boolean? { + contract { returns(null) implies (this@case_6_4 is Number && this@case_6_4 is Int && this@case_6_4 != null) } + return if (this@case_6_4 is Number && this@case_6_4 is Int && this@case_6_4 != null) null else true +} + +// FILE: main.kt + +import contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(value_1: Any?) { + value_1.case_1() + println(value_1.length) +} + +// TESTCASE NUMBER: 2 +fun case_2(value_1: Number?) { + value_1.case_2() + println(value_1.inv()) +} + +// TESTCASE NUMBER: 3 +fun case_3(value_1: Any?) { + value_1.case_3() + println(value_1.inv()) +} + +// TESTCASE NUMBER: 4 +fun case_4(value_1: Any?, value_2: Any?, value_3: Any?) { + when { value_1.case_4_1() -> println(value_1.length) } + when { !value_2.case_4_2() -> println(value_2.length) } + when { value_3.case_4_3() != null -> println(value_3.length) } + when { value_3.case_4_4() == null -> println(value_3.length) } +} + +// TESTCASE NUMBER: 5 +fun case_5(value_1: Number?, value_2: Number?, value_3: Number?) { + if (value_1.case_5_1()) println(value_1.inv()) + if (!value_2.case_5_2()) println(value_2.inv()) + if (value_3.case_5_3() != null) println(value_3.inv()) + if (value_3.case_5_4() == null) println(value_3.inv()) +} + +// TESTCASE NUMBER: 6 +fun case_6(value_1: Any?, value_2: Any?, value_3: Any?) { + if (value_1.case_6_1()) println(value_1.inv()) + if (!value_2.case_6_2()) println(value_2.inv()) + if (value_3.case_6_3() == null) println(value_3.inv()) + if (value_3.case_6_4() != null) println(value_3.inv()) +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/6.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/6.fir.kt new file mode 100644 index 00000000000..78dda41adf0 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/6.fir.kt @@ -0,0 +1,223 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts +// !WITH_NEW_INFERENCE + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, analysis, smartcasts + * NUMBER: 6 + * DESCRIPTION: Smartcasts using Returns effects with complex (conjunction/disjunction) type checking and not-null conditions on receiver and some values (mixed) inside contract. + */ + +// FILE: contracts.kt + +package contracts + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +fun T?.case_1(value_1: Int?) { + contract { returns() implies (this@case_1 == null || this@case_1 !is String || value_1 == null) } + if (!(this@case_1 == null || this@case_1 !is String || value_1 == null)) throw Exception() +} + +// TESTCASE NUMBER: 2 +fun T.case_2(value_2: Any?) { + contract { returns() implies (this@case_2 !is Int || this@case_2 == null || value_2 !is Number || value_2 == null) } + if (!(this@case_2 !is Int || this@case_2 == null || value_2 !is Number || value_2 == null)) throw Exception() +} + +// TESTCASE NUMBER: 3 +fun T?.case_3(value_2: Any?) { + contract { returns() implies (this@case_3 !is Number || this@case_3 !is Int || this@case_3 == null || value_2 == null) } + if (!(this@case_3 !is Number || this@case_3 !is Int || this@case_3 == null || value_2 == null)) throw Exception() +} + +// TESTCASE NUMBER: 4 +inline fun T?.case_4(value_2: Number, value_3: Any?, value_4: String?) { + contract { returns() implies ((this@case_4 !is Number && this@case_4 !is Int) || value_2 !is Int || value_3 == null || value_3 !is Number || value_4 == null) } + if (!((this@case_4 !is Number && this@case_4 !is Int) || value_2 !is Int || value_3 == null || value_3 !is Number || value_4 == null)) throw Exception() +} + +// TESTCASE NUMBER: 5 +fun T?.case_5_1(value_1: Int?): Boolean { + contract { returns(true) implies (this@case_5_1 == null || this@case_5_1 !is String || value_1 == null) } + return this@case_5_1 == null || this@case_5_1 !is String || value_1 == null +} +fun T?.case_5_2(value_1: Int?): Boolean { + contract { returns(false) implies (this@case_5_2 == null || this@case_5_2 !is String || value_1 == null) } + return !(this@case_5_2 == null || this@case_5_2 !is String || value_1 == null) +} +fun T?.case_5_3(value_1: Int?): Boolean? { + contract { returnsNotNull() implies (this@case_5_3 == null || this@case_5_3 !is String || value_1 == null) } + return if (this@case_5_3 == null || this@case_5_3 !is String || value_1 == null) true else null +} +fun T?.case_5_4(value_1: Int?): Boolean? { + contract { returns(null) implies (this@case_5_4 == null || this@case_5_4 !is String || value_1 == null) } + return if (this@case_5_4 == null || this@case_5_4 !is String || value_1 == null) null else true +} + +// TESTCASE NUMBER: 6 +fun T.case_6_1(value_2: Any?): Boolean { + contract { returns(true) implies (this@case_6_1 !is Int || this@case_6_1 == null || value_2 !is Number || value_2 == null) } + return this@case_6_1 !is Int || this@case_6_1 == null || value_2 !is Number || value_2 == null +} +fun T.case_6_2(value_2: Any?): Boolean { + contract { returns(false) implies (this@case_6_2 !is Int || this@case_6_2 == null || value_2 !is Number || value_2 == null) } + return !(this@case_6_2 !is Int || this@case_6_2 == null || value_2 !is Number || value_2 == null) +} +fun T.case_6_3(value_2: Any?): Boolean? { + contract { returnsNotNull() implies (this@case_6_3 !is Int || this@case_6_3 == null || value_2 !is Number || value_2 == null) } + return if (this@case_6_3 !is Int || this@case_6_3 == null || value_2 !is Number || value_2 == null) true else null +} +fun T.case_6_4(value_2: Any?): Boolean? { + contract { returns(null) implies (this@case_6_4 !is Int || this@case_6_4 == null || value_2 !is Number || value_2 == null) } + return if (this@case_6_4 !is Int || this@case_6_4 == null || value_2 !is Number || value_2 == null) null else true +} + +// TESTCASE NUMBER: 7 +fun T?.case_7_1(value_2: Any?): Boolean { + contract { returns(true) implies (this@case_7_1 !is Number || this@case_7_1 !is Int || this@case_7_1 == null || value_2 == null) } + return this@case_7_1 !is Number || this@case_7_1 !is Int || this@case_7_1 == null || value_2 == null +} +fun T?.case_7_2(value_2: Any?): Boolean { + contract { returns(false) implies (this@case_7_2 !is Number || this@case_7_2 !is Int || this@case_7_2 == null || value_2 == null) } + return !(this@case_7_2 !is Number || this@case_7_2 !is Int || this@case_7_2 == null || value_2 == null) +} +fun T?.case_7_3(value_2: Any?): Boolean? { + contract { returnsNotNull() implies (this@case_7_3 !is Number || this@case_7_3 !is Int || this@case_7_3 == null || value_2 == null) } + return if (this@case_7_3 !is Number || this@case_7_3 !is Int || this@case_7_3 == null || value_2 == null) true else null +} +fun T?.case_7_4(value_2: Any?): Boolean? { + contract { returns(null) implies (this@case_7_4 !is Number || this@case_7_4 !is Int || this@case_7_4 == null || value_2 == null) } + return if (this@case_7_4 !is Number || this@case_7_4 !is Int || this@case_7_4 == null || value_2 == null) null else true +} + +// TESTCASE NUMBER: 8 +inline fun T?.case_8_1(value_2: Number, value_3: Any?, value_4: String?): Boolean { + contract { returns(true) implies ((this@case_8_1 !is Number && this@case_8_1 !is Int) || value_2 !is Int || value_3 == null || value_3 !is Number || value_4 == null) } + return (this@case_8_1 !is Number && this@case_8_1 !is Int) || value_2 !is Int || value_3 == null || value_3 !is Number || value_4 == null +} +inline fun T?.case_8_2(value_2: Number, value_3: Any?, value_4: String?): Boolean { + contract { returns(false) implies ((this@case_8_2 !is Number && this@case_8_2 !is Int) || value_2 !is Int || value_3 == null || value_3 !is Number || value_4 == null) } + return !((this@case_8_2 !is Number && this@case_8_2 !is Int) || value_2 !is Int || value_3 == null || value_3 !is Number || value_4 == null) +} +inline fun T?.case_8_3(value_2: Number, value_3: Any?, value_4: String?): Boolean? { + contract { returnsNotNull() implies ((this@case_8_3 is Number || this@case_8_3 is Int) && value_2 is Int && value_3 != null && value_3 is Number && value_4 != null) } + return if ((this@case_8_3 is Number || this@case_8_3 is Int) && value_2 is Int && value_3 != null && value_3 is Number && value_4 != null) true else null +} +inline fun T?.case_8_4(value_2: Number, value_3: Any?, value_4: String?): Boolean? { + contract { returns(null) implies ((this@case_8_4 is Number || this@case_8_4 is Int) && value_2 is Int && value_3 != null && value_3 is Number && value_4 != null) } + return if ((this@case_8_4 is Number || this@case_8_4 is Int) && value_2 is Int && value_3 != null && value_3 is Number && value_4 != null) null else true +} + +// FILE: main.kt + +import contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(value_1: Any?, value_2: Int?) { + value_1.case_1(value_2) + println(value_1.length) + println(value_2.inv()) +} + +// TESTCASE NUMBER: 2 +fun case_2(value_1: Number?, value_2: Any?) { + value_1.case_2(value_2) + println(value_1.inv()) + println(value_2.toByte()) +} + +// TESTCASE NUMBER: 3 +fun case_3(value_1: Any?, value_2: String?) { + value_1.case_3(value_2) + println(value_1.inv()) + println(value_2.length) +} + +// TESTCASE NUMBER: 4 +fun case_4(value_1: Any?, value_2: Number, value_3: Any?, value_4: String?) { + value_1.case_4(value_2, value_3, value_4) + println(value_2.inv()) + println(value_3.toByte()) + println(value_4.length) +} + +// TESTCASE NUMBER: 5 +fun case_5(value_1: Any?, value_2: Int?, value_3: Any?, value_4: Int?, value_5: Any?, value_6: Int?) { + when { + value_1.case_5_1(value_2) -> { + println(value_1.length) + println(value_2.inv()) + } + } + when { + !value_3.case_5_2(value_4) -> { + println(value_3.length) + println(value_4.inv()) + } + } + when { + value_5.case_5_3(value_6) != null -> { + println(value_5.length) + println(value_6.inv()) + } + } +} + +// TESTCASE NUMBER: 6 +fun case_6(value_1: Number?, value_2: Any?, value_3: Number?, value_4: Any?, value_5: Number?, value_6: Any?) { + if (value_1.case_6_1(value_2)) { + println(value_1.inv()) + println(value_2.toByte()) + } + if (!value_3.case_6_2(value_4)) { + println(value_3.inv()) + println(value_4.toByte()) + } + if (value_5.case_6_3(value_6) != null) { + println(value_5.inv()) + println(value_6.toByte()) + } + if (value_5.case_6_4(value_6) == null) { + println(value_5.inv()) + println(value_6.toByte()) + } +} + +// TESTCASE NUMBER: 7 +fun case_7(value_1: Any?, value_2: String?, value_3: Any?, value_4: String?, value_5: Any?, value_6: String?) { + if (value_1.case_7_1(value_2)) { + println(value_1.inv()) + println(value_2.length) + } + if (value_3.case_7_2(value_4)) { + println(value_3.inv()) + println(value_4.length) + } + if (value_5.case_7_3(value_6) != null) { + println(value_5.inv()) + println(value_6.length) + } + if (value_5.case_7_4(value_6) == null) { + println(value_5.inv()) + println(value_6.length) + } +} + +// TESTCASE NUMBER: 8 +fun case_8(value_1: Any?, value_2: Number, value_3: Any?, value_4: String?) { + when { value_1.case_8_1(value_2, value_3, value_4) -> println(value_2.inv()) } + when { value_1.case_8_1(value_2, value_3, value_4) -> println(value_3.toByte()) } + when { value_1.case_8_1(value_2, value_3, value_4) -> println(value_4.length) } + when { !value_1.case_8_2(value_2, value_3, value_4) -> println(value_2.inv()) } + when { !value_1.case_8_2(value_2, value_3, value_4) -> println(value_3.toByte()) } + when { !value_1.case_8_2(value_2, value_3, value_4) -> println(value_4.length) } + when { value_1.case_8_3(value_2, value_3, value_4) == null -> println(value_2.inv()) } + when { value_1.case_8_3(value_2, value_3, value_4) == null -> println(value_3.toByte()) } + when { value_1.case_8_3(value_2, value_3, value_4) == null -> println(value_4.length) } + when { value_1.case_8_4(value_2, value_3, value_4) != null -> println(value_2.inv()) } + when { value_1.case_8_4(value_2, value_3, value_4) != null -> println(value_3.toByte()) } + when { value_1.case_8_4(value_2, value_3, value_4) != null -> println(value_4.length) } +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/7.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/7.fir.kt new file mode 100644 index 00000000000..292b66fc42f --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/7.fir.kt @@ -0,0 +1,368 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts +// !WITH_NEW_INFERENCE + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, analysis, smartcasts + * NUMBER: 7 + * DESCRIPTION: Smartcasts using Returns effects with nested or subsequent contract function calls. + */ + +// FILE: contracts.kt + +package contracts + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +fun case_1_1(value_1: Int?) { + contract { returns() implies (value_1 == null) } + if (!(value_1 == null)) throw Exception() +} +fun case_1_2(value_1: Int?) { + contract { returns() implies (value_1 != null) } + if (!(value_1 != null)) throw Exception() +} + +// TESTCASE NUMBER: 2 +fun case_2_1(value_1: Number?) { + contract { returns() implies (value_1 !is Float) } + if (!(value_1 !is Float)) throw Exception() +} +fun case_2_2(value_1: Number?) { + contract { returns() implies (value_1 !is Int) } + if (!(value_1 !is Int)) throw Exception() +} + +// TESTCASE NUMBER: 3 +fun case_3_1(value_1: Any?) { + contract { returns() implies (value_1 !is String) } + if (!(value_1 !is String)) throw Exception() +} +fun case_3_2(value_1: Any?) { + contract { returns() implies (value_1 is String) } + if (!(value_1 is String)) throw Exception() +} + +// TESTCASE NUMBER: 4 +fun case_4_1(value_1: Any?) { + contract { returns() implies (value_1 !is Number?) } + if (!(value_1 !is Number?)) throw Exception() +} +fun case_4_2(value_1: Number?) { + contract { returns() implies (value_1 == null) } + if (!(value_1 == null)) throw Exception() +} +fun case_4_3(value_1: Number) { + contract { returns() implies (value_1 !is Int) } + if (!(value_1 !is Int)) throw Exception() +} + +// TESTCASE NUMBER: 5 +fun case_5_1(value_1: Int?): Boolean { + contract { returns(true) implies (value_1 == null) } + return value_1 == null +} +fun case_5_2(value_1: Int?): Boolean { + contract { returns(true) implies (value_1 != null) } + return value_1 != null +} +fun case_5_3(value_1: Int?): Boolean { + contract { returns(false) implies (value_1 == null) } + return !(value_1 == null) +} +fun case_5_4(value_1: Int?): Boolean { + contract { returns(false) implies (value_1 != null) } + return !(value_1 != null) +} +fun case_5_5(value_1: Int?): Boolean? { + contract { returnsNotNull() implies (value_1 == null) } + return if (value_1 == null) true else null +} +fun case_5_6(value_1: Int?): Boolean? { + contract { returnsNotNull() implies (value_1 != null) } + return if (value_1 != null) true else null +} +fun case_5_7(value_1: Int?): Boolean? { + contract { returns(null) implies (value_1 == null) } + return if (value_1 == null) null else true +} +fun case_5_8(value_1: Int?): Boolean? { + contract { returns(null) implies (value_1 != null) } + return if (value_1 != null) null else true +} + +// TESTCASE NUMBER: 6 +fun case_6_1(value_1: Number?): Boolean { + contract { returns(true) implies (value_1 !is Float) } + return value_1 !is Float +} +fun case_6_2(value_1: Number?): Boolean { + contract { returns(true) implies (value_1 !is Int) } + return value_1 !is Int +} +fun case_6_3(value_1: Number?): Boolean { + contract { returns(false) implies (value_1 !is Float) } + return !(value_1 !is Float) +} +fun case_6_4(value_1: Number?): Boolean { + contract { returns(false) implies (value_1 !is Int) } + return !(value_1 !is Int) +} +fun case_6_5(value_1: Number?): Boolean? { + contract { returnsNotNull() implies (value_1 !is Float) } + return if (value_1 !is Float) true else null +} +fun case_6_6(value_1: Number?): Boolean? { + contract { returnsNotNull() implies (value_1 !is Int) } + return if (value_1 !is Int) true else null +} +fun case_6_7(value_1: Number?): Boolean? { + contract { returns(null) implies (value_1 !is Float) } + return if (value_1 !is Float) null else true +} +fun case_6_8(value_1: Number?): Boolean? { + contract { returns(null) implies (value_1 !is Int) } + return if (value_1 !is Int) null else true +} + +// TESTCASE NUMBER: 7 +fun case_7_1(value_1: Any?): Boolean { + contract { returns(true) implies (value_1 !is String) } + return value_1 !is String +} +fun case_7_2(value_1: Any?): Boolean { + contract { returns(true) implies (value_1 is String) } + return value_1 is String +} +fun case_7_3(value_1: Any?): Boolean { + contract { returns(false) implies (value_1 !is String) } + return !(value_1 !is String) +} +fun case_7_4(value_1: Any?): Boolean { + contract { returns(false) implies (value_1 is String) } + return !(value_1 is String) +} +fun case_7_5(value_1: Any?): Boolean? { + contract { returnsNotNull() implies (value_1 !is String) } + return if (value_1 !is String) true else null +} +fun case_7_6(value_1: Any?): Boolean? { + contract { returnsNotNull() implies (value_1 is String) } + return if (value_1 is String) true else null +} +fun case_7_7(value_1: Any?): Boolean? { + contract { returns(null) implies (value_1 !is String) } + return if (value_1 !is String) null else true +} +fun case_7_8(value_1: Any?): Boolean? { + contract { returns(null) implies (value_1 is String) } + return if (value_1 is String) null else true +} + +// TESTCASE NUMBER: 8 +fun case_8_1(value_1: Any?): Boolean { + contract { returns(true) implies (value_1 !is Number?) } + return value_1 !is Number? +} +fun case_8_2(value_1: Number?): Boolean { + contract { returns(true) implies (value_1 == null) } + return value_1 == null +} +fun case_8_3(value_1: Number): Boolean { + contract { returns(true) implies (value_1 !is Int) } + return value_1 !is Int +} +fun case_8_4(value_1: Any?): Boolean { + contract { returns(false) implies (value_1 !is Number?) } + return !(value_1 !is Number?) +} +fun case_8_5(value_1: Number?): Boolean { + contract { returns(false) implies (value_1 == null) } + return !(value_1 == null) +} +fun case_8_6(value_1: Number): Boolean { + contract { returns(false) implies (value_1 !is Int) } + return !(value_1 !is Int) +} +fun case_8_7(value_1: Any?): Boolean? { + contract { returnsNotNull() implies (value_1 is Number?) } + return if (value_1 is Number?) true else null +} +fun case_8_8(value_1: Number?): Boolean? { + contract { returnsNotNull() implies (value_1 == null) } + return if (value_1 == null) true else null +} +fun case_8_9(value_1: Number): Boolean? { + contract { returnsNotNull() implies (value_1 !is Int) } + return if (value_1 !is Int) true else null +} +fun case_8_10(value_1: Any?): Boolean? { + contract { returns(null) implies (value_1 is Number?) } + return if (value_1 is Number?) null else true +} +fun case_8_11(value_1: Number?): Boolean? { + contract { returns(null) implies (value_1 == null) } + return if (value_1 == null) null else true +} +fun case_8_12(value_1: Number): Boolean? { + contract { returns(null) implies (value_1 !is Int) } + return if (value_1 !is Int) null else true +} + +// FILE: main.kt + +import contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(value_1: Int?) { + case_1_1(value_1) + value_1.inv() + case_1_2(value_1) + value_1.inv() + case_1_1(value_1) + value_1.inv() +} + +// TESTCASE NUMBER: 2 +fun case_2(value_1: Number?) { + case_2_1(value_1) + value_1.toByte() + case_2_2(value_1) + value_1.inv() +} + +// TESTCASE NUMBER: 3 +fun case_3(value_1: Any?) { + case_3_1(value_1) + value_1.length + case_3_2(value_1) + value_1.length +} + +// TESTCASE NUMBER: 4 +fun case_4(value_1: Any?) { + case_4_1(value_1) + value_1?.toByte() + case_4_2(value_1) + value_1.toByte() + case_4_3(value_1) + value_1.inv() +} + +// TESTCASE NUMBER: 5 +fun case_5(value_1: Int?) { + if (case_5_1(value_1)) { + value_1.inv() + if (case_5_2(value_1)) { + value_1.inv() + case_5_1(value_1) + value_1.inv() + } + } + if (!case_5_3(value_1)) { + value_1.inv() + if (!case_5_4(value_1)) { + value_1.inv() + case_5_1(value_1) + value_1.inv() + } + } + if (case_5_5(value_1) != null) { + value_1.inv() + if (case_5_6(value_1) != null) { + value_1.inv() + case_5_1(value_1) + value_1.inv() + } + } + if (case_5_7(value_1) == null) { + value_1.inv() + if (case_5_8(value_1) == null) { + value_1.inv() + case_5_1(value_1) + value_1.inv() + } + } +} + +// TESTCASE NUMBER: 6 +fun case_6(value_1: Number?) { + when { + case_6_1(value_1) -> { + value_1.toByte() + when { case_6_2(value_1) -> value_1.inv() } + } + } + when { + !case_6_3(value_1) -> { + value_1.toByte() + when { !case_6_4(value_1) -> value_1.inv() } + } + } + when { + case_6_5(value_1) != null -> { + value_1.toByte() + when { case_6_6(value_1) != null -> value_1.inv() } + } + } + when { + case_6_7(value_1) == null -> { + value_1.toByte() + when { case_6_8(value_1) == null -> value_1.inv() } + } + } +} + +// TESTCASE NUMBER: 7 +fun case_7(value_1: Any?) { + if (case_7_1(value_1)) { + value_1.length + if (case_7_2(value_1)) value_1.length + } + if (!case_7_3(value_1)) { + value_1.length + if (!case_7_4(value_1)) value_1.length + } + if (case_7_5(value_1) != null) { + value_1.length + if (case_7_6(value_1) != null) value_1.length + } + if (case_7_7(value_1) == null) { + value_1.length + if (case_7_8(value_1) == null) value_1.length + } +} + +// TESTCASE NUMBER: 8 +fun case_8(value_1: Any?) { + if (case_8_1(value_1)) { + value_1?.toByte() + if (case_8_2(value_1)) { + value_1.toByte() + if (case_8_3(value_1)) value_1.inv() + } + } + if (!case_8_4(value_1)) { + value_1?.toByte() + if (!case_8_5(value_1)) { + value_1.toByte() + if (!case_8_6(value_1)) value_1.inv() + } + } + if (case_8_7(value_1) == null) { + value_1?.toByte() + if (case_8_8(value_1) != null) { + value_1.toByte() + if (case_8_9(value_1) != null) value_1.inv() + } + } + if (case_8_10(value_1) != null) { + value_1?.toByte() + if (case_8_11(value_1) == null) { + value_1.toByte() + if (case_8_12(value_1) == null) value_1.inv() + } + } +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/8.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/8.fir.kt new file mode 100644 index 00000000000..560250b5fcb --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/8.fir.kt @@ -0,0 +1,140 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts +// !WITH_NEW_INFERENCE + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, analysis, smartcasts + * NUMBER: 8 + * DESCRIPTION: Smartcasts using some Returns effects. + * HELPERS: contractFunctions + */ + +// FILE: contracts.kt + +package contracts + +import kotlin.contracts.* + +// TESTCASE NUMBER: 3 +fun T?.case_3(value_1: Int?, value_2: Boolean): Boolean { + contract { + returns(true) implies (value_1 != null) + returns(false) implies (value_1 == null && !value_2) + returns(null) implies (value_1 == null && value_2) + } + + return value_1 == null +} + +// TESTCASE NUMBER: 4 +fun case_4(value_1: Number, block: (() -> Unit)?): Boolean? { + contract { + returns(true) implies (block != null) + returns(false) implies (value_1 is Int) + returns(null) implies (block == null) + } + + return value_1 == null +} + +// TESTCASE NUMBER: 5 +fun String?.case_5(value_1: Number?): Boolean? { + contract { + returns(true) implies (value_1 == null) + returns(false) implies (this@case_5 == null) + returnsNotNull() implies (value_1 is Int) + } + + return value_1 == null +} + +// TESTCASE NUMBER: 6 +fun T?.case_6(value_1: Number, value_2: String?): Boolean? { + contract { + returns(true) implies (this@case_6 == null) + returns(false) implies (value_1 is Int) + returns(null) implies (this@case_6 is String) + returnsNotNull() implies (value_2 == null) + } + + return value_1 == null +} + +// FILE: main.kt + +import contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(value_1: Any?) { + funWithReturns(value_1 !is Number?) + println(value_1?.toByte()) + if (funWithReturnsTrue(value_1 !is Number)) { + println(value_1.toByte()) + if (funWithReturnsNotNull(value_1 is Int) == null) println(value_1.inv()) + } +} + +// TESTCASE NUMBER: 2 +fun case_2(value_1: Any?) { + if (!funWithReturnsFalse(value_1 !is Number?)) { + println(value_1?.toByte()) + funWithReturns(value_1 !is Number) + println(value_1.toByte()) + if (funWithReturnsNull(value_1 !is Int) == null) println(value_1.inv()) + } +} + +// TESTCASE NUMBER: 3 +fun case_3(value_1: Int?, value_2: Any?) { + if (!value_1.case_3(value_1, value_2 is Number?)) { + println(value_2?.toByte()) + println(value_1) + } else if (value_1.case_3(value_1, value_2 is Number?)) { + println(value_2?.toByte()) + } else { + println(value_2?.toByte()) + } +} + +// TESTCASE NUMBER: 4 +fun case_4(value_1: Number, value_2: (() -> Unit)?) { + if (contracts.case_4(value_1, value_2) == true) { + value_1.inv() + } else if (contracts.case_4(value_1, value_2) == false) { + println(value_2) + } else if (contracts.case_4(value_1, value_2) == null) { + value_2() + } +} + +// TESTCASE NUMBER: 5 +fun case_5(value_1: Number?, value_2: String?) { + when (value_2.case_5(value_1)) { + true -> { + println(value_2.length) + println(value_1.toByte()) + } + false -> { + println(value_2.length) + println(value_1.inv()) + } + } +} + +// TESTCASE NUMBER: 6 +fun case_6(value_1: Number, value_2: String?, value_3: Any?) { + when (value_3.case_6(value_1, value_2)) { + true -> { + println(value_3.equals("")) + println(value_2.length) + } + false -> { + println(value_3.length) + println(value_2.length) + } + null -> { + println(value_1.inv()) + } + } +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/9.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/9.fir.kt new file mode 100644 index 00000000000..3a28d75c557 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/9.fir.kt @@ -0,0 +1,37 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts +// SKIP_TXT + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, analysis, smartcasts + * NUMBER: 9 + * DESCRIPTION: Check the lack of smartcasts after non-null assertions or not-null value assignment in lambdas of contract function with 'unknown' or 'at most once' CallsInPlace effects. + * HELPERS: contractFunctions + */ + +// TESTCASE NUMBER: 1 +fun case_1(arg: Int?) { + funWithAtMostOnceCallsInPlace { arg!! } + arg.inc() +} + +// TESTCASE NUMBER: 2 +fun case_2(arg: Int?) { + funWithUnknownCallsInPlace { arg!! } + arg.inc() +} + +// TESTCASE NUMBER: 3 +fun case_3() { + val value_1: Boolean? + funWithAtMostOnceCallsInPlace { value_1 = false } + value_1.not() +} + +// TESTCASE NUMBER: 4 +fun case_4() { + val value_1: Boolean? + funWithUnknownCallsInPlace { value_1 = true } + value_1.not() +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/1.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/1.fir.kt new file mode 100644 index 00000000000..fc7387d6224 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/1.fir.kt @@ -0,0 +1,97 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts +// SKIP_TXT + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (POSITIVE) + * + * SECTIONS: contracts, analysis, smartcasts + * NUMBER: 1 + * DESCRIPTION: Smartcasts using Returns effects with simple type checking, not-null conditions and custom condition (condition for smartcast outside contract). + * HELPERS: contractFunctions + */ + +// TESTCASE NUMBER: 1 +fun case_1(value_1: Any?) { + funWithReturns(value_1 is String) + println(value_1.length) +} + +// TESTCASE NUMBER: 2 +fun case_2(value_1: Int?) { + funWithReturns(value_1 != null) + println(value_1.inc()) +} + +// TESTCASE NUMBER: 3 +fun case_3(value_1: Int?) { + funWithReturns(value_1 == null) + println(value_1) +} + +// TESTCASE NUMBER: 4 +fun case_4(value_1: Any?) { + funWithReturnsAndTypeCheck(value_1) + println(value_1.length) +} + +// TESTCASE NUMBER: 5 +fun case_5(value_1: String?) { + funWithReturnsAndNotNullCheck(value_1) + println(value_1.length) +} + +// TESTCASE NUMBER: 6 +fun case_6(value_1: String?) { + funWithReturnsAndNullCheck(value_1) + println(value_1) +} + +// TESTCASE NUMBER: 7 +object case_7_object { + val prop_1: Int? = 10 +} +fun case_7() { + funWithReturnsAndInvertCondition(case_7_object.prop_1 == null) + case_7_object.prop_1.inc() +} + +// TESTCASE NUMBER: 8 +fun case_8(value_1: Any?) { + if (funWithReturnsTrue(value_1 is String)) println(value_1.length) + if (funWithReturnsTrueAndInvertCondition(value_1 !is String)) println(value_1.length) + if (!funWithReturnsFalse(value_1 is String)) println(value_1.length) + if (!funWithReturnsFalseAndInvertCondition(value_1 !is String)) println(value_1.length) + if (funWithReturnsNotNull(value_1 is String) != null) println(value_1.length) + if (!(funWithReturnsNotNull(value_1 is String) == null)) println(value_1.length) +} + +// TESTCASE NUMBER: 9 +fun case_9(value_1: String?) { + if (funWithReturnsTrue(value_1 != null)) println(value_1.length) + if (funWithReturnsTrueAndInvertCondition(value_1 == null)) println(value_1.length) + if (!funWithReturnsFalse(value_1 != null)) println(value_1.length) + if (!funWithReturnsFalseAndInvertCondition(value_1 == null)) println(value_1.length) + if (funWithReturnsNotNull(value_1 != null) != null) println(value_1.length) + if (!(funWithReturnsNotNull(value_1 != null) == null)) println(value_1.length) + if (!(funWithReturnsNotNullAndInvertCondition(value_1 == null) == null)) println(value_1.length) +} + +// TESTCASE NUMBER: 10 +fun case_10(value_1: Any?) { + if (funWithReturnsTrueAndTypeCheck(value_1)) println(value_1.length) + if (!funWithReturnsFalseAndTypeCheck(value_1)) println(value_1.length) + if (funWithReturnsNotNullAndTypeCheck(value_1) != null) println(value_1.length) + if (!(funWithReturnsNotNullAndTypeCheck(value_1) == null)) println(value_1.length) +} + +// TESTCASE NUMBER: 11 +fun case_11(value_1: Number?, value_2: Int?) { + if (funWithReturnsTrueAndNotNullCheck(value_1)) println(value_1.toByte()) + if (funWithReturnsTrueAndNullCheck(value_1)) println(value_1) + if (!funWithReturnsFalseAndNotNullCheck(value_2)) value_2.inc() + if (!funWithReturnsFalseAndNotNullCheck(value_1)) println(value_1.toByte()) + if (!funWithReturnsFalseAndNullCheck(value_1)) println(value_1) + if (!(funWithReturnsNotNullAndNotNullCheck(value_1) == null)) println(value_1.toByte()) + if (funWithReturnsNotNullAndNotNullCheck(value_1) != null) println(value_1.toByte()) + if (funWithReturnsNotNullAndNullCheck(value_1) != null) println(value_1) +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/10.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/10.fir.kt new file mode 100644 index 00000000000..de1b553bbed --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/10.fir.kt @@ -0,0 +1,48 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (POSITIVE) + * + * SECTIONS: contracts, analysis, smartcasts + * NUMBER: 10 + * DESCRIPTION: Smartcasts with correspond contract function with default value in last parameter. + * ISSUES: KT-26444 + * HELPERS: contractFunctions + */ + +// FILE: contracts.kt + +package contracts + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(value_1: Int?, value_2: Int? = 10): Boolean { + contract { returns(true) implies (value_1 != null) } + return value_1 != null +} + +// TESTCASE NUMBER: 2 +fun case_2(value_1: Int? = 10, value_2: Int? = 10, value_3: Int? = 10): Boolean { + contract { returns(true) implies (value_2 != null) } + return value_1 != null +} + +// FILE: main.kt + +import contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(value_1: Int?) { + if (contracts.case_1(value_1)) { + value_1.inc() + } +} + +// TESTCASE NUMBER: 2 +fun case_2(value_1: Int?) { + if (contracts.case_2(10, value_1)) { + value_1.inc() + } +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/11.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/11.fir.kt new file mode 100644 index 00000000000..027765efe19 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/11.fir.kt @@ -0,0 +1,79 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (POSITIVE) + * + * SECTIONS: contracts, analysis, smartcasts + * NUMBER: 11 + * DESCRIPTION: Check smartcasts with passing same fields of instances of the same class in contract function with conjunction not-null condition. + * ISSUES: KT-26300 + * HELPERS: contractFunctions + */ + +// FILE: contracts.kt + +package contracts + +import kotlin.contracts.* + +// TESTCASE NUMBER: 3 +fun case_3(value_1: Any?, value_2: Any?, value_3: Any?, value_4: Any?) { + contract { returns() implies (value_1 is Float? && value_1 != null && value_2 != null && value_3 != null && value_4 != null) } + if (!(value_1 is Float? && value_1 != null && value_2 != null && value_3 != null && value_4 != null)) throw Exception() +} + +// TESTCASE NUMBER: 4 +fun case_4(value_1: Any?, value_2: Any?, value_3: Any?, value_4: Any?): Boolean { + contract { returns(true) implies (value_1 is Float? && value_1 != null && value_2 != null && value_3 != null && value_4 != null) } + return value_1 is Float? && value_1 != null && value_2 != null && value_3 != null && value_4 != null +} + +// FILE: main.kt + +import contracts.* + +// TESTCASE NUMBER: 1 +class case_1 { + val prop_1: Int? = 10 + fun case_1(value_1: Any?, value_2: Number?) { + val o = case_1() + funWithReturns(value_1 is Float? && value_1 != null && value_2 != null && o.prop_1 != null && this.prop_1 != null) + println(o.prop_1.plus(3)) + println(this.prop_1.plus(3)) + } +} + +// TESTCASE NUMBER: 2 +class case_2 { + val prop_1: Int? = 10 + fun case_2(value_1: Any?, value_2: Number?) { + val o = case_2() + if (funWithReturnsTrue(value_1 is Float? && value_1 != null && value_2 != null && o.prop_1 != null && this.prop_1 != null)) { + println(o.prop_1.plus(3)) + println(this.prop_1.plus(3)) + } + } +} + +// TESTCASE NUMBER: 3 +class case_3 { + val prop_1: Int? = 10 + fun case_3(value_1: Any?, value_2: Number?) { + val o = case_3() + contracts.case_3(value_1, value_2, o.prop_1, this.prop_1) + println(o.prop_1.plus(3)) + println(this.prop_1.plus(3)) + } +} + +// TESTCASE NUMBER: 4 +class case_4 { + val prop_1: Int? = 10 + fun case_4(value_1: Any?, value_2: Number?) { + val o = case_4() + if (contracts.case_4(value_1, value_2, o.prop_1, this.prop_1)) { + println(o.prop_1.plus(3)) + println(this.prop_1.plus(3)) + } + } +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/12.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/12.fir.kt new file mode 100644 index 00000000000..e27bb97132b --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/12.fir.kt @@ -0,0 +1,39 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts +// SKIP_TXT + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (POSITIVE) + * + * SECTIONS: contracts, analysis, smartcasts + * NUMBER: 12 + * DESCRIPTION: Smartcasts after non-null assertions or not-null value assignment in lambdas of contract function with 'exactly once' or 'at least once' CallsInPlace effects. + * UNEXPECTED BEHAVIOUR + * ISSUES: KT-26148 + * HELPERS: contractFunctions + */ + +// TESTCASE NUMBER: 1 +fun case_1(arg: Int?) { + funWithExactlyOnceCallsInPlace { arg!! } + arg.inc() +} + +// TESTCASE NUMBER: 2 +fun case_2(arg: Int?) { + funWithAtLeastOnceCallsInPlace { arg!! } + arg.inc() +} + +// TESTCASE NUMBER: 3 +fun case_3() { + val value_1: Boolean? + funWithExactlyOnceCallsInPlace { value_1 = false } + value_1.not() +} + +// TESTCASE NUMBER: 4 +fun case_4() { + val value_1: Boolean? + funWithAtLeastOnceCallsInPlace { value_1 = true } + value_1.not() +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/13.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/13.fir.kt new file mode 100644 index 00000000000..79abbdcfa00 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/13.fir.kt @@ -0,0 +1,45 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (POSITIVE) + * + * SECTIONS: contracts, analysis, smartcasts + * NUMBER: 13 + * DESCRIPTION: Check smartcast to upper bound of the types in disjunction. + * UNEXPECTED BEHAVIOUR + * ISSUES: KT-1982 + */ + +// FILE: contracts.kt + +package contracts + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +fun T?.case_1() { + contract { returns() implies (this@case_1 is Number || this@case_1 is Int) } + if (!(this@case_1 is Number || this@case_1 is Int)) throw Exception() +} + +// TESTCASE NUMBER: 2 +inline fun T?.case_2(value_2: Number, value_3: Any?, value_4: String?) { + contract { returns() implies ((this@case_2 is Number || this@case_2 is Int) && value_2 is Int && value_3 != null && value_3 is Number && value_4 != null) } + if (!((this is Number || this is Int) && value_2 is Int && value_3 != null && value_3 is Number && value_4 != null)) throw Exception() +} + +// FILE: main.kt + +import contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(value_1: Any?) { + value_1.case_1() + println(value_1.toByte()) +} + +// TESTCASE NUMBER: 2 +fun case_2(value_1: Any?, value_2: Number, value_3: Any?, value_4: String?) { + value_1.case_2(value_2, value_3, value_4) + println(value_1.toByte()) +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/14.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/14.fir.kt new file mode 100644 index 00000000000..bd52565e985 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/14.fir.kt @@ -0,0 +1,85 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (POSITIVE) + * + * SECTIONS: contracts, analysis, smartcasts + * NUMBER: 14 + * DESCRIPTION: Check smartcast with non-null assertion for a contract function. + * UNEXPECTED BEHAVIOUR + * ISSUES: KT-26856 + */ + +// FILE: contracts.kt + +package contracts + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(value_1: Int?): Boolean? { + contract { + returns(true) implies (value_1 != null) + } + + return value_1 != null +} + +// TESTCASE NUMBER: 2 +fun case_2(value_1: Int?): Boolean { + contract { + returns(false) implies (value_1 != null) + } + + return value_1 != null +} + +// TESTCASE NUMBER: 3 +fun case_3(value_1: Int?): Boolean? { + contract { + returnsNotNull() implies (value_1 != null) + } + + return value_1 != null +} + +// TESTCASE NUMBER: 4 +fun case_4(value_1: Any?): Boolean { + contract { + returnsNotNull() implies (value_1 is Number) + } + + return value_1 is Number +} + +// FILE: main.kt + +import contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(value_1: Int?) { + if (contracts.case_1(value_1)!!) { + value_1.inv() + } +} + +// TESTCASE NUMBER: 2 +fun case_2(value_1: Int?) { + if (!contracts.case_2(value_1)!!) { + value_1.inv() + } +} + +// TESTCASE NUMBER: 3 +fun case_3(value_1: Int?) { + if (contracts.case_3(value_1)!!) { + value_1.inv() + } +} + +// TESTCASE NUMBER: 4 +fun case_4(value_1: Any?) { + if (contracts.case_4(value_1) != null) { + value_1.toByte() + } +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/2.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/2.fir.kt new file mode 100644 index 00000000000..6d6854bb381 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/2.fir.kt @@ -0,0 +1,173 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts +// !WITH_NEW_INFERENCE +// SKIP_TXT + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (POSITIVE) + * + * SECTIONS: contracts, analysis, smartcasts + * NUMBER: 2 + * DESCRIPTION: Smartcasts using Returns effects with complex (conjunction/disjunction) type checking and not-null conditions outside contract (custom condition). + * HELPERS: contractFunctions + */ + +// TESTCASE NUMBER: 1 +fun case_1(value_1: Any?, value_2: Any?) { + funWithReturns(value_1 is String && value_2 is Number) + println(value_1.length) + println(value_2.toByte()) +} + +// TESTCASE NUMBER: 2 +fun case_2(value_1: Any?, value_2: Any?) { + funWithReturnsAndInvertCondition(value_1 !is String || value_2 !is Number) + println(value_1.length) + println(value_2.toByte()) +} + +// TESTCASE NUMBER: 3 +fun case_3(value_1: Any?, value_2: Any?) { + funWithReturnsAndInvertCondition(value_1 !is String || value_2 != null) + println(value_1.length) + println(value_2?.toByte()) +} + +// TESTCASE NUMBER: 4 +fun case_4(value_1: Any?, value_2: Number?) { + funWithReturns(value_1 is Float? && value_1 != null && value_2 != null) + println(value_1.dec()) + println(value_2?.toByte()) +} + +// TESTCASE NUMBER: 5 +class case_5_class { + val prop_1: Int? = 10 + + fun case_5(value_1: Any?, value_2: Number?) { + val o = case_5_class() + funWithReturns(value_1 is Float? && value_1 != null && value_2 != null && o.prop_1 != null) + println(value_1.dec()) + println(value_2?.toByte()) + println(o.prop_1.plus(3)) + } +} + +// TESTCASE NUMBER: 6 +fun case_6(value_1: Any?, value_2: Any) { + if (funWithReturnsTrue(value_1 is String && value_2 is Number)) { + println(value_1.length) + println(value_2.toByte()) + } + if (!funWithReturnsFalse(value_1 is String && value_2 is Number)) { + println(value_1.length) + println(value_2.toByte()) + } + if (funWithReturnsNotNull(value_1 is String && value_2 is Number) != null) { + println(value_1.length) + println(value_2.toByte()) + } + if (funWithReturnsNull(value_1 is String && value_2 is Number) == null) { + println(value_1.length) + println(value_2.toByte()) + } +} + +// TESTCASE NUMBER: 7 +fun case_7(value_1: Any?, value_2: Any?) { + if (funWithReturnsTrueAndInvertCondition(value_1 !is String || value_2 !is Number)) { + println(value_1.length) + println(value_2.toByte()) + } + if (!funWithReturnsFalseAndInvertCondition(value_1 !is String || value_2 !is Number)) { + println(value_1.length) + println(value_2.toByte()) + } + if (funWithReturnsNotNullAndInvertCondition(value_1 !is String || value_2 !is Number) != null) { + println(value_1.length) + println(value_2.toByte()) + } + if (funWithReturnsNullAndInvertCondition(value_1 !is String || value_2 !is Number) == null) { + println(value_1.length) + println(value_2.toByte()) + } +} + +// TESTCASE NUMBER: 8 +fun case_8(value_1: Any?, value_2: Any?) { + if (funWithReturnsTrueAndInvertCondition(value_1 !is String || value_2 != null)) { + println(value_1.length) + println(value_2?.toByte()) + } + if (!funWithReturnsFalseAndInvertCondition(value_1 !is String || value_2 != null)) { + println(value_1.length) + println(value_2?.toByte()) + } + if (funWithReturnsNotNullAndInvertCondition(value_1 !is String || value_2 != null) != null) { + println(value_1.length) + println(value_2?.toByte()) + } + if (funWithReturnsNullAndInvertCondition(value_1 !is String || value_2 != null) == null) { + println(value_1.length) + println(value_2?.toByte()) + } +} + +// TESTCASE NUMBER: 9 +fun case_9(value_1: Any?, value_2: Number?) { + if (funWithReturnsTrue(value_1 is Float? && value_1 != null && value_2 != null)) { + println(value_1.dec()) + println(value_2?.toByte()) + } + if (!funWithReturnsFalse(value_1 is Float? && value_1 != null && value_2 != null)) { + println(value_1.dec()) + println(value_2?.toByte()) + } + if (funWithReturnsNotNull(value_1 is Float? && value_1 != null && value_2 != null) != null) { + println(value_1.dec()) + println(value_2?.toByte()) + } + if (funWithReturnsNull(value_1 is Float? && value_1 != null && value_2 != null) == null) { + println(value_1.dec()) + println(value_2?.toByte()) + } +} + +// TESTCASE NUMBER: 10 +class case_10_class { + val prop_1: Int? = 10 + + fun case_10(value_1: Any?, value_2: Number?) { + val o = case_10_class() + if (funWithReturnsTrue(value_1 is Float? && value_1 != null && value_2 != null && o.prop_1 != null && this.prop_1 != null)) { + println(value_1.dec()) + println(value_2?.toByte()) + println(o.prop_1.plus(3)) + } + if (!funWithReturnsFalse(value_1 is Float? && value_1 != null && value_2 != null && o.prop_1 != null && this.prop_1 != null)) { + println(value_1.dec()) + println(value_2?.toByte()) + println(o.prop_1.plus(3)) + } + if (funWithReturnsNotNull(value_1 is Float? && value_1 != null && value_2 != null && o.prop_1 != null && this.prop_1 != null) != null) { + println(value_1.dec()) + println(value_2?.toByte()) + println(o.prop_1.plus(3)) + } + if (funWithReturnsNull(value_1 is Float? && value_1 != null && value_2 != null && o.prop_1 != null && this.prop_1 != null) == null) { + println(value_1.dec()) + println(value_2?.toByte()) + println(o.prop_1.plus(3)) + } + } +} + +/* + * TESTCASE NUMBER: 11 + * UNEXPECTED BEHAVIOUR + * ISSUES: KT-26747 + */ +fun case_11(value_1: Any?, value_2: Any?, value_3: Any?) { + funWithReturnsAndInvertCondition(value_1 !is String || value_2 !is Number || value_3 !is Any?) + println(value_1!!.length) + println(value_2?.toByte()) +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/3.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/3.fir.kt new file mode 100644 index 00000000000..60b9242d686 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/3.fir.kt @@ -0,0 +1,185 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (POSITIVE) + * + * SECTIONS: contracts, analysis, smartcasts + * NUMBER: 3 + * DESCRIPTION: Smartcasts using Returns effects with complex (conjunction/disjunction) type checking and not-null conditions inside contract. + */ + +// FILE: contracts.kt + +package contracts + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(value_1: Any?, value_2: Any?) { + contract { returns() implies (value_1 is String && value_2 is Number) } + if (!(value_1 is String && value_2 is Number)) throw Exception() +} + +// TESTCASE NUMBER: 2 +fun case_2(value_1: Any?, value_2: Any?) { + contract { returns() implies (value_1 is String && value_2 == null) } + if (!(value_1 is String && value_2 == null)) throw Exception() +} + +// TESTCASE NUMBER: 3 +fun case_3(value_1: Any?, value_2: Any?, value_3: Any?, value_4: Any?) { + contract { returns() implies (value_1 is Float? && value_1 != null && value_2 != null && value_3 != null && value_4 != null) } + if (!(value_1 is Float? && value_1 != null && value_2 != null && value_3 != null && value_4 != null)) throw Exception() +} + +// TESTCASE NUMBER: 4 +fun case_4_1(value_1: Any?, value_2: Any?): Boolean { + contract { returns(true) implies (value_1 is String && value_2 is Number) } + return value_1 is String && value_2 is Number +} +fun case_4_2(value_1: Any?, value_2: Any?): Boolean { + contract { returns(false) implies (value_1 is String && value_2 is Number) } + return !(value_1 is String && value_2 is Number) +} +fun case_4_3(value_1: Any?, value_2: Any?): Boolean? { + contract { returnsNotNull() implies (value_1 is String && value_2 is Number) } + return if (value_1 is String && value_2 is Number) true else null +} +fun case_4_4(value_1: Any?, value_2: Any?): Boolean? { + contract { returns(null) implies (value_1 is String && value_2 is Number) } + return if (value_1 is String && value_2 is Number) null else true +} + +// TESTCASE NUMBER: 5 +fun case_5_1(value_1: Any?, value_2: Any?): Boolean { + contract { returns(true) implies (value_1 is String && value_2 == null) } + return value_1 is String && value_2 == null +} +fun case_5_2(value_1: Any?, value_2: Any?): Boolean { + contract { returns(false) implies (value_1 is String && value_2 == null) } + return !(value_1 is String && value_2 == null) +} +fun case_5_3(value_1: Any?, value_2: Any?): Boolean? { + contract { returnsNotNull() implies (value_1 is String && value_2 == null) } + return if (value_1 is String && value_2 == null) true else null +} +fun case_5_4(value_1: Any?, value_2: Any?): Boolean? { + contract { returns(null) implies (value_1 is String && value_2 == null) } + return if (value_1 is String && value_2 == null) null else true +} + +// TESTCASE NUMBER: 6 +fun case_6_1(value_1: Any?, value_2: Any?, value_3: Any?, value_4: Any?): Boolean { + contract { returns(true) implies (value_1 is Float? && value_1 != null && value_2 != null && value_3 != null && value_4 != null) } + return value_1 is Float? && value_1 != null && value_2 != null && value_3 != null && value_4 != null +} +fun case_6_2(value_1: Any?, value_2: Any?, value_3: Any?, value_4: Any?): Boolean { + contract { returns(false) implies (value_1 is Float? && value_1 != null && value_2 != null && value_3 != null && value_4 != null) } + return !(value_1 is Float? && value_1 != null && value_2 != null && value_3 != null && value_4 != null) +} +fun case_6_3(value_1: Any?, value_2: Any?, value_3: Any?, value_4: Any?): Boolean? { + contract { returnsNotNull() implies (value_1 is Float? && value_1 != null && value_2 != null && value_3 != null && value_4 != null) } + return if (value_1 is Float? && value_1 != null && value_2 != null && value_3 != null && value_4 != null) true else null +} +fun case_6_4(value_1: Any?, value_2: Any?, value_3: Any?, value_4: Any?): Boolean? { + contract { returns(null) implies (value_1 is Float? && value_1 != null && value_2 != null && value_3 != null && value_4 != null) } + return if (value_1 is Float? && value_1 != null && value_2 != null && value_3 != null && value_4 != null) null else true +} + +// FILE: main.kt + +import contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(value_1: Any?, value_2: Any?) { + contracts.case_1(value_1, value_2) + println(value_1.length) + println(value_2.toByte()) +} + +// TESTCASE NUMBER: 2 +fun case_2(value_1: Any?, value_2: Any?) { + contracts.case_2(value_1, value_2) + println(value_1.length) + println(value_2?.toByte()) +} + +// TESTCASE NUMBER: 3 +class case_3_class { + val prop_1: Int? = 10 + fun case_3(value_1: Any?, value_2: Number?) { + val o = case_3_class() + contracts.case_3(value_1, value_2, o.prop_1, this.prop_1) + println(value_1.dec()) + println(value_2?.toByte()) + println(o.prop_1.plus(3)) + } +} + +// TESTCASE NUMBER: 4 +fun case_4(value_1: Any?, value_2: Any?) { + if (contracts.case_4_1(value_1, value_2)) { + println(value_1.length) + println(value_2.toByte()) + } + if (!contracts.case_4_2(value_1, value_2)) { + println(value_1.length) + println(value_2.toByte()) + } + if (contracts.case_4_3(value_1, value_2) != null) { + println(value_1.length) + println(value_2.toByte()) + } + if (contracts.case_4_4(value_1, value_2) == null) { + println(value_1.length) + println(value_2.toByte()) + } +} + +// TESTCASE NUMBER: 5 +fun case_5(value_1: Any?, value_2: Any?) { + if (contracts.case_5_1(value_1, value_2)) { + println(value_1.length) + println(value_2?.toByte()) + } + if (!contracts.case_5_2(value_1, value_2)) { + println(value_1.length) + println(value_2?.toByte()) + } + if (contracts.case_5_3(value_1, value_2) != null) { + println(value_1.length) + println(value_2?.toByte()) + } + if (contracts.case_5_4(value_1, value_2) == null) { + println(value_1.length) + println(value_2?.toByte()) + } +} + +// TESTCASE NUMBER: 6 +class case_6_class { + val prop_1: Int? = 10 + fun case_6(value_1: Any?, value_2: Number?) { + val o = case_6_class() + if (contracts.case_6_1(value_1, value_2, o.prop_1, this.prop_1)) { + println(value_1.dec()) + println(value_2?.toByte()) + println(o.prop_1.plus(3)) + } + if (!contracts.case_6_2(value_1, value_2, o.prop_1, this.prop_1)) { + println(value_1.dec()) + println(value_2?.toByte()) + println(o.prop_1.plus(3)) + } + if (contracts.case_6_3(value_1, value_2, o.prop_1, this.prop_1) != null) { + println(value_1.dec()) + println(value_2?.toByte()) + println(o.prop_1.plus(3)) + } + if (contracts.case_6_4(value_1, value_2, o.prop_1, this.prop_1) == null) { + println(value_1.dec()) + println(value_2?.toByte()) + println(o.prop_1.plus(3)) + } + } +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/4.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/4.fir.kt new file mode 100644 index 00000000000..408de5e23cb --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/4.fir.kt @@ -0,0 +1,257 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts +// !WITH_NEW_INFERENCE + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (POSITIVE) + * + * SECTIONS: contracts, analysis, smartcasts + * NUMBER: 4 + * DESCRIPTION: Smartcasts using Returns effects with simple type checking and not-null conditions on receiver inside contract. + */ + +// FILE: contracts.kt + +package contracts + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +fun T.case_1() { + contract { returns() implies (this@case_1 is String) } + if (!(this@case_1 is String)) throw Exception() +} + +// TESTCASE NUMBER: 2 +fun T.case_2() { + contract { returns() implies (this@case_2 is Int) } + if (!(this@case_2 is Int)) throw Exception() +} + +// TESTCASE NUMBER: 3 +fun T?.case_3_1() { + contract { returns() implies (this@case_3_1 != null) } + if (!(this@case_3_1 != null)) throw Exception() +} +fun T?.case_3_2() { + contract { returns() implies (this@case_3_2 == null) } + if (!(this@case_3_2 == null)) throw Exception() +} + +// TESTCASE NUMBER: 4 +fun T.case_4_1() { + contract { returns() implies (this@case_4_1 != null) } + if (!(this@case_4_1 != null)) throw Exception() +} +fun T.case_4_2() { + contract { returns() implies (this@case_4_2 == null) } + if (!(this@case_4_2 == null)) throw Exception() +} + +// TESTCASE NUMBER: 5 +fun T.case_5_1(): Boolean { + contract { returns(true) implies (this@case_5_1 is String) } + return this@case_5_1 is String +} +fun T.case_5_2(): Boolean { + contract { returns(false) implies (this@case_5_2 is String) } + return !(this@case_5_2 is String) +} +fun T.case_5_3(): Boolean? { + contract { returnsNotNull() implies (this@case_5_3 is String) } + return if (this@case_5_3 is String) true else null +} +fun T.case_5_4(): Boolean? { + contract { returns(null) implies (this@case_5_4 is String) } + return if (this@case_5_4 is String) null else true +} + +// TESTCASE NUMBER: 6 +fun T.case_6_1(): Boolean { + contract { returns(true) implies (this@case_6_1 is Int) } + return this@case_6_1 is Int +} +fun T.case_6_2(): Boolean { + contract { returns(false) implies (this@case_6_2 is Int) } + return !(this@case_6_2 is Int) +} +fun T.case_6_3(): Boolean? { + contract { returnsNotNull() implies (this@case_6_3 is Int) } + return if (this@case_6_3 is Int) true else null +} +fun T.case_6_4(): Boolean? { + contract { returns(null) implies (this@case_6_4 is Int) } + return if (this@case_6_4 is Int) null else true +} + +// TESTCASE NUMBER: 7 +fun T?.case_7_1(): Boolean { + contract { returns(true) implies (this@case_7_1 != null) } + return this@case_7_1 != null +} +fun T?.case_7_2(): Boolean { + contract { returns(true) implies (this@case_7_2 == null) } + return this@case_7_2 == null +} +fun T?.case_7_3(): Boolean? { + contract { returnsNotNull() implies (this@case_7_3 == null) } + return if (this@case_7_3 == null) true else null +} +fun T?.case_7_4(): Boolean? { + contract { returns(null) implies (this@case_7_4 == null) } + return if (this@case_7_4 == null) null else true +} +fun T?.case_7_5(): Boolean { + contract { returns(false) implies (this@case_7_5 == null) } + return !(this@case_7_5 == null) +} +fun T?.case_7_6(): Boolean? { + contract { returnsNotNull() implies (this@case_7_6 != null) } + return if (this@case_7_6 != null) true else null +} +fun T?.case_7_7(): Boolean? { + contract { returns(null) implies (this@case_7_7 != null) } + return if (this@case_7_7 != null) null else true +} +fun T?.case_7_8(): Boolean { + contract { returns(false) implies (this@case_7_8 != null) } + return !(this@case_7_8 != null) +} +fun T?.case_7_9(): Boolean { + contract { returns(false) implies (this@case_7_9 == null) } + return !(this@case_7_9 == null) +} +fun T?.case_7_10(): Boolean? { + contract { returnsNotNull() implies (this@case_7_10 == null) } + return if (this@case_7_10 == null) true else null +} +fun T?.case_7_11(): Boolean? { + contract { returns(null) implies (this@case_7_11 == null) } + return if (this@case_7_11 == null) null else true +} + +// TESTCASE NUMBER: 8 +fun T.case_8_1(): Boolean { + contract { returns(true) implies (this@case_8_1 != null) } + return this@case_8_1 != null +} +fun T.case_8_2(): Boolean { + contract { returns(true) implies (this@case_8_2 == null) } + return this@case_8_2 == null +} +fun T.case_8_3(): Boolean? { + contract { returnsNotNull() implies (this@case_8_3 == null) } + return if (this@case_8_3 == null) true else null +} +fun T.case_8_4(): Boolean? { + contract { returns(null) implies (this@case_8_4 == null) } + return if (this@case_8_4 == null) null else true +} + +// TESTCASE NUMBER: 9 +fun T?.case_9_1(): Boolean { + contract { returns(true) implies (this@case_9_1 is Float) } + return this@case_9_1 is Float +} +fun T?.case_9_2(): Boolean { + contract { returns(false) implies (this@case_9_2 is Double) } + return !(this@case_9_2 is Double) +} + +// FILE: main.kt + +import contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(value_1: Any?) { + value_1.case_1() + println(value_1.length) +} + +// TESTCASE NUMBER: 2 +fun case_2(value_1: Number) { + value_1.case_2() + println(value_1.inv()) +} + +// TESTCASE NUMBER: 3 +fun case_3(value_1: String?, value_2: String?) { + value_1.case_3_1() + println(value_1.length) + value_2.case_3_2() + println(value_2) +} + +// TESTCASE NUMBER: 4 +fun case_4(value_1: String?, value_2: String?) { + value_1.case_4_1() + println(value_1.length) + value_2.case_4_2() + println(value_2) +} + +// TESTCASE NUMBER: 5 +fun case_5(value_1: Any?) { + if (value_1.case_5_1()) println(value_1.length) + if (!value_1.case_5_2()) println(value_1.length) + if (value_1.case_5_3() != null) println(value_1.length) + if (value_1.case_5_4() == null) println(value_1.length) +} + +// TESTCASE NUMBER: 6 +fun case_6(value_1: Number) { + when { value_1.case_6_1() -> println(value_1.inv()) } + when { !value_1.case_6_2() -> println(value_1.inv()) } + when { value_1.case_6_3() != null -> println(value_1.inv()) } + when { value_1.case_6_4() == null -> println(value_1.inv()) } +} + +// TESTCASE NUMBER: 7 +fun case_7(value_1: String?) { + if (value_1.case_7_1()) println(value_1.length) + if (value_1.case_7_2()) println(value_1) + if (!(value_1.case_7_3() == null)) println(value_1) + if (!(value_1.case_7_4() != null)) println(value_1) + if (!value_1.case_7_5()) println(value_1) + else println(value_1) + when (value_1.case_7_6() == null) { + true -> println(value_1) + false -> println(value_1.length) + } + if (value_1.case_7_7() != null) println(value_1) + else println(value_1.length) + when { + !value_1.case_7_8() -> println(value_1) + value_1.case_7_8() -> println(value_1) + } + when { + !value_1.case_7_9() -> println(value_1) + value_1.case_7_9() -> println(value_1) + } + when { + value_1.case_7_10() == null -> println(value_1) + value_1.case_7_10() != null -> println(value_1) + } + when { + value_1.case_7_11() != null -> println(value_1) + value_1.case_7_11() == null -> println(value_1) + } +} + +// TESTCASE NUMBER: 8 +fun case_8(value_1: String?, value_2: String?) { + when { value_1.case_8_1() -> println(value_1.length) } + when { value_2.case_8_2() -> println(value_2) } + when { !(value_2.case_8_3() == null) -> println(value_2) } + when { !(value_2.case_8_4() != null) -> println(value_2) } +} + +/* + * TESTCASE NUMBER: 9 + * UNEXPECTED BEHAVIOUR + * ISSUES: KT-1982 + */ +fun case_9(value_1: Any?) { + if (value_1.case_9_1() || !value_1.case_9_2()) { + println(value_1.toByte()) + } +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/5.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/5.fir.kt new file mode 100644 index 00000000000..9bc82faf590 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/5.fir.kt @@ -0,0 +1,133 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (POSITIVE) + * + * SECTIONS: contracts, analysis, smartcasts + * NUMBER: 5 + * DESCRIPTION: Smartcasts using Returns effects with complex (conjunction/disjunction) type checking and not-null conditions on receiver inside contract. + */ + +// FILE: contracts.kt + +package contracts + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +fun T?.case_1() { + contract { returns() implies (this@case_1 != null && this@case_1 is String) } + if (!(this@case_1 != null && this@case_1 is String)) throw Exception() +} + +// TESTCASE NUMBER: 2 +fun T.case_2() { + contract { returns() implies (this@case_2 is Int && this@case_2 != null) } + if (!(this@case_2 is Int && this@case_2 != null)) throw Exception() +} + +// TESTCASE NUMBER: 3 +inline fun T?.case_3() { + contract { returns() implies (this@case_3 is Number && this@case_3 is Int && this@case_3 != null) } + if (!(this@case_3 is Number && this@case_3 is Int && this@case_3 != null)) throw Exception() +} + +// TESTCASE NUMBER: 4 +fun T?.case_4_1(): Boolean { + contract { returns(true) implies (this@case_4_1 != null && this@case_4_1 is String) } + return this@case_4_1 != null && this@case_4_1 is String +} +fun T?.case_4_2(): Boolean { + contract { returns(false) implies (this@case_4_2 != null && this@case_4_2 is String) } + return !(this@case_4_2 != null && this@case_4_2 is String) +} +fun T?.case_4_3(): Boolean? { + contract { returnsNotNull() implies (this@case_4_3 != null && this@case_4_3 is String) } + return if (this@case_4_3 != null && this@case_4_3 is String) true else null +} +fun T?.case_4_4(): Boolean? { + contract { returns(null) implies (this@case_4_4 != null && this@case_4_4 is String) } + return if (this@case_4_4 != null && this@case_4_4 is String) null else true +} + +// TESTCASE NUMBER: 5 +fun T.case_5_1(): Boolean { + contract { returns(true) implies (this@case_5_1 is Int && this@case_5_1 != null) } + return this@case_5_1 is Int && this@case_5_1 != null +} +fun T.case_5_2(): Boolean { + contract { returns(false) implies (this@case_5_2 is Int && this@case_5_2 != null) } + return !(this@case_5_2 is Int && this@case_5_2 != null) +} +fun T.case_5_3(): Boolean? { + contract { returnsNotNull() implies (this@case_5_3 is Int && this@case_5_3 != null) } + return if (this@case_5_3 is Int && this@case_5_3 != null) true else null +} +fun T.case_5_4(): Boolean? { + contract { returns(null) implies (this@case_5_4 is Int && this@case_5_4 != null) } + return if (this@case_5_4 is Int && this@case_5_4 != null) null else true +} + +// TESTCASE NUMBER: 6 +inline fun T?.case_6_1(): Boolean { + contract { returns(true) implies (this@case_6_1 is Number && this@case_6_1 is Int && this@case_6_1 != null) } + return this@case_6_1 is Number && this@case_6_1 is Int && this@case_6_1 != null +} +inline fun T?.case_6_2(): Boolean { + contract { returns(false) implies (this@case_6_2 is Number && this@case_6_2 is Int && this@case_6_2 != null) } + return !(this@case_6_2 is Number && this@case_6_2 is Int && this@case_6_2 != null) +} +inline fun T?.case_6_3(): Boolean? { + contract { returnsNotNull() implies (this@case_6_3 is Number && this@case_6_3 is Int && this@case_6_3 != null) } + return if (this@case_6_3 is Number && this@case_6_3 is Int && this@case_6_3 != null) true else null +} +inline fun T?.case_6_4(): Boolean? { + contract { returns(null) implies (this@case_6_4 is Number && this@case_6_4 is Int && this@case_6_4 != null) } + return if (this@case_6_4 is Number && this@case_6_4 is Int && this@case_6_4 != null) null else true +} + +// FILE: main.kt + +import contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(value_1: Any?) { + value_1.case_1() + println(value_1.length) +} + +// TESTCASE NUMBER: 2 +fun case_2(value_1: Number?) { + value_1.case_2() + println(value_1.inv()) +} + +// TESTCASE NUMBER: 3 +fun case_3(value_1: Any?) { + value_1.case_3() + println(value_1.inv()) +} + +// TESTCASE NUMBER: 4 +fun case_4(value_1: Any?, value_2: Any?, value_3: Any?) { + when { value_1.case_4_1() -> println(value_1.length) } + when { !value_2.case_4_2() -> println(value_2.length) } + when { value_3.case_4_3() != null -> println(value_3.length) } + when { value_3.case_4_4() == null -> println(value_3.length) } +} + +// TESTCASE NUMBER: 5 +fun case_5(value_1: Number?, value_2: Number?, value_3: Number?) { + if (value_1.case_5_1()) println(value_1.inv()) + if (!value_2.case_5_2()) println(value_2.inv()) + if (value_3.case_5_3() != null) println(value_3.inv()) + if (value_3.case_5_4() == null) println(value_3.inv()) +} + +// TESTCASE NUMBER: 6 +fun case_6(value_1: Any?, value_2: Any?, value_3: Any?) { + if (value_1.case_6_1()) println(value_1.inv()) + if (!value_2.case_6_2()) println(value_2.inv()) + if (value_3.case_6_3() != null) println(value_3.inv()) + if (value_3.case_6_4() == null) println(value_3.inv()) +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/6.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/6.fir.kt new file mode 100644 index 00000000000..27ea16b83ca --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/6.fir.kt @@ -0,0 +1,228 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (POSITIVE) + * + * SECTIONS: contracts, analysis, smartcasts + * NUMBER: 6 + * DESCRIPTION: Smartcasts using Returns effects with complex (conjunction/disjunction) type checking and not-null conditions on receiver and some values (mixed) inside contract. + */ + +// FILE: contracts.kt + +package contracts + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +fun T?.case_1(value_1: Int?) { + contract { returns() implies (this@case_1 != null && this@case_1 is String && value_1 != null) } + if (!(this@case_1 != null && this@case_1 is String && value_1 != null)) throw Exception() +} + +// TESTCASE NUMBER: 2 +fun T.case_2(value_2: Any?) { + contract { returns() implies (this@case_2 is Int && this@case_2 != null && value_2 is Number && value_2 != null) } + if (!(this@case_2 is Int && this@case_2 != null && value_2 is Number && value_2 != null)) throw Exception() +} + +// TESTCASE NUMBER: 3 +fun T?.case_3(value_2: Any?) { + contract { returns() implies (this@case_3 is Number && this@case_3 is Int && this@case_3 != null && value_2 != null) } + if (!(this@case_3 is Number && this@case_3 is Int && this@case_3 != null && value_2 != null)) throw Exception() +} + +// TESTCASE NUMBER: 4 +inline fun T?.case_4(value_2: Number, value_3: Any?, value_4: String?) { + contract { returns() implies ((this@case_4 is Number || this@case_4 is Int) && value_2 is Int && value_3 != null && value_3 is Number && value_4 != null) } + if (!((this@case_4 is Number || this@case_4 is Int) && value_2 is Int && value_3 != null && value_3 is Number && value_4 != null)) throw Exception() +} + +// TESTCASE NUMBER: 5 +fun T?.case_5_1(value_1: Int?): Boolean { + contract { returns(true) implies (this@case_5_1 != null && this@case_5_1 is String && value_1 != null) } + return this@case_5_1 != null && this@case_5_1 is String && value_1 != null +} +fun T?.case_5_2(value_1: Int?): Boolean { + contract { returns(false) implies (this@case_5_2 != null && this@case_5_2 is String && value_1 != null) } + return !(this@case_5_2 != null && this@case_5_2 is String && value_1 != null) +} +fun T?.case_5_3(value_1: Int?): Boolean? { + contract { returnsNotNull() implies (this@case_5_3 != null && this@case_5_3 is String && value_1 != null) } + return if (this@case_5_3 != null && this@case_5_3 is String && value_1 != null) true else null +} +fun T?.case_5_4(value_1: Int?): Boolean? { + contract { returns(null) implies (this@case_5_4 != null && this@case_5_4 is String && value_1 != null) } + return if (this@case_5_4 != null && this@case_5_4 is String && value_1 != null) null else true +} + +// TESTCASE NUMBER: 6 +fun T.case_6_1(value_2: Any?): Boolean { + contract { returns(true) implies (this@case_6_1 is Int && this@case_6_1 != null && value_2 is Number && value_2 != null) } + return this@case_6_1 is Int && this@case_6_1 != null && value_2 is Number && value_2 != null +} +fun T.case_6_2(value_2: Any?): Boolean { + contract { returns(false) implies (this@case_6_2 is Int && this@case_6_2 != null && value_2 is Number && value_2 != null) } + return !(this@case_6_2 is Int && this@case_6_2 != null && value_2 is Number && value_2 != null) +} +fun T.case_6_3(value_2: Any?): Boolean? { + contract { returnsNotNull() implies (this@case_6_3 is Int && this@case_6_3 != null && value_2 is Number && value_2 != null) } + return if (this@case_6_3 is Int && this@case_6_3 != null && value_2 is Number && value_2 != null) true else null +} +fun T.case_6_4(value_2: Any?): Boolean? { + contract { returns(null) implies (this@case_6_4 is Int && this@case_6_4 != null && value_2 is Number && value_2 != null) } + return if (this@case_6_4 is Int && this@case_6_4 != null && value_2 is Number && value_2 != null) null else true +} + +// TESTCASE NUMBER: 7 +fun T?.case_7_1(value_2: Any?): Boolean { + contract { returns(true) implies (this@case_7_1 is Number && this@case_7_1 is Int && this@case_7_1 != null && value_2 != null) } + return this@case_7_1 is Number && this@case_7_1 is Int && this@case_7_1 != null && value_2 != null +} +fun T?.case_7_2(value_2: Any?): Boolean { + contract { returns(true) implies (this@case_7_2 is Number && this@case_7_2 is Int && this@case_7_2 != null && value_2 != null) } + return this@case_7_2 is Number && this@case_7_2 is Int && this@case_7_2 != null && value_2 != null +} +fun T?.case_7_3(value_2: Any?): Boolean? { + contract { returnsNotNull() implies (this@case_7_3 is Number && this@case_7_3 is Int && this@case_7_3 != null && value_2 != null) } + return if (this@case_7_3 is Number && this@case_7_3 is Int && this@case_7_3 != null && value_2 != null) true else null +} +fun T?.case_7_4(value_2: Any?): Boolean? { + contract { returns(null) implies (this@case_7_4 is Number && this@case_7_4 is Int && this@case_7_4 != null && value_2 != null) } + return if (this@case_7_4 is Number && this@case_7_4 is Int && this@case_7_4 != null && value_2 != null) null else true +} + +// TESTCASE NUMBER: 8 +inline fun T?.case_8_1(value_2: Number, value_3: Any?, value_4: String?): Boolean { + contract { returns(true) implies ((this@case_8_1 is Number || this@case_8_1 is Int) && value_2 is Int && value_3 != null && value_3 is Number && value_4 != null) } + return (this@case_8_1 is Number || this@case_8_1 is Int) && value_2 is Int && value_3 != null && value_3 is Number && value_4 != null +} +inline fun T?.case_8_2(value_2: Number, value_3: Any?, value_4: String?): Boolean { + contract { returns(false) implies ((this@case_8_2 is Number || this@case_8_2 is Int) && value_2 is Int && value_3 != null && value_3 is Number && value_4 != null) } + return !((this@case_8_2 is Number || this@case_8_2 is Int) && value_2 is Int && value_3 != null && value_3 is Number && value_4 != null) +} +inline fun T?.case_8_3(value_2: Number, value_3: Any?, value_4: String?): Boolean? { + contract { returnsNotNull() implies ((this@case_8_3 is Number || this@case_8_3 is Int) && value_2 is Int && value_3 != null && value_3 is Number && value_4 != null) } + return if ((this@case_8_3 is Number || this@case_8_3 is Int) && value_2 is Int && value_3 != null && value_3 is Number && value_4 != null) true else null +} +inline fun T?.case_8_4(value_2: Number, value_3: Any?, value_4: String?): Boolean? { + contract { returns(null) implies ((this@case_8_4 is Number || this@case_8_4 is Int) && value_2 is Int && value_3 != null && value_3 is Number && value_4 != null) } + return if ((this@case_8_4 is Number || this@case_8_4 is Int) && value_2 is Int && value_3 != null && value_3 is Number && value_4 != null) null else true +} + +// FILE: main.kt + +import contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(value_1: Any?, value_2: Int?) { + value_1.case_1(value_2) + println(value_1.length) + println(value_2.inv()) +} + +// TESTCASE NUMBER: 2 +fun case_2(value_1: Number?, value_2: Any?) { + value_1.case_2(value_2) + println(value_1.inv()) + println(value_2.toByte()) +} + +// TESTCASE NUMBER: 3 +fun case_3(value_1: Any?, value_2: String?) { + value_1.case_3(value_2) + println(value_1.inv()) + println(value_2.length) +} + +// TESTCASE NUMBER: 4 +fun case_4(value_1: Any?, value_2: Number, value_3: Any?, value_4: String?) { + value_1.case_4(value_2, value_3, value_4) + println(value_2.inv()) + println(value_3.toByte()) + println(value_4.length) +} + +// TESTCASE NUMBER: 5 +fun case_5(value_1: Any?, value_2: Int?, value_3: Any?, value_4: Int?, value_5: Any?, value_6: Int?) { + when { + value_1.case_5_1(value_2) -> { + println(value_1.length) + println(value_2.inv()) + } + } + when { + !value_3.case_5_2(value_4) -> { + println(value_3.length) + println(value_4.inv()) + } + } + when { + value_5.case_5_3(value_6) != null -> { + println(value_5.length) + println(value_6.inv()) + } + } + when { + value_5.case_5_4(value_6) == null -> { + println(value_5.length) + println(value_6.inv()) + } + } +} + +// TESTCASE NUMBER: 6 +fun case_6(value_1: Number?, value_2: Any?, value_3: Number?, value_4: Any?, value_5: Number?, value_6: Any?) { + if (value_1.case_6_1(value_2)) { + println(value_1.inv()) + println(value_2.toByte()) + } + if (!value_3.case_6_2(value_4)) { + println(value_3.inv()) + println(value_4.toByte()) + } + if (value_5.case_6_3(value_6) != null) { + println(value_5.inv()) + println(value_6.toByte()) + } + if (value_5.case_6_4(value_6) == null) { + println(value_5.inv()) + println(value_6.toByte()) + } +} + +// TESTCASE NUMBER: 7 +fun case_7(value_1: Any?, value_2: String?, value_3: Any?, value_4: String?, value_5: Any?, value_6: String?) { + if (value_1.case_7_1(value_2)) { + println(value_1.inv()) + println(value_2.length) + } + if (value_3.case_7_2(value_4)) { + println(value_3.inv()) + println(value_4.length) + } + if (value_5.case_7_3(value_6) != null) { + println(value_5.inv()) + println(value_6.length) + } + if (value_5.case_7_4(value_6) == null) { + println(value_5.inv()) + println(value_6.length) + } +} + +// TESTCASE NUMBER: 8 +fun case_8(value_1: Any?, value_2: Number, value_3: Any?, value_4: String?, value_5: Any?, value_6: Number, value_7: Any?, value_8: String?) { + when { value_1.case_8_1(value_2, value_3, value_4) -> println(value_2.inv()) } + when { value_1.case_8_1(value_2, value_3, value_4) -> println(value_3.toByte()) } + when { value_1.case_8_1(value_2, value_3, value_4) -> println(value_4.length) } + when { !value_5.case_8_2(value_6, value_7, value_8) -> println(value_6.inv()) } + when { !value_5.case_8_2(value_6, value_7, value_8) -> println(value_7.toByte()) } + when { !value_5.case_8_2(value_6, value_7, value_8) -> println(value_8.length) } + when { value_5.case_8_3(value_6, value_7, value_8) != null -> println(value_6.inv()) } + when { value_5.case_8_3(value_6, value_7, value_8) != null -> println(value_7.toByte()) } + when { value_5.case_8_3(value_6, value_7, value_8) != null -> println(value_8.length) } + when { value_5.case_8_4(value_6, value_7, value_8) == null -> println(value_6.inv()) } + when { value_5.case_8_4(value_6, value_7, value_8) == null -> println(value_7.toByte()) } + when { value_5.case_8_4(value_6, value_7, value_8) == null -> println(value_8.length) } +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/7.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/7.fir.kt new file mode 100644 index 00000000000..c63006af430 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/7.fir.kt @@ -0,0 +1,363 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (POSITIVE) + * + * SECTIONS: contracts, analysis, smartcasts + * NUMBER: 7 + * DESCRIPTION: Smartcasts using Returns effects with nested or subsequent contract function calls. + */ + +// FILE: contracts.kt + +package contracts + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +fun case_1_1(value_1: Int?) { + contract { returns() implies (value_1 != null) } + if (!(value_1 != null)) throw Exception() +} +fun case_1_2(value_1: Int?) { + contract { returns() implies (value_1 == null) } + if (!(value_1 == null)) throw Exception() +} + +// TESTCASE NUMBER: 2 +fun case_2_1(value_1: Number?) { + contract { returns() implies (value_1 is Float) } + if (!(value_1 is Float)) throw Exception() +} +fun case_2_2(value_1: Number?) { + contract { returns() implies (value_1 is Int) } + if (!(value_1 is Int)) throw Exception() +} + +// TESTCASE NUMBER: 3 +fun case_3_1(value_1: Any?) { + contract { returns() implies (value_1 is String) } + if (!(value_1 is String)) throw Exception() +} +fun case_3_2(value_1: Any?) { + contract { returns() implies (value_1 !is String) } + if (!(value_1 !is String)) throw Exception() +} + +// TESTCASE NUMBER: 4 +fun case_4_1(value_1: Any?) { + contract { returns() implies (value_1 is Number?) } + if (!(value_1 is Number?)) throw Exception() +} +fun case_4_2(value_1: Number?) { + contract { returns() implies (value_1 != null) } + if (!(value_1 != null)) throw Exception() +} +fun case_4_3(value_1: Number) { + contract { returns() implies (value_1 is Int) } + if (!(value_1 is Int)) throw Exception() +} + +// TESTCASE NUMBER: 5 +fun case_5_1(value_1: Int?): Boolean { + contract { returns(true) implies (value_1 != null) } + return value_1 != null +} +fun case_5_2(value_1: Int?): Boolean { + contract { returns(true) implies (value_1 == null) } + return value_1 == null +} +fun case_5_3(value_1: Int?): Boolean { + contract { returns(false) implies (value_1 != null) } + return !(value_1 != null) +} +fun case_5_4(value_1: Int?): Boolean { + contract { returns(false) implies (value_1 == null) } + return !(value_1 == null) +} +fun case_5_5(value_1: Int?): Boolean? { + contract { returnsNotNull() implies (value_1 != null) } + return if (value_1 != null) true else null +} +fun case_5_6(value_1: Int?): Boolean? { + contract { returnsNotNull() implies (value_1 == null) } + return if (value_1 == null) true else null +} +fun case_5_7(value_1: Int?): Boolean? { + contract { returns(null) implies (value_1 != null) } + return if (value_1 != null) null else true +} +fun case_5_8(value_1: Int?): Boolean? { + contract { returns(null) implies (value_1 == null) } + return if (value_1 == null) null else true +} + +// TESTCASE NUMBER: 6 +fun case_6_1(value_1: Number?): Boolean { + contract { returns(true) implies (value_1 is Float) } + return value_1 is Float +} +fun case_6_2(value_1: Number?): Boolean { + contract { returns(true) implies (value_1 is Int) } + return value_1 is Int +} +fun case_6_3(value_1: Number?): Boolean { + contract { returns(false) implies (value_1 is Float) } + return !(value_1 is Float) +} +fun case_6_4(value_1: Number?): Boolean { + contract { returns(false) implies (value_1 is Int) } + return !(value_1 is Int) +} +fun case_6_5(value_1: Number?): Boolean? { + contract { returnsNotNull() implies (value_1 is Float) } + return if (value_1 is Float) true else null +} +fun case_6_6(value_1: Number?): Boolean? { + contract { returnsNotNull() implies (value_1 is Int) } + return if (value_1 is Int) true else null +} +fun case_6_7(value_1: Number?): Boolean? { + contract { returns(null) implies (value_1 is Float) } + return if (value_1 is Float) null else true +} +fun case_6_8(value_1: Number?): Boolean? { + contract { returns(null) implies (value_1 is Int) } + return if (value_1 is Int) null else true +} + +// TESTCASE NUMBER: 7 +fun case_7_1(value_1: Any?): Boolean { + contract { returns(true) implies (value_1 is String) } + return value_1 is String +} +fun case_7_2(value_1: Any?): Boolean { + contract { returns(true) implies (value_1 !is String) } + return value_1 !is String +} +fun case_7_3(value_1: Any?): Boolean { + contract { returns(false) implies (value_1 is String) } + return !(value_1 is String) +} +fun case_7_4(value_1: Any?): Boolean { + contract { returns(false) implies (value_1 !is String) } + return !(value_1 !is String) +} +fun case_7_5(value_1: Any?): Boolean? { + contract { returnsNotNull() implies (value_1 is String) } + return if (value_1 is String) true else null +} +fun case_7_6(value_1: Any?): Boolean? { + contract { returnsNotNull() implies (value_1 !is String) } + return if (value_1 !is String) true else null +} +fun case_7_7(value_1: Any?): Boolean? { + contract { returns(null) implies (value_1 is String) } + return if (value_1 is String) null else true +} +fun case_7_8(value_1: Any?): Boolean? { + contract { returns(null) implies (value_1 !is String) } + return if (value_1 !is String) null else true +} + +// TESTCASE NUMBER: 8 +fun case_8_1(value_1: Any?): Boolean { + contract { returns(true) implies (value_1 is Number?) } + return value_1 is Number? +} +fun case_8_2(value_1: Number?): Boolean { + contract { returns(true) implies (value_1 != null) } + return value_1 != null +} +fun case_8_3(value_1: Number): Boolean { + contract { returns(true) implies (value_1 is Int) } + return value_1 is Int +} +fun case_8_4(value_1: Any?): Boolean { + contract { returns(false) implies (value_1 is Number?) } + return !(value_1 is Number?) +} +fun case_8_5(value_1: Number?): Boolean { + contract { returns(false) implies (value_1 != null) } + return !(value_1 != null) +} +fun case_8_6(value_1: Number): Boolean { + contract { returns(false) implies (value_1 is Int) } + return !(value_1 is Int) +} +fun case_8_7(value_1: Any?): Boolean? { + contract { returnsNotNull() implies (value_1 is Number?) } + return if (value_1 is Number?) true else null +} +fun case_8_8(value_1: Number?): Boolean? { + contract { returnsNotNull() implies (value_1 != null) } + return if (value_1 != null) true else null +} +fun case_8_9(value_1: Number): Boolean? { + contract { returnsNotNull() implies (value_1 is Int) } + return if (value_1 is Int) true else null +} +fun case_8_10(value_1: Any?): Boolean? { + contract { returns(null) implies (value_1 is Number?) } + return if (value_1 is Number?) null else true +} +fun case_8_11(value_1: Number?): Boolean? { + contract { returns(null) implies (value_1 != null) } + return if (value_1 != null) null else true +} +fun case_8_12(value_1: Number): Boolean? { + contract { returns(null) implies (value_1 is Int) } + return if (value_1 is Int) null else true +} + +// FILE: main.kt + +import contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(value_1: Int?) { + case_1_1(value_1) + value_1.inv() + case_1_2(value_1) + value_1.inv() + case_1_1(value_1) + value_1.inv() +} + +// TESTCASE NUMBER: 2 +fun case_2(value_1: Number?) { + case_2_1(value_1) + value_1.toByte() + case_2_2(value_1) + value_1.inv() +} + +// TESTCASE NUMBER: 3 +fun case_3(value_1: Any?) { + case_3_1(value_1) + value_1.length + case_3_2(value_1) + value_1.length +} + +// TESTCASE NUMBER: 4 +fun case_4(value_1: Any?) { + case_4_1(value_1) + value_1?.toByte() + case_4_2(value_1) + value_1.toByte() + case_4_3(value_1) + value_1.inv() +} + +// TESTCASE NUMBER: 5 +fun case_5(value_1: Int?, value_2: Int?) { + if (case_5_1(value_1)) { + value_1.inv() + if (case_5_2(value_1)) { + value_1.inv() + value_1.inv() + } + } + if (!case_5_3(value_2)) { + value_2.inv() + if (!case_5_4(value_2)) { + value_2.inv() + value_2.inv() + } + } + if (case_5_5(value_2) != null) { + value_2.inv() + if (case_5_6(value_2) != null) { + value_2.inv() + value_2.inv() + } + } + if (case_5_7(value_2) == null) { + value_2.inv() + if (case_5_8(value_2) == null) { + value_2.inv() + value_2.inv() + } + } +} + +// TESTCASE NUMBER: 6 +fun case_6(value_1: Number?, value_2: Number?) { + when { + case_6_1(value_1) -> { + value_1.toByte() + when { case_6_2(value_1) -> value_1.inv() } + } + } + when { + !case_6_3(value_2) -> { + value_2.toByte() + when { !case_6_4(value_2) -> value_2.inv() } + } + } + when { + case_6_5(value_2) != null -> { + value_2.toByte() + when { case_6_6(value_2) != null -> value_2.inv() } + } + } + when { + case_6_7(value_2) == null -> { + value_2.toByte() + when { case_6_8(value_2) == null -> value_2.inv() } + } + } +} + +// TESTCASE NUMBER: 7 +fun case_7(value_1: Any?, value_2: Any?) { + if (case_7_1(value_1)) { + value_1.length + if (case_7_2(value_1)) value_1.length + } + if (!case_7_3(value_2)) { + value_2.length + if (!case_7_4(value_2)) value_2.length + } + if (case_7_5(value_2) != null) { + value_2.length + if (case_7_6(value_2) != null) value_2.length + } + if (case_7_7(value_2) == null) { + value_2.length + if (case_7_8(value_2) == null) value_2.length + } +} + +// TESTCASE NUMBER: 8 +fun case_8(value_1: Any?, value_2: Any?) { + if (case_8_1(value_1)) { + value_1?.toByte() + if (case_8_2(value_1)) { + value_1.toByte() + if (case_8_3(value_1)) value_1.inv() + } + } + if (!case_8_4(value_2)) { + value_2?.toByte() + if (!case_8_5(value_2)) { + value_2.toByte() + if (!case_8_6(value_2)) value_2.inv() + } + } + if (case_8_7(value_2) != null) { + value_2?.toByte() + if (case_8_8(value_2) != null) { + value_2.toByte() + if (case_8_9(value_2) != null) value_2.inv() + } + } + if (case_8_10(value_2) == null) { + value_2?.toByte() + if (case_8_11(value_2) == null) { + value_2.toByte() + if (case_8_12(value_2) == null) value_2.inv() + } + } +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/8.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/8.fir.kt new file mode 100644 index 00000000000..7e7007a7d7c --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/8.fir.kt @@ -0,0 +1,148 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts +// !WITH_NEW_INFERENCE + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (POSITIVE) + * + * SECTIONS: contracts, analysis, smartcasts + * NUMBER: 8 + * DESCRIPTION: Smartcasts using some Returns effects. + * HELPERS: contractFunctions + */ + +// FILE: contracts.kt + +package contracts + +import kotlin.contracts.* + +// TESTCASE NUMBER: 3 +fun T?.case_3(value_1: Int?, value_2: Boolean): Boolean { + contract { + returns(true) implies (value_1 == null) + returns(false) implies (value_1 != null && value_2) + returns(null) implies (value_1 != null && !value_2) + } + + return value_1 == null +} + +// TESTCASE NUMBER: 4 +fun case_4(value_1: Number, block: (() -> Unit)?): Boolean? { + contract { + returns(true) implies (value_1 is Int) + returns(false) implies (block == null) + returns(null) implies (block != null) + } + + return value_1 == null +} + +// TESTCASE NUMBER: 5 +fun String?.case_5(value_1: Number?): Boolean? { + contract { + returns(true) implies (value_1 != null) + returns(false) implies (value_1 is Int) + returnsNotNull() implies (this@case_5 != null) + } + + return value_1 == null +} + +// TESTCASE NUMBER: 6 +fun T?.case_6(value_1: Number, value_2: String?): Boolean? { + contract { + returns(true) implies (this@case_6 != null) + returns(false) implies (this@case_6 is String) + returns(null) implies (value_1 is Int) + returnsNotNull() implies (value_2 != null) + } + + return value_1 == null +} + +// FILE: main.kt + +import contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(value_1: Any?) { + funWithReturns(value_1 is Number?) + println(value_1?.toByte()) + if (funWithReturnsTrue(value_1 is Number)) { + println(value_1.toByte()) + if (funWithReturnsNotNull(value_1 is Int) != null) println(value_1.inv()) + } +} + +// TESTCASE NUMBER: 2 +fun case_2(value_1: Any?) { + if (!funWithReturnsFalse(value_1 is Number?)) { + println(value_1?.toByte()) + funWithReturns(value_1 is Number) + println(value_1.toByte()) + if (funWithReturnsNull(value_1 is Int) == null) println(value_1.inv()) + } +} + +// TESTCASE NUMBER: 3 +fun case_3(value_1: Int?, value_2: Any?) { + if (!value_1.case_3(value_1, value_2 is Number?)) { + println(value_2?.toByte()) + println(value_1.inv()) + } else if (value_1.case_3(value_1, value_2 is Number?)) { + println(value_1) + } else { + println(value_1.inv()) + } +} + +// TESTCASE NUMBER: 4 +fun case_4(value_1: Number, value_2: (() -> Unit)?) { + if (contracts.case_4(value_1, value_2) == true) { + value_1.inv() + } else if (contracts.case_4(value_1, value_2) == false) { + println(value_2) + } else if (contracts.case_4(value_1, value_2) == null) { + value_2() + } +} + +/* + * TESTCASE NUMBER: 5 + * UNEXPECTED BEHAVIOUR: unsafe calls + * ISSUES: KT-26612 + */ +fun case_5(value_1: Number?, value_2: String?) { + when (value_2.case_5(value_1)) { + true -> { + println(value_2.length) + println(value_1.toByte()) + } + false -> { + println(value_2.length) + println(value_1.inv()) + } + } +} + +/* + * TESTCASE NUMBER: 6 + * UNEXPECTED BEHAVIOUR: unsafe calls + * ISSUES: KT-26612 + */ +fun case_6(value_1: Number, value_2: String?, value_3: Any?) { + when (value_3.case_6(value_1, value_2)) { + true -> { + println(value_3.equals("")) + println(value_2.length) + } + false -> { + println(value_3.length) + println(value_2.length) + } + null -> { + println(value_1.inv()) + } + } +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/9.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/9.fir.kt new file mode 100644 index 00000000000..88394203483 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/9.fir.kt @@ -0,0 +1,142 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (POSITIVE) + * + * SECTIONS: contracts, analysis, smartcasts + * NUMBER: 9 + * DESCRIPTION: Smartcast using complex condition with some contract functions (Returns effect). + * HELPERS: typesProvider, contractFunctions + */ + +// FILE: contracts.kt + +package contracts + +import kotlin.contracts.* + +// TESTCASE NUMBER: 4 +fun T?.case_4(): Boolean { + contract { returns(true) implies (this@case_4 != null) } + return this@case_4 != null +} +fun T?.case_4_1(): Boolean { + contract { returns(false) implies (this@case_4_1 != null) } + return !(this@case_4_1 != null) +} +fun T?.case_4_2(): Boolean? { + contract { returns(null) implies (this@case_4_2 is String) } + return if (this@case_4_2 is String) null else true +} + +// TESTCASE NUMBER: 11 +fun T?.case_11_1(): Boolean { + contract { returns(false) implies (this@case_11_1 != null) } + return !(this@case_11_1 != null) +} +fun T?.case_11_2(): Boolean? { + contract { returns(null) implies (this@case_11_2 is String) } + return if (this@case_11_2 is String) null else true +} + +// TESTCASE NUMBER: 12 +fun T?.case_12(): Boolean { + contract { returns(false) implies (this@case_12 is String) } + return if (this@case_12 is String) false else true +} + +// FILE: main.kt + +import contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(value_1: Any?) { + if (funWithReturnsTrue(value_1 is String) && funWithReturnsTrueAndNotNullCheck(value_1)) { + println(value_1.length) + } +} + +// TESTCASE NUMBER: 2 +fun case_2(value_1: Any?) { + if (!funWithReturnsFalse(value_1 is String) && !funWithReturnsTrueAndNullCheck(value_1)) { + println(value_1.length) + } +} + +// TESTCASE NUMBER: 3 +fun case_3(value_1: Any?) { + if (funWithReturnsNull(value_1 is String?) == null && funWithReturnsTrue(value_1 != null)) { + println(value_1.length) + } +} + +// TESTCASE NUMBER: 4 +fun case_4(value_1: Any?) { + if (!value_1.case_4_1() && value_1.case_4_2() == null) { + println(value_1.length) + } +} + +// TESTCASE NUMBER: 5 +fun case_5(value_1: Any?, value_2: Boolean) { + if (!funWithReturnsFalse(value_1 is String) && value_2) { + println(value_1.length) + } +} + +// TESTCASE NUMBER: 6 +fun case_6(value_1: Any?, value_2: Boolean?) { + if (funWithReturnsNull(value_1 is String) == null && value_2 != null && value_2) { + println(value_1.length) + } +} + +// TESTCASE NUMBER: 7 +fun case_7(value_1: String?) { + if (funWithReturnsTrueAndNotNullCheck(value_1) && true) { + println(value_1.length) + } +} + +// TESTCASE NUMBER: 8 +fun case_8(value_1: Any?) { + if (funWithReturnsTrueAndNullCheck(value_1) && false) { + println(value_1) + } +} + +// TESTCASE NUMBER: 9 +fun case_9(value_1: Any?) { + if (funWithReturnsFalse(value_1 is String) || funWithReturnsFalse(value_1 is Int)) { + + } else { + println(value_1.length) + println(value_1.inv()) + } +} + +// TESTCASE NUMBER: 10 +fun case_10(value_1: Any?) { + if (funWithReturnsFalse(value_1 is String) || getBoolean()) { + + } else { + println(value_1.length) + } +} + +// TESTCASE NUMBER: 11 +fun case_11(value_1: Any?) { + if (!(value_1.case_11_1() || value_1.case_11_2() != null)) { + println(value_1.length) + } +} + +// TESTCASE NUMBER: 12 +fun case_12(value_1: Any?) { + if (!value_1.case_12() || !value_1.case_12()) { + println(value_1.length) + } + if (!value_1.case_12() && !value_1.case_12()) { + println(value_1.length) + } +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/1.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/1.fir.kt new file mode 100644 index 00000000000..736afec6b6b --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/1.fir.kt @@ -0,0 +1,106 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -UNREACHABLE_CODE -UNUSED_EXPRESSION +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, declarations, contractBuilder, common + * NUMBER: 1 + * DESCRIPTION: Contract isn't first statement. + */ + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +inline fun case_1(block: () -> Unit) { + val value_1 = 1 + contract { } + return block() +} + +// TESTCASE NUMBER: 2 +inline fun case_2(block: () -> Unit) { + 10 - 1 + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} + +// TESTCASE NUMBER: 3 +inline fun case_3(block: () -> Unit) { + throw Exception() + contract { + callsInPlace(block, InvocationKind.UNKNOWN) + } + return block() +} + +/* + * TESTCASE NUMBER: 4 + * ISSUES: KT-26191 + */ +inline fun case_4(block: () -> Unit) { + .0009 + return contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } +} + +/* + * TESTCASE NUMBER: 5 + * ISSUES: KT-26191 + */ +fun case_5(value_1: Int?) { + println("!") + contract { + returns(true) implies (value_1 != null) + } as ContractBuilder +} + +/* + * TESTCASE NUMBER: 6 + * ISSUES: KT-26191 + */ +fun case_6(value_1: Int?) { + 100 + 10 + throw Exception(contract { + returns(true) implies (value_1 != null) + }.toString()) +} + +/* + * TESTCASE NUMBER: 7 + * ISSUES: KT-26191 + */ +fun case_7(value_1: Int?) { + for (i in 0..10) { + println(i) + } + return contract { + returns(true) implies (value_1 != null) + } +} + +/* + * TESTCASE NUMBER: 8 + * ISSUES: KT-26191 + */ +fun case_8(value_1: Int?) { + val f = 10 - 20 + val g = contract { + returns(true) implies (value_1 != null) + } +} + +/* + * TESTCASE NUMBER: 9 + * ISSUES: KT-26191 + */ +fun case_9(number: Int?): Boolean { + val value_1 = number != null + contract { + returns(false) implies (value_1) + } as ContractBuilder + return number == null +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/10.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/10.fir.kt new file mode 100644 index 00000000000..ec12e01b623 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/10.fir.kt @@ -0,0 +1,20 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, declarations, contractBuilder, common + * NUMBER: 10 + * DESCRIPTION: Contract with label after 'contract' keyword. + * ISSUES: KT-26153 + */ + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +inline fun case_1(block: () -> Unit) { + contract test@ { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/11.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/11.fir.kt new file mode 100644 index 00000000000..399a5f5007b --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/11.fir.kt @@ -0,0 +1,38 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, declarations, contractBuilder, common + * NUMBER: 11 + * DESCRIPTION: Functions with contracts and external contract builder. + * ISSUES: KT-26186 + */ + +// FILE: builder.kt + +package builder + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1, 2 +inline fun contractBuilder(block: () -> Unit): ContractBuilder.() -> Unit = { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) +} + +// FILE: main.kt + +import builder.* +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +inline fun case_1(block: () -> Unit) { + contract(contractBuilder(block)) + return block() +} + +// TESTCASE NUMBER: 2 +inline fun case_2(block: () -> Unit) { + contract(builder = contractBuilder(block)) + return block() +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/12.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/12.fir.kt new file mode 100644 index 00000000000..c1977c8ab10 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/12.fir.kt @@ -0,0 +1,46 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, declarations, contractBuilder, common + * NUMBER: 12 + * DESCRIPTION: Functions with contracts and external effect builder. + * ISSUES: KT-26186 + */ + +// FILE: builder.kt + +package builder + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1, 2, 3 +inline fun ContractBuilder.callsInPlaceEffectBuilder(block: () -> Unit) = + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + +fun ContractBuilder.returnsEffectBuilder(value_1: Int?) = + returns(true) implies (value_1 != null) + +// FILE: main.kt + +import builder.* +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +inline fun case_1(block: () -> Unit) { + contract(builder = { callsInPlaceEffectBuilder(block) }) + return block() +} + +// TESTCASE NUMBER: 2 +inline fun case_2(block: () -> Unit) { + contract { callsInPlaceEffectBuilder(block) } + return block() +} + +// TESTCASE NUMBER: 3 +inline fun case_3(value_1: Int?, block: () -> Unit) { + contract({ returnsEffectBuilder(value_1); callsInPlaceEffectBuilder(block) }) + return block() +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/13.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/13.fir.kt new file mode 100644 index 00000000000..687d5e5a49e --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/13.fir.kt @@ -0,0 +1,19 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -UNREACHABLE_CODE -UNUSED_EXPRESSION +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, declarations, contractBuilder, common + * NUMBER: 13 + * DESCRIPTION: Contract function with CallsInPlace effect with not allowed implies. + * ISSUES: KT-26409 + */ + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(value_1: Any?, block: () -> Unit) { + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) implies (value_1 != null) } + if (value_1 != null) block() +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/14.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/14.fir.kt new file mode 100644 index 00000000000..e3a6f71dcbe --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/14.fir.kt @@ -0,0 +1,62 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, declarations, contractBuilder, common + * NUMBER: 14 + * DESCRIPTION: Contract is first statement in control flow terms, but not in tokens order terms. + * ISSUES: KT-26153 + * HELPERS: functions + */ + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +inline fun case_1(block: () -> Unit) { + return contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } +} + +// TESTCASE NUMBER: 2 +fun case_2() = contract { } + +// TESTCASE NUMBER: 3 +inline fun case_3(block: () -> Unit) { + val value_1 = contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + block() +} + +// TESTCASE NUMBER: 4 +inline fun case_4(block: () -> Unit) { + (contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + }) + return block() +} + +// TESTCASE NUMBER: 5 +inline fun case_5(block: () -> Unit) { + test@ contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} + +// TESTCASE NUMBER: 6 +inline fun case_6(block: () -> Unit) { + throw Exception(contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + }.toString()) +} + +// TESTCASE NUMBER: 7 +inline fun case_7(block: () -> Unit) { + funWithAnyArg(contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + }) +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/16.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/16.fir.kt new file mode 100644 index 00000000000..ff737aa3dcc --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/16.fir.kt @@ -0,0 +1,56 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, declarations, contractBuilder, common + * NUMBER: 16 + * DESCRIPTION: Contract isn't in the first position. + * ISSUES: KT-26191 + */ + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(value_1: Int?) { + println("!") + contract { + returns(true) implies (value_1 != null) + } as ContractBuilder +} + +// TESTCASE NUMBER: 2 +fun case_2(value_1: Int?) { + 100 + 10 + throw Exception(contract { + returns(true) implies (value_1 != null) + }.toString()) +} + +// TESTCASE NUMBER: 3 +fun case_3(value_1: Int?) { + for (i in 0..10) { + println(i) + } + return contract { + returns(true) implies (value_1 != null) + } +} + +// TESTCASE NUMBER: 4 +fun case_4(value_1: Int?) { + val f = 10 - 20 + val g = contract { + returns(true) implies (value_1 != null) + } +} + +// TESTCASE NUMBER: 5 +fun case_5(number: Int?): Boolean { + val value_1 = number != null + contract { + returns(false) implies (value_1) + } as ContractBuilder + return number == null +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/17.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/17.fir.kt new file mode 100644 index 00000000000..a10e47e837d --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/17.fir.kt @@ -0,0 +1,32 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -UNREACHABLE_CODE -UNUSED_EXPRESSION +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, declarations, contractBuilder, common + * NUMBER: 17 + * DESCRIPTION: contracts with Nothing expressions in implies. + * DISCUSSION + * ISSUES: KT-25948 + */ + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(): Boolean { + contract { returns(null) implies throw Exception() } + return true +} + +// TESTCASE NUMBER: 2 +fun case_2(): Boolean { + contract { returns(null) implies return return return false } + return true +} + +// TESTCASE NUMBER: 3 +fun case_3(): Boolean { + contract { returns(null) implies return return return false && throw throw throw throw Exception() } + return true +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/2.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/2.fir.kt new file mode 100644 index 00000000000..53f186e7263 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/2.fir.kt @@ -0,0 +1,36 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -UNREACHABLE_CODE -UNUSED_EXPRESSION +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, declarations, contractBuilder, common + * NUMBER: 2 + * DESCRIPTION: contracts with not allowed simple conditions in implies + */ + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(value_1: Boolean): Boolean { + contract { returns(true) implies (value_1 == true) } + return value_1 == true +} + +// TESTCASE NUMBER: 2 +fun case_2(value_1: Boolean): Boolean? { + contract { returnsNotNull() implies (value_1 != false) } + return if (value_1 != false) true else null +} + +// TESTCASE NUMBER: 3 +fun case_3(value_1: String): Boolean { + contract { returns(false) implies (value_1 != "") } + return !(value_1 != "") +} + +// TESTCASE NUMBER: 4 +fun case_4(value_1: Int): Boolean? { + contract { returns(null) implies (value_1 == 0) } + return if (value_1 == 0) null else true +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/3.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/3.fir.kt new file mode 100644 index 00000000000..81db80c1723 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/3.fir.kt @@ -0,0 +1,48 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -UNREACHABLE_CODE -UNUSED_EXPRESSION +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, declarations, contractBuilder, common + * NUMBER: 3 + * DESCRIPTION: contracts with not allowed complex conditions in implies. + */ + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(value_1: Boolean?): Boolean { + contract { returns(true) implies (value_1 != null && value_1 == false) } + return value_1 != null && value_1 == false +} + +// TESTCASE NUMBER: 2 +fun case_2(value_1: Boolean, value_2: Boolean): Boolean? { + contract { returnsNotNull() implies (value_1 != false || value_2) } + return if (value_1 != false || value_2) true else null +} + +// TESTCASE NUMBER: 3 +fun case_3(value_1: String?, value_2: Boolean): Boolean { + contract { returns(false) implies (value_1 != null && value_2 != true) } + return !(value_1 != null && value_2 != true) +} + +// TESTCASE NUMBER: 4 +fun case_4(value_1: Nothing?, value_2: Boolean?): Boolean? { + contract { returns(null) implies (value_1 == null || value_2 != null || value_2 == false) } + return if (value_1 == null || value_2 != null || value_2 == false) null else true +} + +// TESTCASE NUMBER: 5 +fun case_5(value_1: Any?, value_2: String?): Boolean? { + contract { returns(null) implies (value_1 != null && value_2 != null || value_2 == ".") } + return if (value_1 != null && value_2 != null || value_2 == ".") null else true +} + +// TESTCASE NUMBER: 6 +fun case_6(value_1: Boolean, value_2: Int?): Boolean? { + contract { returns(null) implies (value_2 == null && value_1 || value_2 == 0) } + return if (value_2 == null && value_1 || value_2 == 0) null else true +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/4.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/4.fir.kt new file mode 100644 index 00000000000..b788e3d3e6c --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/4.fir.kt @@ -0,0 +1,31 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -UNREACHABLE_CODE -UNUSED_EXPRESSION +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts +// !WITH_NEW_INFERENCE + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, declarations, contractBuilder, common + * NUMBER: 4 + * DESCRIPTION: contracts with not allowed conditions with constants in implies. + */ + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(): Boolean? { + contract { returnsNotNull() implies (null) } + return true +} + +// TESTCASE NUMBER: 2 +fun case_2(): Boolean { + contract { returns(false) implies 0.000001 } + return true +} + +// TESTCASE NUMBER: 3 +fun case_3(): Boolean? { + contract { returns(null) implies "" } + return null +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/5.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/5.fir.kt new file mode 100644 index 00000000000..4dc62e417d1 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/5.fir.kt @@ -0,0 +1,71 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -UNREACHABLE_CODE -UNUSED_EXPRESSION +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts +// !WITH_NEW_INFERENCE + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, declarations, contractBuilder, common + * NUMBER: 5 + * DESCRIPTION: contracts with not allowed expressions in implies. + */ + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(): Boolean { + contract { returns(true) implies (-10) } + return true +} + +// TESTCASE NUMBER: 2 +fun case_2(): Boolean { + contract { returnsNotNull() implies (return return return true) } + return true +} + +// TESTCASE NUMBER: 3 +fun case_3(): Boolean { + contract { returns(false) implies ("..." + "$value_1") } + return true +} + +/* + * TESTCASE NUMBER: 4 + * ISSUES: KT-26386 + */ +fun case_4(): Boolean? { + contract { returns(null) implies case_4() } + return null +} + +// TESTCASE NUMBER: 5 +fun case_5(): Boolean? { + contract { returns(null) implies listOf(0) } + return null +} + +// TESTCASE NUMBER: 6 +fun case_6(value_1: Boolean): Boolean? { + contract { returns(null) implies contract { returns(null) implies (!value_1) } } + return null +} + +// TESTCASE NUMBER: 7 +fun case_7(): Int { + contract { + callsInPlace(::case_7, InvocationKind.EXACTLY_ONCE) + } + return 1 +} + +/* + * TESTCASE NUMBER: 8 + * ISSUES: KT-26386 + */ +fun case_8(): () -> Unit { + contract { + callsInPlace(case_8(), InvocationKind.EXACTLY_ONCE) + } + return {} +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/6.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/6.fir.kt new file mode 100644 index 00000000000..4576b2ba9ff --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/6.fir.kt @@ -0,0 +1,72 @@ +// !LANGUAGE: +AllowContractsForNonOverridableMembers +AllowReifiedGenericsInContracts +// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -UNREACHABLE_CODE -UNUSED_EXPRESSION +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, declarations, contractBuilder, common + * NUMBER: 6 + * DESCRIPTION: contracts with not function parameters in implies. + * HELPERS: typesProvider + */ + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +object case_1 { + val value_1 = getBoolean() + const val value_2 = true + private const val value_3 = false + + fun case_1_1(): Boolean? { + contract { returnsNotNull() implies (value_1) } + return if (value_1) true else null + } + fun case_1_2(): Boolean? { + contract { returns(null) implies (value_2) } + return if (value_2) null else true + } + + fun case_1_3(): Boolean { + contract { returns(true) implies (value_3) } + return value_3 + } +} + +// TESTCASE NUMBER: 2 +class case_2(value_5: Boolean, val value_1: Boolean) { + val value_2 = getBoolean() + + companion object { + const val value_3 = false + private const val value_4 = true + } + + init { + fun case_2_1(): Boolean { + contract { returns(false) implies (value_5) } + return !(value_5) + } + } + + fun case_2_2(): Boolean? { + contract { returns(null) implies (value_1) } + return if (value_1) null else true + } + + fun case_2_3(): Boolean { + contract { returns(true) implies (value_2) } + return value_2 + } + + fun case_2_4(): Boolean { + contract { returns(false) implies (value_3) } + return !(value_3) + } + + inline fun K.case_2_5(): Boolean? { + contract { returnsNotNull() implies (value_4) } + return if (value_4) true else null + } +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/7.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/7.fir.kt new file mode 100644 index 00000000000..c094a7aeec3 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/7.fir.kt @@ -0,0 +1,22 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -UNREACHABLE_CODE -UNUSED_EXPRESSION +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, declarations, contractBuilder, common + * NUMBER: 7 + * DESCRIPTION: Contract function with 'this' labeled by not current extensible object + * ISSUES: KT-26149 + * HELPERS: typesProvider + */ + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +fun T?.case_1() { + fun K?.case_1_1(): Boolean { + contract { returns(true) implies (this@case_1 != null) } + return this@case_1 != null + } +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/8.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/8.fir.kt new file mode 100644 index 00000000000..25addaa8542 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/8.fir.kt @@ -0,0 +1,30 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -UNREACHABLE_CODE -UNUSED_EXPRESSION +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, declarations, contractBuilder, common + * NUMBER: 8 + * DESCRIPTION: Not allowed empty contract. + */ + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +inline fun case_1(block: () -> Unit) { + contract { } + return block() +} + +// TESTCASE NUMBER: 2 +inline fun case_2(block: () -> Unit) { + contract({ }) + return block() +} + +// TESTCASE NUMBER: 3 +inline fun case_3(block: () -> Unit) { + contract(builder = { }) + return block() +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/9.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/9.fir.kt new file mode 100644 index 00000000000..148c4efd599 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/9.fir.kt @@ -0,0 +1,19 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -UNREACHABLE_CODE -UNUSED_EXPRESSION +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, declarations, contractBuilder, common + * NUMBER: 9 + * DESCRIPTION: Function with contract as returned expression. + */ + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +inline fun case_1(block: () -> Unit) = { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/callsInPlace/neg/1.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/callsInPlace/neg/1.fir.kt new file mode 100644 index 00000000000..f3b0d0fe81e --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/callsInPlace/neg/1.fir.kt @@ -0,0 +1,43 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, declarations, contractBuilder, effects, callsInPlace + * NUMBER: 1 + * DESCRIPTION: contract functions with CallsInPlace with dynamic InvocationKind. + * ISSUES: KT-26152 + */ + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1, 2, 3, 4 +val invocationKind: InvocationKind = InvocationKind.EXACTLY_ONCE + +object SampleObject { + val invocationKind = InvocationKind.EXACTLY_ONCE +} + +// TESTCASE NUMBER: 1 +inline fun case_1(invocationKind: InvocationKind, block: () -> Unit) { + contract { callsInPlace(block, invocationKind) } + return block() +} + +// TESTCASE NUMBER: 2 +inline fun case_2(invocationKind: T, block: () -> Unit) { + contract { callsInPlace(block, invocationKind) } + return block() +} + +// TESTCASE NUMBER: 3 +inline fun case_3(block: () -> Unit) { + contract { callsInPlace(block, invocationKind) } + return block() +} + +// TESTCASE NUMBER: 4 +inline fun case_4(block: () -> Unit) { + contract { callsInPlace(block, SampleObject.invocationKind) } + return block() +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/callsInPlace/neg/2.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/callsInPlace/neg/2.fir.kt new file mode 100644 index 00000000000..8d53ae7242f --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/callsInPlace/neg/2.fir.kt @@ -0,0 +1,30 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, declarations, contractBuilder, effects, callsInPlace + * NUMBER: 2 + * DESCRIPTION: functions with contract and duplicate CallsInPlace. + * ISSUES: KT-26150 + */ + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +inline fun case_1(block: () -> Unit) { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} + +// TESTCASE NUMBER: 2 +inline fun case_2(block: () -> Unit) { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + callsInPlace(block, InvocationKind.AT_MOST_ONCE) + } + return block() +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/common/neg/1.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/common/neg/1.fir.kt new file mode 100644 index 00000000000..fc7aaacd756 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/common/neg/1.fir.kt @@ -0,0 +1,61 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, declarations, contractBuilder, effects, common + * NUMBER: 1 + * DESCRIPTION: Indirect effect functions call. + * ISSUES: KT-26175 + */ + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +inline fun case_1(block: () -> Unit) { + contract { + { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }() + } + return block() +} + +// TESTCASE NUMBER: 2 +fun case_2(x: Any?): Boolean { + contract { + returns(true).apply { implies (x is Number) } // 'Returns' as result + } + return x is Number +} + +// TESTCASE NUMBER: 3 +fun case_3(x: Any?): Boolean { + contract { + returns(true).also { it implies (x is Number) } // 'Returns' as result + } + return x is Number +} + +// TESTCASE NUMBER: 4 +fun case_4(x: Any?): Boolean { + contract { + returns(true).let { it implies (x is Number) } // 'ConditionalEffect' as result + } + return x is Number +} + +// TESTCASE NUMBER: 5 +fun case_5(x: Any?): Boolean { + contract { + returns(true).run { implies (x is Number) } // 'ConditionalEffect' as result + } + return x is Number +} + +// TESTCASE NUMBER: 6 +fun case_6(x: Any?): Boolean { + contract { + returns(true).takeIf { it implies (x is Number); false } // null, must be unrecognized effect + } + return x is Number +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/1.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/1.fir.kt new file mode 100644 index 00000000000..5c6e81553cb --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/1.fir.kt @@ -0,0 +1,36 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, declarations, contractBuilder, effects, returns + * NUMBER: 1 + * DESCRIPTION: Using equality with expressions in implies. + * ISSUES: KT-26178 + */ + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(x: Any?): Boolean { + contract { returns(true) implies (x == -.15f) } + return x !is Number +} + +// TESTCASE NUMBER: 2 +fun case_2(x: Any?): Boolean { + contract { returns(true) implies (x == "..." + ".") } + return x !is Number +} + +// TESTCASE NUMBER: 3 +fun case_3(x: Int, y: Int): Boolean { + contract { returns(true) implies (x > y) } + return x > y +} + +// TESTCASE NUMBER: 4 +fun case_4(x: Any?, y: Any?): Boolean { + contract { returns(true) implies (x == y.toString()) } + return x !is Number +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/2.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/2.fir.kt new file mode 100644 index 00000000000..a3d377e40bf --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/2.fir.kt @@ -0,0 +1,43 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, declarations, contractBuilder, effects, returns + * NUMBER: 2 + * DESCRIPTION: Using equality with not labeled 'this' in implies. + */ + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +fun Any?.case_1(): Boolean { + contract { + returns(true) implies (this != null) + } + return this != null +} + +// TESTCASE NUMBER: 2 +fun Any?.case_2(): Boolean { + contract { + returnsNotNull() implies (this is Number?) + } + return this is Number? +} + +// TESTCASE NUMBER: 3 +fun T?.case_3(): Boolean { + contract { + returnsNotNull() implies (this != null) + } + return this != null +} + +// TESTCASE NUMBER: 4 +inline fun T.case_4(): Boolean { + contract { + returns(null) implies (this is Int) + } + return this is Int +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/3.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/3.fir.kt new file mode 100644 index 00000000000..cd90cfdfad8 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/3.fir.kt @@ -0,0 +1,21 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, declarations, contractBuilder, effects, returns + * NUMBER: 3 + * DESCRIPTION: Using reference equality in implies. + * ISSUES: KT-26177 + * HELPERS: objects + */ + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(x: Any?): Boolean { + contract { + returns(true) implies (x === EmptyObject) // should be not allowed + } + return x === EmptyObject +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/4.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/4.fir.kt new file mode 100644 index 00000000000..5ee8f3cb8cb --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/4.fir.kt @@ -0,0 +1,30 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, declarations, contractBuilder, effects, returns + * NUMBER: 4 + * DESCRIPTION: Using equality with literals in implies. + * ISSUES: KT-26178 + */ + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(x: Any?): Boolean { + contract { returns(true) implies (x == .15f) } + return x == .15f +} + +// TESTCASE NUMBER: 2 +fun case_2(x: Any?) { + contract { returns() implies (x == "...") } + if (x != "...") throw Exception() +} + +// TESTCASE NUMBER: 3 +fun case_3(x: Any?): Boolean { + contract { returns(true) implies (x == '-') } + return x == '-' +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/5.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/5.fir.kt new file mode 100644 index 00000000000..c2e47d6113c --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/5.fir.kt @@ -0,0 +1,18 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, declarations, contractBuilder, effects, returns + * NUMBER: 5 + * DESCRIPTION: Contract on the extension function with Boolean upper bound (Boolean or Nothing) or smartcast to Boolean. + * DISCUSSION + */ + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +fun T.case_1(): Boolean? { + contract { returns(null) implies (!this@case_1) } + return if (!this) null else true +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/6.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/6.fir.kt new file mode 100644 index 00000000000..dd97fe25869 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/6.fir.kt @@ -0,0 +1,53 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, declarations, contractBuilder, effects, returns + * NUMBER: 6 + * DESCRIPTION: Contract on the extension function with smartcast to Boolean. + */ + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +fun Boolean?.case_1(): Boolean { + contract { returns(true) implies (this@case_1 != null && this@case_1) } + return this != null && this +} + +// TESTCASE NUMBER: 2 +fun T?.case_2(): Boolean { + contract { returns(true) implies (this@case_2 != null && this@case_2 !is Nothing && this@case_2) } + return this != null && this !is Nothing && this +} + +// TESTCASE NUMBER: 3 +fun T?.case_3() { + contract { returns() implies (this@case_3 == null || this@case_3 is Boolean? && !this@case_3) } + if (!(this == null || this is Boolean? && !this)) throw Exception() +} + +// TESTCASE NUMBER: 4 +fun case_4(value_1: Boolean?): Boolean { + contract { returns(true) implies (value_1 != null && !value_1) } + return value_1 != null && !value_1 +} + +// TESTCASE NUMBER: 5 +fun Boolean.case_5(value_1: Any?): Boolean? { + contract { returnsNotNull() implies (value_1 is Boolean? && value_1 != null && value_1) } + return if (value_1 is Boolean? && value_1 != null && value_1) true else null +} + +// TESTCASE NUMBER: 6 +fun Boolean?.case_6(): Boolean? { + contract { returnsNotNull() implies (this@case_6 != null && this@case_6) } + return if (this@case_6 != null && this@case_6) true else null +} + +// TESTCASE NUMBER: 7 +fun T.case_7(value_1: Any?): Boolean? { + contract { returnsNotNull() implies (value_1 is Boolean? && value_1 != null && value_1 && this@case_7 != null && this@case_7) } + return if (value_1 is Boolean? && value_1 != null && value_1 && this@case_7 != null && this@case_7) true else null +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/7.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/7.fir.kt new file mode 100644 index 00000000000..2188aca6064 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/7.fir.kt @@ -0,0 +1,25 @@ +// !LANGUAGE: +AllowContractsForNonOverridableMembers +AllowReifiedGenericsInContracts +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, declarations, contractBuilder, effects, returns + * NUMBER: 7 + * DESCRIPTION: Returns effect with type checking with generic parameter + * ISSUES: KT-26296 + */ + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +fun T.case_1() { + contract { returns() implies (this@case_1 is T) } + if (!(this@case_1 is T)) throw Exception() +} + +// TESTCASE NUMBER: 2 +fun T?.case_2(value_1: K?) { + contract { returns() implies (this@case_2 is T && value_1 is K) } + if (!(this@case_2 is T && value_1 is K)) throw Exception() +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/pos/1.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/pos/1.fir.kt new file mode 100644 index 00000000000..9559330f1d6 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/pos/1.fir.kt @@ -0,0 +1,85 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts +// !DIAGNOSTICS: -FINAL_UPPER_BOUND + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (POSITIVE) + * + * SECTIONS: contracts, declarations, contractBuilder, effects, returns + * NUMBER: 1 + * DESCRIPTION: Returns effect with simple conditions. + * HELPERS: classes + */ + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +fun case_1(value_1: Boolean) { + contract { returns() implies (value_1) } + if (!value_1) throw Exception() +} + +// TESTCASE NUMBER: 2 +fun case_2(value_1: Boolean): Boolean { + contract { returns(false) implies (!value_1) } + return value_1 +} + +// TESTCASE NUMBER: 3 +fun Boolean.case_3() { + contract { returns() implies (!this@case_3) } + if (this@case_3) throw Exception() +} + +// TESTCASE NUMBER: 5 +fun case_5(value_1: Any?) { + contract { returns() implies (value_1 is String) } + if (value_1 !is String) throw Exception() +} + +// TESTCASE NUMBER: 6 +fun case_6(value_1: Any?) { + contract { returns() implies (value_1 !is String?) } + if (value_1 is String?) throw Exception() +} + +// TESTCASE NUMBER: 7 +fun Any?.case_7() { + contract { returns() implies (this@case_7 is Number) } + if (this !is Number) throw Exception() +} + +// TESTCASE NUMBER: 8 +fun T?.case_8() { + contract { returns() implies (this@case_8 !is ClassLevel3?) } + if (this is ClassLevel3?) throw Exception() +} + +// TESTCASE NUMBER: 9 +fun T.case_9(): Boolean? { + contract { returns(null) implies (this@case_9 is Byte?) } + return if (this is Byte?) null else true +} + +// TESTCASE NUMBER: 10 +fun case_10(value_1: Any?) { + contract { returns() implies (value_1 == null) } + if (value_1 != null) throw Exception() +} + +// TESTCASE NUMBER: 11 +fun case_11(value_1: Any?): Boolean? { + contract { returns(null) implies (value_1 != null) } + return if (value_1 != null) null else true +} + +// TESTCASE NUMBER: 12 +fun Char.case_12() { + contract { returns() implies (this@case_12 == null) } + if (this@case_12 != null) throw Exception() +} + +// TESTCASE NUMBER: 13 +fun T?.case_13() { + contract { returns() implies (this@case_13 == null) } + if (this != null) throw Exception() +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractFunction/neg/1.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractFunction/neg/1.fir.kt new file mode 100644 index 00000000000..ee49eddf1a4 --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractFunction/neg/1.fir.kt @@ -0,0 +1,18 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, declarations, contractFunction + * NUMBER: 1 + * DESCRIPTION: Check that recursion isn't allowed in contract functions with CallsInPlace effect. + */ + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +inline fun case_1(block: () -> Unit) { + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } + block() + case_1(block) +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractFunction/neg/2.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractFunction/neg/2.fir.kt new file mode 100644 index 00000000000..4bbf979bd8d --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractFunction/neg/2.fir.kt @@ -0,0 +1,82 @@ +// !LANGUAGE: +AllowContractsForNonOverridableMembers +AllowReifiedGenericsInContracts +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, declarations, contractFunction + * NUMBER: 2 + * DESCRIPTION: Check report about use contracts in literal functions, lambdas or not top-level functions. + * ISSUES: KT-26149 + * HELPERS: classes + */ + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +fun case_1() { + val fun_1 = fun(block: () -> Unit) { + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } + return block() + } + + fun_1 { throw Exception() } + println("1") +} + +// TESTCASE NUMBER: 2 +fun case_2() { + val lambda_1 = { block: () -> Unit -> + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } + block() + } + + lambda_1 { throw Exception() } + println("1") +} + +/* + * TESTCASE NUMBER: 4 + * ISSUES: KT-26244 + */ +class case_4 : ClassLevel3() { + + fun T.case_4_1(): Boolean { + contract { returns(false) implies (this@case_4 !is ClassLevel1) } + return this == null + } + + fun T.case_4_2() { + contract { returns() implies (!this@case_4_2) } + if (this) throw Exception() + } + + fun T.case_4_3_wrap() { + fun case_4_3_contract() { + contract { returns() implies (this@case_4_3_wrap is ClassLevel1) } + if (this@case_4_3_wrap !is ClassLevel1) throw Exception() + } + case_4_3_contract() + println("!") + } + + fun case_4_3() = ClassLevel3().case_4_3_wrap() +} + +/* + * TESTCASE NUMBER: 5 + * ISSUES: KT-26244 + */ +class case_5 : ClassLevel5() { + inner class case_5_1 { + fun K.case_5_1_1() { + contract { returns() implies (this@case_5_1 !is ClassLevel1 && this@case_5_1 != null || this@case_5 is ClassLevel1 && this@case_5_1_1 is Float) } + if (!(this@case_5_1 !is ClassLevel1 && this@case_5_1 != null || this@case_5 is ClassLevel1 && this is Float)) throw Exception() + } + + fun case_5_1_2() { + contract { returns() implies (this@case_5_1 !is ClassLevel1 || this@case_5 is ClassLevel1 || this@case_5_1 == null) } + if (!(this@case_5_1 !is ClassLevel1 || this@case_5 is ClassLevel1 || this@case_5_1 == null)) throw Exception() + } + } +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractFunction/neg/4.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractFunction/neg/4.fir.kt new file mode 100644 index 00000000000..efc6b67071c --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractFunction/neg/4.fir.kt @@ -0,0 +1,66 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE) + * + * SECTIONS: contracts, declarations, contractFunction + * NUMBER: 4 + * DESCRIPTION: Check that fun with contract and CallsInPlace effect is an inline function. + * ISSUES: KT-27090 + */ + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +val Boolean.case_1: () -> Unit + get() { + contract { + returns() implies (this@case_1) + } + return {} + } + +// TESTCASE NUMBER: 2 +val (() -> Unit).case_2: () -> Unit + get() { + contract { + callsInPlace(this@case_2, InvocationKind.EXACTLY_ONCE) + } + return {} + } + +// TESTCASE NUMBER: 3 +var Boolean.case_3: () -> Unit + get() { + return {} + } + set(value) { + contract { + callsInPlace(value, InvocationKind.EXACTLY_ONCE) + } + } + +// TESTCASE NUMBER: 4 +var (() -> Unit).case_4: () -> Unit + get() { + return {} + } + set(value) { + contract { + callsInPlace(this@case_4, InvocationKind.EXACTLY_ONCE) + } + } + +// TESTCASE NUMBER: 5 +val Boolean.case_5: () -> Unit + get() { + contract { + returns() implies (this@case_5) + } + + if (!this@case_5) + throw Exception() + + return {} + } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractFunction/pos/1.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractFunction/pos/1.fir.kt new file mode 100644 index 00000000000..5852642145c --- /dev/null +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractFunction/pos/1.fir.kt @@ -0,0 +1,36 @@ +// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts + +/* + * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (POSITIVE) + * + * SECTIONS: contracts, declarations, contractFunction + * NUMBER: 1 + * DESCRIPTION: Use a contract function before the declaration it. + */ + +import kotlin.contracts.* + +// TESTCASE NUMBER: 1 +fun case_1_1(x: Any?) { + if (case_1_2(x)) { + x.length + } +} + +// TESTCASE NUMBER: 2 +fun case_2_1(x: Number?) { + case_2_2(x) + println(x.toByte()) +} + +// TESTCASE NUMBER: 1 +fun case_1_2(x: Any?): Boolean { + contract { returns(true) implies (x is String) } + return x is String +} + +// TESTCASE NUMBER: 2 +fun case_2_2(x: Any?) { + contract { returns() implies(x != null) } + if (x == null) throw Exception() +}