Effects: add test on (de)serialization of contracts

- Add ContractDescriptorRenderer
- Add option to dump function contracts in DescriptorRendererOptions
- Add parsing of LANGUAGE_VERSION directive in AbstractLoadJava
- Add tests on serialization-deserializaton identity of contracts

==========
Introduction of EffectSystem: 13/18
This commit is contained in:
Dmitry Savvinov
2017-10-03 15:02:46 +03:00
parent 75ad20f823
commit d20c770a25
29 changed files with 699 additions and 19 deletions
@@ -0,0 +1,24 @@
// LANGUAGE_VERSION: 1.3
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
package test
import kotlin.internal.contracts.*
fun <X, Y, Z, R> callsEffectWithKind(block: (X, Y, Z) -> R) {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
}
inline fun callsEffectImplicitUnknown(x: Int, y: Int, block: () -> Unit) {
contract {
callsInPlace(block)
}
}
inline fun callsEffectExplicitUnknown(x: Int, block: () -> Unit) {
contract {
callsInPlace(block, InvocationKind.UNKNOWN)
}
}
@@ -0,0 +1,10 @@
package test
public inline fun callsEffectExplicitUnknown(/*0*/ x: kotlin.Int, /*1*/ block: () -> kotlin.Unit): kotlin.Unit
CallsInPlace(block, UNKNOWN)
public inline fun callsEffectImplicitUnknown(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.Int, /*2*/ block: () -> kotlin.Unit): kotlin.Unit
CallsInPlace(block, UNKNOWN)
public fun </*0*/ X, /*1*/ Y, /*2*/ Z, /*3*/ R> callsEffectWithKind(/*0*/ block: (X, Y, Z) -> R): kotlin.Unit
CallsInPlace(block, EXACTLY_ONCE)
@@ -0,0 +1,14 @@
// LANGUAGE_VERSION: 1.3
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
package test
import kotlin.internal.contracts.*
class A
fun deeplyNested(x: Any?, y: Any?, b: Boolean, s: String?) {
contract {
returns(true) implies (((x is Int && x is String) || (x is Int && y is A) || b || (!b)) && s != null && (y is A || x is String))
}
}
@@ -0,0 +1,8 @@
package test
public fun deeplyNested(/*0*/ x: kotlin.Any?, /*1*/ y: kotlin.Any?, /*2*/ b: kotlin.Boolean, /*3*/ s: kotlin.String?): kotlin.Unit
Returns(TRUE) -> ((x is Int && x is String) || (x is Int && y is A) || b || (!b)) && s != null && (y is A || x is String)
public final class A {
/*primary*/ public constructor A()
}
@@ -0,0 +1,33 @@
// LANGUAGE_VERSION: 1.3
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
package test
import kotlin.internal.contracts.*
// this tests specifically use primitive condition (predicate/value) as the
// first argument of sequence, so that it would be optimized and embedded into message
fun embedVariable(x: Any, b: Boolean) {
contract {
returns() implies (b && x is String)
}
}
fun embedInstancePredicate(x: Any, y: Any?) {
contract {
returns() implies (x is String && y is String)
}
}
fun embedNullCheckPredicate(x: Any?, y: Int?) {
contract {
returns() implies (y != null && x is String)
}
}
fun Boolean.embedReceiverReference(b: Boolean) {
contract {
returns() implies (!this@embedReceiverReference && b)
}
}
@@ -0,0 +1,13 @@
package test
public fun embedInstancePredicate(/*0*/ x: kotlin.Any, /*1*/ y: kotlin.Any?): kotlin.Unit
Returns(WILDCARD) -> x is String && y is String
public fun embedNullCheckPredicate(/*0*/ x: kotlin.Any?, /*1*/ y: kotlin.Int?): kotlin.Unit
Returns(WILDCARD) -> y != null && x is String
public fun embedVariable(/*0*/ x: kotlin.Any, /*1*/ b: kotlin.Boolean): kotlin.Unit
Returns(WILDCARD) -> b && x is String
public fun kotlin.Boolean.embedReceiverReference(/*0*/ b: kotlin.Boolean): kotlin.Unit
Returns(WILDCARD) -> (!<this>) && b
@@ -0,0 +1,65 @@
// LANGUAGE_VERSION: 1.3
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
package test
import kotlin.internal.contracts.*
public inline fun <R> run(block: () -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
public inline fun <T, R> T.run(block: T.() -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
public inline fun <T, R> with(receiver: T, block: T.() -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return receiver.block()
}
public inline fun <T> T.apply(block: T.() -> Unit): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block()
return this
}
public inline fun <T> T.also(block: (T) -> Unit): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block(this)
return this
}
public inline fun <T, R> T.let(block: (T) -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block(this)
}
public inline fun <T> T.takeIf(predicate: (T) -> Boolean): T? {
contract {
callsInPlace(predicate, InvocationKind.EXACTLY_ONCE)
}
return if (predicate(this)) this else null
}
public inline fun repeat(times: Int, action: (Int) -> Unit) {
contract { callsInPlace(action) }
for (index in 0..times - 1) {
action(index)
}
}
@@ -0,0 +1,25 @@
package test
public inline fun repeat(/*0*/ times: kotlin.Int, /*1*/ action: (kotlin.Int) -> kotlin.Unit): kotlin.Unit
CallsInPlace(action, UNKNOWN)
public inline fun </*0*/ R> run(/*0*/ block: () -> R): R
CallsInPlace(block, EXACTLY_ONCE)
public inline fun </*0*/ T, /*1*/ R> with(/*0*/ receiver: T, /*1*/ block: T.() -> R): R
CallsInPlace(block, EXACTLY_ONCE)
public inline fun </*0*/ T> T.also(/*0*/ block: (T) -> kotlin.Unit): T
CallsInPlace(block, EXACTLY_ONCE)
public inline fun </*0*/ T> T.apply(/*0*/ block: T.() -> kotlin.Unit): T
CallsInPlace(block, EXACTLY_ONCE)
public inline fun </*0*/ T, /*1*/ R> T.let(/*0*/ block: (T) -> R): R
CallsInPlace(block, EXACTLY_ONCE)
public inline fun </*0*/ T, /*1*/ R> T.run(/*0*/ block: T.() -> R): R
CallsInPlace(block, EXACTLY_ONCE)
public inline fun </*0*/ T> T.takeIf(/*0*/ predicate: (T) -> kotlin.Boolean): T?
CallsInPlace(predicate, EXACTLY_ONCE)
@@ -0,0 +1,20 @@
// LANGUAGE_VERSION: 1.3
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
package test
import kotlin.internal.contracts.*
class A
fun simpleIsInstace(x: Any?) {
contract {
returns(true) implies (x is A)
}
}
fun Any?.receiverIsInstance() {
contract {
returns(true) implies (this@receiverIsInstance is A)
}
}
@@ -0,0 +1,11 @@
package test
public fun simpleIsInstace(/*0*/ x: kotlin.Any?): kotlin.Unit
Returns(TRUE) -> x is A
public fun kotlin.Any?.receiverIsInstance(): kotlin.Unit
Returns(TRUE) -> <this> is A
public final class A {
/*primary*/ public constructor A()
}
@@ -0,0 +1,22 @@
// LANGUAGE_VERSION: 1.3
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
package test
import kotlin.internal.contracts.*
fun orSequence(x: Any?, y: Any?, b: Boolean) {
contract {
returns() implies (x is String || y is Int || !b)
}
}
class A
class B
fun andSequence(x: Any?, y: Any?, b:Boolean) {
contract {
returns() implies (x is A && x is B && ((y is A) && b))
}
}
@@ -0,0 +1,15 @@
package test
public fun andSequence(/*0*/ x: kotlin.Any?, /*1*/ y: kotlin.Any?, /*2*/ b: kotlin.Boolean): kotlin.Unit
Returns(WILDCARD) -> x is A && x is B && y is A && b
public fun orSequence(/*0*/ x: kotlin.Any?, /*1*/ y: kotlin.Any?, /*2*/ b: kotlin.Boolean): kotlin.Unit
Returns(WILDCARD) -> x is String || y is Int || (!b)
public final class A {
/*primary*/ public constructor A()
}
public final class B {
/*primary*/ public constructor B()
}
@@ -0,0 +1,44 @@
// LANGUAGE_VERSION: 1.3
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
package test
import kotlin.internal.contracts.*
fun twoReturnsValue(b: Boolean) {
contract {
returns(true) implies b
returns(false) implies (!b)
}
}
fun threeReturnsValue(b: Boolean) {
contract {
returnsNotNull() implies (b != null)
returns(true) implies (b)
returns(false) implies (!b)
}
}
fun returnsAndFinished(b: Boolean) {
contract {
returns(true) implies (b)
returns() implies (b != null)
returns(false) implies (!b)
}
}
fun returnsAndCalls(b: Boolean, block: () -> Unit) {
contract {
returns(false) implies (!b)
callsInPlace(block)
returns(true) implies (b)
}
}
fun severalCalls(x: () -> Unit, y: () -> Unit) {
contract {
callsInPlace(x, InvocationKind.AT_MOST_ONCE)
callsInPlace(y, InvocationKind.AT_LEAST_ONCE)
}
}
@@ -0,0 +1,24 @@
package test
public fun returnsAndCalls(/*0*/ b: kotlin.Boolean, /*1*/ block: () -> kotlin.Unit): kotlin.Unit
Returns(FALSE) -> !b
CallsInPlace(block, UNKNOWN)
Returns(TRUE) -> b
public fun returnsAndFinished(/*0*/ b: kotlin.Boolean): kotlin.Unit
Returns(TRUE) -> b
Returns(WILDCARD) -> b != null
Returns(FALSE) -> !b
public fun severalCalls(/*0*/ x: () -> kotlin.Unit, /*1*/ y: () -> kotlin.Unit): kotlin.Unit
CallsInPlace(x, AT_MOST_ONCE)
CallsInPlace(y, AT_LEAST_ONCE)
public fun threeReturnsValue(/*0*/ b: kotlin.Boolean): kotlin.Unit
Returns(NOT_NULL) -> b != null
Returns(TRUE) -> b
Returns(FALSE) -> !b
public fun twoReturnsValue(/*0*/ b: kotlin.Boolean): kotlin.Unit
Returns(TRUE) -> b
Returns(FALSE) -> !b
@@ -0,0 +1,20 @@
// LANGUAGE_VERSION: 1.3
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
package test
import kotlin.internal.contracts.*
fun foo(x: Any?): Boolean {
contract {
returns() implies (x is String)
}
return bar(x)
}
fun bar(x: Any?): Boolean {
contract {
returns() implies (x is Int)
}
return foo(x)
}
@@ -0,0 +1,8 @@
package test
public fun bar(/*0*/ x: kotlin.Any?): kotlin.Boolean
Returns(WILDCARD) -> x is Int
public fun foo(/*0*/ x: kotlin.Any?): kotlin.Boolean
Returns(WILDCARD) -> x is String
@@ -0,0 +1,13 @@
// LANGUAGE_VERSION: 1.3
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
package test
import kotlin.internal.contracts.*
fun foo(n: Int, x: Any?): Boolean {
contract {
returns(true) implies (x is String)
}
return if (n == 0) x is String else foo(n - 1, x)
}
@@ -0,0 +1,4 @@
package test
public fun foo(/*0*/ n: kotlin.Int, /*1*/ x: kotlin.Any?): kotlin.Boolean
Returns(TRUE) -> x is String
@@ -0,0 +1,13 @@
// LANGUAGE_VERSION: 1.3
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
package test
import kotlin.internal.contracts.*
fun Any?.isNotNull(): Boolean {
contract {
returns(true) implies (this@isNotNull != null)
}
return this != null
}
@@ -0,0 +1,5 @@
package test
public fun kotlin.Any?.isNotNull(): kotlin.Boolean
Returns(TRUE) -> <this> != null