b29a6e48fb
- Introduce new language feature 'ReadDeserializedContracts', which allows to deserialize contracts from metadata. - Introduce new language feature 'AllowContractsForCustomFunctions', which allows reading contracts from sources. - Use new features instead of combination 'CallsInPlaceEffect || ReturnsEffect' - Rename 'CallsInPlaceEffect' -> 'UseCallsInPlaceEffect', 'ReturnsEffect' -> 'UseReturnsEffect'. As names suggest, they control if it is allowed to use corresponding effect in analysis. We have to introduce separate 'ReadDeserializedContracts' to enable contracts only in some modules of the project, because libraries are read with project-wide settings (see KT-20692).
104 lines
2.4 KiB
Kotlin
Vendored
104 lines
2.4 KiB
Kotlin
Vendored
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
|
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
|
// !WITH_NEW_INFERENCE
|
|
|
|
import kotlin.internal.contracts.*
|
|
|
|
fun myAssert(condition: Boolean) {
|
|
contract {
|
|
returns() implies (condition)
|
|
}
|
|
if (!condition) throw kotlin.IllegalArgumentException("Assertion failed")
|
|
}
|
|
|
|
fun isString(x: Any?): Boolean {
|
|
contract {
|
|
returns(true) implies (x is String)
|
|
}
|
|
return x is String
|
|
}
|
|
|
|
fun isInt(x: Any?): Boolean {
|
|
contract {
|
|
returns(true) implies (x is Int)
|
|
}
|
|
return x is Int
|
|
}
|
|
|
|
fun notEqualsNull(x: Any?): Boolean {
|
|
contract {
|
|
returns(true) implies (x != null)
|
|
}
|
|
return x != null
|
|
}
|
|
|
|
fun equalsTrue(x: Boolean): Boolean {
|
|
contract {
|
|
returns(true) implies x
|
|
}
|
|
return x == true
|
|
}
|
|
|
|
fun nullWhenNotString(x: Any?): String? {
|
|
contract {
|
|
returnsNotNull() implies (x is String)
|
|
}
|
|
return x as? String
|
|
}
|
|
|
|
|
|
|
|
|
|
// ========== Actual tests ============
|
|
|
|
fun nested1(x: Any?) {
|
|
if (equalsTrue(isString(x))) {
|
|
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
|
}
|
|
else {
|
|
x.<!UNRESOLVED_REFERENCE!>length<!>
|
|
}
|
|
}
|
|
|
|
fun nested2(x: Any?) {
|
|
myAssert(equalsTrue(isString(x)))
|
|
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
|
}
|
|
|
|
fun nested3(x: Any?) {
|
|
myAssert(equalsTrue(notEqualsNull(nullWhenNotString(x))))
|
|
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
|
}
|
|
|
|
fun branchedAndNested(x: Any?, y: Any?) {
|
|
myAssert(equalsTrue(notEqualsNull(nullWhenNotString(x))) && equalsTrue(isString(y)))
|
|
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
|
<!DEBUG_INFO_SMARTCAST!>y<!>.length
|
|
}
|
|
|
|
|
|
fun br(y: Any?) {
|
|
if (myAssert(y is Int) == Unit && myAssert(y is String) == Unit) {
|
|
<!DEBUG_INFO_SMARTCAST!>y<!>.length
|
|
<!DEBUG_INFO_SMARTCAST!>y<!>.inc()
|
|
}
|
|
}
|
|
|
|
fun branchedAndNestedWithNativeOperators(x: Any?, y: Any?) {
|
|
myAssert(
|
|
equalsTrue(notEqualsNull(nullWhenNotString(x))) // x is String
|
|
&&
|
|
(
|
|
(myAssert(y is Int) == Unit && myAssert(y is String) == Unit) // y is Int, String
|
|
||
|
|
equalsTrue(isInt(y) && isString(y)) // y is Int, String
|
|
)
|
|
&&
|
|
(1 == 2 || y is Int || isString(y))
|
|
)
|
|
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
|
y.<!UNRESOLVED_REFERENCE!>length<!>
|
|
y.<!NI;NONE_APPLICABLE, OI;UNRESOLVED_REFERENCE_WRONG_RECEIVER!>inc<!>()
|
|
}
|
|
|