[FIR] Implement checks for contract not allowed

^KT-55423 Fixed
This commit is contained in:
Kirill Rakhman
2023-02-08 12:03:36 +01:00
committed by Space Team
parent b2fbf8bed5
commit f946ddeb40
50 changed files with 377 additions and 178 deletions
@@ -10,19 +10,19 @@ 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) }
<!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
}
open fun openMemeber(x: Boolean) {
contract { returns() implies (x) }
<!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
}
suspend fun suspendMember(x: Boolean) {
contract { returns() implies (x) }
}
@@ -44,43 +44,43 @@ suspend fun suspendTopLevel(x: Boolean) {
// Top-level operator
operator fun Boolean.plus(x: Boolean): Boolean {
contract { returns() implies (x) }
<!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
return x
}
val topLevelLambda: (Boolean) -> Unit = { x: Boolean ->
contract { returns() implies (x) }
<!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
}
val topLevelAnonymousFunction = fun (x: Boolean) {
contract { returns() implies (x) }
<!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
}
var topLevelPropertyAccessors: Int? = <!PROPERTY_INITIALIZER_NO_BACKING_FIELD!>42<!>
get() {
contract { <!ERROR_IN_CONTRACT_DESCRIPTION!>returns() implies (<!UNRESOLVED_REFERENCE!>field<!> != null)<!> }
<!CONTRACT_NOT_ALLOWED!>contract<!> { <!ERROR_IN_CONTRACT_DESCRIPTION!>returns() implies (<!UNRESOLVED_REFERENCE!>field<!> != null)<!> }
return 42
}
set(value) {
contract { <!ERROR_IN_CONTRACT_DESCRIPTION!>returns() implies (<!UNRESOLVED_REFERENCE!>field<!> != null)<!> }
<!CONTRACT_NOT_ALLOWED!>contract<!> { <!ERROR_IN_CONTRACT_DESCRIPTION!>returns() implies (<!UNRESOLVED_REFERENCE!>field<!> != null)<!> }
}
// ============= Local =====================
fun test() {
fun localDeclaration(x: Boolean) {
contract { returns() implies (x) }
<!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
}
suspend fun suspendlocalDeclaration(x: Boolean) {
contract { returns() implies (x) }
<!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
}
val localAnonymousFunction = fun (x: Boolean) {
contract { returns() implies (x) }
<!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
}
val localLambda: (Boolean) -> Unit = { x: Boolean ->
contract { returns() implies (x) }
<!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
}
}
@@ -10,19 +10,19 @@ open class Class {
fun member(x: Boolean) {
<!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
}
inline fun inlineMember(x: Boolean) {
<!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
}
abstract fun abstractMember(x: Boolean) {
<!CONTRACT_NOT_ALLOWED, CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
}
open fun openMemeber(x: Boolean) {
<!CONTRACT_NOT_ALLOWED, CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
}
suspend fun suspendMember(x: Boolean) {
<!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
}
@@ -83,4 +83,4 @@ fun test() {
val localLambda: (Boolean) -> Unit = { x: Boolean ->
<!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
}
}
}
@@ -7,6 +7,11 @@ import kotlin.contracts.*
// ============= Class =====================
open class Class {
constructor(f: () -> Unit = {}) {
contract { callsInPlace(f, InvocationKind.EXACTLY_ONCE) }
f()
}
fun member(x: Boolean) {
contract { returns() implies (x) }
}
@@ -16,11 +21,11 @@ open class Class {
}
abstract fun abstractMember(x: Boolean) {
contract { returns() implies (x) }
<!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
}
open fun openMemeber(x: Boolean) {
contract { returns() implies (x) }
<!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
}
suspend fun suspendMember(x: Boolean) {
@@ -30,17 +35,17 @@ open class Class {
open class Inheritor : Class() {
override fun openMemeber(x: Boolean) {
contract { returns() implies (x) }
<!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
}
final override fun abstractMember(x: Boolean) {
contract { returns() implies (x) }
<!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
}
}
interface Interface {
fun implicitlyOpenMember(x: Boolean) {
contract { returns() implies (x) }
<!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
}
}
@@ -59,43 +64,43 @@ suspend fun suspendTopLevel(x: Boolean) {
// Top-level operator
operator fun Boolean.plus(x: Boolean): Boolean {
contract { returns() implies (x) }
<!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
return x
}
val topLevelLambda: (Boolean) -> Unit = { x: Boolean ->
contract { returns() implies (x) }
<!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
}
val topLevelAnonymousFunction = fun (x: Boolean) {
contract { returns() implies (x) }
<!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
}
var topLevelPropertyAccessors: Int? = <!PROPERTY_INITIALIZER_NO_BACKING_FIELD!>42<!>
get() {
contract { <!ERROR_IN_CONTRACT_DESCRIPTION!>returns() implies (<!UNRESOLVED_REFERENCE!>field<!> != null)<!> }
<!CONTRACT_NOT_ALLOWED!>contract<!> { <!ERROR_IN_CONTRACT_DESCRIPTION!>returns() implies (<!UNRESOLVED_REFERENCE!>field<!> != null)<!> }
return 42
}
set(value) {
contract { <!ERROR_IN_CONTRACT_DESCRIPTION!>returns() implies (<!UNRESOLVED_REFERENCE!>field<!> != null)<!> }
<!CONTRACT_NOT_ALLOWED!>contract<!> { <!ERROR_IN_CONTRACT_DESCRIPTION!>returns() implies (<!UNRESOLVED_REFERENCE!>field<!> != null)<!> }
}
// ============= Local =====================
fun test() {
fun localDeclaration(x: Boolean) {
contract { returns() implies (x) }
<!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
}
suspend fun suspendlocalDeclaration(x: Boolean) {
contract { returns() implies (x) }
<!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
}
val localAnonymousFunction = fun (x: Boolean) {
contract { returns() implies (x) }
<!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
}
val localLambda: (Boolean) -> Unit = { x: Boolean ->
contract { returns() implies (x) }
<!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
}
}
@@ -7,6 +7,11 @@ import kotlin.contracts.*
// ============= Class =====================
open class Class {
constructor(f: () -> Unit = {}) {
contract { callsInPlace(f, InvocationKind.EXACTLY_ONCE) }
f()
}
fun member(x: Boolean) {
contract { returns() implies (x) }
}
@@ -16,7 +16,7 @@ public fun topLevel(/*0*/ x: kotlin.Boolean): kotlin.Unit
public operator fun kotlin.Boolean.plus(/*0*/ x: kotlin.Boolean): kotlin.Boolean
public open class Class {
public constructor Class()
public constructor Class(/*0*/ f: () -> kotlin.Unit = ...)
public abstract fun abstractMember(/*0*/ x: kotlin.Boolean): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
@@ -7,30 +7,30 @@ import kotlin.contracts.*
fun foo(y: Boolean) {
val x: Int = 42
contract {
<!CONTRACT_NOT_ALLOWED("Contract should be the first statement")!>contract<!> {
returns() implies y
}
}
inline fun case1(block: () -> Unit) {
val contracts = listOf(
contract {
<!CONTRACT_NOT_ALLOWED!>contract<!> {
callsInPlace(<!USAGE_IS_NOT_INLINABLE!>block<!>, InvocationKind.EXACTLY_ONCE)
}, contract {
}, <!CONTRACT_NOT_ALLOWED!>contract<!> {
callsInPlace(<!USAGE_IS_NOT_INLINABLE!>block<!>, InvocationKind.EXACTLY_ONCE)
}
)
block()
}
inline fun case_2(block: () -> Unit) = contract {
inline fun case_2(block: () -> Unit) = <!CONTRACT_NOT_ALLOWED("Contracts are only allowed in function body blocks")!>contract<!> {
callsInPlace(<!USAGE_IS_NOT_INLINABLE!>block<!>, InvocationKind.EXACTLY_ONCE)
}
fun case_3(block: () -> Unit) {
class Class {
fun innerFun(block2: () -> Unit) {
contract {
<!CONTRACT_NOT_ALLOWED("Contracts are not allowed for local functions")!>contract<!> {
callsInPlace(block2, InvocationKind.EXACTLY_ONCE)
}
block2()
@@ -41,7 +41,7 @@ fun case_3(block: () -> Unit) {
inline fun case_4(number: Int?): Boolean {
val cond = number != null
contract {
<!CONTRACT_NOT_ALLOWED!>contract<!> {
returns(false) implies (cond)
} as ContractBuilder
return number == null
@@ -49,8 +49,8 @@ inline fun case_4(number: Int?): Boolean {
inline fun case_5(cond: Boolean): Boolean {
run {
contract {
returns(true) implies (cond)
<!CONTRACT_NOT_ALLOWED!>contract<!> {
<!ERROR_IN_CONTRACT_DESCRIPTION!>returns(true) implies (cond)<!>
}
}
return true
@@ -59,7 +59,7 @@ inline fun case_5(cond: Boolean): Boolean {
inline fun case_6(cond: Boolean): Boolean {
run {
val x = 10
contract {
<!CONTRACT_NOT_ALLOWED!>contract<!> {
returns(true) implies (cond)
}
}
@@ -68,8 +68,8 @@ inline fun case_6(cond: Boolean): Boolean {
fun case_7(cond: Boolean): Boolean {
fun innerFun() {
contract {
returns(true) implies (cond)
<!CONTRACT_NOT_ALLOWED!>contract<!> {
<!ERROR_IN_CONTRACT_DESCRIPTION!>returns(true) implies (cond)<!>
}
}
return true
@@ -4,13 +4,13 @@ import kotlin.contracts.*
class A {
var x: Int = 0
get() = f(x)
set(value) contract [returns() implies (value != null)] {
set(value) contract <!CONTRACT_NOT_ALLOWED!>[returns() implies (value != null)]<!> {
field = value + 1
}
var y: Double = 0.0
get() = g(y)
set(value) contract [returns() implies (value != null)] {
set(value) contract <!CONTRACT_NOT_ALLOWED!>[returns() implies (value != null)]<!> {
field = value * 2
}