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:
Dmitry Savvinov
2017-10-03 15:02:51 +03:00
parent f487525a1d
commit 4434db4d69
120 changed files with 4179 additions and 1 deletions
@@ -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
}
}
@@ -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
@@ -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<!>)
}
@@ -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