Forbid val field initialization inside EXACLTY_ONCE lambda
unless the lambda is inline. This way, final field will remain final.
This commit is contained in:
@@ -1,26 +0,0 @@
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// IGNORE_BACKEND: NATIVE
|
||||
// WITH_RUNTIME
|
||||
// IGNORE_LIGHT_ANALYSIS
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun runOnce(action: () -> Unit) {
|
||||
contract {
|
||||
callsInPlace(action, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
action()
|
||||
}
|
||||
|
||||
class Foo {
|
||||
val res: String
|
||||
init {
|
||||
runOnce {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
return Foo().res
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseCallsInPlaceEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.internal.ContractsDsl
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
@kotlin.contracts.ExperimentalContracts
|
||||
inline fun inlineMe(block: () -> Unit) {
|
||||
contract {
|
||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
block()
|
||||
}
|
||||
|
||||
@kotlin.contracts.ExperimentalContracts
|
||||
inline fun crossinlineMe(crossinline block: () -> Unit) {
|
||||
contract {
|
||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
block()
|
||||
}
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
@kotlin.contracts.ExperimentalContracts
|
||||
inline fun noinlineMe(noinline block: () -> Unit) {
|
||||
contract {
|
||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
block()
|
||||
}
|
||||
|
||||
@kotlin.contracts.ExperimentalContracts
|
||||
fun notinline(block: () -> Unit) {
|
||||
contract {
|
||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
block()
|
||||
}
|
||||
|
||||
@kotlin.contracts.ExperimentalContracts
|
||||
class Test {
|
||||
val a: String
|
||||
val b: String
|
||||
val c: String
|
||||
val d: String
|
||||
|
||||
init {
|
||||
inlineMe {
|
||||
a = "allowed"
|
||||
}
|
||||
crossinlineMe {
|
||||
b = "not allowed"
|
||||
}
|
||||
noinlineMe {
|
||||
c = "not allowed"
|
||||
}
|
||||
notinline {
|
||||
d = "not allowed"
|
||||
}
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseCallsInPlaceEffect
|
||||
// !USE_EXPERIMENTAL: kotlin.internal.ContractsDsl
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
@kotlin.contracts.ExperimentalContracts
|
||||
inline fun inlineMe(block: () -> Unit) {
|
||||
contract {
|
||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
block()
|
||||
}
|
||||
|
||||
@kotlin.contracts.ExperimentalContracts
|
||||
inline fun crossinlineMe(crossinline block: () -> Unit) {
|
||||
contract {
|
||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
block()
|
||||
}
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
@kotlin.contracts.ExperimentalContracts
|
||||
inline fun noinlineMe(noinline block: () -> Unit) {
|
||||
contract {
|
||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
block()
|
||||
}
|
||||
|
||||
@kotlin.contracts.ExperimentalContracts
|
||||
fun notinline(block: () -> Unit) {
|
||||
contract {
|
||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
block()
|
||||
}
|
||||
|
||||
@kotlin.contracts.ExperimentalContracts
|
||||
class Test {
|
||||
val a: String
|
||||
val b: String
|
||||
val c: String
|
||||
val d: String
|
||||
|
||||
init {
|
||||
inlineMe {
|
||||
a = "allowed"
|
||||
}
|
||||
crossinlineMe {
|
||||
<!CAPTURED_VAL_INITIALIZATION!>b<!> = "not allowed"
|
||||
}
|
||||
noinlineMe {
|
||||
<!CAPTURED_VAL_INITIALIZATION!>c<!> = "not allowed"
|
||||
}
|
||||
notinline {
|
||||
<!CAPTURED_VAL_INITIALIZATION!>d<!> = "not allowed"
|
||||
}
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package
|
||||
|
||||
@kotlin.contracts.ExperimentalContracts public inline fun crossinlineMe(/*0*/ crossinline block: () -> kotlin.Unit): kotlin.Unit
|
||||
CallsInPlace(block, EXACTLY_ONCE)
|
||||
|
||||
@kotlin.contracts.ExperimentalContracts public inline fun inlineMe(/*0*/ block: () -> kotlin.Unit): kotlin.Unit
|
||||
CallsInPlace(block, EXACTLY_ONCE)
|
||||
|
||||
@kotlin.Suppress(names = {"NOTHING_TO_INLINE"}) @kotlin.contracts.ExperimentalContracts public inline fun noinlineMe(/*0*/ noinline block: () -> kotlin.Unit): kotlin.Unit
|
||||
CallsInPlace(block, EXACTLY_ONCE)
|
||||
|
||||
@kotlin.contracts.ExperimentalContracts public fun notinline(/*0*/ block: () -> kotlin.Unit): kotlin.Unit
|
||||
CallsInPlace(block, EXACTLY_ONCE)
|
||||
|
||||
@kotlin.contracts.ExperimentalContracts public final class Test {
|
||||
public constructor Test()
|
||||
public final val a: kotlin.String
|
||||
public final val b: kotlin.String
|
||||
public final val c: kotlin.String
|
||||
public final val d: kotlin.String
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
+1
-1
@@ -86,7 +86,7 @@ class DefiniteInitializationInInitSection {
|
||||
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val y: Int<!>
|
||||
|
||||
init {
|
||||
myRun { x = 42 }
|
||||
myRun { <!CAPTURED_VAL_INITIALIZATION!>x<!> = 42 }
|
||||
unknownRun { <!CAPTURED_MEMBER_VAL_INITIALIZATION!>y<!> = 239 }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user