[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
@@ -3678,6 +3678,13 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token, token,
) )
} }
add(FirErrors.CONTRACT_NOT_ALLOWED) { firDiagnostic ->
ContractNotAllowedImpl(
firDiagnostic.a,
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirErrors.NO_GET_METHOD) { firDiagnostic -> add(FirErrors.NO_GET_METHOD) { firDiagnostic ->
NoGetMethodImpl( NoGetMethodImpl(
firDiagnostic as KtPsiDiagnostic, firDiagnostic as KtPsiDiagnostic,
@@ -2567,6 +2567,11 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
abstract val reason: String abstract val reason: String
} }
abstract class ContractNotAllowed : KtFirDiagnostic<KtElement>() {
override val diagnosticClass get() = ContractNotAllowed::class
abstract val reason: String
}
abstract class NoGetMethod : KtFirDiagnostic<KtArrayAccessExpression>() { abstract class NoGetMethod : KtFirDiagnostic<KtArrayAccessExpression>() {
override val diagnosticClass get() = NoGetMethod::class override val diagnosticClass get() = NoGetMethod::class
} }
@@ -3096,6 +3096,12 @@ internal class ErrorInContractDescriptionImpl(
override val token: KtLifetimeToken, override val token: KtLifetimeToken,
) : KtFirDiagnostic.ErrorInContractDescription(), KtAbstractFirDiagnostic<KtElement> ) : KtFirDiagnostic.ErrorInContractDescription(), KtAbstractFirDiagnostic<KtElement>
internal class ContractNotAllowedImpl(
override val reason: String,
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
) : KtFirDiagnostic.ContractNotAllowed(), KtAbstractFirDiagnostic<KtElement>
internal class NoGetMethodImpl( internal class NoGetMethodImpl(
override val firDiagnostic: KtPsiDiagnostic, override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken, override val token: KtLifetimeToken,
@@ -107,6 +107,7 @@ internal object FirLazyBodiesCalculator {
constructor.apply { constructor.apply {
replaceBody(newConstructor.body) replaceBody(newConstructor.body)
replaceContractDescription(newConstructor.contractDescription)
replaceDelegatedConstructor(newConstructor.delegatedConstructor) replaceDelegatedConstructor(newConstructor.delegatedConstructor)
replaceValueParameterDefaultValues(valueParameters, newConstructor.valueParameters) replaceValueParameterDefaultValues(valueParameters, newConstructor.valueParameters)
} }
@@ -10,7 +10,7 @@ inline fun <reified T> requreIsInstance(value: Any) contract <!UNSUPPORTED_FEATU
} }
val Any?.myLength: Int? val Any?.myLength: Int?
get() contract <!UNSUPPORTED_FEATURE!>[ get() contract <!CONTRACT_NOT_ALLOWED, UNSUPPORTED_FEATURE!>[
<!ERROR_IN_CONTRACT_DESCRIPTION!>returnsNotNull() implies (this@length is String)<!> <!ERROR_IN_CONTRACT_DESCRIPTION!>returnsNotNull() implies (this@length is String)<!>
]<!> = (this as? String)?.length ]<!> = (this as? String)?.length
@@ -12,8 +12,8 @@ fun Any?.isNotNull(): Boolean {
@OptIn(ExperimentalContracts::class) @OptIn(ExperimentalContracts::class)
val Any?.isNotNull: Boolean val Any?.isNotNull: Boolean
get() { get() {
contract { <!CONTRACT_NOT_ALLOWED!>contract<!> {
returns(true) implies (this@isNotNull != null) returns(true) implies (this@isNotNull != null)
} }
return this@isNotNull != null return this@isNotNull != null
} }
@@ -7,13 +7,13 @@ interface A {
@OptIn(ExperimentalContracts::class) @OptIn(ExperimentalContracts::class)
var Any?.isNotNull: Boolean var Any?.isNotNull: Boolean
get() { get() {
contract { <!CONTRACT_NOT_ALLOWED!>contract<!> {
returns(true) implies (this@isNotNull != null) returns(true) implies (this@isNotNull != null)
} }
return this != null return this != null
} }
set(value) { set(value) {
<!WRONG_IMPLIES_CONDITION!>contract { <!WRONG_IMPLIES_CONDITION!><!CONTRACT_NOT_ALLOWED!>contract<!> {
returns() implies (this@isNotNull != null) returns() implies (this@isNotNull != null)
<!ERROR_IN_CONTRACT_DESCRIPTION!>require(<!SENSELESS_COMPARISON!>this != null<!>)<!> <!ERROR_IN_CONTRACT_DESCRIPTION!>require(<!SENSELESS_COMPARISON!>this != null<!>)<!>
}<!> }<!>
@@ -1272,6 +1272,9 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
val ERROR_IN_CONTRACT_DESCRIPTION by error<KtElement>(PositioningStrategy.SELECTOR_BY_QUALIFIED) { val ERROR_IN_CONTRACT_DESCRIPTION by error<KtElement>(PositioningStrategy.SELECTOR_BY_QUALIFIED) {
parameter<String>("reason") parameter<String>("reason")
} }
val CONTRACT_NOT_ALLOWED by error<KtElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED) {
parameter<String>("reason")
}
} }
val CONVENTIONS by object : DiagnosticGroup("Conventions") { val CONVENTIONS by object : DiagnosticGroup("Conventions") {
@@ -668,6 +668,7 @@ object FirErrors {
// Function contracts // Function contracts
val ERROR_IN_CONTRACT_DESCRIPTION by error1<KtElement, String>(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED) val ERROR_IN_CONTRACT_DESCRIPTION by error1<KtElement, String>(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED)
val CONTRACT_NOT_ALLOWED by error1<KtElement, String>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
// Conventions // Conventions
val NO_GET_METHOD by error0<KtArrayAccessExpression>(SourceElementPositioningStrategies.ARRAY_ACCESS) val NO_GET_METHOD by error0<KtArrayAccessExpression>(SourceElementPositioningStrategies.ARRAY_ACCESS)
@@ -64,6 +64,7 @@ object CommonExpressionCheckers : ExpressionCheckers() {
FirAssignmentOperatorCallChecker, FirAssignmentOperatorCallChecker,
FirNamedVarargChecker, FirNamedVarargChecker,
FirUnderscoredTypeArgumentSyntaxChecker, FirUnderscoredTypeArgumentSyntaxChecker,
FirContractNotFirstStatementChecker,
) )
override val propertyAccessExpressionCheckers: Set<FirPropertyAccessExpressionChecker> override val propertyAccessExpressionCheckers: Set<FirPropertyAccessExpressionChecker>
@@ -6,27 +6,38 @@
package org.jetbrains.kotlin.fir.analysis.checkers.declaration package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.KtFakeSourceElementKind import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.KtRealSourceElementKind
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.diagnostics.reportOn import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.contracts.FirResolvedContractDescription import org.jetbrains.kotlin.fir.contracts.FirResolvedContractDescription
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
import org.jetbrains.kotlin.fir.declarations.FirContractDescriptionOwner import org.jetbrains.kotlin.fir.declarations.FirContractDescriptionOwner
import org.jetbrains.kotlin.fir.declarations.FirFunction import org.jetbrains.kotlin.fir.declarations.FirFunction
import org.jetbrains.kotlin.fir.declarations.FirPropertyAccessor
import org.jetbrains.kotlin.fir.declarations.utils.*
object FirContractChecker : FirFunctionChecker() { object FirContractChecker : FirFunctionChecker() {
// TODO: The message should vary. Migrate this to [ConeEffectExtractor] when creating fine-grained errors. // TODO: The message should vary. Migrate this to [ConeEffectExtractor] when creating fine-grained errors.
private const val UNEXPECTED_CONSTRUCTION = "unexpected construction in contract description" private const val UNEXPECTED_CONSTRUCTION = "unexpected construction in contract description"
override fun check(declaration: FirFunction, context: CheckerContext, reporter: DiagnosticReporter) { override fun check(declaration: FirFunction, context: CheckerContext, reporter: DiagnosticReporter) {
if (declaration !is FirContractDescriptionOwner || if (declaration !is FirContractDescriptionOwner) return
declaration.contractDescription !is FirResolvedContractDescription val contractDescription = declaration.contractDescription as? FirResolvedContractDescription ?: return
) {
return
}
checkUnresolvedEffects(contractDescription, context, reporter)
checkContractNotAllowed(declaration, contractDescription, context, reporter)
}
private fun checkUnresolvedEffects(
contractDescription: FirResolvedContractDescription,
context: CheckerContext,
reporter: DiagnosticReporter
) {
// Any statements that [ConeEffectExtractor] cannot extract effects will be in `unresolvedEffects`. // Any statements that [ConeEffectExtractor] cannot extract effects will be in `unresolvedEffects`.
for (unresolvedEffect in (declaration.contractDescription as FirResolvedContractDescription).unresolvedEffects) { for (unresolvedEffect in contractDescription.unresolvedEffects) {
val statement = unresolvedEffect.statement val statement = unresolvedEffect.statement
if (statement.source == null || statement.source!!.kind is KtFakeSourceElementKind) continue if (statement.source == null || statement.source!!.kind is KtFakeSourceElementKind) continue
@@ -35,4 +46,22 @@ object FirContractChecker : FirFunctionChecker() {
reporter.reportOn(statement.source, FirErrors.ERROR_IN_CONTRACT_DESCRIPTION, UNEXPECTED_CONSTRUCTION, context) reporter.reportOn(statement.source, FirErrors.ERROR_IN_CONTRACT_DESCRIPTION, UNEXPECTED_CONSTRUCTION, context)
} }
} }
private fun checkContractNotAllowed(
declaration: FirFunction,
contractDescription: FirResolvedContractDescription,
context: CheckerContext,
reporter: DiagnosticReporter
) {
val source = contractDescription.source
if (source?.kind !is KtRealSourceElementKind) return
fun contractNotAllowed(message: String) = reporter.reportOn(source, FirErrors.CONTRACT_NOT_ALLOWED, message, context)
if (declaration is FirPropertyAccessor || declaration is FirAnonymousFunction) contractNotAllowed("Contracts are only allowed for functions")
else if (declaration.isAbstract || declaration.isOpen || declaration.isOverride) contractNotAllowed("Contracts are not allowed for open or override functions")
else if (declaration.isOperator) contractNotAllowed("Contracts are not allowed for operator functions")
else if (declaration.symbol.callableId.isLocal || declaration.visibility == Visibilities.Local) contractNotAllowed("Contracts are not allowed for local functions")
}
} }
@@ -0,0 +1,39 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.checkers.expression
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.FirFunction
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.expressions.impl.FirContractCallBlock
import org.jetbrains.kotlin.fir.expressions.impl.FirSingleExpressionBlock
import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol
import org.jetbrains.kotlin.name.StandardClassIds
object FirContractNotFirstStatementChecker : FirFunctionCallChecker() {
override fun check(expression: FirFunctionCall, context: CheckerContext, reporter: DiagnosticReporter) {
if (StandardClassIds.Callables.contract != expression.toResolvedCallableSymbol()?.callableId) return
val containingDeclaration = context.containingDeclarations.last()
if (!(containingDeclaration is FirFunction && expression.isCorrectlyPlacedIn(containingDeclaration))) {
val message = if (containingDeclaration is FirFunction && containingDeclaration.body is FirSingleExpressionBlock) {
"Contracts are only allowed in function body blocks"
} else {
"Contract should be the first statement"
}
reporter.reportOn(expression.source, FirErrors.CONTRACT_NOT_ALLOWED, message, context)
}
}
private fun FirFunctionCall.isCorrectlyPlacedIn(functionDeclaration: FirFunction): Boolean {
val firstStatement = functionDeclaration.body?.statements?.first()
return firstStatement is FirContractCallBlock && firstStatement.call == this
}
}
@@ -134,6 +134,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONST_VAL_WITHOUT
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONST_VAL_WITH_DELEGATE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONST_VAL_WITH_DELEGATE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONST_VAL_WITH_GETTER import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONST_VAL_WITH_GETTER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONST_VAL_WITH_NON_CONST_INITIALIZER import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONST_VAL_WITH_NON_CONST_INITIALIZER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONTRACT_NOT_ALLOWED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CYCLIC_CONSTRUCTOR_DELEGATION_CALL import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CYCLIC_CONSTRUCTOR_DELEGATION_CALL
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CYCLIC_GENERIC_UPPER_BOUND import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CYCLIC_GENERIC_UPPER_BOUND
@@ -1909,6 +1910,7 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
// Function contracts // Function contracts
map.put(ERROR_IN_CONTRACT_DESCRIPTION, "Error in contract description", TO_STRING) map.put(ERROR_IN_CONTRACT_DESCRIPTION, "Error in contract description", TO_STRING)
map.put(CONTRACT_NOT_ALLOWED, "{0}", TO_STRING)
// Conventions // Conventions
map.put(NO_GET_METHOD, "No get method providing array access") map.put(NO_GET_METHOD, "No get method providing array access")
@@ -10,6 +10,8 @@ import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.fir.FirImplementationDetail import org.jetbrains.kotlin.fir.FirImplementationDetail
import org.jetbrains.kotlin.fir.FirModuleData import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.builder.FirBuilderDsl import org.jetbrains.kotlin.fir.builder.FirBuilderDsl
import org.jetbrains.kotlin.fir.contracts.FirContractDescription
import org.jetbrains.kotlin.fir.contracts.impl.FirEmptyContractDescription
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.FirConstructorBuilder import org.jetbrains.kotlin.fir.declarations.builder.FirConstructorBuilder
import org.jetbrains.kotlin.fir.expressions.FirAnnotation import org.jetbrains.kotlin.fir.expressions.FirAnnotation
@@ -44,6 +46,7 @@ class FirJavaConstructor @FirImplementationDetail constructor(
) : FirConstructor() { ) : FirConstructor() {
override val receiverParameter: FirReceiverParameter? get() = null override val receiverParameter: FirReceiverParameter? get() = null
override var deprecationsProvider: DeprecationsProvider = UnresolvedDeprecationProvider override var deprecationsProvider: DeprecationsProvider = UnresolvedDeprecationProvider
override val contractDescription: FirContractDescription get() = FirEmptyContractDescription
init { init {
symbol.bind(this) symbol.bind(this)
@@ -100,6 +103,10 @@ class FirJavaConstructor @FirImplementationDetail constructor(
return this return this
} }
override fun <D> transformContractDescription(transformer: FirTransformer<D>, data: D): FirConstructor {
return this
}
override fun <D> transformStatus(transformer: FirTransformer<D>, data: D): FirJavaConstructor { override fun <D> transformStatus(transformer: FirTransformer<D>, data: D): FirJavaConstructor {
status = status.transformSingle(transformer, data) status = status.transformSingle(transformer, data)
return this return this
@@ -152,6 +159,9 @@ class FirJavaConstructor @FirImplementationDetail constructor(
} }
override fun replaceControlFlowGraphReference(newControlFlowGraphReference: FirControlFlowGraphReference?) {} override fun replaceControlFlowGraphReference(newControlFlowGraphReference: FirControlFlowGraphReference?) {}
override fun replaceContractDescription(newContractDescription: FirContractDescription) {
error("Contract description cannot be replaced for FirJavaConstructor")
}
override fun replaceBody(newBody: FirBlock?) { override fun replaceBody(newBody: FirBlock?) {
error("Body cannot be replaced for FirJavaConstructor") error("Body cannot be replaced for FirJavaConstructor")
@@ -1045,8 +1045,9 @@ class DeclarationsConverter(
annotations += modifiers.annotations annotations += modifiers.annotations
typeParameters += constructorTypeParametersFromConstructedClass(classWrapper.classBuilder.typeParameters) typeParameters += constructorTypeParametersFromConstructedClass(classWrapper.classBuilder.typeParameters)
valueParameters += firValueParameters.map { it.firValueParameter } valueParameters += firValueParameters.map { it.firValueParameter }
val (body, _) = convertFunctionBody(block, null, allowLegacyContractDescription = true) val (body, contractDescription) = convertFunctionBody(block, null, allowLegacyContractDescription = true)
this.body = body this.body = body
contractDescription?.let { this.contractDescription = it }
context.firFunctionTargets.removeLast() context.firFunctionTargets.removeLast()
this.contextReceivers.addAll(convertContextReceivers(secondaryConstructor.getParent()!!.getParent()!!)) this.contextReceivers.addAll(convertContextReceivers(secondaryConstructor.getParent()!!.getParent()!!))
}.also { }.also {
@@ -1736,14 +1737,15 @@ class DeclarationsConverter(
).map { it.firValueParameter } ).map { it.firValueParameter }
} }
val allowLegacyContractDescription = outerContractDescription == null && !isLocal val allowLegacyContractDescription = outerContractDescription == null
val bodyWithContractDescription = convertFunctionBody(block, expression, allowLegacyContractDescription) val bodyWithContractDescription = convertFunctionBody(block, expression, allowLegacyContractDescription)
this.body = bodyWithContractDescription.first this.body = bodyWithContractDescription.first
val contractDescription = outerContractDescription ?: bodyWithContractDescription.second val contractDescription = outerContractDescription ?: bodyWithContractDescription.second
contractDescription?.let { contractDescription?.let {
// TODO: add error reporting for contracts on lambdas
if (this is FirSimpleFunctionBuilder) { if (this is FirSimpleFunctionBuilder) {
this.contractDescription = it this.contractDescription = it
} else if (this is FirAnonymousFunctionBuilder) {
this.contractDescription = it
} }
} }
} }
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusIm
import org.jetbrains.kotlin.fir.diagnostics.* import org.jetbrains.kotlin.fir.diagnostics.*
import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.* import org.jetbrains.kotlin.fir.expressions.builder.*
import org.jetbrains.kotlin.fir.expressions.impl.FirContractCallBlock
import org.jetbrains.kotlin.fir.expressions.impl.FirSingleExpressionBlock import org.jetbrains.kotlin.fir.expressions.impl.FirSingleExpressionBlock
import org.jetbrains.kotlin.fir.expressions.impl.buildSingleExpressionBlock import org.jetbrains.kotlin.fir.expressions.impl.buildSingleExpressionBlock
import org.jetbrains.kotlin.fir.lightTree.LightTree2Fir import org.jetbrains.kotlin.fir.lightTree.LightTree2Fir
@@ -201,6 +202,13 @@ class ExpressionsConverter(
body = if (block != null) { body = if (block != null) {
declarationsConverter.withOffset(expressionSource.startOffset) { declarationsConverter.withOffset(expressionSource.startOffset) {
declarationsConverter.convertBlockExpressionWithoutBuilding(block!!).apply { declarationsConverter.convertBlockExpressionWithoutBuilding(block!!).apply {
statements.firstOrNull()?.let {
if (it.isContractBlockFirCheck()) {
this@buildAnonymousFunction.contractDescription = it.toLegacyRawContractDescription()
statements[0] = FirContractCallBlock(it)
}
}
if (statements.isEmpty()) { if (statements.isEmpty()) {
statements.add( statements.add(
buildReturnExpression { buildReturnExpression {
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.fir.declarations.utils.*
import org.jetbrains.kotlin.fir.diagnostics.* import org.jetbrains.kotlin.fir.diagnostics.*
import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.* import org.jetbrains.kotlin.fir.expressions.builder.*
import org.jetbrains.kotlin.fir.expressions.impl.FirContractCallBlock
import org.jetbrains.kotlin.fir.expressions.impl.FirSingleExpressionBlock import org.jetbrains.kotlin.fir.expressions.impl.FirSingleExpressionBlock
import org.jetbrains.kotlin.fir.extensions.extensionService import org.jetbrains.kotlin.fir.extensions.extensionService
import org.jetbrains.kotlin.fir.references.builder.* import org.jetbrains.kotlin.fir.references.builder.*
@@ -365,13 +366,13 @@ open class RawFirBuilder(
} }
} }
private fun KtDeclarationWithBody.buildFirBody(allowLegacyContractDescription: Boolean): Pair<FirBlock?, FirContractDescription?> = private fun KtDeclarationWithBody.buildFirBody(): Pair<FirBlock?, FirContractDescription?> =
if (hasBody()) { if (hasBody()) {
buildOrLazyBlock { buildOrLazyBlock {
if (hasBlockBody()) { if (hasBlockBody()) {
val block = bodyBlockExpression?.accept(this@Visitor, Unit) as? FirBlock val block = bodyBlockExpression?.accept(this@Visitor, Unit) as? FirBlock
val contractDescription = when { val contractDescription = when {
allowLegacyContractDescription && !hasContractEffectList() -> block?.let(::processLegacyContractDescription) !hasContractEffectList() -> block?.let(::processLegacyContractDescription)
else -> null else -> null
} }
return@buildFirBody block to contractDescription return@buildFirBody block to contractDescription
@@ -471,9 +472,9 @@ open class RawFirBuilder(
} }
} }
val outerContractDescription = this@toFirPropertyAccessor.obtainContractDescription() val outerContractDescription = this@toFirPropertyAccessor.obtainContractDescription()
val bodyWithContractDescription = this@toFirPropertyAccessor.buildFirBody(allowLegacyContractDescription = true) val (body, innerContractDescription) = this@toFirPropertyAccessor.buildFirBody()
this.body = bodyWithContractDescription.first this.body = body
val contractDescription = outerContractDescription ?: bodyWithContractDescription.second val contractDescription = outerContractDescription ?: innerContractDescription
contractDescription?.let { contractDescription?.let {
this.contractDescription = it this.contractDescription = it
} }
@@ -1484,13 +1485,14 @@ open class RawFirBuilder(
listOf() listOf()
withCapturedTypeParameters(true, functionSource, actualTypeParameters) { withCapturedTypeParameters(true, functionSource, actualTypeParameters) {
val outerContractDescription = function.obtainContractDescription() val outerContractDescription = function.obtainContractDescription()
val bodyWithContractDescription = function.buildFirBody(!isLocalFunction) val (body, innerContractDescription) = function.buildFirBody()
this.body = bodyWithContractDescription.first this.body = body
val contractDescription = outerContractDescription ?: bodyWithContractDescription.second val contractDescription = outerContractDescription ?: innerContractDescription
contractDescription?.let { contractDescription?.let {
// TODO: add error reporting for contracts on lambdas
if (this is FirSimpleFunctionBuilder) { if (this is FirSimpleFunctionBuilder) {
this.contractDescription = it this.contractDescription = it
} else if (this is FirAnonymousFunctionBuilder) {
this.contractDescription = it
} }
} }
} }
@@ -1601,6 +1603,13 @@ open class RawFirBuilder(
FirSingleExpressionBlock(errorExpression.toReturn()) FirSingleExpressionBlock(errorExpression.toReturn())
} else { } else {
configureBlockWithoutBuilding(ktBody).apply { configureBlockWithoutBuilding(ktBody).apply {
statements.firstOrNull()?.let {
if (it.isContractBlockFirCheck()) {
this@buildAnonymousFunction.contractDescription = it.toLegacyRawContractDescription()
statements[0] = FirContractCallBlock(it)
}
}
if (statements.isEmpty()) { if (statements.isEmpty()) {
statements.add( statements.add(
buildReturnExpression { buildReturnExpression {
@@ -1660,7 +1669,8 @@ open class RawFirBuilder(
extractValueParametersTo(this, symbol, ValueParameterDeclaration.FUNCTION) extractValueParametersTo(this, symbol, ValueParameterDeclaration.FUNCTION)
val (body, _) = buildFirBody(allowLegacyContractDescription = true) val (body, contractDescription) = buildFirBody()
contractDescription?.let { this.contractDescription = it }
this.body = body this.body = body
this@RawFirBuilder.context.firFunctionTargets.removeLast() this@RawFirBuilder.context.firFunctionTargets.removeLast()
}.also { }.also {
@@ -2757,7 +2767,7 @@ open class RawFirBuilder(
} }
} }
private fun buildErrorTopLevelDeclarationForDanglingModifierList(modifierList : KtModifierList) = buildDanglingModifierList { private fun buildErrorTopLevelDeclarationForDanglingModifierList(modifierList: KtModifierList) = buildDanglingModifierList {
this.source = modifierList.toFirSourceElement(KtFakeSourceElementKind.DanglingModifierList) this.source = modifierList.toFirSourceElement(KtFakeSourceElementKind.DanglingModifierList)
moduleData = baseModuleData moduleData = baseModuleData
origin = FirDeclarationOrigin.Source origin = FirDeclarationOrigin.Source
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fakeElement import org.jetbrains.kotlin.fakeElement
import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.contracts.FirContractDescription import org.jetbrains.kotlin.fir.contracts.FirContractDescription
import org.jetbrains.kotlin.fir.contracts.FirLegacyRawContractDescription
import org.jetbrains.kotlin.fir.contracts.builder.buildLegacyRawContractDescription import org.jetbrains.kotlin.fir.contracts.builder.buildLegacyRawContractDescription
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
@@ -43,6 +44,8 @@ import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.types.ConstantValueKind import org.jetbrains.kotlin.types.ConstantValueKind
import org.jetbrains.kotlin.types.expressions.OperatorConventions import org.jetbrains.kotlin.types.expressions.OperatorConventions
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
fun String.parseCharacter(): CharacterWithDiagnostic { fun String.parseCharacter(): CharacterWithDiagnostic {
// Strip the quotes // Strip the quotes
@@ -495,18 +498,29 @@ fun <T> FirPropertyBuilder.generateAccessorsByDelegate(
fun processLegacyContractDescription(block: FirBlock): FirContractDescription? { fun processLegacyContractDescription(block: FirBlock): FirContractDescription? {
if (block.isContractPresentFirCheck()) { if (block.isContractPresentFirCheck()) {
val contractCall = block.replaceFirstStatement<FirFunctionCall> { FirContractCallBlock(it) } val contractCall = block.replaceFirstStatement<FirFunctionCall> { FirContractCallBlock(it) }
return buildLegacyRawContractDescription { return contractCall.toLegacyRawContractDescription()
source = contractCall.source
this.contractCall = contractCall
}
} }
return null return null
} }
fun FirFunctionCall.toLegacyRawContractDescription(): FirLegacyRawContractDescription {
return buildLegacyRawContractDescription {
this.source = this@toLegacyRawContractDescription.source
this.contractCall = this@toLegacyRawContractDescription
}
}
fun FirBlock.isContractPresentFirCheck(): Boolean { fun FirBlock.isContractPresentFirCheck(): Boolean {
val firstStatement = statements.firstOrNull() ?: return false val firstStatement = statements.firstOrNull() ?: return false
val contractCall = firstStatement as? FirFunctionCall ?: return false return firstStatement.isContractBlockFirCheck()
}
@OptIn(ExperimentalContracts::class)
fun FirStatement.isContractBlockFirCheck(): Boolean {
contract { returns(true) implies (this@isContractBlockFirCheck is FirFunctionCall) }
val contractCall = this as? FirFunctionCall ?: return false
if (contractCall.calleeReference.name.asString() != "contract") return false if (contractCall.calleeReference.name.asString() != "contract") return false
val receiver = contractCall.explicitReceiver as? FirQualifiedAccessExpression ?: return true val receiver = contractCall.explicitReceiver as? FirQualifiedAccessExpression ?: return true
if (!contractCall.checkReceiver("contracts")) return false if (!contractCall.checkReceiver("contracts")) return false
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.fakeElement import org.jetbrains.kotlin.fakeElement
import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.contracts.impl.FirEmptyContractDescription
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.buildAnonymousFunctionCopy import org.jetbrains.kotlin.fir.declarations.builder.buildAnonymousFunctionCopy
import org.jetbrains.kotlin.fir.declarations.builder.buildContextReceiver import org.jetbrains.kotlin.fir.declarations.builder.buildContextReceiver
@@ -36,6 +37,7 @@ import org.jetbrains.kotlin.fir.resolve.inference.extractLambdaInfoFromFunctionT
import org.jetbrains.kotlin.fir.resolve.substitution.createTypeSubstitutorByTypeConstructor import org.jetbrains.kotlin.fir.resolve.substitution.createTypeSubstitutorByTypeConstructor
import org.jetbrains.kotlin.fir.resolve.transformers.FirCallCompletionResultsWriterTransformer import org.jetbrains.kotlin.fir.resolve.transformers.FirCallCompletionResultsWriterTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.FirStatusResolver import org.jetbrains.kotlin.fir.resolve.transformers.FirStatusResolver
import org.jetbrains.kotlin.fir.resolve.transformers.contracts.runContractResolveForFunction
import org.jetbrains.kotlin.fir.resolve.transformers.transformVarargTypeToArrayType import org.jetbrains.kotlin.fir.resolve.transformers.transformVarargTypeToArrayType
import org.jetbrains.kotlin.fir.scopes.impl.FirMemberTypeParameterScope import org.jetbrains.kotlin.fir.scopes.impl.FirMemberTypeParameterScope
import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol
@@ -590,6 +592,10 @@ open class FirDeclarationsResolveTransformer(
// For class members everything should be already prepared // For class members everything should be already prepared
prepareSignatureForBodyResolve(simpleFunction) prepareSignatureForBodyResolve(simpleFunction)
simpleFunction.transformStatus(this, simpleFunction.resolveStatus().mode()) simpleFunction.transformStatus(this, simpleFunction.resolveStatus().mode())
if (simpleFunction.contractDescription != FirEmptyContractDescription) {
simpleFunction.runContractResolveForFunction(session, scopeSession, context)
}
} }
context.forFunctionBody(simpleFunction, components) { context.forFunctionBody(simpleFunction, components) {
withFullBodyResolve { withFullBodyResolve {
@@ -730,6 +736,11 @@ open class FirDeclarationsResolveTransformer(
anonymousFunction.transformReceiverParameter(transformer, ResolutionMode.ContextIndependent) anonymousFunction.transformReceiverParameter(transformer, ResolutionMode.ContextIndependent)
anonymousFunction.valueParameters.forEach { it.transformReturnTypeRef(transformer, ResolutionMode.ContextIndependent) } anonymousFunction.valueParameters.forEach { it.transformReturnTypeRef(transformer, ResolutionMode.ContextIndependent) }
} }
if (anonymousFunction.contractDescription != FirEmptyContractDescription) {
anonymousFunction.runContractResolveForFunction(session, scopeSession, context)
}
return when (data) { return when (data) {
is ResolutionMode.ContextDependent, is ResolutionMode.ContextDependentDelegate -> { is ResolutionMode.ContextDependent, is ResolutionMode.ContextDependentDelegate -> {
context.storeContextForAnonymousFunction(anonymousFunction) context.storeContextForAnonymousFunction(anonymousFunction)
@@ -18,7 +18,6 @@ import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.buildAnonymousFunction import org.jetbrains.kotlin.fir.declarations.builder.buildAnonymousFunction
import org.jetbrains.kotlin.fir.declarations.builder.buildReceiverParameter import org.jetbrains.kotlin.fir.declarations.builder.buildReceiverParameter
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty
import org.jetbrains.kotlin.fir.errorTypeFromPrototype
import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.* import org.jetbrains.kotlin.fir.expressions.builder.*
import org.jetbrains.kotlin.fir.expressions.impl.FirContractCallBlock import org.jetbrains.kotlin.fir.expressions.impl.FirContractCallBlock
@@ -26,7 +25,6 @@ import org.jetbrains.kotlin.fir.moduleData
import org.jetbrains.kotlin.fir.references.builder.buildSimpleNamedReference import org.jetbrains.kotlin.fir.references.builder.buildSimpleNamedReference
import org.jetbrains.kotlin.fir.resolve.ResolutionMode import org.jetbrains.kotlin.fir.resolve.ResolutionMode
import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeContractDescriptionError
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.BodyResolveContext import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.BodyResolveContext
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirAbstractBodyResolveTransformerDispatcher import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirAbstractBodyResolveTransformerDispatcher
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirDeclarationsResolveTransformer import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirDeclarationsResolveTransformer
@@ -72,19 +70,8 @@ abstract class FirAbstractContractResolveTransformerDispatcher(
simpleFunction: FirSimpleFunction, simpleFunction: FirSimpleFunction,
data: ResolutionMode data: ResolutionMode
): FirSimpleFunction { ): FirSimpleFunction {
if (!simpleFunction.hasContractToResolve) { if (!simpleFunction.hasContractToResolve) return simpleFunction
return simpleFunction
}
val containingDeclaration = context.containerIfAny
if (containingDeclaration != null && containingDeclaration !is FirClass) {
simpleFunction.replaceReturnTypeRef(
simpleFunction.returnTypeRef.errorTypeFromPrototype(
ConeContractDescriptionError("Local function can not be used in contract description")
)
)
return simpleFunction
}
@Suppress("UNCHECKED_CAST")
return context.withSimpleFunction(simpleFunction, session) { return context.withSimpleFunction(simpleFunction, session) {
context.forFunctionBody(simpleFunction, components) { context.forFunctionBody(simpleFunction, components) {
transformContractDescriptionOwner(simpleFunction) transformContractDescriptionOwner(simpleFunction)
@@ -92,6 +79,15 @@ abstract class FirAbstractContractResolveTransformerDispatcher(
} }
} }
override fun transformAnonymousFunction(anonymousFunction: FirAnonymousFunction, data: ResolutionMode): FirAnonymousFunction {
if (!anonymousFunction.hasContractToResolve) return anonymousFunction
return context.forFunctionBody(anonymousFunction, components) {
transformContractDescriptionOwner(anonymousFunction)
}
}
override fun transformScript(script: FirScript, data: ResolutionMode): FirScript { override fun transformScript(script: FirScript, data: ResolutionMode): FirScript {
return script return script
} }
@@ -282,7 +278,14 @@ abstract class FirAbstractContractResolveTransformerDispatcher(
} }
override fun transformConstructor(constructor: FirConstructor, data: ResolutionMode): FirConstructor { override fun transformConstructor(constructor: FirConstructor, data: ResolutionMode): FirConstructor {
return constructor if (!constructor.hasContractToResolve) {
return constructor
}
return context.withConstructor(constructor) {
context.forConstructorBody(constructor, session) {
transformContractDescriptionOwner(constructor)
}
}
} }
override fun transformEnumEntry(enumEntry: FirEnumEntry, data: ResolutionMode): FirEnumEntry { override fun transformEnumEntry(enumEntry: FirEnumEntry, data: ResolutionMode): FirEnumEntry {
@@ -302,15 +305,13 @@ abstract class FirAbstractContractResolveTransformerDispatcher(
private val FirContractDescriptionOwner.valueParameters: List<FirValueParameter> private val FirContractDescriptionOwner.valueParameters: List<FirValueParameter>
get() = when (this) { get() = when (this) {
is FirSimpleFunction -> valueParameters is FirFunction -> valueParameters
is FirPropertyAccessor -> valueParameters
else -> error() else -> error()
} }
private val FirContractDescriptionOwner.body: FirBlock private val FirContractDescriptionOwner.body: FirBlock
get() = when (this) { get() = when (this) {
is FirSimpleFunction -> body!! is FirFunction -> body!!
is FirPropertyAccessor -> body!!
else -> error() else -> error()
} }
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirFunction
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.resolve.ResolutionMode import org.jetbrains.kotlin.fir.resolve.ResolutionMode
import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.ScopeSession
@@ -52,3 +53,13 @@ fun <F : FirClassLikeDeclaration> F.runContractResolveForLocalClass(
return this.transformSingle(transformer, ResolutionMode.ContextIndependent) return this.transformSingle(transformer, ResolutionMode.ContextIndependent)
} }
fun <F : FirFunction> F.runContractResolveForFunction(
session: FirSession,
scopeSession: ScopeSession,
outerBodyResolveContext: BodyResolveContext,
): F {
val transformer = FirContractResolveTransformer(session, scopeSession, outerBodyResolveContext)
return this.transformSingle(transformer, ResolutionMode.ContextIndependent)
}
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirLabel import org.jetbrains.kotlin.fir.FirLabel
import org.jetbrains.kotlin.fir.FirModuleData import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.contracts.FirContractDescription
import org.jetbrains.kotlin.fir.expressions.FirAnnotation import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirBlock import org.jetbrains.kotlin.fir.expressions.FirBlock
import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference
@@ -24,7 +25,7 @@ import org.jetbrains.kotlin.fir.visitors.*
* DO NOT MODIFY IT MANUALLY * DO NOT MODIFY IT MANUALLY
*/ */
abstract class FirAnonymousFunction : FirFunction(), FirTypeParametersOwner { abstract class FirAnonymousFunction : FirFunction(), FirTypeParametersOwner, FirContractDescriptionOwner {
abstract override val source: KtSourceElement? abstract override val source: KtSourceElement?
abstract override val resolvePhase: FirResolvePhase abstract override val resolvePhase: FirResolvePhase
abstract override val annotations: List<FirAnnotation> abstract override val annotations: List<FirAnnotation>
@@ -41,6 +42,7 @@ abstract class FirAnonymousFunction : FirFunction(), FirTypeParametersOwner {
abstract override val controlFlowGraphReference: FirControlFlowGraphReference? abstract override val controlFlowGraphReference: FirControlFlowGraphReference?
abstract override val valueParameters: List<FirValueParameter> abstract override val valueParameters: List<FirValueParameter>
abstract override val body: FirBlock? abstract override val body: FirBlock?
abstract override val contractDescription: FirContractDescription
abstract override val symbol: FirAnonymousFunctionSymbol abstract override val symbol: FirAnonymousFunctionSymbol
abstract val label: FirLabel? abstract val label: FirLabel?
abstract val invocationKind: EventOccurrencesRange? abstract val invocationKind: EventOccurrencesRange?
@@ -76,6 +78,8 @@ abstract class FirAnonymousFunction : FirFunction(), FirTypeParametersOwner {
abstract override fun replaceBody(newBody: FirBlock?) abstract override fun replaceBody(newBody: FirBlock?)
abstract override fun replaceContractDescription(newContractDescription: FirContractDescription)
abstract fun replaceInvocationKind(newInvocationKind: EventOccurrencesRange?) abstract fun replaceInvocationKind(newInvocationKind: EventOccurrencesRange?)
abstract fun replaceInlineStatus(newInlineStatus: InlineStatus) abstract fun replaceInlineStatus(newInlineStatus: InlineStatus)
@@ -94,5 +98,7 @@ abstract class FirAnonymousFunction : FirFunction(), FirTypeParametersOwner {
abstract override fun <D> transformBody(transformer: FirTransformer<D>, data: D): FirAnonymousFunction abstract override fun <D> transformBody(transformer: FirTransformer<D>, data: D): FirAnonymousFunction
abstract override fun <D> transformContractDescription(transformer: FirTransformer<D>, data: D): FirAnonymousFunction
abstract override fun <D> transformTypeParameters(transformer: FirTransformer<D>, data: D): FirAnonymousFunction abstract override fun <D> transformTypeParameters(transformer: FirTransformer<D>, data: D): FirAnonymousFunction
} }
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.declarations
import org.jetbrains.kotlin.KtSourceElement import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirModuleData import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.contracts.FirContractDescription
import org.jetbrains.kotlin.fir.expressions.FirAnnotation import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirBlock import org.jetbrains.kotlin.fir.expressions.FirBlock
import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall
@@ -23,7 +24,7 @@ import org.jetbrains.kotlin.fir.visitors.*
* DO NOT MODIFY IT MANUALLY * DO NOT MODIFY IT MANUALLY
*/ */
abstract class FirConstructor : FirFunction(), FirTypeParameterRefsOwner { abstract class FirConstructor : FirFunction(), FirTypeParameterRefsOwner, FirContractDescriptionOwner {
abstract override val source: KtSourceElement? abstract override val source: KtSourceElement?
abstract override val resolvePhase: FirResolvePhase abstract override val resolvePhase: FirResolvePhase
abstract override val moduleData: FirModuleData abstract override val moduleData: FirModuleData
@@ -39,6 +40,7 @@ abstract class FirConstructor : FirFunction(), FirTypeParameterRefsOwner {
abstract override val contextReceivers: List<FirContextReceiver> abstract override val contextReceivers: List<FirContextReceiver>
abstract override val controlFlowGraphReference: FirControlFlowGraphReference? abstract override val controlFlowGraphReference: FirControlFlowGraphReference?
abstract override val valueParameters: List<FirValueParameter> abstract override val valueParameters: List<FirValueParameter>
abstract override val contractDescription: FirContractDescription
abstract override val annotations: List<FirAnnotation> abstract override val annotations: List<FirAnnotation>
abstract override val symbol: FirConstructorSymbol abstract override val symbol: FirConstructorSymbol
abstract val delegatedConstructor: FirDelegatedConstructorCall? abstract val delegatedConstructor: FirDelegatedConstructorCall?
@@ -67,6 +69,8 @@ abstract class FirConstructor : FirFunction(), FirTypeParameterRefsOwner {
abstract override fun replaceValueParameters(newValueParameters: List<FirValueParameter>) abstract override fun replaceValueParameters(newValueParameters: List<FirValueParameter>)
abstract override fun replaceContractDescription(newContractDescription: FirContractDescription)
abstract override fun replaceAnnotations(newAnnotations: List<FirAnnotation>) abstract override fun replaceAnnotations(newAnnotations: List<FirAnnotation>)
abstract fun replaceDelegatedConstructor(newDelegatedConstructor: FirDelegatedConstructorCall?) abstract fun replaceDelegatedConstructor(newDelegatedConstructor: FirDelegatedConstructorCall?)
@@ -83,6 +87,8 @@ abstract class FirConstructor : FirFunction(), FirTypeParameterRefsOwner {
abstract override fun <D> transformValueParameters(transformer: FirTransformer<D>, data: D): FirConstructor abstract override fun <D> transformValueParameters(transformer: FirTransformer<D>, data: D): FirConstructor
abstract override fun <D> transformContractDescription(transformer: FirTransformer<D>, data: D): FirConstructor
abstract override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirConstructor abstract override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirConstructor
abstract fun <D> transformDelegatedConstructor(transformer: FirTransformer<D>, data: D): FirConstructor abstract fun <D> transformDelegatedConstructor(transformer: FirTransformer<D>, data: D): FirConstructor
@@ -10,6 +10,7 @@ package org.jetbrains.kotlin.fir.declarations.builder
import org.jetbrains.kotlin.KtSourceElement import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.fir.FirModuleData import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.builder.FirBuilderDsl import org.jetbrains.kotlin.fir.builder.FirBuilderDsl
import org.jetbrains.kotlin.fir.contracts.FirContractDescription
import org.jetbrains.kotlin.fir.declarations.DeprecationsProvider import org.jetbrains.kotlin.fir.declarations.DeprecationsProvider
import org.jetbrains.kotlin.fir.declarations.FirConstructor import org.jetbrains.kotlin.fir.declarations.FirConstructor
import org.jetbrains.kotlin.fir.declarations.FirContextReceiver import org.jetbrains.kotlin.fir.declarations.FirContextReceiver
@@ -55,6 +56,7 @@ interface FirAbstractConstructorBuilder : FirFunctionBuilder {
abstract val typeParameters: MutableList<FirTypeParameterRef> abstract val typeParameters: MutableList<FirTypeParameterRef>
abstract var receiverParameter: FirReceiverParameter? abstract var receiverParameter: FirReceiverParameter?
abstract var controlFlowGraphReference: FirControlFlowGraphReference? abstract var controlFlowGraphReference: FirControlFlowGraphReference?
abstract var contractDescription: FirContractDescription
abstract var symbol: FirConstructorSymbol abstract var symbol: FirConstructorSymbol
abstract var delegatedConstructor: FirDelegatedConstructorCall? abstract var delegatedConstructor: FirDelegatedConstructorCall?
override fun build(): FirConstructor override fun build(): FirConstructor
@@ -15,6 +15,8 @@ import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.builder.FirAnnotationContainerBuilder import org.jetbrains.kotlin.fir.builder.FirAnnotationContainerBuilder
import org.jetbrains.kotlin.fir.builder.FirBuilderDsl import org.jetbrains.kotlin.fir.builder.FirBuilderDsl
import org.jetbrains.kotlin.fir.builder.toMutableOrEmpty import org.jetbrains.kotlin.fir.builder.toMutableOrEmpty
import org.jetbrains.kotlin.fir.contracts.FirContractDescription
import org.jetbrains.kotlin.fir.contracts.impl.FirEmptyContractDescription
import org.jetbrains.kotlin.fir.declarations.DeprecationsProvider import org.jetbrains.kotlin.fir.declarations.DeprecationsProvider
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
import org.jetbrains.kotlin.fir.declarations.FirContextReceiver import org.jetbrains.kotlin.fir.declarations.FirContextReceiver
@@ -61,6 +63,7 @@ class FirAnonymousFunctionBuilder : FirFunctionBuilder, FirAnnotationContainerBu
var controlFlowGraphReference: FirControlFlowGraphReference? = null var controlFlowGraphReference: FirControlFlowGraphReference? = null
override val valueParameters: MutableList<FirValueParameter> = mutableListOf() override val valueParameters: MutableList<FirValueParameter> = mutableListOf()
override var body: FirBlock? = null override var body: FirBlock? = null
var contractDescription: FirContractDescription = FirEmptyContractDescription
lateinit var symbol: FirAnonymousFunctionSymbol lateinit var symbol: FirAnonymousFunctionSymbol
var label: FirLabel? = null var label: FirLabel? = null
var invocationKind: EventOccurrencesRange? = null var invocationKind: EventOccurrencesRange? = null
@@ -86,6 +89,7 @@ class FirAnonymousFunctionBuilder : FirFunctionBuilder, FirAnnotationContainerBu
controlFlowGraphReference, controlFlowGraphReference,
valueParameters, valueParameters,
body, body,
contractDescription,
symbol, symbol,
label, label,
invocationKind, invocationKind,
@@ -141,6 +145,7 @@ inline fun buildAnonymousFunctionCopy(original: FirAnonymousFunction, init: FirA
copyBuilder.controlFlowGraphReference = original.controlFlowGraphReference copyBuilder.controlFlowGraphReference = original.controlFlowGraphReference
copyBuilder.valueParameters.addAll(original.valueParameters) copyBuilder.valueParameters.addAll(original.valueParameters)
copyBuilder.body = original.body copyBuilder.body = original.body
copyBuilder.contractDescription = original.contractDescription
copyBuilder.symbol = original.symbol copyBuilder.symbol = original.symbol
copyBuilder.label = original.label copyBuilder.label = original.label
copyBuilder.invocationKind = original.invocationKind copyBuilder.invocationKind = original.invocationKind
@@ -13,6 +13,8 @@ import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.builder.FirAnnotationContainerBuilder import org.jetbrains.kotlin.fir.builder.FirAnnotationContainerBuilder
import org.jetbrains.kotlin.fir.builder.FirBuilderDsl import org.jetbrains.kotlin.fir.builder.FirBuilderDsl
import org.jetbrains.kotlin.fir.builder.toMutableOrEmpty import org.jetbrains.kotlin.fir.builder.toMutableOrEmpty
import org.jetbrains.kotlin.fir.contracts.FirContractDescription
import org.jetbrains.kotlin.fir.contracts.impl.FirEmptyContractDescription
import org.jetbrains.kotlin.fir.declarations.DeprecationsProvider import org.jetbrains.kotlin.fir.declarations.DeprecationsProvider
import org.jetbrains.kotlin.fir.declarations.FirConstructor import org.jetbrains.kotlin.fir.declarations.FirConstructor
import org.jetbrains.kotlin.fir.declarations.FirContextReceiver import org.jetbrains.kotlin.fir.declarations.FirContextReceiver
@@ -57,6 +59,7 @@ open class FirConstructorBuilder : FirAbstractConstructorBuilder, FirAnnotationC
override var dispatchReceiverType: ConeSimpleKotlinType? = null override var dispatchReceiverType: ConeSimpleKotlinType? = null
override val contextReceivers: MutableList<FirContextReceiver> = mutableListOf() override val contextReceivers: MutableList<FirContextReceiver> = mutableListOf()
override val valueParameters: MutableList<FirValueParameter> = mutableListOf() override val valueParameters: MutableList<FirValueParameter> = mutableListOf()
override var contractDescription: FirContractDescription = FirEmptyContractDescription
override val annotations: MutableList<FirAnnotation> = mutableListOf() override val annotations: MutableList<FirAnnotation> = mutableListOf()
override lateinit var symbol: FirConstructorSymbol override lateinit var symbol: FirConstructorSymbol
override var delegatedConstructor: FirDelegatedConstructorCall? = null override var delegatedConstructor: FirDelegatedConstructorCall? = null
@@ -78,6 +81,7 @@ open class FirConstructorBuilder : FirAbstractConstructorBuilder, FirAnnotationC
dispatchReceiverType, dispatchReceiverType,
contextReceivers.toMutableOrEmpty(), contextReceivers.toMutableOrEmpty(),
valueParameters, valueParameters,
contractDescription,
annotations.toMutableOrEmpty(), annotations.toMutableOrEmpty(),
symbol, symbol,
delegatedConstructor, delegatedConstructor,
@@ -122,6 +126,7 @@ inline fun buildConstructorCopy(original: FirConstructor, init: FirConstructorBu
copyBuilder.dispatchReceiverType = original.dispatchReceiverType copyBuilder.dispatchReceiverType = original.dispatchReceiverType
copyBuilder.contextReceivers.addAll(original.contextReceivers) copyBuilder.contextReceivers.addAll(original.contextReceivers)
copyBuilder.valueParameters.addAll(original.valueParameters) copyBuilder.valueParameters.addAll(original.valueParameters)
copyBuilder.contractDescription = original.contractDescription
copyBuilder.annotations.addAll(original.annotations) copyBuilder.annotations.addAll(original.annotations)
copyBuilder.symbol = original.symbol copyBuilder.symbol = original.symbol
copyBuilder.delegatedConstructor = original.delegatedConstructor copyBuilder.delegatedConstructor = original.delegatedConstructor
@@ -14,6 +14,8 @@ import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.builder.FirAnnotationContainerBuilder import org.jetbrains.kotlin.fir.builder.FirAnnotationContainerBuilder
import org.jetbrains.kotlin.fir.builder.FirBuilderDsl import org.jetbrains.kotlin.fir.builder.FirBuilderDsl
import org.jetbrains.kotlin.fir.builder.toMutableOrEmpty import org.jetbrains.kotlin.fir.builder.toMutableOrEmpty
import org.jetbrains.kotlin.fir.contracts.FirContractDescription
import org.jetbrains.kotlin.fir.contracts.impl.FirEmptyContractDescription
import org.jetbrains.kotlin.fir.declarations.DeprecationsProvider import org.jetbrains.kotlin.fir.declarations.DeprecationsProvider
import org.jetbrains.kotlin.fir.declarations.FirConstructor import org.jetbrains.kotlin.fir.declarations.FirConstructor
import org.jetbrains.kotlin.fir.declarations.FirContextReceiver import org.jetbrains.kotlin.fir.declarations.FirContextReceiver
@@ -58,6 +60,7 @@ class FirPrimaryConstructorBuilder : FirAbstractConstructorBuilder, FirAnnotatio
override var dispatchReceiverType: ConeSimpleKotlinType? = null override var dispatchReceiverType: ConeSimpleKotlinType? = null
override val contextReceivers: MutableList<FirContextReceiver> = mutableListOf() override val contextReceivers: MutableList<FirContextReceiver> = mutableListOf()
override val valueParameters: MutableList<FirValueParameter> = mutableListOf() override val valueParameters: MutableList<FirValueParameter> = mutableListOf()
override var contractDescription: FirContractDescription = FirEmptyContractDescription
override val annotations: MutableList<FirAnnotation> = mutableListOf() override val annotations: MutableList<FirAnnotation> = mutableListOf()
override lateinit var symbol: FirConstructorSymbol override lateinit var symbol: FirConstructorSymbol
override var delegatedConstructor: FirDelegatedConstructorCall? = null override var delegatedConstructor: FirDelegatedConstructorCall? = null
@@ -80,6 +83,7 @@ class FirPrimaryConstructorBuilder : FirAbstractConstructorBuilder, FirAnnotatio
dispatchReceiverType, dispatchReceiverType,
contextReceivers.toMutableOrEmpty(), contextReceivers.toMutableOrEmpty(),
valueParameters, valueParameters,
contractDescription,
annotations.toMutableOrEmpty(), annotations.toMutableOrEmpty(),
symbol, symbol,
delegatedConstructor, delegatedConstructor,
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
import org.jetbrains.kotlin.fir.FirLabel import org.jetbrains.kotlin.fir.FirLabel
import org.jetbrains.kotlin.fir.FirModuleData import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.contracts.FirContractDescription
import org.jetbrains.kotlin.fir.declarations.DeprecationsProvider import org.jetbrains.kotlin.fir.declarations.DeprecationsProvider
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
import org.jetbrains.kotlin.fir.declarations.FirContextReceiver import org.jetbrains.kotlin.fir.declarations.FirContextReceiver
@@ -54,6 +55,7 @@ internal class FirAnonymousFunctionImpl(
override var controlFlowGraphReference: FirControlFlowGraphReference?, override var controlFlowGraphReference: FirControlFlowGraphReference?,
override val valueParameters: MutableList<FirValueParameter>, override val valueParameters: MutableList<FirValueParameter>,
override var body: FirBlock?, override var body: FirBlock?,
override var contractDescription: FirContractDescription,
override val symbol: FirAnonymousFunctionSymbol, override val symbol: FirAnonymousFunctionSymbol,
override var label: FirLabel?, override var label: FirLabel?,
override var invocationKind: EventOccurrencesRange?, override var invocationKind: EventOccurrencesRange?,
@@ -80,6 +82,7 @@ internal class FirAnonymousFunctionImpl(
controlFlowGraphReference?.accept(visitor, data) controlFlowGraphReference?.accept(visitor, data)
valueParameters.forEach { it.accept(visitor, data) } valueParameters.forEach { it.accept(visitor, data) }
body?.accept(visitor, data) body?.accept(visitor, data)
contractDescription.accept(visitor, data)
label?.accept(visitor, data) label?.accept(visitor, data)
typeParameters.forEach { it.accept(visitor, data) } typeParameters.forEach { it.accept(visitor, data) }
typeRef.accept(visitor, data) typeRef.accept(visitor, data)
@@ -94,6 +97,7 @@ internal class FirAnonymousFunctionImpl(
controlFlowGraphReference = controlFlowGraphReference?.transform(transformer, data) controlFlowGraphReference = controlFlowGraphReference?.transform(transformer, data)
transformValueParameters(transformer, data) transformValueParameters(transformer, data)
transformBody(transformer, data) transformBody(transformer, data)
transformContractDescription(transformer, data)
label = label?.transform(transformer, data) label = label?.transform(transformer, data)
transformTypeParameters(transformer, data) transformTypeParameters(transformer, data)
typeRef = typeRef.transform(transformer, data) typeRef = typeRef.transform(transformer, data)
@@ -130,6 +134,11 @@ internal class FirAnonymousFunctionImpl(
return this return this
} }
override fun <D> transformContractDescription(transformer: FirTransformer<D>, data: D): FirAnonymousFunctionImpl {
contractDescription = contractDescription.transform(transformer, data)
return this
}
override fun <D> transformTypeParameters(transformer: FirTransformer<D>, data: D): FirAnonymousFunctionImpl { override fun <D> transformTypeParameters(transformer: FirTransformer<D>, data: D): FirAnonymousFunctionImpl {
typeParameters.transformInplace(transformer, data) typeParameters.transformInplace(transformer, data)
return this return this
@@ -176,6 +185,10 @@ internal class FirAnonymousFunctionImpl(
body = newBody body = newBody
} }
override fun replaceContractDescription(newContractDescription: FirContractDescription) {
contractDescription = newContractDescription
}
override fun replaceInvocationKind(newInvocationKind: EventOccurrencesRange?) { override fun replaceInvocationKind(newInvocationKind: EventOccurrencesRange?) {
invocationKind = newInvocationKind invocationKind = newInvocationKind
} }
@@ -9,6 +9,7 @@ package org.jetbrains.kotlin.fir.declarations.impl
import org.jetbrains.kotlin.KtSourceElement import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.fir.FirModuleData import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.contracts.FirContractDescription
import org.jetbrains.kotlin.fir.declarations.DeprecationsProvider import org.jetbrains.kotlin.fir.declarations.DeprecationsProvider
import org.jetbrains.kotlin.fir.declarations.FirConstructor import org.jetbrains.kotlin.fir.declarations.FirConstructor
import org.jetbrains.kotlin.fir.declarations.FirContextReceiver import org.jetbrains.kotlin.fir.declarations.FirContextReceiver
@@ -52,6 +53,7 @@ internal class FirConstructorImpl(
override val dispatchReceiverType: ConeSimpleKotlinType?, override val dispatchReceiverType: ConeSimpleKotlinType?,
override var contextReceivers: MutableOrEmptyList<FirContextReceiver>, override var contextReceivers: MutableOrEmptyList<FirContextReceiver>,
override val valueParameters: MutableList<FirValueParameter>, override val valueParameters: MutableList<FirValueParameter>,
override var contractDescription: FirContractDescription,
override var annotations: MutableOrEmptyList<FirAnnotation>, override var annotations: MutableOrEmptyList<FirAnnotation>,
override val symbol: FirConstructorSymbol, override val symbol: FirConstructorSymbol,
override var delegatedConstructor: FirDelegatedConstructorCall?, override var delegatedConstructor: FirDelegatedConstructorCall?,
@@ -72,6 +74,7 @@ internal class FirConstructorImpl(
contextReceivers.forEach { it.accept(visitor, data) } contextReceivers.forEach { it.accept(visitor, data) }
controlFlowGraphReference?.accept(visitor, data) controlFlowGraphReference?.accept(visitor, data)
valueParameters.forEach { it.accept(visitor, data) } valueParameters.forEach { it.accept(visitor, data) }
contractDescription.accept(visitor, data)
annotations.forEach { it.accept(visitor, data) } annotations.forEach { it.accept(visitor, data) }
delegatedConstructor?.accept(visitor, data) delegatedConstructor?.accept(visitor, data)
body?.accept(visitor, data) body?.accept(visitor, data)
@@ -85,6 +88,7 @@ internal class FirConstructorImpl(
contextReceivers.transformInplace(transformer, data) contextReceivers.transformInplace(transformer, data)
controlFlowGraphReference = controlFlowGraphReference?.transform(transformer, data) controlFlowGraphReference = controlFlowGraphReference?.transform(transformer, data)
transformValueParameters(transformer, data) transformValueParameters(transformer, data)
transformContractDescription(transformer, data)
transformAnnotations(transformer, data) transformAnnotations(transformer, data)
transformDelegatedConstructor(transformer, data) transformDelegatedConstructor(transformer, data)
transformBody(transformer, data) transformBody(transformer, data)
@@ -116,6 +120,11 @@ internal class FirConstructorImpl(
return this return this
} }
override fun <D> transformContractDescription(transformer: FirTransformer<D>, data: D): FirConstructorImpl {
contractDescription = contractDescription.transform(transformer, data)
return this
}
override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirConstructorImpl { override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirConstructorImpl {
annotations.transformInplace(transformer, data) annotations.transformInplace(transformer, data)
return this return this
@@ -164,6 +173,10 @@ internal class FirConstructorImpl(
valueParameters.addAll(newValueParameters) valueParameters.addAll(newValueParameters)
} }
override fun replaceContractDescription(newContractDescription: FirContractDescription) {
contractDescription = newContractDescription
}
override fun replaceAnnotations(newAnnotations: List<FirAnnotation>) { override fun replaceAnnotations(newAnnotations: List<FirAnnotation>) {
annotations = newAnnotations.toMutableOrEmpty() annotations = newAnnotations.toMutableOrEmpty()
} }
@@ -10,6 +10,7 @@ package org.jetbrains.kotlin.fir.declarations.impl
import org.jetbrains.kotlin.KtSourceElement import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.fir.FirImplementationDetail import org.jetbrains.kotlin.fir.FirImplementationDetail
import org.jetbrains.kotlin.fir.FirModuleData import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.contracts.FirContractDescription
import org.jetbrains.kotlin.fir.declarations.DeprecationsProvider import org.jetbrains.kotlin.fir.declarations.DeprecationsProvider
import org.jetbrains.kotlin.fir.declarations.FirConstructor import org.jetbrains.kotlin.fir.declarations.FirConstructor
import org.jetbrains.kotlin.fir.declarations.FirContextReceiver import org.jetbrains.kotlin.fir.declarations.FirContextReceiver
@@ -53,6 +54,7 @@ class FirPrimaryConstructor @FirImplementationDetail constructor(
override val dispatchReceiverType: ConeSimpleKotlinType?, override val dispatchReceiverType: ConeSimpleKotlinType?,
override var contextReceivers: MutableOrEmptyList<FirContextReceiver>, override var contextReceivers: MutableOrEmptyList<FirContextReceiver>,
override val valueParameters: MutableList<FirValueParameter>, override val valueParameters: MutableList<FirValueParameter>,
override var contractDescription: FirContractDescription,
override var annotations: MutableOrEmptyList<FirAnnotation>, override var annotations: MutableOrEmptyList<FirAnnotation>,
override val symbol: FirConstructorSymbol, override val symbol: FirConstructorSymbol,
override var delegatedConstructor: FirDelegatedConstructorCall?, override var delegatedConstructor: FirDelegatedConstructorCall?,
@@ -73,6 +75,7 @@ class FirPrimaryConstructor @FirImplementationDetail constructor(
contextReceivers.forEach { it.accept(visitor, data) } contextReceivers.forEach { it.accept(visitor, data) }
controlFlowGraphReference?.accept(visitor, data) controlFlowGraphReference?.accept(visitor, data)
valueParameters.forEach { it.accept(visitor, data) } valueParameters.forEach { it.accept(visitor, data) }
contractDescription.accept(visitor, data)
annotations.forEach { it.accept(visitor, data) } annotations.forEach { it.accept(visitor, data) }
delegatedConstructor?.accept(visitor, data) delegatedConstructor?.accept(visitor, data)
body?.accept(visitor, data) body?.accept(visitor, data)
@@ -86,6 +89,7 @@ class FirPrimaryConstructor @FirImplementationDetail constructor(
contextReceivers.transformInplace(transformer, data) contextReceivers.transformInplace(transformer, data)
controlFlowGraphReference = controlFlowGraphReference?.transform(transformer, data) controlFlowGraphReference = controlFlowGraphReference?.transform(transformer, data)
transformValueParameters(transformer, data) transformValueParameters(transformer, data)
transformContractDescription(transformer, data)
transformAnnotations(transformer, data) transformAnnotations(transformer, data)
transformDelegatedConstructor(transformer, data) transformDelegatedConstructor(transformer, data)
transformBody(transformer, data) transformBody(transformer, data)
@@ -117,6 +121,11 @@ class FirPrimaryConstructor @FirImplementationDetail constructor(
return this return this
} }
override fun <D> transformContractDescription(transformer: FirTransformer<D>, data: D): FirPrimaryConstructor {
contractDescription = contractDescription.transform(transformer, data)
return this
}
override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirPrimaryConstructor { override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirPrimaryConstructor {
annotations.transformInplace(transformer, data) annotations.transformInplace(transformer, data)
return this return this
@@ -165,6 +174,10 @@ class FirPrimaryConstructor @FirImplementationDetail constructor(
valueParameters.addAll(newValueParameters) valueParameters.addAll(newValueParameters)
} }
override fun replaceContractDescription(newContractDescription: FirContractDescription) {
contractDescription = newContractDescription
}
override fun replaceAnnotations(newAnnotations: List<FirAnnotation>) { override fun replaceAnnotations(newAnnotations: List<FirAnnotation>) {
annotations = newAnnotations.toMutableOrEmpty() annotations = newAnnotations.toMutableOrEmpty()
} }
@@ -89,6 +89,8 @@ object BuilderConfigurator : AbstractBuilderConfigurator<FirTreeBuilder>(FirTree
parents += abstractConstructorBuilder parents += abstractConstructorBuilder
defaultNull("delegatedConstructor") defaultNull("delegatedConstructor")
defaultNull("body") defaultNull("body")
default("contractDescription", "FirEmptyContractDescription")
useTypes(emptyContractDescriptionType)
} }
} }
@@ -266,7 +268,9 @@ object BuilderConfigurator : AbstractBuilderConfigurator<FirTreeBuilder>(FirTree
parents += functionBuilder parents += functionBuilder
defaultNull("invocationKind", "label", "body", "controlFlowGraphReference") defaultNull("invocationKind", "label", "body", "controlFlowGraphReference")
default("inlineStatus", "InlineStatus.Unknown") default("inlineStatus", "InlineStatus.Unknown")
default("contractDescription", "FirEmptyContractDescription")
withCopy() withCopy()
useTypes(emptyContractDescriptionType)
} }
builder(propertyAccessor) { builder(propertyAccessor) {
@@ -60,12 +60,12 @@ object FirTreeBuilder : AbstractFirTreeBuilder() {
val simpleFunction by element(Declaration, function, contractDescriptionOwner, typeParametersOwner) val simpleFunction by element(Declaration, function, contractDescriptionOwner, typeParametersOwner)
val propertyAccessor by element(Declaration, function, contractDescriptionOwner, typeParametersOwner) val propertyAccessor by element(Declaration, function, contractDescriptionOwner, typeParametersOwner)
val backingField by element(Declaration, variable, typeParametersOwner, statement) val backingField by element(Declaration, variable, typeParametersOwner, statement)
val constructor by element(Declaration, function, typeParameterRefsOwner) val constructor by element(Declaration, function, typeParameterRefsOwner, contractDescriptionOwner)
val file by element(Declaration, declaration) val file by element(Declaration, declaration)
val script by element(Declaration, declaration) val script by element(Declaration, declaration)
val packageDirective by element(Other) val packageDirective by element(Other)
val anonymousFunction by element(Declaration, function, typeParametersOwner) val anonymousFunction by element(Declaration, function, typeParametersOwner, contractDescriptionOwner)
val anonymousFunctionExpression by element(Expression, expression) val anonymousFunctionExpression by element(Expression, expression)
val anonymousObject by element(Declaration, klass, controlFlowGraphOwner) val anonymousObject by element(Declaration, klass, controlFlowGraphOwner)
@@ -10,19 +10,19 @@ open class Class {
fun member(x: Boolean) { fun member(x: Boolean) {
contract { returns() implies (x) } contract { returns() implies (x) }
} }
inline fun inlineMember(x: Boolean) { inline fun inlineMember(x: Boolean) {
contract { returns() implies (x) } contract { returns() implies (x) }
} }
abstract fun abstractMember(x: Boolean) { abstract fun abstractMember(x: Boolean) {
contract { returns() implies (x) } <!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
} }
open fun openMemeber(x: Boolean) { open fun openMemeber(x: Boolean) {
contract { returns() implies (x) } <!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
} }
suspend fun suspendMember(x: Boolean) { suspend fun suspendMember(x: Boolean) {
contract { returns() implies (x) } contract { returns() implies (x) }
} }
@@ -44,43 +44,43 @@ suspend fun suspendTopLevel(x: Boolean) {
// Top-level operator // Top-level operator
operator fun Boolean.plus(x: Boolean): Boolean { operator fun Boolean.plus(x: Boolean): Boolean {
contract { returns() implies (x) } <!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
return x return x
} }
val topLevelLambda: (Boolean) -> Unit = { x: Boolean -> val topLevelLambda: (Boolean) -> Unit = { x: Boolean ->
contract { returns() implies (x) } <!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
} }
val topLevelAnonymousFunction = fun (x: Boolean) { 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<!> var topLevelPropertyAccessors: Int? = <!PROPERTY_INITIALIZER_NO_BACKING_FIELD!>42<!>
get() { 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 return 42
} }
set(value) { 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 ===================== // ============= Local =====================
fun test() { fun test() {
fun localDeclaration(x: Boolean) { fun localDeclaration(x: Boolean) {
contract { returns() implies (x) } <!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
} }
suspend fun suspendlocalDeclaration(x: Boolean) { suspend fun suspendlocalDeclaration(x: Boolean) {
contract { returns() implies (x) } <!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
} }
val localAnonymousFunction = fun (x: Boolean) { val localAnonymousFunction = fun (x: Boolean) {
contract { returns() implies (x) } <!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
} }
val localLambda: (Boolean) -> Unit = { x: Boolean -> 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) { fun member(x: Boolean) {
<!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) } <!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
} }
inline fun inlineMember(x: Boolean) { inline fun inlineMember(x: Boolean) {
<!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) } <!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
} }
abstract fun abstractMember(x: Boolean) { abstract fun abstractMember(x: Boolean) {
<!CONTRACT_NOT_ALLOWED, CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) } <!CONTRACT_NOT_ALLOWED, CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
} }
open fun openMemeber(x: Boolean) { open fun openMemeber(x: Boolean) {
<!CONTRACT_NOT_ALLOWED, CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) } <!CONTRACT_NOT_ALLOWED, CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
} }
suspend fun suspendMember(x: Boolean) { suspend fun suspendMember(x: Boolean) {
<!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) } <!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
} }
@@ -83,4 +83,4 @@ fun test() {
val localLambda: (Boolean) -> Unit = { x: Boolean -> val localLambda: (Boolean) -> Unit = { x: Boolean ->
<!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) } <!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
} }
} }
@@ -7,6 +7,11 @@ import kotlin.contracts.*
// ============= Class ===================== // ============= Class =====================
open class Class { open class Class {
constructor(f: () -> Unit = {}) {
contract { callsInPlace(f, InvocationKind.EXACTLY_ONCE) }
f()
}
fun member(x: Boolean) { fun member(x: Boolean) {
contract { returns() implies (x) } contract { returns() implies (x) }
} }
@@ -16,11 +21,11 @@ open class Class {
} }
abstract fun abstractMember(x: Boolean) { abstract fun abstractMember(x: Boolean) {
contract { returns() implies (x) } <!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
} }
open fun openMemeber(x: Boolean) { open fun openMemeber(x: Boolean) {
contract { returns() implies (x) } <!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
} }
suspend fun suspendMember(x: Boolean) { suspend fun suspendMember(x: Boolean) {
@@ -30,17 +35,17 @@ open class Class {
open class Inheritor : Class() { open class Inheritor : Class() {
override fun openMemeber(x: Boolean) { override fun openMemeber(x: Boolean) {
contract { returns() implies (x) } <!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
} }
final override fun abstractMember(x: Boolean) { final override fun abstractMember(x: Boolean) {
contract { returns() implies (x) } <!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
} }
} }
interface Interface { interface Interface {
fun implicitlyOpenMember(x: Boolean) { 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 // Top-level operator
operator fun Boolean.plus(x: Boolean): Boolean { operator fun Boolean.plus(x: Boolean): Boolean {
contract { returns() implies (x) } <!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
return x return x
} }
val topLevelLambda: (Boolean) -> Unit = { x: Boolean -> val topLevelLambda: (Boolean) -> Unit = { x: Boolean ->
contract { returns() implies (x) } <!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
} }
val topLevelAnonymousFunction = fun (x: Boolean) { 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<!> var topLevelPropertyAccessors: Int? = <!PROPERTY_INITIALIZER_NO_BACKING_FIELD!>42<!>
get() { 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 return 42
} }
set(value) { 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 ===================== // ============= Local =====================
fun test() { fun test() {
fun localDeclaration(x: Boolean) { fun localDeclaration(x: Boolean) {
contract { returns() implies (x) } <!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
} }
suspend fun suspendlocalDeclaration(x: Boolean) { suspend fun suspendlocalDeclaration(x: Boolean) {
contract { returns() implies (x) } <!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
} }
val localAnonymousFunction = fun (x: Boolean) { val localAnonymousFunction = fun (x: Boolean) {
contract { returns() implies (x) } <!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
} }
val localLambda: (Boolean) -> Unit = { x: Boolean -> 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 ===================== // ============= Class =====================
open class Class { open class Class {
constructor(f: () -> Unit = {}) {
contract { callsInPlace(f, InvocationKind.EXACTLY_ONCE) }
f()
}
fun member(x: Boolean) { fun member(x: Boolean) {
contract { returns() implies (x) } 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 operator fun kotlin.Boolean.plus(/*0*/ x: kotlin.Boolean): kotlin.Boolean
public open class Class { 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 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 equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
@@ -7,30 +7,30 @@ import kotlin.contracts.*
fun foo(y: Boolean) { fun foo(y: Boolean) {
val x: Int = 42 val x: Int = 42
contract { <!CONTRACT_NOT_ALLOWED("Contract should be the first statement")!>contract<!> {
returns() implies y returns() implies y
} }
} }
inline fun case1(block: () -> Unit) { inline fun case1(block: () -> Unit) {
val contracts = listOf( val contracts = listOf(
contract { <!CONTRACT_NOT_ALLOWED!>contract<!> {
callsInPlace(<!USAGE_IS_NOT_INLINABLE!>block<!>, InvocationKind.EXACTLY_ONCE) callsInPlace(<!USAGE_IS_NOT_INLINABLE!>block<!>, InvocationKind.EXACTLY_ONCE)
}, contract { }, <!CONTRACT_NOT_ALLOWED!>contract<!> {
callsInPlace(<!USAGE_IS_NOT_INLINABLE!>block<!>, InvocationKind.EXACTLY_ONCE) callsInPlace(<!USAGE_IS_NOT_INLINABLE!>block<!>, InvocationKind.EXACTLY_ONCE)
} }
) )
block() 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) callsInPlace(<!USAGE_IS_NOT_INLINABLE!>block<!>, InvocationKind.EXACTLY_ONCE)
} }
fun case_3(block: () -> Unit) { fun case_3(block: () -> Unit) {
class Class { class Class {
fun innerFun(block2: () -> Unit) { fun innerFun(block2: () -> Unit) {
contract { <!CONTRACT_NOT_ALLOWED("Contracts are not allowed for local functions")!>contract<!> {
callsInPlace(block2, InvocationKind.EXACTLY_ONCE) callsInPlace(block2, InvocationKind.EXACTLY_ONCE)
} }
block2() block2()
@@ -41,7 +41,7 @@ fun case_3(block: () -> Unit) {
inline fun case_4(number: Int?): Boolean { inline fun case_4(number: Int?): Boolean {
val cond = number != null val cond = number != null
contract { <!CONTRACT_NOT_ALLOWED!>contract<!> {
returns(false) implies (cond) returns(false) implies (cond)
} as ContractBuilder } as ContractBuilder
return number == null return number == null
@@ -49,8 +49,8 @@ inline fun case_4(number: Int?): Boolean {
inline fun case_5(cond: Boolean): Boolean { inline fun case_5(cond: Boolean): Boolean {
run { run {
contract { <!CONTRACT_NOT_ALLOWED!>contract<!> {
returns(true) implies (cond) <!ERROR_IN_CONTRACT_DESCRIPTION!>returns(true) implies (cond)<!>
} }
} }
return true return true
@@ -59,7 +59,7 @@ inline fun case_5(cond: Boolean): Boolean {
inline fun case_6(cond: Boolean): Boolean { inline fun case_6(cond: Boolean): Boolean {
run { run {
val x = 10 val x = 10
contract { <!CONTRACT_NOT_ALLOWED!>contract<!> {
returns(true) implies (cond) returns(true) implies (cond)
} }
} }
@@ -68,8 +68,8 @@ inline fun case_6(cond: Boolean): Boolean {
fun case_7(cond: Boolean): Boolean { fun case_7(cond: Boolean): Boolean {
fun innerFun() { fun innerFun() {
contract { <!CONTRACT_NOT_ALLOWED!>contract<!> {
returns(true) implies (cond) <!ERROR_IN_CONTRACT_DESCRIPTION!>returns(true) implies (cond)<!>
} }
} }
return true return true
@@ -4,13 +4,13 @@ import kotlin.contracts.*
class A { class A {
var x: Int = 0 var x: Int = 0
get() = f(x) get() = f(x)
set(value) contract [returns() implies (value != null)] { set(value) contract <!CONTRACT_NOT_ALLOWED!>[returns() implies (value != null)]<!> {
field = value + 1 field = value + 1
} }
var y: Double = 0.0 var y: Double = 0.0
get() = g(y) get() = g(y)
set(value) contract [returns() implies (value != null)] { set(value) contract <!CONTRACT_NOT_ALLOWED!>[returns() implies (value != null)]<!> {
field = value * 2 field = value * 2
} }
@@ -6,14 +6,14 @@ import kotlin.contracts.*
// TESTCASE NUMBER: 1 // TESTCASE NUMBER: 1
inline fun case_1(block: () -> Unit) { inline fun case_1(block: () -> Unit) {
val value_1 = 1 val value_1 = 1
contract { } <!CONTRACT_NOT_ALLOWED!>contract<!> { }
return block() return block()
} }
// TESTCASE NUMBER: 2 // TESTCASE NUMBER: 2
inline fun case_2(block: () -> Unit) { inline fun case_2(block: () -> Unit) {
10 - 1 10 - 1
contract { <!CONTRACT_NOT_ALLOWED!>contract<!> {
callsInPlace(<!USAGE_IS_NOT_INLINABLE!>block<!>, InvocationKind.EXACTLY_ONCE) callsInPlace(<!USAGE_IS_NOT_INLINABLE!>block<!>, InvocationKind.EXACTLY_ONCE)
} }
return block() return block()
@@ -22,7 +22,7 @@ inline fun case_2(block: () -> Unit) {
// TESTCASE NUMBER: 3 // TESTCASE NUMBER: 3
inline fun case_3(block: () -> Unit) { inline fun case_3(block: () -> Unit) {
throw Exception() throw Exception()
contract { <!CONTRACT_NOT_ALLOWED!>contract<!> {
callsInPlace(<!USAGE_IS_NOT_INLINABLE!>block<!>, InvocationKind.UNKNOWN) callsInPlace(<!USAGE_IS_NOT_INLINABLE!>block<!>, InvocationKind.UNKNOWN)
} }
return block() return block()
@@ -34,7 +34,7 @@ inline fun case_3(block: () -> Unit) {
*/ */
inline fun case_4(block: () -> Unit) { inline fun case_4(block: () -> Unit) {
.0009 .0009
return contract { return <!CONTRACT_NOT_ALLOWED!>contract<!> {
callsInPlace(<!USAGE_IS_NOT_INLINABLE!>block<!>, InvocationKind.EXACTLY_ONCE) callsInPlace(<!USAGE_IS_NOT_INLINABLE!>block<!>, InvocationKind.EXACTLY_ONCE)
} }
} }
@@ -45,7 +45,7 @@ inline fun case_4(block: () -> Unit) {
*/ */
fun case_5(value_1: Int?) { fun case_5(value_1: Int?) {
println("!") println("!")
contract { <!CONTRACT_NOT_ALLOWED!>contract<!> {
returns(true) implies (value_1 != null) returns(true) implies (value_1 != null)
} <!CAST_NEVER_SUCCEEDS!>as<!> ContractBuilder } <!CAST_NEVER_SUCCEEDS!>as<!> ContractBuilder
} }
@@ -56,7 +56,7 @@ fun case_5(value_1: Int?) {
*/ */
fun case_6(value_1: Int?) { fun case_6(value_1: Int?) {
100 + 10 100 + 10
throw Exception(contract { throw Exception(<!CONTRACT_NOT_ALLOWED!>contract<!> {
returns(true) implies (value_1 != null) returns(true) implies (value_1 != null)
}.toString()) }.toString())
} }
@@ -69,7 +69,7 @@ fun case_7(value_1: Int?) {
for (i in 0..10) { for (i in 0..10) {
println(i) println(i)
} }
return contract { return <!CONTRACT_NOT_ALLOWED!>contract<!> {
returns(true) implies (value_1 != null) returns(true) implies (value_1 != null)
} }
} }
@@ -80,7 +80,7 @@ fun case_7(value_1: Int?) {
*/ */
fun case_8(value_1: Int?) { fun case_8(value_1: Int?) {
val f = 10 - 20 val f = 10 - 20
val g = contract { val g = <!CONTRACT_NOT_ALLOWED!>contract<!> {
returns(true) implies (value_1 != null) returns(true) implies (value_1 != null)
} }
} }
@@ -91,7 +91,7 @@ fun case_8(value_1: Int?) {
*/ */
fun case_9(number: Int?): Boolean { fun case_9(number: Int?): Boolean {
val value_1 = number != null val value_1 = number != null
contract { <!CONTRACT_NOT_ALLOWED!>contract<!> {
returns(false) implies (value_1) returns(false) implies (value_1)
} <!CAST_NEVER_SUCCEEDS!>as<!> ContractBuilder } <!CAST_NEVER_SUCCEEDS!>as<!> ContractBuilder
return number == null return number == null
@@ -5,17 +5,17 @@ import kotlin.contracts.*
// TESTCASE NUMBER: 1 // TESTCASE NUMBER: 1
inline fun case_1(block: () -> Unit) { inline fun case_1(block: () -> Unit) {
return contract { return <!CONTRACT_NOT_ALLOWED!>contract<!> {
callsInPlace(<!USAGE_IS_NOT_INLINABLE!>block<!>, InvocationKind.EXACTLY_ONCE) callsInPlace(<!USAGE_IS_NOT_INLINABLE!>block<!>, InvocationKind.EXACTLY_ONCE)
} }
} }
// TESTCASE NUMBER: 2 // TESTCASE NUMBER: 2
fun case_2() = contract { } fun case_2() = <!CONTRACT_NOT_ALLOWED!>contract<!> { }
// TESTCASE NUMBER: 3 // TESTCASE NUMBER: 3
inline fun case_3(block: () -> Unit) { inline fun case_3(block: () -> Unit) {
val value_1 = contract { val value_1 = <!CONTRACT_NOT_ALLOWED!>contract<!> {
callsInPlace(<!USAGE_IS_NOT_INLINABLE!>block<!>, InvocationKind.EXACTLY_ONCE) callsInPlace(<!USAGE_IS_NOT_INLINABLE!>block<!>, InvocationKind.EXACTLY_ONCE)
} }
block() block()
@@ -39,14 +39,14 @@ inline fun case_5(block: () -> Unit) {
// TESTCASE NUMBER: 6 // TESTCASE NUMBER: 6
inline fun case_6(block: () -> Unit) { inline fun case_6(block: () -> Unit) {
throw Exception(contract { throw Exception(<!CONTRACT_NOT_ALLOWED!>contract<!> {
callsInPlace(<!USAGE_IS_NOT_INLINABLE!>block<!>, InvocationKind.EXACTLY_ONCE) callsInPlace(<!USAGE_IS_NOT_INLINABLE!>block<!>, InvocationKind.EXACTLY_ONCE)
}.toString()) }.toString())
} }
// TESTCASE NUMBER: 7 // TESTCASE NUMBER: 7
inline fun case_7(block: () -> Unit) { inline fun case_7(block: () -> Unit) {
funWithAnyArg(contract { funWithAnyArg(<!CONTRACT_NOT_ALLOWED!>contract<!> {
callsInPlace(<!USAGE_IS_NOT_INLINABLE!>block<!>, InvocationKind.EXACTLY_ONCE) callsInPlace(<!USAGE_IS_NOT_INLINABLE!>block<!>, InvocationKind.EXACTLY_ONCE)
}) })
} }
@@ -1,47 +0,0 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE
// !OPT_IN: kotlin.contracts.ExperimentalContracts
import kotlin.contracts.*
// TESTCASE NUMBER: 1
fun case_1(value_1: Int?) {
println("!")
contract {
returns(true) implies (value_1 != null)
} <!CAST_NEVER_SUCCEEDS!>as<!> ContractBuilder
}
// TESTCASE NUMBER: 2
fun case_2(value_1: Int?) {
100 + 10
throw Exception(contract {
returns(true) implies (value_1 != null)
}.toString())
}
// TESTCASE NUMBER: 3
fun case_3(value_1: Int?) {
for (i in 0..10) {
println(i)
}
return contract {
returns(true) implies (value_1 != null)
}
}
// TESTCASE NUMBER: 4
fun case_4(value_1: Int?) {
val f = 10 - 20
val g = contract {
returns(true) implies (value_1 != null)
}
}
// TESTCASE NUMBER: 5
fun case_5(number: Int?): Boolean {
val value_1 = number != null
contract {
returns(false) implies (value_1)
} <!CAST_NEVER_SUCCEEDS!>as<!> ContractBuilder
return number == null
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_VARIABLE // !DIAGNOSTICS: -UNUSED_VARIABLE
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
@@ -38,7 +38,7 @@ fun case_5(): Boolean? {
// TESTCASE NUMBER: 6 // TESTCASE NUMBER: 6
fun case_6(value_1: Boolean): Boolean? { fun case_6(value_1: Boolean): Boolean? {
contract { <!ERROR_IN_CONTRACT_DESCRIPTION!>returns(null) implies <!ARGUMENT_TYPE_MISMATCH!>contract { returns(null) implies (!value_1) }<!><!> } contract { <!ERROR_IN_CONTRACT_DESCRIPTION!>returns(null) implies <!ARGUMENT_TYPE_MISMATCH!><!CONTRACT_NOT_ALLOWED!>contract<!> { returns(null) implies (!value_1) }<!><!> }
return null return null
} }
@@ -36,7 +36,7 @@ class case_2(value_5: Boolean, val value_1: Boolean) {
init { init {
fun case_2_1(): Boolean { fun case_2_1(): Boolean {
contract { returns(false) implies (value_5) } <!CONTRACT_NOT_ALLOWED!>contract<!> { <!ERROR_IN_CONTRACT_DESCRIPTION!>returns(false) implies (value_5)<!> }
return !(value_5) return !(value_5)
} }
} }
@@ -6,7 +6,7 @@ import kotlin.contracts.*
// TESTCASE NUMBER: 1 // TESTCASE NUMBER: 1
fun <T> T?.case_1() { fun <T> T?.case_1() {
fun <K> K?.case_1_1(): Boolean { fun <K> K?.case_1_1(): Boolean {
contract { returns(true) implies (this@case_1 != null) } <!CONTRACT_NOT_ALLOWED!>contract<!> { <!ERROR_IN_CONTRACT_DESCRIPTION!>returns(true) implies (this@case_1 != null)<!> }
return this@case_1 != null return this@case_1 != null
} }
} }
@@ -5,7 +5,7 @@ import kotlin.contracts.*
// TESTCASE NUMBER: 1 // TESTCASE NUMBER: 1
inline fun case_1(block: () -> Unit) = { inline fun case_1(block: () -> Unit) = {
contract { <!CONTRACT_NOT_ALLOWED!>contract<!> {
callsInPlace(<!USAGE_IS_NOT_INLINABLE!>block<!>, InvocationKind.EXACTLY_ONCE) <!ERROR_IN_CONTRACT_DESCRIPTION!>callsInPlace(block, InvocationKind.EXACTLY_ONCE)<!>
} }
} }
@@ -6,7 +6,7 @@ import kotlin.contracts.*
// TESTCASE NUMBER: 1 // TESTCASE NUMBER: 1
fun case_1() { fun case_1() {
val fun_1 = fun(block: () -> Unit) { val fun_1 = fun(block: () -> Unit) {
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } <!CONTRACT_NOT_ALLOWED!>contract<!> { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
return block() return block()
} }
@@ -17,7 +17,7 @@ fun case_1() {
// TESTCASE NUMBER: 2 // TESTCASE NUMBER: 2
fun case_2() { fun case_2() {
val lambda_1 = { block: () -> Unit -> val lambda_1 = { block: () -> Unit ->
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } <!CONTRACT_NOT_ALLOWED!>contract<!> { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
block() block()
} }
@@ -43,7 +43,7 @@ class case_4 : ClassLevel3() {
fun <T>T.case_4_3_wrap() { fun <T>T.case_4_3_wrap() {
fun case_4_3_contract() { fun case_4_3_contract() {
contract { returns() implies (this@case_4_3_wrap is ClassLevel1) } <!CONTRACT_NOT_ALLOWED!>contract<!> { <!ERROR_IN_CONTRACT_DESCRIPTION!>returns() implies (this@case_4_3_wrap is ClassLevel1)<!> }
if (this@case_4_3_wrap !is ClassLevel1) throw Exception() if (this@case_4_3_wrap !is ClassLevel1) throw Exception()
} }
case_4_3_contract() case_4_3_contract()
@@ -6,7 +6,7 @@ import kotlin.contracts.*
// TESTCASE NUMBER: 1 // TESTCASE NUMBER: 1
val Boolean.case_1: () -> Unit val Boolean.case_1: () -> Unit
get() { get() {
contract { <!CONTRACT_NOT_ALLOWED!>contract<!> {
returns() implies (this@case_1) returns() implies (this@case_1)
} }
return {} return {}
@@ -15,7 +15,7 @@ val Boolean.case_1: () -> Unit
// TESTCASE NUMBER: 2 // TESTCASE NUMBER: 2
val (() -> Unit).case_2: () -> Unit val (() -> Unit).case_2: () -> Unit
get() { get() {
contract { <!CONTRACT_NOT_ALLOWED!>contract<!> {
callsInPlace(this@case_2, InvocationKind.EXACTLY_ONCE) callsInPlace(this@case_2, InvocationKind.EXACTLY_ONCE)
} }
return {} return {}
@@ -27,7 +27,7 @@ var Boolean.case_3: () -> Unit
return {} return {}
} }
set(value) { set(value) {
<!WRONG_INVOCATION_KIND!>contract { <!WRONG_INVOCATION_KIND!><!CONTRACT_NOT_ALLOWED!>contract<!> {
callsInPlace(value, InvocationKind.EXACTLY_ONCE) callsInPlace(value, InvocationKind.EXACTLY_ONCE)
}<!> }<!>
} }
@@ -38,7 +38,7 @@ var (() -> Unit).case_4: () -> Unit
return {} return {}
} }
set(value) { set(value) {
contract { <!CONTRACT_NOT_ALLOWED!>contract<!> {
callsInPlace(this@case_4, InvocationKind.EXACTLY_ONCE) callsInPlace(this@case_4, InvocationKind.EXACTLY_ONCE)
} }
} }
@@ -46,7 +46,7 @@ var (() -> Unit).case_4: () -> Unit
// TESTCASE NUMBER: 5 // TESTCASE NUMBER: 5
val Boolean.case_5: () -> Unit val Boolean.case_5: () -> Unit
get() { get() {
contract { <!CONTRACT_NOT_ALLOWED!>contract<!> {
returns() implies (this@case_5) returns() implies (this@case_5)
} }
@@ -17,6 +17,7 @@ object StandardClassIds {
val BASE_INTERNAL_IR_PACKAGE = BASE_INTERNAL_PACKAGE.child(Name.identifier("ir")) val BASE_INTERNAL_IR_PACKAGE = BASE_INTERNAL_PACKAGE.child(Name.identifier("ir"))
val BASE_COROUTINES_PACKAGE = BASE_KOTLIN_PACKAGE.child(Name.identifier("coroutines")) val BASE_COROUTINES_PACKAGE = BASE_KOTLIN_PACKAGE.child(Name.identifier("coroutines"))
val BASE_ENUMS_PACKAGE = BASE_KOTLIN_PACKAGE.child(Name.identifier("enums")) val BASE_ENUMS_PACKAGE = BASE_KOTLIN_PACKAGE.child(Name.identifier("enums"))
val BASE_CONTRACTS_PACKAGE = BASE_KOTLIN_PACKAGE.child(Name.identifier("contracts"))
val builtInsPackages = setOf( val builtInsPackages = setOf(
BASE_KOTLIN_PACKAGE, BASE_KOTLIN_PACKAGE,
@@ -216,6 +217,8 @@ object StandardClassIds {
val clone = "clone".callableId(Cloneable) val clone = "clone".callableId(Cloneable)
val not = "not".callableId(Boolean) val not = "not".callableId(Boolean)
val contract = "contract".callableId(BASE_CONTRACTS_PACKAGE)
} }
object Java { object Java {