Effects: add diagnostic tests on contracts
- Make AbstractDiagnosticsTest dump function contracts - Add diagnostics tests on parsing contracts - Add diagnostics tests on smartcats in presence of functions with contracts - Add diagnostics tests on initialization and flow in presence of in-place called lambdas ========== Introduction of EffectSystem: 16/18
This commit is contained in:
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
// !LANGUAGE: +ReturnsEffect
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.internal.contracts.*
|
||||
|
||||
fun myAssert(condition: Boolean) {
|
||||
contract {
|
||||
returns() implies (condition)
|
||||
}
|
||||
if (!condition) throw kotlin.IllegalArgumentException("Assertion failed")
|
||||
}
|
||||
|
||||
fun testWithCatch(x: Any?) {
|
||||
try {
|
||||
myAssert(x is String)
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
} catch (e: java.lang.IllegalArgumentException) { }
|
||||
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
package
|
||||
|
||||
public fun myAssert(/*0*/ condition: kotlin.Boolean): kotlin.Unit
|
||||
Returns(WILDCARD) -> condition
|
||||
|
||||
public fun testWithCatch(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
// !LANGUAGE: +ReturnsEffect
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.internal.contracts.*
|
||||
|
||||
fun isString(x: Any?): Boolean {
|
||||
contract {
|
||||
returns(true) implies (x is String)
|
||||
}
|
||||
return x is String
|
||||
}
|
||||
|
||||
fun testEqualsWithConstant(x: Any?) {
|
||||
if (isString(x) == true) {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun testNotEqualsWithConstant(x: Any?) {
|
||||
if (isString(x) != true) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
}
|
||||
|
||||
fun unknownFunction(): Any? = 42
|
||||
|
||||
fun testEqualsWithUnknown(x: Any?) {
|
||||
if (isString(x) == unknownFunction()) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
|
||||
fun testNotEqualsWithUnknown(x: Any?) {
|
||||
if (isString(x) != unknownFunction()) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
|
||||
fun testEqualsWithVariable(x: Any?, b: Boolean) {
|
||||
if (isString(x) == b) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun testNotEqualsWithVariable(x: Any?, b: Boolean) {
|
||||
if (isString(x) != b) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package
|
||||
|
||||
public fun isString(/*0*/ x: kotlin.Any?): kotlin.Boolean
|
||||
Returns(TRUE) -> x is String
|
||||
|
||||
public fun testEqualsWithConstant(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun testEqualsWithUnknown(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun testEqualsWithVariable(/*0*/ x: kotlin.Any?, /*1*/ b: kotlin.Boolean): kotlin.Unit
|
||||
public fun testNotEqualsWithConstant(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun testNotEqualsWithUnknown(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun testNotEqualsWithVariable(/*0*/ x: kotlin.Any?, /*1*/ b: kotlin.Boolean): kotlin.Unit
|
||||
public fun unknownFunction(): kotlin.Any?
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
// !LANGUAGE: +ReturnsEffect
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
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.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>inc<!>()
|
||||
}
|
||||
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
package
|
||||
|
||||
public fun br(/*0*/ y: kotlin.Any?): kotlin.Unit
|
||||
public fun branchedAndNested(/*0*/ x: kotlin.Any?, /*1*/ y: kotlin.Any?): kotlin.Unit
|
||||
public fun branchedAndNestedWithNativeOperators(/*0*/ x: kotlin.Any?, /*1*/ y: kotlin.Any?): kotlin.Unit
|
||||
public fun equalsTrue(/*0*/ x: kotlin.Boolean): kotlin.Boolean
|
||||
Returns(TRUE) -> x
|
||||
|
||||
public fun isInt(/*0*/ x: kotlin.Any?): kotlin.Boolean
|
||||
Returns(TRUE) -> x is Int
|
||||
|
||||
public fun isString(/*0*/ x: kotlin.Any?): kotlin.Boolean
|
||||
Returns(TRUE) -> x is String
|
||||
|
||||
public fun myAssert(/*0*/ condition: kotlin.Boolean): kotlin.Unit
|
||||
Returns(WILDCARD) -> condition
|
||||
|
||||
public fun nested1(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun nested2(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun nested3(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun notEqualsNull(/*0*/ x: kotlin.Any?): kotlin.Boolean
|
||||
Returns(TRUE) -> x != null
|
||||
|
||||
public fun nullWhenNotString(/*0*/ x: kotlin.Any?): kotlin.String?
|
||||
Returns(NOT_NULL) -> x is String
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
// !LANGUAGE: +ReturnsEffect
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.internal.contracts.*
|
||||
|
||||
fun isString(x: Any?): Boolean {
|
||||
contract {
|
||||
returns(true) implies (x is String)
|
||||
}
|
||||
return x is String
|
||||
}
|
||||
|
||||
|
||||
fun notIsString(x: Any?): Boolean {
|
||||
contract {
|
||||
returns(false) implies (x is String)
|
||||
}
|
||||
return x !is String
|
||||
}
|
||||
|
||||
fun notIsInt(x: Any?): Boolean {
|
||||
contract {
|
||||
returns(false) implies (x !is Int)
|
||||
}
|
||||
return x !is Int
|
||||
}
|
||||
|
||||
fun intersectingInfo(x: Any?, y: Any?) {
|
||||
if ((isString(x) && y is String) || (!notIsString(x) && !notIsInt(y))) {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
y.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
y.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>inc<!>()
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
y.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
y.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>inc<!>()
|
||||
}
|
||||
}
|
||||
|
||||
fun intersectingInfo2(x: Any?, y: Any?) {
|
||||
// In each arg of "||"-operator presented fact "x is String" which should lead to smartcast.
|
||||
// Also there are 3 additional facts: "x is Int", "y is String", "y is Int". One
|
||||
// of them is absent in each arg of "||"-operator, so they *shouldn't* lead to smartcast
|
||||
|
||||
if ((isString(x) && !notIsInt(x) && y is String) ||
|
||||
(!notIsString(x) && isString(y) && y is Int) ||
|
||||
(x is String && !notIsInt(y) && x is Int)) {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
x.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>inc<!>()
|
||||
y.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
y.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>inc<!>()
|
||||
}
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>inc<!>()
|
||||
y.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
y.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>inc<!>()
|
||||
}
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package
|
||||
|
||||
public fun intersectingInfo(/*0*/ x: kotlin.Any?, /*1*/ y: kotlin.Any?): kotlin.Unit
|
||||
public fun intersectingInfo2(/*0*/ x: kotlin.Any?, /*1*/ y: kotlin.Any?): kotlin.Unit
|
||||
public fun isString(/*0*/ x: kotlin.Any?): kotlin.Boolean
|
||||
Returns(TRUE) -> x is String
|
||||
|
||||
public fun notIsInt(/*0*/ x: kotlin.Any?): kotlin.Boolean
|
||||
Returns(FALSE) -> x !is Int
|
||||
|
||||
public fun notIsString(/*0*/ x: kotlin.Any?): kotlin.Boolean
|
||||
Returns(FALSE) -> x is String
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
// !LANGUAGE: +ReturnsEffect
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.internal.contracts.*
|
||||
|
||||
fun notIsString(x: Any?): Boolean {
|
||||
contract {
|
||||
returns(false) implies (x is String)
|
||||
}
|
||||
return x !is String
|
||||
}
|
||||
|
||||
fun notIsInt(x: Any?): Boolean {
|
||||
contract {
|
||||
returns(false) implies (x is Int)
|
||||
}
|
||||
return x !is Int
|
||||
}
|
||||
|
||||
fun testDeMorgan(x: Any?) {
|
||||
// !(x !is String || x !is Int)
|
||||
// x is String && x is Int
|
||||
if (!(notIsString(x) || notIsInt(x))) {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.inc()
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>inc<!>()
|
||||
}
|
||||
}
|
||||
|
||||
fun testDeMorgan2(x: Any?) {
|
||||
// x !is String || x !is Int
|
||||
if (notIsString(x) || notIsInt(x)) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>inc<!>()
|
||||
}
|
||||
else {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.inc()
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package
|
||||
|
||||
public fun notIsInt(/*0*/ x: kotlin.Any?): kotlin.Boolean
|
||||
Returns(FALSE) -> x is Int
|
||||
|
||||
public fun notIsString(/*0*/ x: kotlin.Any?): kotlin.Boolean
|
||||
Returns(FALSE) -> x is String
|
||||
|
||||
public fun testDeMorgan(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun testDeMorgan2(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
Vendored
+86
@@ -0,0 +1,86 @@
|
||||
// !LANGUAGE: +ReturnsEffect
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.internal.contracts.*
|
||||
|
||||
fun onlyTrue(b: Boolean): Boolean {
|
||||
contract {
|
||||
returns(true) implies (b)
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
fun onlyFalse(b: Boolean): Boolean {
|
||||
contract {
|
||||
returns(false) implies (!b)
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
fun trueAndFalse(b: Boolean): Boolean {
|
||||
contract {
|
||||
returns(true) implies (b)
|
||||
returns(false) implies (!b)
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ==== actual tests ====
|
||||
|
||||
fun useOnlyTrueInTrueBranch(x: Any?) {
|
||||
if (onlyTrue(x is String)) {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun useOnlyTrueInFalseBranch(x: Any?) {
|
||||
if (onlyTrue(x !is String)) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
// No smartcast here, we don't know that condition is false here
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun useOnlyFalseInTrueBranch(x: Any?) {
|
||||
if (onlyFalse(x is String)) {
|
||||
// No smartcast here, we don't know that condition is true here
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun useOnlyFalseInFalseBranch(x: Any?) {
|
||||
if (onlyFalse(x !is String)) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
}
|
||||
|
||||
fun useTrueAndFalseInTrueBranch(x: Any?) {
|
||||
if (trueAndFalse(x is String)) {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun useTrueAndFalseInFalseBranch(x: Any?) {
|
||||
if (trueAndFalse(x !is String)) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
}
|
||||
Vendored
+18
@@ -0,0 +1,18 @@
|
||||
package
|
||||
|
||||
public fun onlyFalse(/*0*/ b: kotlin.Boolean): kotlin.Boolean
|
||||
Returns(FALSE) -> !b
|
||||
|
||||
public fun onlyTrue(/*0*/ b: kotlin.Boolean): kotlin.Boolean
|
||||
Returns(TRUE) -> b
|
||||
|
||||
public fun trueAndFalse(/*0*/ b: kotlin.Boolean): kotlin.Boolean
|
||||
Returns(TRUE) -> b
|
||||
Returns(FALSE) -> !b
|
||||
|
||||
public fun useOnlyFalseInFalseBranch(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun useOnlyFalseInTrueBranch(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun useOnlyTrueInFalseBranch(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun useOnlyTrueInTrueBranch(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun useTrueAndFalseInFalseBranch(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun useTrueAndFalseInTrueBranch(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
Vendored
+67
@@ -0,0 +1,67 @@
|
||||
// !LANGUAGE: +CallsInPlaceEffect +ReturnsEffect
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.internal.contracts.*
|
||||
|
||||
fun callsAndInverts(b: Boolean, block: () -> Unit): Boolean {
|
||||
contract {
|
||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||
returns(true) implies (!b)
|
||||
returns(false) implies b
|
||||
}
|
||||
|
||||
block()
|
||||
return !b
|
||||
}
|
||||
|
||||
|
||||
|
||||
fun smartcastAndInitialization(x: Any?) {
|
||||
val y: Int
|
||||
|
||||
if (callsAndInverts(x !is String) { y = 42 }) {
|
||||
println(y)
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
} else {
|
||||
println(y)
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
println(y)
|
||||
}
|
||||
|
||||
fun inPresenceOfLazy(x: Any?, unknownBoolean: Boolean) {
|
||||
val y: Int
|
||||
|
||||
if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) {
|
||||
println(<!UNINITIALIZED_VARIABLE!>y<!>)
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
else {
|
||||
println(y)
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
println(y)
|
||||
}
|
||||
|
||||
fun isPresenceOfLazy2(x: Any?, unknownBoolean: Boolean) {
|
||||
val y: Int
|
||||
if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
else {
|
||||
println(<!UNINITIALIZED_VARIABLE!>y<!>)
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
println(y)
|
||||
}
|
||||
|
||||
fun isPresenceOfLazy3(x: Any?, unknownBoolean: Boolean) {
|
||||
val y: Int
|
||||
if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
println(<!UNINITIALIZED_VARIABLE!>y<!>)
|
||||
}
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
package
|
||||
|
||||
public fun callsAndInverts(/*0*/ b: kotlin.Boolean, /*1*/ block: () -> kotlin.Unit): kotlin.Boolean
|
||||
CallsInPlace(block, EXACTLY_ONCE)
|
||||
Returns(TRUE) -> !b
|
||||
Returns(FALSE) -> b
|
||||
|
||||
public fun inPresenceOfLazy(/*0*/ x: kotlin.Any?, /*1*/ unknownBoolean: kotlin.Boolean): kotlin.Unit
|
||||
public fun isPresenceOfLazy2(/*0*/ x: kotlin.Any?, /*1*/ unknownBoolean: kotlin.Boolean): kotlin.Unit
|
||||
public fun isPresenceOfLazy3(/*0*/ x: kotlin.Any?, /*1*/ unknownBoolean: kotlin.Boolean): kotlin.Unit
|
||||
public fun smartcastAndInitialization(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
// !LANGUAGE: +ReturnsEffect
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.internal.contracts.*
|
||||
|
||||
fun nullWhenNull(x: Int?): Int? {
|
||||
contract {
|
||||
returnsNotNull() implies (x != null)
|
||||
}
|
||||
return x?.inc()
|
||||
}
|
||||
|
||||
fun testNullWhenNull(x: Int?) {
|
||||
if (nullWhenNull(x) == null) {
|
||||
x<!UNSAFE_CALL!>.<!>dec()
|
||||
}
|
||||
else {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.dec()
|
||||
}
|
||||
|
||||
if (nullWhenNull(x) != null) {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.dec()
|
||||
}
|
||||
else {
|
||||
x<!UNSAFE_CALL!>.<!>dec()
|
||||
}
|
||||
|
||||
x<!UNSAFE_CALL!>.<!>dec()
|
||||
}
|
||||
|
||||
// NB. it is the same function as `nullWhenNull`, but annotations specifies other facet of the function behaviour
|
||||
fun notNullWhenNotNull (x: Int?): Int? {
|
||||
contract {
|
||||
returns(null) implies (x == null)
|
||||
}
|
||||
return x?.inc()
|
||||
}
|
||||
|
||||
fun testNotNullWhenNotNull (x: Int?) {
|
||||
if (notNullWhenNotNull(x) == null) {
|
||||
<!SENSELESS_COMPARISON!><!DEBUG_INFO_CONSTANT!>x<!> == null<!>
|
||||
}
|
||||
else {
|
||||
x<!UNSAFE_CALL!>.<!>dec()
|
||||
}
|
||||
|
||||
if (notNullWhenNotNull(x) != null) {
|
||||
x<!UNSAFE_CALL!>.<!>dec()
|
||||
}
|
||||
else {
|
||||
<!SENSELESS_COMPARISON!><!DEBUG_INFO_CONSTANT!>x<!> == null<!>
|
||||
}
|
||||
|
||||
x<!UNSAFE_CALL!>.<!>dec()
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package
|
||||
|
||||
public fun notNullWhenNotNull(/*0*/ x: kotlin.Int?): kotlin.Int?
|
||||
Returns(NULL) -> x == null
|
||||
|
||||
public fun nullWhenNull(/*0*/ x: kotlin.Int?): kotlin.Int?
|
||||
Returns(NOT_NULL) -> x != null
|
||||
|
||||
public fun testNotNullWhenNotNull(/*0*/ x: kotlin.Int?): kotlin.Unit
|
||||
public fun testNullWhenNull(/*0*/ x: kotlin.Int?): kotlin.Unit
|
||||
Vendored
+79
@@ -0,0 +1,79 @@
|
||||
// !LANGUAGE: +ReturnsEffect
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.internal.contracts.*
|
||||
|
||||
fun trueWhenString(x: Any?): Boolean {
|
||||
contract {
|
||||
returns(true) implies (x is String)
|
||||
}
|
||||
return x is String
|
||||
}
|
||||
|
||||
fun trueWhenInt(x: Any?): Boolean {
|
||||
contract {
|
||||
returns(true) implies (x is Int)
|
||||
}
|
||||
return x is Int
|
||||
}
|
||||
|
||||
fun falseWhenString(x: Any?): Boolean {
|
||||
contract {
|
||||
returns(false) implies (x is String)
|
||||
}
|
||||
return x !is String
|
||||
}
|
||||
|
||||
fun falseWhenInt(x: Any?): Boolean {
|
||||
contract {
|
||||
returns(false) implies (x is Int)
|
||||
}
|
||||
return x !is Int
|
||||
}
|
||||
|
||||
|
||||
// ==== Actual tests ====
|
||||
|
||||
fun truetrue(x: Any?) {
|
||||
if (trueWhenString(x) && trueWhenInt(x)) {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.inc()
|
||||
}
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>inc<!>()
|
||||
}
|
||||
|
||||
fun truefalse(x: Any?) {
|
||||
if (trueWhenString(x) && falseWhenInt(x)) {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
x.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>inc<!>()
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>inc<!>()
|
||||
}
|
||||
}
|
||||
|
||||
fun falsetrue(x: Any?) {
|
||||
if (falseWhenString(x) && trueWhenInt(x)) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.inc()
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>inc<!>()
|
||||
}
|
||||
}
|
||||
|
||||
fun falsefalse(x: Any?) {
|
||||
if (falseWhenString(x) && falseWhenInt(x)) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>inc<!>()
|
||||
}
|
||||
else {
|
||||
// Note that we can't argue that we have any of smartcasts here,
|
||||
// because we don't know which one of both arguments was 'false' to bring us here
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>inc<!>()
|
||||
}
|
||||
}
|
||||
Vendored
+18
@@ -0,0 +1,18 @@
|
||||
package
|
||||
|
||||
public fun falseWhenInt(/*0*/ x: kotlin.Any?): kotlin.Boolean
|
||||
Returns(FALSE) -> x is Int
|
||||
|
||||
public fun falseWhenString(/*0*/ x: kotlin.Any?): kotlin.Boolean
|
||||
Returns(FALSE) -> x is String
|
||||
|
||||
public fun falsefalse(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun falsetrue(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun trueWhenInt(/*0*/ x: kotlin.Any?): kotlin.Boolean
|
||||
Returns(TRUE) -> x is Int
|
||||
|
||||
public fun trueWhenString(/*0*/ x: kotlin.Any?): kotlin.Boolean
|
||||
Returns(TRUE) -> x is String
|
||||
|
||||
public fun truefalse(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun truetrue(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
// !LANGUAGE: +ReturnsEffect
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.internal.contracts.*
|
||||
|
||||
fun trueWhenString(x: Any?): Boolean {
|
||||
contract {
|
||||
returns(true) implies (x is String)
|
||||
}
|
||||
return x is String
|
||||
}
|
||||
|
||||
fun falseWhenString(x: Any?): Boolean {
|
||||
contract {
|
||||
returns(false) implies (x is String)
|
||||
}
|
||||
return x !is String
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
fun annotatedTrueAndTrue(x: Any?) {
|
||||
if (trueWhenString(x) && true) {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun annotatedTrueAndFalse(x: Any?) {
|
||||
if (trueWhenString(x) && false) {
|
||||
// Unreachable
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun annotatedFalseAndTrue(x: Any?) {
|
||||
if (falseWhenString(x) && true) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
}
|
||||
|
||||
fun annotatedFalseAndFalse(x: Any?) {
|
||||
if (falseWhenString(x) && false) {
|
||||
// Unreachable
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package
|
||||
|
||||
public fun annotatedFalseAndFalse(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun annotatedFalseAndTrue(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun annotatedTrueAndFalse(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun annotatedTrueAndTrue(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun falseWhenString(/*0*/ x: kotlin.Any?): kotlin.Boolean
|
||||
Returns(FALSE) -> x is String
|
||||
|
||||
public fun trueWhenString(/*0*/ x: kotlin.Any?): kotlin.Boolean
|
||||
Returns(TRUE) -> x is String
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
// !LANGUAGE: +ReturnsEffect
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.internal.contracts.*
|
||||
|
||||
fun trueWhenString(x: Any?): Boolean {
|
||||
contract {
|
||||
returns(true) implies (x is String)
|
||||
}
|
||||
return x is String
|
||||
}
|
||||
|
||||
fun falseWhenString(x: Any?): Boolean {
|
||||
contract {
|
||||
returns(false) implies (x is String)
|
||||
}
|
||||
return x !is String
|
||||
}
|
||||
|
||||
fun unknownFunction(x: Any?) = x == 42
|
||||
|
||||
|
||||
|
||||
|
||||
fun annotatedTrue(x: Any?) {
|
||||
if (trueWhenString(x) && unknownFunction(x)) {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun annotatedFalse(x: Any?) {
|
||||
if (falseWhenString(x) && unknownFunction(x)) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun annotatedTrueWithVariable(x: Any?, b: Boolean) {
|
||||
if (trueWhenString(x) && b) {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun annotatedFalseWithVariable(x: Any?, b: Boolean) {
|
||||
if (falseWhenString(x) && b) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package
|
||||
|
||||
public fun annotatedFalse(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun annotatedFalseWithVariable(/*0*/ x: kotlin.Any?, /*1*/ b: kotlin.Boolean): kotlin.Unit
|
||||
public fun annotatedTrue(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun annotatedTrueWithVariable(/*0*/ x: kotlin.Any?, /*1*/ b: kotlin.Boolean): kotlin.Unit
|
||||
public fun falseWhenString(/*0*/ x: kotlin.Any?): kotlin.Boolean
|
||||
Returns(FALSE) -> x is String
|
||||
|
||||
public fun trueWhenString(/*0*/ x: kotlin.Any?): kotlin.Boolean
|
||||
Returns(TRUE) -> x is String
|
||||
|
||||
public fun unknownFunction(/*0*/ x: kotlin.Any?): kotlin.Boolean
|
||||
Vendored
+45
@@ -0,0 +1,45 @@
|
||||
// !LANGUAGE: +ReturnsEffect
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.internal.contracts.*
|
||||
|
||||
fun myEqualsNull(x: Int?): Boolean {
|
||||
contract {
|
||||
returns(false) implies (x != null)
|
||||
}
|
||||
return x == null
|
||||
}
|
||||
|
||||
fun myEqualsNotNull(x: Int?): Boolean {
|
||||
contract {
|
||||
returns(true) implies (x != null)
|
||||
}
|
||||
return x != null
|
||||
}
|
||||
|
||||
fun testBasicEquals(x: Int?) {
|
||||
x<!UNSAFE_CALL!>.<!>inc()
|
||||
|
||||
if (myEqualsNull(x)) {
|
||||
x<!UNSAFE_CALL!>.<!>inc()
|
||||
}
|
||||
else {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.inc()
|
||||
}
|
||||
|
||||
x<!UNSAFE_CALL!>.<!>inc()
|
||||
}
|
||||
|
||||
fun testBasicNotEquals(x: Int?) {
|
||||
x<!UNSAFE_CALL!>.<!>inc()
|
||||
|
||||
if (myEqualsNotNull(x)) {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.inc()
|
||||
}
|
||||
else {
|
||||
x<!UNSAFE_CALL!>.<!>inc()
|
||||
}
|
||||
|
||||
x<!UNSAFE_CALL!>.<!>inc()
|
||||
}
|
||||
|
||||
compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/equalsOperator.txt
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
package
|
||||
|
||||
public fun myEqualsNotNull(/*0*/ x: kotlin.Int?): kotlin.Boolean
|
||||
Returns(TRUE) -> x != null
|
||||
|
||||
public fun myEqualsNull(/*0*/ x: kotlin.Int?): kotlin.Boolean
|
||||
Returns(FALSE) -> x != null
|
||||
|
||||
public fun testBasicEquals(/*0*/ x: kotlin.Int?): kotlin.Unit
|
||||
public fun testBasicNotEquals(/*0*/ x: kotlin.Int?): kotlin.Unit
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
// !LANGUAGE: +ReturnsEffect
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.internal.contracts.*
|
||||
|
||||
fun safeIsString(x: Any?): Boolean? {
|
||||
contract {
|
||||
returns(true) implies (x is String)
|
||||
}
|
||||
return x?.let { it is String }
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
fun equalsTrue(x: Any?) {
|
||||
if (safeIsString(x) == true) {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun equalsFalse(x: Any?) {
|
||||
if (safeIsString(x) == false) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun equalsNull(x: Any?) {
|
||||
if (safeIsString(x) == null) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun notEqualsTrue(x: Any?) {
|
||||
if (safeIsString(x) != true) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
}
|
||||
|
||||
fun notEqualsFalse(x: Any?) {
|
||||
if (safeIsString(x) != false) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun notEqualsNull(x: Any?) {
|
||||
if (safeIsString(x) != null) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package
|
||||
|
||||
public fun equalsFalse(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun equalsNull(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun equalsTrue(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun notEqualsFalse(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun notEqualsNull(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun notEqualsTrue(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun safeIsString(/*0*/ x: kotlin.Any?): kotlin.Boolean?
|
||||
Returns(TRUE) -> x is String
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
// !LANGUAGE: +ReturnsEffect
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.internal.contracts.*
|
||||
|
||||
fun isString(x: Any?): Boolean {
|
||||
contract {
|
||||
returns(true) implies (x is String)
|
||||
}
|
||||
return x is String
|
||||
}
|
||||
|
||||
|
||||
fun notIsString(x: Any?): Boolean {
|
||||
contract {
|
||||
returns(false) implies (x is String)
|
||||
}
|
||||
return x !is String
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
fun testSimple(x: Any?) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
|
||||
if (isString(x)) {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun testSpilling(x: Any?) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
|
||||
if (isString(x)) <!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
|
||||
fun testInversion(x: Any?) {
|
||||
if (notIsString(x)) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
}
|
||||
|
||||
fun testInversionSpilling(x: Any?) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
|
||||
if (notIsString(x)) else <!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package
|
||||
|
||||
public fun isString(/*0*/ x: kotlin.Any?): kotlin.Boolean
|
||||
Returns(TRUE) -> x is String
|
||||
|
||||
public fun notIsString(/*0*/ x: kotlin.Any?): kotlin.Boolean
|
||||
Returns(FALSE) -> x is String
|
||||
|
||||
public fun testInversion(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun testInversionSpilling(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun testSimple(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun testSpilling(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
Vendored
+76
@@ -0,0 +1,76 @@
|
||||
// !LANGUAGE: +ReturnsEffect
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.internal.contracts.*
|
||||
|
||||
fun trueWhenString(x: Any?): Boolean {
|
||||
contract {
|
||||
returns(true) implies (x is String)
|
||||
}
|
||||
return x is String
|
||||
}
|
||||
|
||||
fun trueWhenInt(x: Any?): Boolean {
|
||||
contract {
|
||||
returns(true) implies (x is Int)
|
||||
}
|
||||
return x is Int
|
||||
}
|
||||
|
||||
fun falseWhenString(x: Any?): Boolean {
|
||||
contract {
|
||||
returns(false) implies (x is String)
|
||||
}
|
||||
return x !is String
|
||||
}
|
||||
|
||||
fun falseWhenInt(x: Any?): Boolean {
|
||||
contract {
|
||||
returns(false) implies (x is Int)
|
||||
}
|
||||
return x !is Int
|
||||
}
|
||||
|
||||
fun truetrue(x: Any?) {
|
||||
if (trueWhenString(x) || trueWhenInt(x)) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>inc<!>()
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>inc<!>()
|
||||
}
|
||||
}
|
||||
|
||||
fun truefalse(x: Any?) {
|
||||
if (trueWhenString(x) || falseWhenInt(x)) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>inc<!>()
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.inc()
|
||||
}
|
||||
}
|
||||
|
||||
fun falsetrue(x: Any?) {
|
||||
if (falseWhenString(x) || trueWhenInt(x)) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>inc<!>()
|
||||
}
|
||||
else {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
x.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>inc<!>()
|
||||
}
|
||||
}
|
||||
|
||||
fun falsefalse(x: Any?) {
|
||||
if (falseWhenString(x) || falseWhenInt(x)) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>inc<!>()
|
||||
}
|
||||
else {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.inc()
|
||||
}
|
||||
}
|
||||
Vendored
+18
@@ -0,0 +1,18 @@
|
||||
package
|
||||
|
||||
public fun falseWhenInt(/*0*/ x: kotlin.Any?): kotlin.Boolean
|
||||
Returns(FALSE) -> x is Int
|
||||
|
||||
public fun falseWhenString(/*0*/ x: kotlin.Any?): kotlin.Boolean
|
||||
Returns(FALSE) -> x is String
|
||||
|
||||
public fun falsefalse(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun falsetrue(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun trueWhenInt(/*0*/ x: kotlin.Any?): kotlin.Boolean
|
||||
Returns(TRUE) -> x is Int
|
||||
|
||||
public fun trueWhenString(/*0*/ x: kotlin.Any?): kotlin.Boolean
|
||||
Returns(TRUE) -> x is String
|
||||
|
||||
public fun truefalse(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun truetrue(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
// !LANGUAGE: +ReturnsEffect
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.internal.contracts.*
|
||||
|
||||
fun trueWhenString(x: Any?): Boolean {
|
||||
contract {
|
||||
returns(true) implies (x is String)
|
||||
}
|
||||
return x is String
|
||||
}
|
||||
|
||||
fun falseWhenString(x: Any?): Boolean {
|
||||
contract {
|
||||
returns(false) implies (x is String)
|
||||
}
|
||||
return x !is String
|
||||
}
|
||||
|
||||
fun annotatedTrueOrTrue(x: Any?) {
|
||||
if (trueWhenString(x) || true) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
// Unreachable
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun annotatedTrueOrFalse(x: Any?) {
|
||||
if (trueWhenString(x) || false) {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun annotatedFalseOrTrue(x: Any?) {
|
||||
if (falseWhenString(x) || true) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
// Unreachable
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
}
|
||||
|
||||
fun annotatedFalseOrFalse(x: Any?) {
|
||||
if (falseWhenString(x) || false) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package
|
||||
|
||||
public fun annotatedFalseOrFalse(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun annotatedFalseOrTrue(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun annotatedTrueOrFalse(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun annotatedTrueOrTrue(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun falseWhenString(/*0*/ x: kotlin.Any?): kotlin.Boolean
|
||||
Returns(FALSE) -> x is String
|
||||
|
||||
public fun trueWhenString(/*0*/ x: kotlin.Any?): kotlin.Boolean
|
||||
Returns(TRUE) -> x is String
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
// !LANGUAGE: +ReturnsEffect
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.internal.contracts.*
|
||||
|
||||
fun trueWhenString(x: Any?): Boolean {
|
||||
contract {
|
||||
returns(true) implies (x is String)
|
||||
}
|
||||
return x is String
|
||||
}
|
||||
|
||||
fun falseWhenString(x: Any?): Boolean {
|
||||
contract {
|
||||
returns(false) implies (x is String)
|
||||
}
|
||||
return x !is String
|
||||
}
|
||||
|
||||
fun unknownFunction(x: Any?) = x == 42
|
||||
|
||||
|
||||
|
||||
|
||||
fun annotatedTrue(x: Any?) {
|
||||
if (trueWhenString(x) || unknownFunction(x)) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun annotatedFalse(x: Any?) {
|
||||
if (falseWhenString(x) || unknownFunction(x)) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
}
|
||||
|
||||
fun annotatedTrueWithVariable(x: Any?, b: Boolean) {
|
||||
if (trueWhenString(x) || b) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun annotatedFalseWithVariable(x: Any?, b: Boolean) {
|
||||
if (falseWhenString(x) || b) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package
|
||||
|
||||
public fun annotatedFalse(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun annotatedFalseWithVariable(/*0*/ x: kotlin.Any?, /*1*/ b: kotlin.Boolean): kotlin.Unit
|
||||
public fun annotatedTrue(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun annotatedTrueWithVariable(/*0*/ x: kotlin.Any?, /*1*/ b: kotlin.Boolean): kotlin.Unit
|
||||
public fun falseWhenString(/*0*/ x: kotlin.Any?): kotlin.Boolean
|
||||
Returns(FALSE) -> x is String
|
||||
|
||||
public fun trueWhenString(/*0*/ x: kotlin.Any?): kotlin.Boolean
|
||||
Returns(TRUE) -> x is String
|
||||
|
||||
public fun unknownFunction(/*0*/ x: kotlin.Any?): kotlin.Boolean
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// !LANGUAGE: +ReturnsEffect
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.internal.contracts.*
|
||||
|
||||
fun isString(x: Any?): Boolean {
|
||||
contract {
|
||||
returns(true) implies (x is String)
|
||||
}
|
||||
return x is String
|
||||
}
|
||||
|
||||
fun incorrectPartDoesntMatter(x: Any?) {
|
||||
if (isString(x) && <!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>) {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package
|
||||
|
||||
public fun incorrectPartDoesntMatter(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun isString(/*0*/ x: kotlin.Any?): kotlin.Boolean
|
||||
Returns(TRUE) -> x is String
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
// !LANGUAGE: +ReturnsEffect
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.internal.contracts.*
|
||||
|
||||
fun Any?.isNull(): Boolean {
|
||||
contract {
|
||||
returns(false) implies (this@isNull != null)
|
||||
}
|
||||
return this == null
|
||||
}
|
||||
|
||||
fun smartcastOnReceiver(x: Int?) {
|
||||
if (x.isNull()) {
|
||||
x<!UNSAFE_CALL!>.<!>inc()
|
||||
}
|
||||
else {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.dec()
|
||||
}
|
||||
}
|
||||
|
||||
class UnstableReceiver {
|
||||
var x: Int? = 42
|
||||
|
||||
fun smartcastOnUnstableReceiver() {
|
||||
if (x.isNull()) {
|
||||
x<!UNSAFE_CALL!>.<!>inc()
|
||||
}
|
||||
else {
|
||||
<!SMARTCAST_IMPOSSIBLE!>x<!>.dec()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package
|
||||
|
||||
public fun smartcastOnReceiver(/*0*/ x: kotlin.Int?): kotlin.Unit
|
||||
public fun kotlin.Any?.isNull(): kotlin.Boolean
|
||||
Returns(FALSE) -> <this> != null
|
||||
|
||||
public final class UnstableReceiver {
|
||||
public constructor UnstableReceiver()
|
||||
public final var x: kotlin.Int?
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public final fun smartcastOnUnstableReceiver(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
// !LANGUAGE: +ReturnsEffect
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.internal.contracts.*
|
||||
|
||||
fun myAssert(condition: Boolean) {
|
||||
contract {
|
||||
returns() implies (condition)
|
||||
}
|
||||
if (!condition) throw kotlin.IllegalArgumentException("Assertion failed")
|
||||
}
|
||||
|
||||
fun testAssertSmartcast(x: Any?) {
|
||||
myAssert(x is String)
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
|
||||
fun testInvertedAssert(x: Any?) {
|
||||
myAssert(x !is String)
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
|
||||
fun testSpilling(x: Any?) {
|
||||
if (x != null) {
|
||||
myAssert(x is String)
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
|
||||
fun testAssertInIf(x: Any?) {
|
||||
if (myAssert(x is String) == Unit) {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
else {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
}
|
||||
|
||||
fun testTryCatch(x: Any?) {
|
||||
try {
|
||||
myAssert(x is String)
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
} catch (e: kotlin.IllegalArgumentException) {
|
||||
|
||||
}
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
|
||||
fun testUncertainFlow(x: Any?) {
|
||||
repeat(x.toString().length) {
|
||||
myAssert(x is String)
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
|
||||
fun testAtLeastOnceFlow(x: Any?) {
|
||||
do {
|
||||
myAssert(x is String)
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
} while (x != null)
|
||||
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package
|
||||
|
||||
public fun myAssert(/*0*/ condition: kotlin.Boolean): kotlin.Unit
|
||||
Returns(WILDCARD) -> condition
|
||||
|
||||
public fun testAssertInIf(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun testAssertSmartcast(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun testAtLeastOnceFlow(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun testInvertedAssert(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun testSpilling(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun testTryCatch(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun testUncertainFlow(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
Vendored
+58
@@ -0,0 +1,58 @@
|
||||
// !LANGUAGE: +ReturnsEffect
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.internal.contracts.*
|
||||
|
||||
|
||||
fun nullWhenString(x: Any?): Int? {
|
||||
contract {
|
||||
returns(null) implies (x is String)
|
||||
}
|
||||
return if (x is String) null else 42
|
||||
}
|
||||
|
||||
fun nullWhenNotString(x: Any?): Int? {
|
||||
contract {
|
||||
returns(null) implies (x !is String)
|
||||
}
|
||||
return if (x !is String) null else 42
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ==== Actual tests =====
|
||||
|
||||
|
||||
fun test1(x: Any?) {
|
||||
// condition == true <=> function returned null <=> 'x' is String
|
||||
if (nullWhenString(x) == null) {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun test2(x: Any?) {
|
||||
// Observe that condition == false <=>* function returned null <=> 'x' is String
|
||||
// *correct only for at most binary types, which is exactly the case for nullability comparisons
|
||||
if (nullWhenString(x) != null) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun test3(x: Any?) {
|
||||
// condition == false <=> function returned not-null, but we don't know anything about when function returns not-null
|
||||
if (nullWhenNotString(x) == null) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
package
|
||||
|
||||
public fun nullWhenNotString(/*0*/ x: kotlin.Any?): kotlin.Int?
|
||||
Returns(NULL) -> x !is String
|
||||
|
||||
public fun nullWhenString(/*0*/ x: kotlin.Any?): kotlin.Int?
|
||||
Returns(NULL) -> x is String
|
||||
|
||||
public fun test1(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun test2(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun test3(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
// !LANGUAGE: +ReturnsEffect
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.internal.contracts.*
|
||||
|
||||
// ===== Definitions ====
|
||||
fun isString(x: Any?): Boolean {
|
||||
contract {
|
||||
returns(true) implies (x is String)
|
||||
}
|
||||
return x is String
|
||||
}
|
||||
|
||||
|
||||
// ==== Actual tests =======
|
||||
|
||||
fun implicitAlwaysFalse(x: Any?) {
|
||||
if (isString(x) && !isString(x)) {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun implicitAlwaysFalseSpilling(x: Any?) {
|
||||
if (isString(x) && !isString(x)) {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package
|
||||
|
||||
public fun implicitAlwaysFalse(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun implicitAlwaysFalseSpilling(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun isString(/*0*/ x: kotlin.Any?): kotlin.Boolean
|
||||
Returns(TRUE) -> x is String
|
||||
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
// !LANGUAGE: +ReturnsEffect
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.internal.contracts.*
|
||||
|
||||
fun isString(x: Any?): Boolean {
|
||||
contract {
|
||||
returns(true) implies (x is String)
|
||||
}
|
||||
return x is String
|
||||
}
|
||||
|
||||
fun exhaustive(x: Any?) {
|
||||
when (isString(x)) {
|
||||
true -> <!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
false -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
|
||||
when(!isString(x)) {
|
||||
true -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
false -> <!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
}
|
||||
|
||||
fun smartcastInElse(x: Any?) {
|
||||
when (isString(x)) {
|
||||
false -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
else -> <!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
|
||||
when (!isString(x)) {
|
||||
true -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
else -> <!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package
|
||||
|
||||
public fun exhaustive(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun isString(/*0*/ x: kotlin.Any?): kotlin.Boolean
|
||||
Returns(TRUE) -> x is String
|
||||
|
||||
public fun smartcastInElse(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
// !LANGUAGE: +ReturnsEffect
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.internal.contracts.*
|
||||
|
||||
fun safeIsString(x: Any?): Boolean? {
|
||||
contract {
|
||||
returns(true) implies (x is String)
|
||||
}
|
||||
return x?.let { it is String }
|
||||
}
|
||||
|
||||
fun elseWithNullableResult(x: Any?) {
|
||||
when (safeIsString(x)) {
|
||||
false -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
else -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
|
||||
when (safeIsString(x)) {
|
||||
true -> <!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
else -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
|
||||
when (safeIsString(x)) {
|
||||
true -> <!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
false -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
else -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
|
||||
when (safeIsString(x)) {
|
||||
true -> <!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
null -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
else -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun exhaustiveWithNullableResult(x: Any?) {
|
||||
when (safeIsString(x)) {
|
||||
true -> <!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
false -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
null -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
|
||||
when (safeIsString(x)) {
|
||||
false -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
true -> <!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
null -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
|
||||
when (safeIsString(x)) {
|
||||
false -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
null -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
true -> <!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
package
|
||||
|
||||
public fun elseWithNullableResult(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun exhaustiveWithNullableResult(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun safeIsString(/*0*/ x: kotlin.Any?): kotlin.Boolean?
|
||||
Returns(TRUE) -> x is String
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
// !LANGUAGE: +ReturnsEffect
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.internal.contracts.*
|
||||
|
||||
fun isString(x: Any?): Boolean {
|
||||
contract {
|
||||
returns(true) implies (x is String)
|
||||
}
|
||||
return x is String
|
||||
}
|
||||
|
||||
fun exhaustive(x: Any?) {
|
||||
when {
|
||||
isString(x) -> <!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
!isString(x) -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
|
||||
when {
|
||||
!isString(x) -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
isString(x) -> <!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
}
|
||||
|
||||
fun smartcastInElse(x: Any?) {
|
||||
when {
|
||||
!isString(x) -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
else -> <!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package
|
||||
|
||||
public fun exhaustive(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun isString(/*0*/ x: kotlin.Any?): kotlin.Boolean
|
||||
Returns(TRUE) -> x is String
|
||||
|
||||
public fun smartcastInElse(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
Reference in New Issue
Block a user