[FIR-TEST] Add new testdata generated after changes in previous commit
This commit is contained in:
+51
@@ -0,0 +1,51 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseCallsInPlaceEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
inline fun <T> myRun(block: () -> T): T {
|
||||
contract {
|
||||
<!INAPPLICABLE_CANDIDATE!>callsInPlace<!>(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return block()
|
||||
}
|
||||
|
||||
fun getBoolean(): Boolean = false
|
||||
|
||||
fun test() {
|
||||
val x: Int
|
||||
|
||||
if (getBoolean())
|
||||
myRun {
|
||||
while (getBoolean()) {
|
||||
do {
|
||||
myRun {
|
||||
if (getBoolean()) {
|
||||
x = 42 // No reassignment because of break
|
||||
}
|
||||
else {
|
||||
x = 43 // No reassignment because of break
|
||||
}
|
||||
}
|
||||
break
|
||||
} while (getBoolean())
|
||||
// Loop executed exectly once, initializing x
|
||||
myRun { x.inc() }
|
||||
|
||||
myRun { x = 42 }
|
||||
break
|
||||
}
|
||||
// x is I?D here because loop could've been execited
|
||||
// VAL_REASSIGNMENT isn't reported because of repeating diagnostic
|
||||
x = 42
|
||||
// x is ID now
|
||||
}
|
||||
else
|
||||
myRun {
|
||||
x = 42
|
||||
}
|
||||
// x is ID because both branches are ID
|
||||
|
||||
x.inc()
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseCallsInPlaceEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
inline fun <T> myRun(block: () -> T): T {
|
||||
contract {
|
||||
<!INAPPLICABLE_CANDIDATE!>callsInPlace<!>(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return block()
|
||||
}
|
||||
|
||||
fun functionWithExpressionBody(x: Int): Boolean = myRun {
|
||||
if (x == 0) return true
|
||||
if (x == 1) return false
|
||||
return functionWithExpressionBody(x - 2)
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseCallsInPlaceEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun <T> myRun(block: () -> T): T {
|
||||
contract {
|
||||
<!INAPPLICABLE_CANDIDATE!>callsInPlace<!>(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return block()
|
||||
}
|
||||
|
||||
fun functionWithSideEffects(x: Int): Int = x + 1 // ...and some other useful side-effects
|
||||
|
||||
fun log(s: String) = Unit // some logging or println or whatever returning Unit
|
||||
|
||||
fun implicitCastWithIf(s: String) {
|
||||
myRun { if (s == "") functionWithSideEffects(42) else log(s) }
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseCallsInPlaceEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
inline fun myRun(block: () -> Unit): Unit {
|
||||
contract {
|
||||
<!INAPPLICABLE_CANDIDATE!>callsInPlace<!>(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
block()
|
||||
}
|
||||
|
||||
fun test() {
|
||||
myRun { throw java.lang.<!UNRESOLVED_REFERENCE!>IllegalArgumentException<!>() }
|
||||
val x: Int = 42
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseCallsInPlaceEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
inline fun myRun(block: () -> Unit): Unit {
|
||||
contract {
|
||||
<!INAPPLICABLE_CANDIDATE!>callsInPlace<!>(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return block()
|
||||
}
|
||||
|
||||
inline fun unknownRun(block: () -> Unit) { block() }
|
||||
|
||||
fun foo() {
|
||||
val x: Int
|
||||
myRun {
|
||||
unknownRun { println("shouldn't change anything") }
|
||||
x = 42
|
||||
}
|
||||
println(x)
|
||||
}
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseCallsInPlaceEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
inline fun <T> myRun(block: () -> T): T {
|
||||
contract {
|
||||
<!INAPPLICABLE_CANDIDATE!>callsInPlace<!>(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return block()
|
||||
}
|
||||
|
||||
inline fun <T, R> T.myLet(block: (T) -> R): R {
|
||||
contract {
|
||||
<!INAPPLICABLE_CANDIDATE!>callsInPlace<!>(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return block(this)
|
||||
}
|
||||
|
||||
inline fun unknownRun(block: () -> Unit) = block()
|
||||
|
||||
fun getBool(): Boolean = false
|
||||
|
||||
fun threeLevelsReturnNoInitialization(x: Int?): Int? {
|
||||
// Inner always jumps to outer
|
||||
// And middle always calls inner
|
||||
// So, in fact, middle never finished normally
|
||||
// Hence 'y = 54' in middle is unreachable, and middle doesn't performs definite initialization
|
||||
// Hence, outer doesn't performs definite initialization
|
||||
val y: Int
|
||||
myRun outer@ {
|
||||
myRun middle@ {
|
||||
x.myLet inner@ {
|
||||
if (it == null) {
|
||||
y = 42
|
||||
return@outer Unit
|
||||
}
|
||||
else {
|
||||
return@outer Unit
|
||||
}
|
||||
}
|
||||
}
|
||||
// Possible to report unreachable here
|
||||
y = 54
|
||||
}
|
||||
return y.inc()
|
||||
}
|
||||
|
||||
fun threeLevelsReturnWithInitialization(x: Int?): Int? {
|
||||
val y: Int
|
||||
myRun outer@ {
|
||||
myRun middle@ {
|
||||
x.myLet inner@ {
|
||||
if (it == null) {
|
||||
y = 42
|
||||
return@outer Unit
|
||||
}
|
||||
else {
|
||||
y = 34
|
||||
return@outer Unit
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return y.inc()
|
||||
}
|
||||
|
||||
fun threeLevelsReturnWithUnknown(x: Int?): Int? {
|
||||
val y: Int
|
||||
myRun outer@ {
|
||||
unknownRun middle@ {
|
||||
x.myLet inner@ {
|
||||
if (it == null) {
|
||||
y = 42
|
||||
return@outer Unit
|
||||
}
|
||||
else {
|
||||
y = 34
|
||||
return@outer Unit
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return y.inc()
|
||||
}
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER -INVISIBLE_MEMBER -INVISIBLE_REFERENCE
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseCallsInPlaceEffect
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
inline fun <T> myRun(block: () -> T): T {
|
||||
contract {
|
||||
<!INAPPLICABLE_CANDIDATE!>callsInPlace<!>(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return block()
|
||||
}
|
||||
|
||||
fun innerComputation(): Int = 42
|
||||
fun outerComputation(): Int = 52
|
||||
|
||||
fun log() = Unit
|
||||
|
||||
fun outerFinallyInitializes() {
|
||||
val x: Int
|
||||
|
||||
try {
|
||||
myRun {
|
||||
try {
|
||||
x = innerComputation()
|
||||
} catch (e: java.lang.Exception) {
|
||||
log()
|
||||
}
|
||||
// possible reassignment if innerComputation finished
|
||||
x = 42
|
||||
// x is ID here
|
||||
}
|
||||
|
||||
// Definite reassignment here, cause can get here only if myRun finished
|
||||
// Not reported because of repeating diagnostic
|
||||
x = outerComputation()
|
||||
} catch (e: java.lang.Exception) {
|
||||
// can catch exception thrown by the inner, so x can be not initialized
|
||||
x.inc()
|
||||
log()
|
||||
} finally {
|
||||
// Possible reassignment (e.g. if everything finished)
|
||||
// Not reported because of repeating diagnostic
|
||||
x = 42
|
||||
}
|
||||
|
||||
// Properly initialized
|
||||
x.inc()
|
||||
}
|
||||
|
||||
fun innerFinallyInitializes() {
|
||||
val x: Int
|
||||
try {
|
||||
myRun {
|
||||
try {
|
||||
innerComputation()
|
||||
} catch (e: java.lang.Exception) {
|
||||
log()
|
||||
} finally {
|
||||
x = 42
|
||||
}
|
||||
}
|
||||
|
||||
// Properly initialized
|
||||
x.inc()
|
||||
} catch (e: java.lang.Exception) {
|
||||
log()
|
||||
}
|
||||
|
||||
// Still can be unitialized because we don't know what can happen in try-block
|
||||
// (e.g., OutOfMemory exception could've happened even before myRun was executed)
|
||||
x.inc()
|
||||
}
|
||||
|
||||
|
||||
fun innerFinallyInitializesOuterRethrows() {
|
||||
val x: Int
|
||||
try {
|
||||
myRun {
|
||||
try {
|
||||
innerComputation()
|
||||
} catch (e: java.lang.Exception) {
|
||||
log()
|
||||
} finally {
|
||||
x = 42
|
||||
}
|
||||
}
|
||||
|
||||
// Properly initialized
|
||||
x.inc()
|
||||
} catch (e: java.lang.Exception) {
|
||||
log()
|
||||
throw e
|
||||
}
|
||||
|
||||
// Guaranteed to be initialized because all catch-clauses are rethrowing
|
||||
x.inc()
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseCallsInPlaceEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
inline fun <T> myRun(block: () -> T): T {
|
||||
contract {
|
||||
<!INAPPLICABLE_CANDIDATE!>callsInPlace<!>(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return block()
|
||||
}
|
||||
|
||||
fun innerComputation(): Int = 42
|
||||
fun outerComputation(): Int = 52
|
||||
|
||||
fun innerTryCatchInitializes() {
|
||||
val x: Int
|
||||
|
||||
try {
|
||||
myRun {
|
||||
try {
|
||||
x = innerComputation()
|
||||
x.inc()
|
||||
}
|
||||
catch (e: java.lang.Exception) {
|
||||
// Potential reassignment because x.inc() could threw
|
||||
x = 42
|
||||
x.inc()
|
||||
}
|
||||
}
|
||||
// Can get here only when inlined lambda exited properly, i.e. x is initialized
|
||||
x.inc()
|
||||
outerComputation()
|
||||
|
||||
} catch (e: java.lang.Exception) {
|
||||
// Can get here if innerComputation() threw an exception that wasn't catched by the inner catch (x is not initialized)
|
||||
// OR if outerComputation() threw an exception (x is initialized because we reach outer computation only when inner finished ok)
|
||||
// So, x=I? here
|
||||
x.inc()
|
||||
|
||||
// Potential reasignment
|
||||
x = 42
|
||||
}
|
||||
// Here x=I because outer try-catch either exited normally (x=I) or catched exception (x=I, with reassingment, though)
|
||||
x.inc()
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseCallsInPlaceEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
inline fun <T, R> T.myLet(block: (T) -> R): R {
|
||||
contract {
|
||||
<!INAPPLICABLE_CANDIDATE!>callsInPlace<!>(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return block(this)
|
||||
}
|
||||
|
||||
|
||||
fun nonLocalReturnWithElvis(x: Int?): Int? {
|
||||
x?.myLet { return 42 }
|
||||
return x?.inc()
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseCallsInPlaceEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
inline fun myRun(block: () -> Unit): Unit {
|
||||
contract {
|
||||
<!INAPPLICABLE_CANDIDATE!>callsInPlace<!>(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return block()
|
||||
}
|
||||
|
||||
fun getBool(): Boolean = false
|
||||
|
||||
fun withLabeledReturn() {
|
||||
val y: Int
|
||||
|
||||
val x = myRun outer@ {
|
||||
myRun { return@outer Unit }
|
||||
y = 42
|
||||
}
|
||||
|
||||
println(y)
|
||||
println(x)
|
||||
}
|
||||
|
||||
fun withLabeledReturn2(y: Int) {
|
||||
myRun outer@ {
|
||||
myRun { return@outer Unit }
|
||||
println(y)
|
||||
}
|
||||
println(y)
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
inline fun <T> Any?.myRun(block: () -> T): T {
|
||||
contract {
|
||||
<!INAPPLICABLE_CANDIDATE!>callsInPlace<!>(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return block()
|
||||
}
|
||||
|
||||
fun bad(): String {
|
||||
val x: String? = null
|
||||
|
||||
x?.myRun { return "" }
|
||||
}
|
||||
|
||||
fun ok(): String {
|
||||
val x: String? = null
|
||||
|
||||
x?.run { return "non-null" } ?: return "null"
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseCallsInPlaceEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
inline fun <T> myRun(block: () -> T): T {
|
||||
contract {
|
||||
<!INAPPLICABLE_CANDIDATE!>callsInPlace<!>(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return block()
|
||||
}
|
||||
|
||||
fun exitOnlyThroughLocalReturns(b: Boolean) {
|
||||
var x: Int
|
||||
var s: String
|
||||
|
||||
myRun {
|
||||
if (b) {
|
||||
x = 42
|
||||
return@myRun
|
||||
}
|
||||
|
||||
if (!b) {
|
||||
s = "hello"
|
||||
x = 42
|
||||
return@myRun
|
||||
}
|
||||
else {
|
||||
s = "world"
|
||||
x = 239
|
||||
}
|
||||
}
|
||||
|
||||
x.inc()
|
||||
s.length
|
||||
}
|
||||
|
||||
fun exitOnlyThroughNonLocalReturns(b: Boolean?) {
|
||||
var x: Int
|
||||
var s: String
|
||||
myRun {
|
||||
if (b == null) {
|
||||
x = 42
|
||||
return
|
||||
}
|
||||
|
||||
if (b.not()) {
|
||||
x = 54
|
||||
}
|
||||
|
||||
if (x == 42) {
|
||||
return
|
||||
}
|
||||
else {
|
||||
x = 42
|
||||
s = "hello"
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
x.inc()
|
||||
s.length
|
||||
}
|
||||
|
||||
fun nonLocalReturnAndOrdinaryExit(b: Boolean) {
|
||||
var x: Int
|
||||
var s: String
|
||||
myRun {
|
||||
if (b) {
|
||||
x = 42
|
||||
return
|
||||
}
|
||||
x = 54
|
||||
s = "hello"
|
||||
}
|
||||
x.inc()
|
||||
s.length
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseCallsInPlaceEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
inline fun myRun(block: () -> Unit) {
|
||||
contract {
|
||||
<!INAPPLICABLE_CANDIDATE!>callsInPlace<!>(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
block()
|
||||
}
|
||||
|
||||
inline fun <T> unknownRun(block: () -> T): T = block()
|
||||
|
||||
fun throwIfNotCalled() {
|
||||
val x: Int
|
||||
myRun outer@ {
|
||||
unknownRun {
|
||||
myRun {
|
||||
x = 42
|
||||
return@outer
|
||||
}
|
||||
}
|
||||
throw java.lang.<!UNRESOLVED_REFERENCE!>IllegalArgumentException<!>()
|
||||
}
|
||||
// x *is* initialized here, because if myRun was never called -> exception
|
||||
// were thrown and control flow wouldn't be here
|
||||
println(x)
|
||||
}
|
||||
|
||||
fun catchThrowIfNotCalled() {
|
||||
val x: Int
|
||||
try {
|
||||
myRun outer@ {
|
||||
unknownRun {
|
||||
myRun {
|
||||
x = 42
|
||||
return@outer
|
||||
}
|
||||
}
|
||||
throw java.lang.<!UNRESOLVED_REFERENCE!>IllegalArgumentException<!>()
|
||||
}
|
||||
} catch (ignored: java.lang.IllegalArgumentException) { }
|
||||
|
||||
// x *isn't* initialized here!
|
||||
println(x)
|
||||
}
|
||||
Vendored
+58
@@ -0,0 +1,58 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseCallsInPlaceEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun <T> myRun(block: () -> T): T {
|
||||
contract {
|
||||
<!INAPPLICABLE_CANDIDATE!>callsInPlace<!>(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return block()
|
||||
}
|
||||
|
||||
fun someComputation(): Int = 42
|
||||
|
||||
fun tryCatchInlined() {
|
||||
val x: Int
|
||||
|
||||
myRun {
|
||||
try {
|
||||
x = someComputation()
|
||||
x.inc()
|
||||
}
|
||||
catch (e: java.lang.Exception) {
|
||||
x.inc()
|
||||
}
|
||||
}
|
||||
x = 42
|
||||
x.inc()
|
||||
}
|
||||
|
||||
fun possibleReassignmentInTryCatch() {
|
||||
val x: Int
|
||||
|
||||
myRun {
|
||||
try {
|
||||
x = someComputation()
|
||||
x.inc()
|
||||
}
|
||||
catch (e: java.lang.Exception) {
|
||||
x = 42
|
||||
x.inc()
|
||||
}
|
||||
x.inc()
|
||||
}
|
||||
x.inc()
|
||||
}
|
||||
|
||||
fun tryCatchOuter() {
|
||||
val x: Int
|
||||
try {
|
||||
myRun { x = someComputation() }
|
||||
x.inc()
|
||||
}
|
||||
catch (e: java.lang.Exception) {
|
||||
x.inc()
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseCallsInPlaceEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER -UNUSED_PARAMETER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
inline fun <T> myRun(block: () -> T): T {
|
||||
contract {
|
||||
<!INAPPLICABLE_CANDIDATE!>callsInPlace<!>(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return block()
|
||||
}
|
||||
|
||||
fun someComputation(): Int = 42
|
||||
|
||||
fun report(x: Int) = Unit
|
||||
|
||||
fun innerTryCatchFinally() {
|
||||
val x: Int
|
||||
|
||||
myRun {
|
||||
try {
|
||||
x = someComputation()
|
||||
report(x)
|
||||
} catch (e: java.lang.Exception) {
|
||||
x = 42
|
||||
report(x)
|
||||
} finally {
|
||||
x = 0
|
||||
}
|
||||
}
|
||||
|
||||
x.inc()
|
||||
}
|
||||
compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/typeMismatch.fir.kt
Vendored
+19
@@ -0,0 +1,19 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseCallsInPlaceEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun <T> myRun(block: () -> T): T {
|
||||
contract {
|
||||
<!INAPPLICABLE_CANDIDATE!>callsInPlace<!>(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return block()
|
||||
}
|
||||
|
||||
fun foo(x: Int): Int = x + 1
|
||||
|
||||
fun typeMismatchInLambda(y: String): Int {
|
||||
val x = myRun { <!INAPPLICABLE_CANDIDATE!>foo<!>(y) }
|
||||
return x
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseCallsInPlaceEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
inline fun <T> myRun(block: () -> T): T {
|
||||
contract {
|
||||
<!INAPPLICABLE_CANDIDATE!>callsInPlace<!>(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return block()
|
||||
}
|
||||
|
||||
fun throwInLambda(): Int {
|
||||
val x = myRun { throw java.lang.<!UNRESOLVED_REFERENCE!>IllegalArgumentException<!>(); 42 }
|
||||
return x
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseCallsInPlaceEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun <T> runTwice(block: () -> T): T {
|
||||
contract {
|
||||
<!INAPPLICABLE_CANDIDATE!>callsInPlace<!>(block, InvocationKind.AT_LEAST_ONCE)
|
||||
}
|
||||
block()
|
||||
return block();
|
||||
};
|
||||
|
||||
fun <T> runOnce(block: () -> T): T {
|
||||
contract {
|
||||
<!INAPPLICABLE_CANDIDATE!>callsInPlace<!>(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return block();
|
||||
};
|
||||
|
||||
fun valueReassignment() {
|
||||
val x: Int
|
||||
x.inc()
|
||||
runTwice { x = 42 }
|
||||
x.inc()
|
||||
}
|
||||
|
||||
fun shadowing() {
|
||||
val x: Int
|
||||
runTwice { val x: Int; x = 42; x.inc() }
|
||||
x.inc()
|
||||
}
|
||||
|
||||
fun branchingFlow(a: Any?) {
|
||||
val x: Int
|
||||
x.inc()
|
||||
if (a is String) {
|
||||
runTwice { x = 42 }
|
||||
}
|
||||
else {
|
||||
x = 43
|
||||
}
|
||||
x.inc()
|
||||
}
|
||||
|
||||
fun branchingFlowWithMissingBranches(a: Any?) {
|
||||
val x: Int
|
||||
if (a is String) {
|
||||
runTwice { x = 42 }
|
||||
}
|
||||
|
||||
x.inc()
|
||||
}
|
||||
|
||||
fun repeatingFlow(n: Int) {
|
||||
val x: Int
|
||||
x.inc()
|
||||
|
||||
for (i in 1..n) {
|
||||
runTwice { x = 42 }
|
||||
}
|
||||
|
||||
x.inc()
|
||||
}
|
||||
|
||||
fun repeatingFlow2(n: Int) {
|
||||
val x: Int
|
||||
|
||||
for (i in 1..n) {
|
||||
runTwice { x = 42 }
|
||||
}
|
||||
|
||||
x.inc()
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseCallsInPlaceEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun <T> runTwice(block: () -> T): T {
|
||||
contract {
|
||||
<!INAPPLICABLE_CANDIDATE!>callsInPlace<!>(block, InvocationKind.AT_LEAST_ONCE)
|
||||
}
|
||||
block()
|
||||
return block();
|
||||
};
|
||||
|
||||
fun testInitialization() {
|
||||
var x: Int
|
||||
x.inc()
|
||||
runTwice { x = 42 }
|
||||
x.inc()
|
||||
x = 43
|
||||
x.inc()
|
||||
}
|
||||
|
||||
fun repeatingFlow(n: Int) {
|
||||
var x: Int
|
||||
for (i in 1..n) {
|
||||
runTwice { x = 42 }
|
||||
}
|
||||
x.inc()
|
||||
}
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseCallsInPlaceEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun <T> runTwice(block: () -> T): T {
|
||||
contract {
|
||||
<!INAPPLICABLE_CANDIDATE!>callsInPlace<!>(block, InvocationKind.AT_LEAST_ONCE)
|
||||
}
|
||||
block()
|
||||
return block();
|
||||
};
|
||||
|
||||
fun <T> funWithUnknownInvocations(block: () -> T) = block()
|
||||
|
||||
fun indefiniteFlow() {
|
||||
var x: Int
|
||||
|
||||
funWithUnknownInvocations { runTwice { x = 42 } }
|
||||
|
||||
x.inc()
|
||||
}
|
||||
|
||||
fun shadowing() {
|
||||
var x: Int
|
||||
runTwice { val x: Int; x = 42; x.inc() }
|
||||
x.inc()
|
||||
}
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseCallsInPlaceEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun <T> myRun(block: () -> T): T {
|
||||
contract {
|
||||
<!INAPPLICABLE_CANDIDATE!>callsInPlace<!>(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return block()
|
||||
}
|
||||
|
||||
fun initialization() {
|
||||
val x: Int
|
||||
myRun {
|
||||
x = 42
|
||||
42
|
||||
}
|
||||
x.inc()
|
||||
}
|
||||
|
||||
fun shadowing() {
|
||||
val x = 42
|
||||
myRun {
|
||||
val x = 43
|
||||
x.inc()
|
||||
}
|
||||
x.inc()
|
||||
}
|
||||
|
||||
fun nestedDefiniteAssignment() {
|
||||
val x: Int
|
||||
myRun {
|
||||
val y = "Hello"
|
||||
myRun {
|
||||
x = 42
|
||||
}
|
||||
y.length
|
||||
}
|
||||
x.inc()
|
||||
}
|
||||
|
||||
fun deeplyNestedDefiniteAssignment() {
|
||||
val x: Int
|
||||
myRun {
|
||||
val y: String
|
||||
myRun {
|
||||
val z: String
|
||||
myRun {
|
||||
z = "Hello"
|
||||
y = "World"
|
||||
x = 42
|
||||
}
|
||||
z.length
|
||||
}
|
||||
y.length
|
||||
}
|
||||
x.inc()
|
||||
}
|
||||
|
||||
fun branchingFlow(a: Any?) {
|
||||
val x: Int
|
||||
|
||||
if (a is String) {
|
||||
myRun { x = 42 }
|
||||
}
|
||||
else {
|
||||
myRun { x = 43 }
|
||||
}
|
||||
|
||||
x.inc()
|
||||
}
|
||||
|
||||
fun returningValue() {
|
||||
val x: Int
|
||||
val hello = myRun { x = 42; "hello" }
|
||||
x.inc()
|
||||
hello.length
|
||||
}
|
||||
|
||||
fun unknownRun(block: () -> Unit) = block()
|
||||
|
||||
class DefiniteInitializationInInitSection {
|
||||
val x: Int
|
||||
val y: Int
|
||||
|
||||
init {
|
||||
myRun { x = 42 }
|
||||
unknownRun { y = 239 }
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseCallsInPlaceEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun <T> myRun(block: () -> T): T {
|
||||
contract {
|
||||
<!INAPPLICABLE_CANDIDATE!>callsInPlace<!>(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return block()
|
||||
}
|
||||
|
||||
fun reassignmentInUsualFlow() {
|
||||
val x: Int
|
||||
myRun { x = 42 }
|
||||
x = 43
|
||||
x.inc()
|
||||
}
|
||||
|
||||
fun reassignment() {
|
||||
val x = 42
|
||||
myRun {
|
||||
x = 43
|
||||
}
|
||||
x.inc()
|
||||
}
|
||||
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseCallsInPlaceEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun <T> myRun(block: () -> T): T {
|
||||
contract {
|
||||
<!INAPPLICABLE_CANDIDATE!>callsInPlace<!>(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return block()
|
||||
}
|
||||
|
||||
fun myRepeat(n: Int, action: () -> Unit) {
|
||||
contract {
|
||||
<!INAPPLICABLE_CANDIDATE!>callsInPlace<!>(action)
|
||||
}
|
||||
for (i in 1..n) action()
|
||||
}
|
||||
|
||||
fun branchingIndetermineFlow(a: Any?) {
|
||||
val x: Int
|
||||
|
||||
if (a is String) {
|
||||
myRepeat(a.length) {
|
||||
// Val reassignment because we know that repeat's lambda called in-place
|
||||
myRun { x = 42 }
|
||||
}
|
||||
}
|
||||
else {
|
||||
myRun { x = 43 }
|
||||
}
|
||||
|
||||
x.inc()
|
||||
}
|
||||
|
||||
fun nonAnonymousLambdas() {
|
||||
val x: Int
|
||||
val initializer = { x = 42 }
|
||||
myRun(initializer)
|
||||
x.inc()
|
||||
}
|
||||
|
||||
fun multipleAssignments() {
|
||||
val x: Int
|
||||
myRepeat(42) {
|
||||
// Val reassignment because we know that repeat's lambda called in-place
|
||||
myRun { x = 42 }
|
||||
}
|
||||
x.inc()
|
||||
}
|
||||
|
||||
fun funWithUnknownInvocations(block: () -> Unit) = block()
|
||||
|
||||
fun nestedIndefiniteAssignment() {
|
||||
val x: Int
|
||||
// Captured val initialization reported, because we don't know anything about funWithUnknownInvocations
|
||||
funWithUnknownInvocations { myRun { x = 42 } }
|
||||
x.inc()
|
||||
}
|
||||
|
||||
class InitializationForbiddenInNonInitSection {
|
||||
val x: Int
|
||||
|
||||
fun setup() {
|
||||
myRun { x = 42 }
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseCallsInPlaceEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun <T> myRun(block: () -> T): T {
|
||||
contract {
|
||||
<!INAPPLICABLE_CANDIDATE!>callsInPlace<!>(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return block()
|
||||
}
|
||||
|
||||
fun definiteVarInitialization() {
|
||||
var x: Int
|
||||
myRun { x = 42 }
|
||||
x.inc()
|
||||
}
|
||||
|
||||
fun definiteVarReassignment() {
|
||||
var x: Int
|
||||
myRun { x = 42 }
|
||||
x.inc()
|
||||
myRun { x = 43 }
|
||||
x.inc()
|
||||
x = 44
|
||||
x.inc()
|
||||
}
|
||||
|
||||
fun nestedVarInitialization() {
|
||||
var x: Int
|
||||
myRun { myRun { myRun { x = 42 } } }
|
||||
x.inc()
|
||||
myRun { myRun { myRun { x = 42 } } }
|
||||
}
|
||||
|
||||
|
||||
fun notAnExpression() {
|
||||
var x: Int = 0
|
||||
myRun { if (true) x = 42 }
|
||||
x.inc()
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseCallsInPlaceEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun <T> myRun(block: () -> T): T {
|
||||
contract {
|
||||
<!INAPPLICABLE_CANDIDATE!>callsInPlace<!>(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return block()
|
||||
}
|
||||
|
||||
fun indefiniteVarReassignment(n: Int) {
|
||||
var x: Int
|
||||
repeat(n) {
|
||||
myRun { x = 42 }
|
||||
}
|
||||
x.inc()
|
||||
}
|
||||
|
||||
fun nonAnonymousLambdas() {
|
||||
// Named lambdas are not inlined, even in theory it could be done for some simple cases as this one
|
||||
var x: Int
|
||||
val initializer = { x = 42 }
|
||||
myRun(initializer)
|
||||
x.inc()
|
||||
}
|
||||
|
||||
fun branchingIndetermineFlow(a: Any) {
|
||||
var x: Int
|
||||
|
||||
if (a is String) {
|
||||
repeat(a.length) {
|
||||
myRun { x = 42 }
|
||||
}
|
||||
}
|
||||
else {
|
||||
myRun { x = 43 }
|
||||
}
|
||||
|
||||
x.inc()
|
||||
}
|
||||
|
||||
fun funWithUnknownInvocations(block: () -> Unit) = block()
|
||||
|
||||
fun nestedIndefiniteAssignment() {
|
||||
val x: Int
|
||||
funWithUnknownInvocations { myRun { x = 42 } }
|
||||
x.inc()
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseCallsInPlaceEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun <T, R> T.myLet(block: (T) -> R): R {
|
||||
contract {
|
||||
<!INAPPLICABLE_CANDIDATE!>callsInPlace<!>(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return block(this)
|
||||
}
|
||||
|
||||
fun initializationWithReceiver(y: String) {
|
||||
val x: Int
|
||||
y.myLet { x = 42 }
|
||||
x.inc()
|
||||
}
|
||||
|
||||
fun initializationWithSafeCall(y: String?) {
|
||||
val x: Int
|
||||
y?.myLet { x = 42 }
|
||||
x.inc()
|
||||
}
|
||||
|
||||
fun sanityCheck(x: Int, y: String): Int {
|
||||
y.let { return x }
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseCallsInPlaceEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun <T> inPlace(block: () -> T): T {
|
||||
contract {
|
||||
<!INAPPLICABLE_CANDIDATE!>callsInPlace<!>(block)
|
||||
}
|
||||
return block()
|
||||
}
|
||||
|
||||
fun reassignmentAndNoInitializaiton() {
|
||||
val x: Int
|
||||
inPlace { x = 42 }
|
||||
x.inc()
|
||||
}
|
||||
Vendored
+42
@@ -0,0 +1,42 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
package my
|
||||
|
||||
// Accepts block, can't be distinguished from kotlin.contract without resolve
|
||||
fun contract(block: () -> Unit) {}
|
||||
|
||||
// Accepts int, potentially can be distinguished from kotlin.contract by PSI,
|
||||
// but as of Kotlin 1.3.0, we don't do that
|
||||
fun contract(i: Int) {}
|
||||
|
||||
fun doStuff() {}
|
||||
|
||||
class SomeClass {
|
||||
|
||||
fun contract() {}
|
||||
|
||||
fun callMemberContractWithThis() {
|
||||
this.contract()
|
||||
}
|
||||
|
||||
fun callMemberContractWithoutThis() {
|
||||
contract()
|
||||
}
|
||||
|
||||
fun callTopLevelSamePsiInMember() {
|
||||
contract { }
|
||||
}
|
||||
}
|
||||
|
||||
fun callTopLevelSamePsi() {
|
||||
contract { }
|
||||
}
|
||||
|
||||
fun callTopLevelDifferentPsi() {
|
||||
contract(42)
|
||||
}
|
||||
|
||||
fun callTopLevelSamePsiNotFirstStatement() {
|
||||
doStuff()
|
||||
contract { }
|
||||
}
|
||||
Vendored
+23
@@ -0,0 +1,23 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun foo(b: Boolean): Boolean {
|
||||
contract {
|
||||
// pointless, can be reduced to just "b"
|
||||
returns(true) implies (b == true)
|
||||
}
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
fun bar(b: Boolean?): Boolean {
|
||||
contract {
|
||||
// not pointless, but not supported yet
|
||||
returns(true) implies (b == true)
|
||||
}
|
||||
if (b == null) throw java.lang.<!UNRESOLVED_REFERENCE!>IllegalArgumentException<!>("")
|
||||
return b
|
||||
}
|
||||
Vendored
+14
@@ -0,0 +1,14 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun bar(x: Int): Boolean = x == 0
|
||||
|
||||
fun foo(x: Int): Boolean {
|
||||
contract {
|
||||
returns(true) implies (bar(x))
|
||||
}
|
||||
return x == 0
|
||||
}
|
||||
Vendored
+86
@@ -0,0 +1,86 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER -NOTHING_TO_INLINE -ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS -ABSTRACT_FUNCTION_WITH_BODY -UNUSED_PARAMETER -UNUSED_VARIABLE -EXPERIMENTAL_FEATURE_WARNING
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
|
||||
// ============= Class =====================
|
||||
open class Class {
|
||||
fun member(x: Boolean) {
|
||||
contract { returns() implies (x) }
|
||||
}
|
||||
|
||||
inline fun inlineMember(x: Boolean) {
|
||||
contract { returns() implies (x) }
|
||||
}
|
||||
|
||||
abstract fun abstractMember(x: Boolean) {
|
||||
contract { returns() implies (x) }
|
||||
}
|
||||
|
||||
open fun openMemeber(x: Boolean) {
|
||||
contract { returns() implies (x) }
|
||||
}
|
||||
|
||||
suspend fun suspendMember(x: Boolean) {
|
||||
contract { returns() implies (x) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ============= Top-level =====================
|
||||
fun topLevel(x: Boolean) {
|
||||
contract { returns() implies (x) }
|
||||
}
|
||||
|
||||
inline fun inlineTopLevel(x: Boolean) {
|
||||
contract { returns() implies (x) }
|
||||
}
|
||||
|
||||
suspend fun suspendTopLevel(x: Boolean) {
|
||||
contract { returns() implies (x) }
|
||||
}
|
||||
|
||||
// Top-level operator
|
||||
operator fun Boolean.plus(x: Boolean): Boolean {
|
||||
contract { returns() implies (x) }
|
||||
return x
|
||||
}
|
||||
|
||||
val topLevelLambda: (Boolean) -> Unit = { x: Boolean ->
|
||||
contract { returns() implies (x) }
|
||||
}
|
||||
|
||||
val topLevelAnonymousFunction = fun (x: Boolean) {
|
||||
contract { returns() implies (x) }
|
||||
}
|
||||
|
||||
var topLevelPropertyAccessors: Int? = 42
|
||||
get() {
|
||||
contract { returns() implies (field != null) }
|
||||
return 42
|
||||
}
|
||||
set(value) {
|
||||
contract { returns() implies (field != null) }
|
||||
}
|
||||
|
||||
|
||||
// ============= Local =====================
|
||||
fun test() {
|
||||
fun localDeclaration(x: Boolean) {
|
||||
contract { returns() implies (x) }
|
||||
}
|
||||
|
||||
suspend fun suspendlocalDeclaration(x: Boolean) {
|
||||
contract { returns() implies (x) }
|
||||
}
|
||||
|
||||
val localAnonymousFunction = fun (x: Boolean) {
|
||||
contract { returns() implies (x) }
|
||||
}
|
||||
|
||||
val localLambda: (Boolean) -> Unit = { x: Boolean ->
|
||||
contract { returns() implies (x) }
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun emptyContract() {
|
||||
contract { }
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER -NOTHING_TO_INLINE -ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS -ABSTRACT_FUNCTION_WITH_BODY -UNUSED_PARAMETER -UNUSED_VARIABLE -EXPERIMENTAL_FEATURE_WARNING
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun ifInContract(x: Any?, boolean: Boolean) {
|
||||
contract {
|
||||
if (boolean) {
|
||||
returns() implies (x is String)
|
||||
} else {
|
||||
returns() implies (x is Int)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun whenInContract(x: Any?, boolean: Boolean) {
|
||||
contract {
|
||||
when (boolean) {
|
||||
true -> returns() implies (x is String)
|
||||
else -> returns() implies (x is Int)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun forInContract(x: Any?) {
|
||||
contract {
|
||||
for (i in 0..1) {
|
||||
returns() implies (x is String)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun whileInContract(x: Any?) {
|
||||
contract {
|
||||
while (false) {
|
||||
returns() implies (x is String)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun doWhileInContract(x: Any?) {
|
||||
contract {
|
||||
do {
|
||||
returns() implies (x is String)
|
||||
} while (false)
|
||||
}
|
||||
}
|
||||
|
||||
fun localValInContract(x: Any?) {
|
||||
contract {
|
||||
val y: Int = 42
|
||||
returns() implies (x is String)
|
||||
}
|
||||
}
|
||||
Vendored
+30
@@ -0,0 +1,30 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun equalsWithVariables(x: Any?, y: Any?) {
|
||||
contract {
|
||||
returns() implies (x == y)
|
||||
}
|
||||
}
|
||||
|
||||
fun identityEqualsWithVariables(x: Any?, y: Any?) {
|
||||
contract {
|
||||
returns() implies (x === y)
|
||||
}
|
||||
}
|
||||
|
||||
fun equalConstants() {
|
||||
contract {
|
||||
returns() implies (null == null)
|
||||
}
|
||||
}
|
||||
|
||||
fun get(): Int? = null
|
||||
fun equalNullWithCall() {
|
||||
contract {
|
||||
returns() implies (get() == null)
|
||||
}
|
||||
}
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun foo(boolean: Boolean) {
|
||||
contract {
|
||||
(returns() implies (boolean)) <!UNRESOLVED_REFERENCE!>implies<!> (!boolean)
|
||||
}
|
||||
}
|
||||
compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/nonLambdaLiteralAsArgument.fir.kt
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER -EXPOSED_PARAMETER_TYPE
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun passLambdaValue(l: ContractBuilder.() -> Unit) {
|
||||
contract(l)
|
||||
}
|
||||
|
||||
fun passAnonymousFunction(x: Boolean) {
|
||||
contract(fun ContractBuilder.() {
|
||||
<!UNRESOLVED_REFERENCE!>returns<!>() <!UNRESOLVED_REFERENCE!>implies<!> x
|
||||
})
|
||||
}
|
||||
Vendored
+76
@@ -0,0 +1,76 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER -UNUSED_VARIABLE -REDUNDANT_LABEL_WARNING -UNUSED_PARAMETER -NOTHING_TO_INLINE -CAST_NEVER_SUCCEEDS
|
||||
// Issues: KT-26153, KT-26191
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun foo(y: Boolean) {
|
||||
val x: Int = 42
|
||||
contract {
|
||||
returns() implies y
|
||||
}
|
||||
}
|
||||
|
||||
inline fun case1(block: () -> Unit) {
|
||||
val contracts = listOf(
|
||||
contract {
|
||||
<!INAPPLICABLE_CANDIDATE!>callsInPlace<!>(block, InvocationKind.EXACTLY_ONCE)
|
||||
}, contract {
|
||||
<!INAPPLICABLE_CANDIDATE!>callsInPlace<!>(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
)
|
||||
block()
|
||||
}
|
||||
|
||||
inline fun case_2(block: () -> Unit) = contract {
|
||||
<!INAPPLICABLE_CANDIDATE!>callsInPlace<!>(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
|
||||
fun case_3(block: () -> Unit) {
|
||||
class Class {
|
||||
fun innerFun(block2: () -> Unit) {
|
||||
contract {
|
||||
<!INAPPLICABLE_CANDIDATE!>callsInPlace<!>(block2, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
block2()
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
inline fun case_4(number: Int?): Boolean {
|
||||
val cond = number != null
|
||||
contract {
|
||||
returns(false) implies (cond)
|
||||
} as ContractBuilder
|
||||
return number == null
|
||||
}
|
||||
|
||||
inline fun case_5(cond: Boolean): Boolean {
|
||||
run {
|
||||
contract {
|
||||
returns(true) implies (cond)
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
inline fun case_6(cond: Boolean): Boolean {
|
||||
run {
|
||||
val x = 10
|
||||
contract {
|
||||
returns(true) implies (cond)
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
fun case_7(cond: Boolean): Boolean {
|
||||
fun innerFun() {
|
||||
contract {
|
||||
returns(true) implies (cond)
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
Vendored
+25
@@ -0,0 +1,25 @@
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !LANGUAGE: +UseReturnsEffect
|
||||
// Issue: KT-26386
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun case_1(): Boolean {
|
||||
contract { returns(null) implies case_1() }
|
||||
return true
|
||||
}
|
||||
|
||||
fun case_2(): Boolean {
|
||||
contract { returns(null) implies case_3() }
|
||||
return true
|
||||
}
|
||||
|
||||
fun case_3(): Boolean {
|
||||
contract { returns(null) implies case_2() }
|
||||
return true
|
||||
}
|
||||
|
||||
fun case_4(): Boolean {
|
||||
kotlin.contracts.contract { returns(null) implies case_1() }
|
||||
return true
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !LANGUAGE: +UseReturnsEffect
|
||||
// Issue: KT-26386
|
||||
|
||||
fun myRun(block: () -> Unit) {
|
||||
block()
|
||||
}
|
||||
|
||||
fun contract(block: () -> Unit) {
|
||||
block()
|
||||
}
|
||||
|
||||
fun case_1(): Boolean? {
|
||||
contract { case_1() }
|
||||
return null
|
||||
}
|
||||
|
||||
fun case_2(): Boolean? {
|
||||
contract { case_3() }
|
||||
return null
|
||||
}
|
||||
|
||||
fun case_3(): Boolean? {
|
||||
contract { case_2() }
|
||||
return null
|
||||
}
|
||||
|
||||
fun case4() {
|
||||
contract {
|
||||
myRun {
|
||||
val s: String
|
||||
run {
|
||||
s = "hello"
|
||||
}
|
||||
s.length
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+14
@@ -0,0 +1,14 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
class Foo(val x: Int?) {
|
||||
fun isXNull(): Boolean {
|
||||
contract {
|
||||
returns(false) implies (x != null)
|
||||
}
|
||||
return x != null
|
||||
}
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
inline fun <reified T> referToReifiedGeneric(x: Any?) {
|
||||
contract {
|
||||
returns() implies (x is T)
|
||||
}
|
||||
}
|
||||
|
||||
class Generic<T> {
|
||||
fun referToCaptured(x: Any?) {
|
||||
contract {
|
||||
returns() implies (x is T)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun referToSubstituted(x: Any?) {
|
||||
contract {
|
||||
returns() implies (x is Generic<String>)
|
||||
}
|
||||
}
|
||||
|
||||
fun referToSubstitutedWithStar(x: Any?) {
|
||||
contract {
|
||||
returns() implies (x is Generic<*>)
|
||||
}
|
||||
}
|
||||
|
||||
typealias GenericString = Generic<String>
|
||||
typealias FunctionalType = () -> Unit
|
||||
typealias SimpleType = Int
|
||||
|
||||
fun referToAliasedGeneric(x: Any?) {
|
||||
contract {
|
||||
returns() implies (x is GenericString)
|
||||
}
|
||||
}
|
||||
|
||||
fun referToAliasedFunctionType(x: Any?) {
|
||||
contract {
|
||||
returns() implies (x is FunctionalType)
|
||||
}
|
||||
}
|
||||
|
||||
fun referToAliasedSimpleType(x: Any?) {
|
||||
contract {
|
||||
returns() implies (x is SimpleType)
|
||||
}
|
||||
}
|
||||
Vendored
+12
@@ -0,0 +1,12 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun Any?.foo(): Boolean {
|
||||
contract {
|
||||
returns(true) implies (this != null)
|
||||
}
|
||||
return this != null
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.InvocationKind
|
||||
|
||||
inline fun foo(block: () -> Unit) {
|
||||
kotlin.contracts.contract {
|
||||
<!INAPPLICABLE_CANDIDATE!>callsInPlace<!>(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
block()
|
||||
}
|
||||
|
||||
fun main() {
|
||||
val x: Int
|
||||
foo {
|
||||
x = 42
|
||||
}
|
||||
println(x)
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// See KT-28847
|
||||
|
||||
class Foo(val str: String?) {
|
||||
val first = run {
|
||||
str.isNullOrEmpty()
|
||||
second
|
||||
}
|
||||
|
||||
val second = str.isNullOrEmpty()
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun test(x: Any?) {
|
||||
if (isString(x)) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun isString(x: Any?): Boolean {
|
||||
contract {
|
||||
returns(true) implies (x is String)
|
||||
}
|
||||
return x is String
|
||||
}
|
||||
|
||||
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
// !LANGUAGE: +ReadDeserializedContracts +UseReturnsEffect
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
fun testCheckSmartcast(x: Any?) {
|
||||
check(x is String)
|
||||
x.length
|
||||
}
|
||||
|
||||
fun testCheckUnreachableCode() {
|
||||
check(false)
|
||||
// Can't be reported without notion of 'iff'
|
||||
println("Can't get here!")
|
||||
}
|
||||
|
||||
fun testCheckWithMessage(x: Any?) {
|
||||
check(x is String) { "x is not String!" }
|
||||
x.length
|
||||
}
|
||||
|
||||
fun testCheckWithFailingMessage(x: Any?) {
|
||||
check(x is String) { throw kotlin.<!UNRESOLVED_REFERENCE!>IllegalStateException<!>("What a strange idea") }
|
||||
x.length
|
||||
}
|
||||
|
||||
fun testCheckNotNullWithMessage(x: Int?) {
|
||||
checkNotNull(x) { "x is null!" }
|
||||
x.inc()
|
||||
}
|
||||
|
||||
fun testCheckNotNull(x: Int?) {
|
||||
checkNotNull(x)
|
||||
x.inc()
|
||||
}
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
// !LANGUAGE: +ReadDeserializedContracts +UseCallsInPlaceEffect
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
fun testRunWithUnitReturn() {
|
||||
val x: Int
|
||||
run { x = 42 }
|
||||
println(x)
|
||||
}
|
||||
|
||||
fun testRunWithReturnValue() {
|
||||
val x: Int
|
||||
val y = run {
|
||||
x = 42
|
||||
"hello"
|
||||
}
|
||||
println(x)
|
||||
println(y)
|
||||
}
|
||||
|
||||
fun testRunWithCoercionToUnit() {
|
||||
val x: Int
|
||||
run {
|
||||
x = 42
|
||||
"hello"
|
||||
}
|
||||
}
|
||||
|
||||
fun testRunWithReceiver(x: Int) {
|
||||
val s: String
|
||||
x.run {
|
||||
s = this.toString()
|
||||
}
|
||||
println(s)
|
||||
}
|
||||
|
||||
fun testWith(x: Int) {
|
||||
val s: String
|
||||
with(x) {
|
||||
s = toString()
|
||||
}
|
||||
println(s)
|
||||
}
|
||||
|
||||
fun testApply(x: Int) {
|
||||
val y: Int
|
||||
val z: Int = x.apply { y = 42 }
|
||||
println(y)
|
||||
println(z)
|
||||
}
|
||||
|
||||
fun testAlso(x: Int) {
|
||||
val y: Int
|
||||
x.also { y = it + 1 }
|
||||
println(y)
|
||||
}
|
||||
|
||||
fun testLet(x: Int) {
|
||||
val z: Int
|
||||
val y: String = x.let {
|
||||
z = 42
|
||||
(it + 1).toString()
|
||||
}
|
||||
println(z)
|
||||
println(y)
|
||||
}
|
||||
|
||||
fun testTakeIf(x: Int?) {
|
||||
val y: Int
|
||||
x.takeIf {
|
||||
y = 42
|
||||
it != null
|
||||
}
|
||||
println(y)
|
||||
}
|
||||
|
||||
fun testTakeUnless(x: Int?) {
|
||||
val y: Int
|
||||
x.takeIf {
|
||||
y = 42
|
||||
it != null
|
||||
}
|
||||
println(y)
|
||||
}
|
||||
|
||||
fun testRepeatOnVal(x: Int) {
|
||||
val y: Int
|
||||
repeat(x) {
|
||||
// reassignment instead of captured val initialization
|
||||
y = 42
|
||||
}
|
||||
println(y)
|
||||
}
|
||||
|
||||
fun testRepeatOnVar(x: Int) {
|
||||
var y: Int
|
||||
repeat(x) {
|
||||
// no reassignment reported
|
||||
y = 42
|
||||
}
|
||||
// but here we still unsure if 'y' was initialized
|
||||
println(y)
|
||||
}
|
||||
|
||||
fun testRepeatOnInitializedVar(x: Int) {
|
||||
var y: Int = 24
|
||||
repeat(x) {
|
||||
y = 42
|
||||
}
|
||||
println(y)
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// !LANGUAGE: +ReadDeserializedContracts +UseReturnsEffect
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
fun testIsNullOrBlank(x: String?) {
|
||||
if (x.isNullOrBlank()) {
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
else {
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun testIsNotNullOrBlank(x: String?) {
|
||||
if (!x.isNullOrBlank()) {
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// !LANGUAGE: +ReadDeserializedContracts +UseReturnsEffect
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
fun testIsNullOrEmpty(x: String?) {
|
||||
if (x.isNullOrEmpty()) {
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
else {
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun testIsNotNullOrEmpty(x: String?) {
|
||||
if (!x.isNullOrEmpty()) {
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
// !LANGUAGE: +ReadDeserializedContracts +UseReturnsEffect
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
fun testRequireSmartcast(x: Any?) {
|
||||
require(x is String)
|
||||
x.length
|
||||
}
|
||||
|
||||
fun testRequireUnreachableCode() {
|
||||
require(false)
|
||||
println("Can't get here!")
|
||||
}
|
||||
|
||||
fun testRequireWithMessage(x: Any?) {
|
||||
require(x is String) { "x is not String!" }
|
||||
x.length
|
||||
}
|
||||
|
||||
fun testRequireWithFailingMessage(x: Any?) {
|
||||
require(x is String) { throw kotlin.<!UNRESOLVED_REFERENCE!>IllegalStateException<!>("What a strange idea") }
|
||||
x.length
|
||||
}
|
||||
|
||||
fun tesRequireNotNullWithMessage(x: Int?) {
|
||||
requireNotNull(x) { "x is null!"}
|
||||
x.inc()
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// !LANGUAGE: +ReadDeserializedContracts +UseCallsInPlaceEffect
|
||||
|
||||
fun test(lock: Any) {
|
||||
val x: Int
|
||||
|
||||
synchronized(lock) {
|
||||
x = 42
|
||||
}
|
||||
|
||||
x.inc()
|
||||
}
|
||||
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun myAssert(condition: Boolean, message: String = "") {
|
||||
contract {
|
||||
returns() implies (condition)
|
||||
}
|
||||
if (!condition) throw kotlin.<!UNRESOLVED_REFERENCE!>IllegalArgumentException<!>(message)
|
||||
}
|
||||
|
||||
fun test(x: Any?) {
|
||||
myAssert(x is String)
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun myAssert(condition: Boolean) {
|
||||
contract {
|
||||
returns() implies (condition)
|
||||
}
|
||||
if (!condition) throw kotlin.<!UNRESOLVED_REFERENCE!>IllegalArgumentException<!>("Assertion failed")
|
||||
}
|
||||
|
||||
fun testWithCatch(x: Any?) {
|
||||
try {
|
||||
myAssert(x is String)
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
} catch (e: java.lang.IllegalArgumentException) { }
|
||||
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.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) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun testNotEqualsWithConstant(x: Any?) {
|
||||
if (isString(x) != true) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>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<!>
|
||||
}
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
// !WITH_NEW_INFERENCE
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun myAssert(condition: Boolean) {
|
||||
contract {
|
||||
returns() implies (condition)
|
||||
}
|
||||
if (!condition) throw kotlin.<!UNRESOLVED_REFERENCE!>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))) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun nested2(x: Any?) {
|
||||
myAssert(equalsTrue(isString(x)))
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
|
||||
fun nested3(x: Any?) {
|
||||
myAssert(equalsTrue(notEqualsNull(nullWhenNotString(x))))
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
|
||||
fun branchedAndNested(x: Any?, y: Any?) {
|
||||
myAssert(equalsTrue(notEqualsNull(nullWhenNotString(x))) && equalsTrue(isString(y)))
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
y.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
|
||||
|
||||
fun br(y: Any?) {
|
||||
if (myAssert(y is Int) == Unit && myAssert(y is String) == Unit) {
|
||||
y.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
y.<!AMBIGUITY!>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))
|
||||
)
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
y.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
y.<!AMBIGUITY!>inc<!>()
|
||||
}
|
||||
|
||||
Vendored
+38
@@ -0,0 +1,38 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
//
|
||||
// ISSUE: KT-28672
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun CharSequence?.isNullOrEmpty(): Boolean {
|
||||
contract {
|
||||
returns(false) implies (this@isNullOrEmpty != null)
|
||||
}
|
||||
|
||||
return this == null || this.length == 0
|
||||
}
|
||||
|
||||
fun smartcastOnReceiver(s: String?) {
|
||||
with(s) {
|
||||
if (isNullOrEmpty()) {
|
||||
length
|
||||
}
|
||||
else {
|
||||
length
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun mixedReceiver(s: String?) {
|
||||
if (!s.isNullOrEmpty()) {
|
||||
with(s) {
|
||||
length
|
||||
}
|
||||
} else {
|
||||
with(s) {
|
||||
length
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+38
@@ -0,0 +1,38 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect +ContractsOnCallsWithImplicitReceiver
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
//
|
||||
// ISSUE: KT-28672
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun CharSequence?.isNullOrEmpty(): Boolean {
|
||||
contract {
|
||||
returns(false) implies (this@isNullOrEmpty != null)
|
||||
}
|
||||
|
||||
return this == null || this.length == 0
|
||||
}
|
||||
|
||||
fun smartcastOnReceiver(s: String?) {
|
||||
with(s) {
|
||||
if (isNullOrEmpty()) {
|
||||
length
|
||||
}
|
||||
else {
|
||||
length
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun mixedReceiver(s: String?) {
|
||||
if (!s.isNullOrEmpty()) {
|
||||
with(s) {
|
||||
length
|
||||
}
|
||||
} else {
|
||||
with(s) {
|
||||
length
|
||||
}
|
||||
}
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
// !WITH_NEW_INFERENCE
|
||||
|
||||
import kotlin.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))) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
y.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
y.<!AMBIGUITY!>inc<!>()
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
y.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
y.<!AMBIGUITY!>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)) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!AMBIGUITY!>inc<!>()
|
||||
y.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
y.<!AMBIGUITY!>inc<!>()
|
||||
}
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!AMBIGUITY!>inc<!>()
|
||||
y.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
y.<!AMBIGUITY!>inc<!>()
|
||||
}
|
||||
|
||||
Vendored
+45
@@ -0,0 +1,45 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
// !WITH_NEW_INFERENCE
|
||||
|
||||
import kotlin.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))) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!AMBIGUITY!>inc<!>()
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!AMBIGUITY!>inc<!>()
|
||||
}
|
||||
}
|
||||
|
||||
fun testDeMorgan2(x: Any?) {
|
||||
// x !is String || x !is Int
|
||||
if (notIsString(x) || notIsInt(x)) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!AMBIGUITY!>inc<!>()
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!AMBIGUITY!>inc<!>()
|
||||
}
|
||||
}
|
||||
Vendored
+87
@@ -0,0 +1,87 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.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)) {
|
||||
x.<!UNRESOLVED_REFERENCE!>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 {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun useTrueAndFalseInTrueBranch(x: Any?) {
|
||||
if (trueAndFalse(x is String)) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun useTrueAndFalseInFalseBranch(x: Any?) {
|
||||
if (trueAndFalse(x !is String)) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect +UseCallsInPlaceEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun callsAndInverts(b: Boolean, block: () -> Unit): Boolean {
|
||||
contract {
|
||||
<!INAPPLICABLE_CANDIDATE!>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)
|
||||
x.<!UNRESOLVED_REFERENCE!>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(y)
|
||||
x.<!UNRESOLVED_REFERENCE!>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 }) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
println(y)
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
println(y)
|
||||
}
|
||||
|
||||
fun isPresenceOfLazy3(x: Any?, unknownBoolean: Boolean) {
|
||||
val y: Int
|
||||
if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
println(y)
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
// !WITH_NEW_INFERENCE
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun nullWhenNull(x: Int?): Int? {
|
||||
contract {
|
||||
returnsNotNull() implies (x != null)
|
||||
}
|
||||
return x?.inc()
|
||||
}
|
||||
|
||||
fun testNullWhenNull(x: Int?) {
|
||||
if (nullWhenNull(x) == null) {
|
||||
x.<!AMBIGUITY!>dec<!>()
|
||||
}
|
||||
else {
|
||||
x.<!AMBIGUITY!>dec<!>()
|
||||
}
|
||||
|
||||
if (nullWhenNull(x) != null) {
|
||||
x.<!AMBIGUITY!>dec<!>()
|
||||
}
|
||||
else {
|
||||
x.<!AMBIGUITY!>dec<!>()
|
||||
}
|
||||
|
||||
x.<!AMBIGUITY!>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) {
|
||||
x == null
|
||||
}
|
||||
else {
|
||||
x.<!AMBIGUITY!>dec<!>()
|
||||
}
|
||||
|
||||
if (notNullWhenNotNull(x) != null) {
|
||||
x.<!AMBIGUITY!>dec<!>()
|
||||
}
|
||||
else {
|
||||
x == null
|
||||
}
|
||||
|
||||
x.<!AMBIGUITY!>dec<!>()
|
||||
}
|
||||
compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/andOperator.fir.kt
Vendored
+81
@@ -0,0 +1,81 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
// !WITH_NEW_INFERENCE
|
||||
|
||||
import kotlin.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)) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!AMBIGUITY!>inc<!>()
|
||||
}
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!AMBIGUITY!>inc<!>()
|
||||
}
|
||||
|
||||
fun truefalse(x: Any?) {
|
||||
if (trueWhenString(x) && falseWhenInt(x)) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!AMBIGUITY!>inc<!>()
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!AMBIGUITY!>inc<!>()
|
||||
}
|
||||
}
|
||||
|
||||
fun falsetrue(x: Any?) {
|
||||
if (falseWhenString(x) && trueWhenInt(x)) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!AMBIGUITY!>inc<!>()
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!AMBIGUITY!>inc<!>()
|
||||
}
|
||||
}
|
||||
|
||||
fun falsefalse(x: Any?) {
|
||||
if (falseWhenString(x) && falseWhenInt(x)) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!AMBIGUITY!>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.<!AMBIGUITY!>inc<!>()
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.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) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun annotatedTrueAndFalse(x: Any?) {
|
||||
if (trueWhenString(x) && false) {
|
||||
// Unreachable
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun annotatedFalseAndTrue(x: Any?) {
|
||||
if (falseWhenString(x) && true) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun annotatedFalseAndFalse(x: Any?) {
|
||||
if (falseWhenString(x) && false) {
|
||||
// Unreachable
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.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 {
|
||||
x.<!UNRESOLVED_REFERENCE!>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 {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
// !WITH_NEW_INFERENCE
|
||||
|
||||
import kotlin.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.<!AMBIGUITY!>inc<!>()
|
||||
|
||||
if (myEqualsNull(x)) {
|
||||
x.<!AMBIGUITY!>inc<!>()
|
||||
}
|
||||
else {
|
||||
x.<!AMBIGUITY!>inc<!>()
|
||||
}
|
||||
|
||||
x.<!AMBIGUITY!>inc<!>()
|
||||
}
|
||||
|
||||
fun testBasicNotEquals(x: Int?) {
|
||||
x.<!AMBIGUITY!>inc<!>()
|
||||
|
||||
if (myEqualsNotNull(x)) {
|
||||
x.<!AMBIGUITY!>inc<!>()
|
||||
}
|
||||
else {
|
||||
x.<!AMBIGUITY!>inc<!>()
|
||||
}
|
||||
|
||||
x.<!AMBIGUITY!>inc<!>()
|
||||
}
|
||||
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.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) {
|
||||
x.<!UNRESOLVED_REFERENCE!>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 {
|
||||
x.<!UNRESOLVED_REFERENCE!>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<!>
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.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)) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun testSpilling(x: Any?) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
|
||||
if (isString(x)) x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
|
||||
fun testInversion(x: Any?) {
|
||||
if (notIsString(x)) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun testInversionSpilling(x: Any?) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
|
||||
if (notIsString(x)) else x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
|
||||
Vendored
+78
@@ -0,0 +1,78 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
// !WITH_NEW_INFERENCE
|
||||
|
||||
import kotlin.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.<!AMBIGUITY!>inc<!>()
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!AMBIGUITY!>inc<!>()
|
||||
}
|
||||
}
|
||||
|
||||
fun truefalse(x: Any?) {
|
||||
if (trueWhenString(x) || falseWhenInt(x)) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!AMBIGUITY!>inc<!>()
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!AMBIGUITY!>inc<!>()
|
||||
}
|
||||
}
|
||||
|
||||
fun falsetrue(x: Any?) {
|
||||
if (falseWhenString(x) || trueWhenInt(x)) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!AMBIGUITY!>inc<!>()
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!AMBIGUITY!>inc<!>()
|
||||
}
|
||||
}
|
||||
|
||||
fun falsefalse(x: Any?) {
|
||||
if (falseWhenString(x) || falseWhenInt(x)) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!AMBIGUITY!>inc<!>()
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!AMBIGUITY!>inc<!>()
|
||||
}
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.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) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun annotatedFalseOrTrue(x: Any?) {
|
||||
if (falseWhenString(x) || true) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
// Unreachable
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun annotatedFalseOrFalse(x: Any?) {
|
||||
if (falseWhenString(x) || false) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.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 {
|
||||
x.<!UNRESOLVED_REFERENCE!>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 {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun isString(x: Any?): Boolean {
|
||||
contract {
|
||||
returns(true) implies (x is String)
|
||||
}
|
||||
return x is String
|
||||
}
|
||||
|
||||
fun incorrectPartDoesntMatter(x: Any?) {
|
||||
if (isString(x) && 1) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
// !WITH_NEW_INFERENCE
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun Any?.isNull(): Boolean {
|
||||
contract {
|
||||
returns(false) implies (this@isNull != null)
|
||||
}
|
||||
return this == null
|
||||
}
|
||||
|
||||
fun smartcastOnReceiver(x: Int?) {
|
||||
if (x.isNull()) {
|
||||
x.<!AMBIGUITY!>inc<!>()
|
||||
}
|
||||
else {
|
||||
x.<!AMBIGUITY!>dec<!>()
|
||||
}
|
||||
}
|
||||
|
||||
class UnstableReceiver {
|
||||
var x: Int? = 42
|
||||
|
||||
fun smartcastOnUnstableReceiver() {
|
||||
if (x.isNull()) {
|
||||
x.<!AMBIGUITY!>inc<!>()
|
||||
}
|
||||
else {
|
||||
x.<!AMBIGUITY!>dec<!>()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun Any.nullWhenString(): Any? {
|
||||
contract {
|
||||
returns(null) implies (this@nullWhenString is String)
|
||||
}
|
||||
return if (this is String) null else this
|
||||
}
|
||||
|
||||
fun test(x: Int?) {
|
||||
if (x?.nullWhenString() == null) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun myAssert(condition: Boolean) {
|
||||
contract {
|
||||
returns() implies (condition)
|
||||
}
|
||||
if (!condition) throw kotlin.<!UNRESOLVED_REFERENCE!>IllegalArgumentException<!>("Assertion failed")
|
||||
}
|
||||
|
||||
fun testAssertSmartcast(x: Any?) {
|
||||
myAssert(x is String)
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
|
||||
fun testInvertedAssert(x: Any?) {
|
||||
myAssert(x !is String)
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
|
||||
fun testSpilling(x: Any?) {
|
||||
if (x != null) {
|
||||
myAssert(x is String)
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
|
||||
fun testAssertInIf(x: Any?) {
|
||||
if (myAssert(x is String) == Unit) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun testTryCatch(x: Any?) {
|
||||
try {
|
||||
myAssert(x is String)
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
} catch (e: kotlin.IllegalArgumentException) {
|
||||
|
||||
}
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
|
||||
fun testUncertainFlow(x: Any?) {
|
||||
repeat(x.toString().length) {
|
||||
myAssert(x is String)
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
|
||||
fun testAtLeastOnceFlow(x: Any?) {
|
||||
do {
|
||||
myAssert(x is String)
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
} while (x != null)
|
||||
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.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) {
|
||||
x.<!UNRESOLVED_REFERENCE!>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 {
|
||||
x.<!UNRESOLVED_REFERENCE!>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
+32
@@ -0,0 +1,32 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.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)) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
else {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun implicitAlwaysFalseSpilling(x: Any?) {
|
||||
if (isString(x) && !isString(x)) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun f3(value: String?) {
|
||||
if (!value.isNullOrEmpty() is Boolean) {
|
||||
value.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.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 -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
false -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
|
||||
when(!isString(x)) {
|
||||
true -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
false -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun smartcastInElse(x: Any?) {
|
||||
when (isString(x)) {
|
||||
false -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
else -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
|
||||
when (!isString(x)) {
|
||||
true -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
else -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.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 -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
else -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
|
||||
when (safeIsString(x)) {
|
||||
true -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
false -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
else -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
|
||||
when (safeIsString(x)) {
|
||||
true -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
null -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
else -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun exhaustiveWithNullableResult(x: Any?) {
|
||||
when (safeIsString(x)) {
|
||||
true -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
false -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
null -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
|
||||
when (safeIsString(x)) {
|
||||
false -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
true -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
null -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
|
||||
when (safeIsString(x)) {
|
||||
false -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
null -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
true -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
Vendored
+31
@@ -0,0 +1,31 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun isString(x: Any?): Boolean {
|
||||
contract {
|
||||
returns(true) implies (x is String)
|
||||
}
|
||||
return x is String
|
||||
}
|
||||
|
||||
fun exhaustive(x: Any?) {
|
||||
when {
|
||||
isString(x) -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
!isString(x) -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
|
||||
when {
|
||||
!isString(x) -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
isString(x) -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun smartcastInElse(x: Any?) {
|
||||
when {
|
||||
!isString(x) -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
else -> x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user