[FIR-TEST] Add tests for contracts resolve

This commit is contained in:
Dmitriy Novozhilov
2020-04-10 14:48:43 +03:00
parent 17c6122987
commit d808f3e4fb
21 changed files with 1077 additions and 0 deletions
@@ -0,0 +1,88 @@
digraph atLeastOnce_kt {
graph [nodesep=3]
node [shape=box penwidth=2]
edge [penwidth=2]
subgraph cluster_0 {
color=red
0 [label="Enter function inlineRun" style="filled" fillcolor=red];
2 [label="Function call: R|<local>/block|.R|FakeOverride<kotlin/Function0.invoke: R|kotlin/Unit|>|()"];
1 [label="Exit function inlineRun" style="filled" fillcolor=red];
}
0 -> {2};
2 -> {1};
subgraph cluster_1 {
color=red
3 [label="Enter function myRun" style="filled" fillcolor=red];
5 [label="Function call: R|<local>/block|.R|FakeOverride<kotlin/Function0.invoke: R|kotlin/Unit|>|()"];
4 [label="Exit function myRun" style="filled" fillcolor=red];
}
3 -> {5};
5 -> {4};
subgraph cluster_2 {
color=red
6 [label="Enter function test_1" style="filled" fillcolor=red];
8 [label="Variable declaration: lval x: R|kotlin/Int|"];
9 [label="Postponed enter to lambda"];
subgraph cluster_3 {
color=blue
14 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
16 [label="Const: Int(1)"];
17 [label="Assignment: R|<local>/x|"];
15 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
10 [label="Postponed exit from lambda"];
11 [label="Function call: R|/inlineRun|(...)"];
12 [label="Access variable R|<local>/x|"];
13 [label="Function call: R|<local>/x|.R|kotlin/Int.inc|()"];
7 [label="Exit function test_1" style="filled" fillcolor=red];
}
6 -> {8};
8 -> {9};
9 -> {14};
9 -> {10} [color=red];
10 -> {11};
11 -> {12};
12 -> {13};
13 -> {7};
14 -> {16};
15 -> {14};
15 -> {10} [color=green];
16 -> {17};
17 -> {15};
subgraph cluster_4 {
color=red
18 [label="Enter function test_2" style="filled" fillcolor=red];
20 [label="Variable declaration: lval x: R|kotlin/Int|"];
21 [label="Postponed enter to lambda"];
subgraph cluster_5 {
color=blue
26 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
28 [label="Const: Int(1)"];
29 [label="Assignment: R|<local>/x|"];
27 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
22 [label="Postponed exit from lambda"];
23 [label="Function call: R|/myRun|(...)"];
24 [label="Access variable R|<local>/x|"];
25 [label="Function call: R|<local>/x|.R|kotlin/Int.inc|()"];
19 [label="Exit function test_2" style="filled" fillcolor=red];
}
18 -> {20};
20 -> {21};
21 -> {26};
21 -> {22} [color=red];
22 -> {23};
23 -> {24};
24 -> {25};
25 -> {19};
26 -> {28};
27 -> {26};
27 -> {22} [color=green];
28 -> {29};
29 -> {27};
}
@@ -0,0 +1,33 @@
// !DUMP_CFG
import kotlin.contracts.*
inline fun inlineRun(block: () -> Unit) {
contract {
callsInPlace(block, InvocationKind.AT_LEAST_ONCE)
}
block()
}
fun myRun(block: () -> Unit) {
contract {
callsInPlace(block, InvocationKind.AT_LEAST_ONCE)
}
block()
}
fun test_1() {
val x: Int
inlineRun {
x = 1
}
x.inc()
}
fun test_2() {
val x: Int
myRun {
x = 1
}
x.inc()
}
@@ -0,0 +1,35 @@
FILE: atLeastOnce.kt
public final inline fun inlineRun(block: R|() -> kotlin/Unit|): R|kotlin/Unit|
[R|Contract description]
<
CallsInPlace(block, AT_LEAST_ONCE)
>
{
[StubStatement]
R|<local>/block|.R|FakeOverride<kotlin/Function0.invoke: R|kotlin/Unit|>|()
}
public final fun myRun(block: R|() -> kotlin/Unit|): R|kotlin/Unit|
[R|Contract description]
<
CallsInPlace(block, AT_LEAST_ONCE)
>
{
[StubStatement]
R|<local>/block|.R|FakeOverride<kotlin/Function0.invoke: R|kotlin/Unit|>|()
}
public final fun test_1(): R|kotlin/Unit| {
lval x: R|kotlin/Int|
R|/inlineRun|(<L> = inlineRun@fun <anonymous>(): R|kotlin/Unit| <kind=AT_LEAST_ONCE> {
R|<local>/x| = Int(1)
}
)
R|<local>/x|.R|kotlin/Int.inc|()
}
public final fun test_2(): R|kotlin/Unit| {
lval x: R|kotlin/Int|
R|/myRun|(<L> = myRun@fun <anonymous>(): R|kotlin/Unit| <kind=AT_LEAST_ONCE> {
R|<local>/x| = Int(1)
}
)
R|<local>/x|.R|kotlin/Int.inc|()
}
@@ -0,0 +1,86 @@
digraph atMostOnce_kt {
graph [nodesep=3]
node [shape=box penwidth=2]
edge [penwidth=2]
subgraph cluster_0 {
color=red
0 [label="Enter function inlineRun" style="filled" fillcolor=red];
2 [label="Function call: R|<local>/block|.R|FakeOverride<kotlin/Function0.invoke: R|kotlin/Unit|>|()"];
1 [label="Exit function inlineRun" style="filled" fillcolor=red];
}
0 -> {2};
2 -> {1};
subgraph cluster_1 {
color=red
3 [label="Enter function myRun" style="filled" fillcolor=red];
5 [label="Function call: R|<local>/block|.R|FakeOverride<kotlin/Function0.invoke: R|kotlin/Unit|>|()"];
4 [label="Exit function myRun" style="filled" fillcolor=red];
}
3 -> {5};
5 -> {4};
subgraph cluster_2 {
color=red
6 [label="Enter function test_1" style="filled" fillcolor=red];
8 [label="Variable declaration: lval x: R|kotlin/Int|"];
9 [label="Postponed enter to lambda"];
subgraph cluster_3 {
color=blue
14 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
16 [label="Const: Int(1)"];
17 [label="Assignment: R|<local>/x|"];
15 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
10 [label="Postponed exit from lambda"];
11 [label="Function call: R|/inlineRun|(...)"];
12 [label="Access variable R|<local>/x|"];
13 [label="Function call: R|<local>/x|.R|kotlin/Int.inc|()"];
7 [label="Exit function test_1" style="filled" fillcolor=red];
}
6 -> {8};
8 -> {9};
9 -> {14};
9 -> {10} [color=red];
10 -> {11};
11 -> {12};
12 -> {13};
13 -> {7};
14 -> {15 16};
15 -> {10} [color=green];
16 -> {17};
17 -> {15};
subgraph cluster_4 {
color=red
18 [label="Enter function test_2" style="filled" fillcolor=red];
20 [label="Variable declaration: lval x: R|kotlin/Int|"];
21 [label="Postponed enter to lambda"];
subgraph cluster_5 {
color=blue
26 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
28 [label="Const: Int(1)"];
29 [label="Assignment: R|<local>/x|"];
27 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
22 [label="Postponed exit from lambda"];
23 [label="Function call: R|/myRun|(...)"];
24 [label="Access variable R|<local>/x|"];
25 [label="Function call: R|<local>/x|.R|kotlin/Int.inc|()"];
19 [label="Exit function test_2" style="filled" fillcolor=red];
}
18 -> {20};
20 -> {21};
21 -> {26};
21 -> {22} [color=red];
22 -> {23};
23 -> {24};
24 -> {25};
25 -> {19};
26 -> {27 28};
27 -> {22} [color=green];
28 -> {29};
29 -> {27};
}
@@ -0,0 +1,33 @@
// !DUMP_CFG
import kotlin.contracts.*
inline fun inlineRun(block: () -> Unit) {
contract {
callsInPlace(block, InvocationKind.AT_MOST_ONCE)
}
block()
}
fun myRun(block: () -> Unit) {
contract {
callsInPlace(block, InvocationKind.AT_MOST_ONCE)
}
block()
}
fun test_1() {
val x: Int
inlineRun {
x = 1
}
x.inc()
}
fun test_2() {
val x: Int
myRun {
x = 1
}
x.inc()
}
@@ -0,0 +1,35 @@
FILE: atMostOnce.kt
public final inline fun inlineRun(block: R|() -> kotlin/Unit|): R|kotlin/Unit|
[R|Contract description]
<
CallsInPlace(block, AT_MOST_ONCE)
>
{
[StubStatement]
R|<local>/block|.R|FakeOverride<kotlin/Function0.invoke: R|kotlin/Unit|>|()
}
public final fun myRun(block: R|() -> kotlin/Unit|): R|kotlin/Unit|
[R|Contract description]
<
CallsInPlace(block, AT_MOST_ONCE)
>
{
[StubStatement]
R|<local>/block|.R|FakeOverride<kotlin/Function0.invoke: R|kotlin/Unit|>|()
}
public final fun test_1(): R|kotlin/Unit| {
lval x: R|kotlin/Int|
R|/inlineRun|(<L> = inlineRun@fun <anonymous>(): R|kotlin/Unit| <kind=AT_MOST_ONCE> {
R|<local>/x| = Int(1)
}
)
R|<local>/x|.R|kotlin/Int.inc|()
}
public final fun test_2(): R|kotlin/Unit| {
lval x: R|kotlin/Int|
R|/myRun|(<L> = myRun@fun <anonymous>(): R|kotlin/Unit| <kind=AT_MOST_ONCE> {
R|<local>/x| = Int(1)
}
)
R|<local>/x|.R|kotlin/Int.inc|()
}
@@ -0,0 +1,92 @@
digraph exactlyOnce_kt {
graph [nodesep=3]
node [shape=box penwidth=2]
edge [penwidth=2]
subgraph cluster_0 {
color=red
0 [label="Enter function inlineRun" style="filled" fillcolor=red];
2 [label="Function call: R|<local>/block|.R|FakeOverride<kotlin/Function0.invoke: R|kotlin/Unit|>|()"];
1 [label="Exit function inlineRun" style="filled" fillcolor=red];
}
0 -> {2};
2 -> {1};
subgraph cluster_1 {
color=red
3 [label="Enter function myRun" style="filled" fillcolor=red];
5 [label="Function call: R|<local>/block|.R|FakeOverride<kotlin/Function0.invoke: R|kotlin/Unit|>|()"];
4 [label="Exit function myRun" style="filled" fillcolor=red];
}
3 -> {5};
5 -> {4};
subgraph cluster_2 {
color=red
6 [label="Enter function test_1" style="filled" fillcolor=red];
8 [label="Variable declaration: lval x: R|kotlin/Int|"];
9 [label="Postponed enter to lambda"];
subgraph cluster_3 {
color=blue
15 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
17 [label="Const: Int(1)"];
18 [label="Assignment: R|<local>/x|"];
16 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
12 [label="Call arguments union" style="filled" fillcolor=yellow];
10 [label="Postponed exit from lambda"];
11 [label="Function call: R|/inlineRun|(...)"];
13 [label="Access variable R|<local>/x|"];
14 [label="Function call: R|<local>/x|.R|kotlin/Int.inc|()"];
7 [label="Exit function test_1" style="filled" fillcolor=red];
}
6 -> {8};
8 -> {9};
9 -> {15};
9 -> {10} [color=red];
10 -> {11} [color=green];
11 -> {13};
12 -> {11} [color=red];
13 -> {14};
14 -> {7};
15 -> {17};
16 -> {10} [color=green];
16 -> {12} [color=red];
17 -> {18};
18 -> {16};
subgraph cluster_4 {
color=red
19 [label="Enter function test_2" style="filled" fillcolor=red];
21 [label="Variable declaration: lval x: R|kotlin/Int|"];
22 [label="Postponed enter to lambda"];
subgraph cluster_5 {
color=blue
28 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
30 [label="Const: Int(1)"];
31 [label="Assignment: R|<local>/x|"];
29 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
25 [label="Call arguments union" style="filled" fillcolor=yellow];
23 [label="Postponed exit from lambda"];
24 [label="Function call: R|/myRun|(...)"];
26 [label="Access variable R|<local>/x|"];
27 [label="Function call: R|<local>/x|.R|kotlin/Int.inc|()"];
20 [label="Exit function test_2" style="filled" fillcolor=red];
}
19 -> {21};
21 -> {22};
22 -> {28};
22 -> {23} [color=red];
23 -> {24} [color=green];
24 -> {26};
25 -> {24} [color=red];
26 -> {27};
27 -> {20};
28 -> {30};
29 -> {23} [color=green];
29 -> {25} [color=red];
30 -> {31};
31 -> {29};
}
@@ -0,0 +1,33 @@
// !DUMP_CFG
import kotlin.contracts.*
inline fun inlineRun(block: () -> Unit) {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block()
}
fun myRun(block: () -> Unit) {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block()
}
fun test_1() {
val x: Int
inlineRun {
x = 1
}
x.inc()
}
fun test_2() {
val x: Int
myRun {
x = 1
}
x.inc()
}
@@ -0,0 +1,35 @@
FILE: exactlyOnce.kt
public final inline fun inlineRun(block: R|() -> kotlin/Unit|): R|kotlin/Unit|
[R|Contract description]
<
CallsInPlace(block, EXACTLY_ONCE)
>
{
[StubStatement]
R|<local>/block|.R|FakeOverride<kotlin/Function0.invoke: R|kotlin/Unit|>|()
}
public final fun myRun(block: R|() -> kotlin/Unit|): R|kotlin/Unit|
[R|Contract description]
<
CallsInPlace(block, EXACTLY_ONCE)
>
{
[StubStatement]
R|<local>/block|.R|FakeOverride<kotlin/Function0.invoke: R|kotlin/Unit|>|()
}
public final fun test_1(): R|kotlin/Unit| {
lval x: R|kotlin/Int|
R|/inlineRun|(<L> = inlineRun@fun <anonymous>(): R|kotlin/Unit| <kind=EXACTLY_ONCE> {
R|<local>/x| = Int(1)
}
)
R|<local>/x|.R|kotlin/Int.inc|()
}
public final fun test_2(): R|kotlin/Unit| {
lval x: R|kotlin/Int|
R|/myRun|(<L> = myRun@fun <anonymous>(): R|kotlin/Unit| <kind=EXACTLY_ONCE> {
R|<local>/x| = Int(1)
}
)
R|<local>/x|.R|kotlin/Int.inc|()
}
@@ -0,0 +1,88 @@
digraph unknown_kt {
graph [nodesep=3]
node [shape=box penwidth=2]
edge [penwidth=2]
subgraph cluster_0 {
color=red
0 [label="Enter function inlineRun" style="filled" fillcolor=red];
2 [label="Function call: R|<local>/block|.R|FakeOverride<kotlin/Function0.invoke: R|kotlin/Unit|>|()"];
1 [label="Exit function inlineRun" style="filled" fillcolor=red];
}
0 -> {2};
2 -> {1};
subgraph cluster_1 {
color=red
3 [label="Enter function myRun" style="filled" fillcolor=red];
5 [label="Function call: R|<local>/block|.R|FakeOverride<kotlin/Function0.invoke: R|kotlin/Unit|>|()"];
4 [label="Exit function myRun" style="filled" fillcolor=red];
}
3 -> {5};
5 -> {4};
subgraph cluster_2 {
color=red
6 [label="Enter function test_1" style="filled" fillcolor=red];
8 [label="Variable declaration: lval x: R|kotlin/Int|"];
9 [label="Postponed enter to lambda"];
subgraph cluster_3 {
color=blue
14 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
16 [label="Const: Int(1)"];
17 [label="Assignment: R|<local>/x|"];
15 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
10 [label="Postponed exit from lambda"];
11 [label="Function call: R|/inlineRun|(...)"];
12 [label="Access variable R|<local>/x|"];
13 [label="Function call: R|<local>/x|.R|kotlin/Int.inc|()"];
7 [label="Exit function test_1" style="filled" fillcolor=red];
}
6 -> {8};
8 -> {9};
9 -> {14};
9 -> {10} [color=red];
10 -> {11};
11 -> {12};
12 -> {13};
13 -> {7};
14 -> {15 16};
15 -> {14};
15 -> {10} [color=green];
16 -> {17};
17 -> {15};
subgraph cluster_4 {
color=red
18 [label="Enter function test_2" style="filled" fillcolor=red];
20 [label="Variable declaration: lval x: R|kotlin/Int|"];
21 [label="Postponed enter to lambda"];
subgraph cluster_5 {
color=blue
26 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
28 [label="Const: Int(1)"];
29 [label="Assignment: R|<local>/x|"];
27 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
}
22 [label="Postponed exit from lambda"];
23 [label="Function call: R|/myRun|(...)"];
24 [label="Access variable R|<local>/x|"];
25 [label="Function call: R|<local>/x|.R|kotlin/Int.inc|()"];
19 [label="Exit function test_2" style="filled" fillcolor=red];
}
18 -> {20};
20 -> {21};
21 -> {26};
21 -> {22} [color=red];
22 -> {23};
23 -> {24};
24 -> {25};
25 -> {19};
26 -> {27 28};
27 -> {26};
27 -> {22} [color=green];
28 -> {29};
29 -> {27};
}
@@ -0,0 +1,33 @@
// !DUMP_CFG
import kotlin.contracts.*
inline fun inlineRun(block: () -> Unit) {
contract {
callsInPlace(block, InvocationKind.UNKNOWN)
}
block()
}
fun myRun(block: () -> Unit) {
contract {
callsInPlace(block, InvocationKind.UNKNOWN)
}
block()
}
fun test_1() {
val x: Int
inlineRun {
x = 1
}
x.inc()
}
fun test_2() {
val x: Int
myRun {
x = 1
}
x.inc()
}
@@ -0,0 +1,35 @@
FILE: unknown.kt
public final inline fun inlineRun(block: R|() -> kotlin/Unit|): R|kotlin/Unit|
[R|Contract description]
<
CallsInPlace(block, UNKNOWN)
>
{
[StubStatement]
R|<local>/block|.R|FakeOverride<kotlin/Function0.invoke: R|kotlin/Unit|>|()
}
public final fun myRun(block: R|() -> kotlin/Unit|): R|kotlin/Unit|
[R|Contract description]
<
CallsInPlace(block, UNKNOWN)
>
{
[StubStatement]
R|<local>/block|.R|FakeOverride<kotlin/Function0.invoke: R|kotlin/Unit|>|()
}
public final fun test_1(): R|kotlin/Unit| {
lval x: R|kotlin/Int|
R|/inlineRun|(<L> = inlineRun@fun <anonymous>(): R|kotlin/Unit| <kind=UNKNOWN> {
R|<local>/x| = Int(1)
}
)
R|<local>/x|.R|kotlin/Int.inc|()
}
public final fun test_2(): R|kotlin/Unit| {
lval x: R|kotlin/Int|
R|/myRun|(<L> = myRun@fun <anonymous>(): R|kotlin/Unit| <kind=UNKNOWN> {
R|<local>/x| = Int(1)
}
)
R|<local>/x|.R|kotlin/Int.inc|()
}
@@ -0,0 +1,69 @@
import kotlin.contracts.*
fun myRequire(b: Boolean) {
contract {
returns() implies (b)
}
if (!b) throw IllegalStateException()
}
fun myRequireAnd(b1: Boolean, b2: Boolean) {
contract {
returns() implies (b1 && b2)
}
if (!(b1 && b2)) throw IllegalStateException()
}
fun myRequireOr(b1: Boolean, b2: Boolean) {
contract {
returns() implies (b1 || b2)
}
if (!(b1 || b2)) throw IllegalStateException()
}
fun myRequireNot(b: Boolean) {
contract {
returns() implies (!b)
}
if (b) throw IllegalStateException()
}
// ----------------------------------------------------
interface A {
fun foo()
}
interface B : A {
fun bar()
}
interface C : A {
fun baz()
}
// ----------------------------------------------------
fun test_1(x: Any) {
myRequire(x is A)
x.foo()
}
fun test_2(x: Any) {
myRequireAnd(x is B, x is C)
x.foo()
x.bar()
x.baz()
}
fun test_3(x: Any) {
myRequireOr(x is B, x is C)
x.foo() // OK
x.<!UNRESOLVED_REFERENCE!>bar<!>() // Error
x.<!UNRESOLVED_REFERENCE!>baz<!>() // Error
}
fun test_4(x: Any) {
myRequireNot(x !is A)
x.foo()
}
@@ -0,0 +1,89 @@
FILE: booleanOperators.kt
public final fun myRequire(b: R|kotlin/Boolean|): R|kotlin/Unit|
[R|Contract description]
<
Returns(WILDCARD) -> b
>
{
[StubStatement]
when () {
R|<local>/b|.R|kotlin/Boolean.not|() -> {
throw R|java/lang/IllegalStateException.IllegalStateException|()
}
}
}
public final fun myRequireAnd(b1: R|kotlin/Boolean|, b2: R|kotlin/Boolean|): R|kotlin/Unit|
[R|Contract description]
<
Returns(WILDCARD) -> (b1) && (b2)
>
{
[StubStatement]
when () {
R|<local>/b1| && R|<local>/b2|.R|kotlin/Boolean.not|() -> {
throw R|java/lang/IllegalStateException.IllegalStateException|()
}
}
}
public final fun myRequireOr(b1: R|kotlin/Boolean|, b2: R|kotlin/Boolean|): R|kotlin/Unit|
[R|Contract description]
<
Returns(WILDCARD) -> (b1) || (b2)
>
{
[StubStatement]
when () {
R|<local>/b1| || R|<local>/b2|.R|kotlin/Boolean.not|() -> {
throw R|java/lang/IllegalStateException.IllegalStateException|()
}
}
}
public final fun myRequireNot(b: R|kotlin/Boolean|): R|kotlin/Unit|
[R|Contract description]
<
Returns(WILDCARD) -> (!)b
>
{
[StubStatement]
when () {
R|<local>/b| -> {
throw R|java/lang/IllegalStateException.IllegalStateException|()
}
}
}
public abstract interface A : R|kotlin/Any| {
public abstract fun foo(): R|kotlin/Unit|
}
public abstract interface B : R|A| {
public abstract fun bar(): R|kotlin/Unit|
}
public abstract interface C : R|A| {
public abstract fun baz(): R|kotlin/Unit|
}
public final fun test_1(x: R|kotlin/Any|): R|kotlin/Unit| {
R|/myRequire|((R|<local>/x| is R|A|))
R|<local>/x|.R|/A.foo|()
}
public final fun test_2(x: R|kotlin/Any|): R|kotlin/Unit| {
R|/myRequireAnd|((R|<local>/x| is R|B|), (R|<local>/x| is R|C|))
R|<local>/x|.R|/A.foo|()
R|<local>/x|.R|/B.bar|()
R|<local>/x|.R|/C.baz|()
}
public final fun test_3(x: R|kotlin/Any|): R|kotlin/Unit| {
R|/myRequireOr|((R|<local>/x| is R|B|), (R|<local>/x| is R|C|))
R|<local>/x|.R|/A.foo|()
R|<local>/x|.<Unresolved name: bar>#()
R|<local>/x|.<Unresolved name: baz>#()
}
public final fun test_4(x: R|kotlin/Any|): R|kotlin/Unit| {
R|/myRequireNot|((R|<local>/x| !is R|A|))
R|<local>/x|.R|/A.foo|()
}
@@ -0,0 +1,31 @@
import kotlin.contracts.*
fun checkNotNull(x: Any?) {
contract {
returns(true) implies (x != null)
returns(false) implies (x == null)
}
return x != null
}
fun trickyRequireNotNull(x: Any?) {
contract {
returns() implies (!(x == null))
}
if (x == null) {
throw IllegalStateException()
}
}
fun test_1(x: String?) {
if (checkNotNull(x)) {
x.length // OK
} else {
x.<!INAPPLICABLE_CANDIDATE!>length<!> // Error
}
}
fun test_2(x: String?) {
trickyRequireNotNull(x)
x.length
}
@@ -0,0 +1,40 @@
FILE: eqNotEq.kt
public final fun checkNotNull(x: R|kotlin/Any?|): R|kotlin/Unit|
[R|Contract description]
<
Returns(TRUE) -> x != null
Returns(FALSE) -> x == null
>
{
[StubStatement]
^checkNotNull !=(R|<local>/x|, Null(null))
}
public final fun trickyRequireNotNull(x: R|kotlin/Any?|): R|kotlin/Unit|
[R|Contract description]
<
Returns(WILDCARD) -> !x == null
>
{
[StubStatement]
when () {
==(R|<local>/x|, Null(null)) -> {
throw R|java/lang/IllegalStateException.IllegalStateException|()
}
}
}
public final fun test_1(x: R|kotlin/String?|): R|kotlin/Unit| {
when () {
R|/checkNotNull|(R|<local>/x|) -> {
R|<local>/x|.R|kotlin/String.length|
}
else -> {
R|<local>/x|.<Inapplicable(WRONG_RECEIVER): [kotlin/String.length]>#
}
}
}
public final fun test_2(x: R|kotlin/String?|): R|kotlin/Unit| {
R|/trickyRequireNotNull|(R|<local>/x|)
R|<local>/x|.R|kotlin/String.length|
}
@@ -0,0 +1,43 @@
import kotlin.contracts.*
interface A
fun A.foo() {}
fun Any?.myRequireNotNull() {
contract {
returns() implies (this@myRequireNotNull != null)
}
if (this == null) throw IllegalStateException()
}
fun test_1(x: A?) {
x.myRequireNotNull()
x.foo()
}
fun test_2(x: A?) {
x.myRequireNotNull()
with(x) {
foo()
}
}
fun test_3(x: A?) {
with(x) {
myRequireNotNull()
}
x.<!INAPPLICABLE_CANDIDATE!>foo<!>()
}
fun test_4(x: A?) {
with(x) {
myRequireNotNull()
foo()
}
}
fun A?.test_5() {
myRequireNotNull()
foo()
}
@@ -0,0 +1,48 @@
FILE: receivers.kt
public abstract interface A : R|kotlin/Any| {
}
public final fun R|A|.foo(): R|kotlin/Unit| {
}
public final fun R|kotlin/Any?|.myRequireNotNull(): R|kotlin/Unit|
[R|Contract description]
<
Returns(WILDCARD) -> this != null
>
{
[StubStatement]
when () {
==(this@R|/myRequireNotNull|, Null(null)) -> {
throw R|java/lang/IllegalStateException.IllegalStateException|()
}
}
}
public final fun test_1(x: R|A?|): R|kotlin/Unit| {
R|<local>/x|.R|/myRequireNotNull|()
R|<local>/x|.R|/foo|()
}
public final fun test_2(x: R|A?|): R|kotlin/Unit| {
R|<local>/x|.R|/myRequireNotNull|()
R|kotlin/with|<R|A|, R|kotlin/Unit|>(R|<local>/x|, <L> = with@fun R|A|.<anonymous>(): R|kotlin/Unit| <kind=EXACTLY_ONCE> {
this@R|special/anonymous|.R|/foo|()
}
)
}
public final fun test_3(x: R|A?|): R|kotlin/Unit| {
R|kotlin/with|<R|A?|, R|kotlin/Unit|>(R|<local>/x|, <L> = with@fun R|A?|.<anonymous>(): R|kotlin/Unit| <kind=EXACTLY_ONCE> {
this@R|special/anonymous|.R|/myRequireNotNull|()
}
)
R|<local>/x|.<Inapplicable(WRONG_RECEIVER): [/foo]>#()
}
public final fun test_4(x: R|A?|): R|kotlin/Unit| {
R|kotlin/with|<R|A?|, R|kotlin/Unit|>(R|<local>/x|, <L> = with@fun R|A?|.<anonymous>(): R|kotlin/Unit| <kind=EXACTLY_ONCE> {
this@R|special/anonymous|.R|/myRequireNotNull|()
this@R|special/anonymous|.R|/foo|()
}
)
}
public final fun R|A?|.test_5(): R|kotlin/Unit| {
this@R|/test_5|.R|/myRequireNotNull|()
this@R|/test_5|.R|/foo|()
}
@@ -0,0 +1,17 @@
import kotlin.contracts.*
fun checkIsString(x: Any) {
contract {
returns(true) implies (x is String)
returns(false) implies (x !is String)
}
return x is String
}
fun test(x: Any) {
if (checkIsString(x)) {
x.length // OK
} else {
x.<!UNRESOLVED_REFERENCE!>length<!> // Error
}
}
@@ -0,0 +1,22 @@
FILE: typePredicate.kt
public final fun checkIsString(x: R|kotlin/Any|): R|kotlin/Unit|
[R|Contract description]
<
Returns(TRUE) -> x is kotlin/String
Returns(FALSE) -> x !is kotlin/String
>
{
[StubStatement]
^checkIsString (R|<local>/x| is R|kotlin/String|)
}
public final fun test(x: R|kotlin/Any|): R|kotlin/Unit| {
when () {
R|/checkIsString|(R|<local>/x|) -> {
R|<local>/x|.R|kotlin/String.length|
}
else -> {
R|<local>/x|.<Unresolved name: length>#
}
}
}