[FIR] Put new contract syntax under feauture flag

^KT-55171 Fixed
This commit is contained in:
Dmitriy Novozhilov
2023-01-23 18:05:13 +02:00
committed by Space Team
parent 2783aa13f5
commit 4c96495eef
22 changed files with 147 additions and 10 deletions
@@ -1385,6 +1385,12 @@ public class DiagnosisCompilerFirTestdataTestGenerated extends AbstractDiagnosis
runTest("compiler/fir/analysis-tests/testData/resolve/contracts/contractFromOtherModule_samePackage.kt");
}
@Test
@TestMetadata("disabledFeature.kt")
public void testDisabledFeature() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/contracts/disabledFeature.kt");
}
@Test
@TestMetadata("genericContract.kt")
public void testGenericContract() throws Exception {
@@ -1208,6 +1208,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
runTest("compiler/fir/analysis-tests/testData/resolve/contracts/contractFromOtherModule_samePackage.kt");
}
@TestMetadata("disabledFeature.kt")
public void testDisabledFeature() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/contracts/disabledFeature.kt");
}
@TestMetadata("genericContract.kt")
public void testGenericContract() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/contracts/genericContract.kt");
@@ -1,3 +1,4 @@
// LANGUAGE: +ContractSyntaxV2
// SKIP_JAVAC
// This directive is needed to skip this test in LazyBodyIsNotTouchedTilContractsPhaseTestGenerated,
// because it fails to parse module structure of multimodule test
@@ -1,3 +1,4 @@
// LANGUAGE: +ContractSyntaxV2
// SKIP_JAVAC
// This directive is needed to skip this test in LazyBodyIsNotTouchedTilContractsPhaseTestGenerated,
// because it fails to parse module structure of multimodule test
@@ -0,0 +1,34 @@
FILE: disabledFeature.kt
public final inline fun <reified T> requreIsInstance(value: R|kotlin/Any|): R|kotlin/Unit|
[R|Contract description]
<
Returns(WILDCARD) -> value is T
>
{
when () {
(R|<local>/value| !is R|T|) -> {
throw R|java/lang/IllegalArgumentException.IllegalArgumentException|()
}
}
}
public final val R|kotlin/Any?|.myLength: R|kotlin/Int?|
public get(): R|kotlin/Int?|
[R|Contract description]
<
>
{
^ (this@R|/myLength| as? R|kotlin/String|)?.{ $subj$.R|kotlin/String.length| }
}
public final fun test_1(x: R|kotlin/Any|): R|kotlin/Unit| {
R|/requreIsInstance|<R|kotlin/String|>(R|<local>/x|)
R|<local>/x|.R|kotlin/String.length|
}
public final fun test_2(x: R|kotlin/Any|): R|kotlin/Unit| {
when () {
!=(R|<local>/x|.R|/myLength|, Null(null)) -> {
R|<local>/x|.<Unresolved name: length>#
}
}
}
@@ -0,0 +1,26 @@
// LANGUAGE: -ContractSyntaxV2
// WITH_STDLIB
import kotlin.contracts.*
inline fun <reified T> requreIsInstance(value: Any) contract <!UNSUPPORTED_FEATURE!>[
returns() implies (value is T)
]<!> {
if (value !is T) throw IllegalArgumentException()
}
val Any?.myLength: Int?
get() contract <!UNSUPPORTED_FEATURE!>[
<!ERROR_IN_CONTRACT_DESCRIPTION!>returnsNotNull() implies (this@length is String)<!>
]<!> = (this as? String)?.length
fun test_1(x: Any) {
requreIsInstance<String>(x)
x.length
}
fun test_2(x: Any) {
if (x.myLength != null) {
x.<!UNRESOLVED_REFERENCE!>length<!>
}
}
@@ -1,3 +1,4 @@
// LANGUAGE: +ContractSyntaxV2
// WITH_STDLIB
import kotlin.contracts.*
@@ -1,3 +1,4 @@
// LANGUAGE: +ContractSyntaxV2
import kotlin.contracts.*
fun test1(arg: Any?) contract [
@@ -19,4 +20,4 @@ fun test3(arg: Any?): Boolean contract [
] {
require(arg != null)
return true
}
}
@@ -1385,6 +1385,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
runTest("compiler/fir/analysis-tests/testData/resolve/contracts/contractFromOtherModule_samePackage.kt");
}
@Test
@TestMetadata("disabledFeature.kt")
public void testDisabledFeature() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/contracts/disabledFeature.kt");
}
@Test
@TestMetadata("genericContract.kt")
public void testGenericContract() throws Exception {
@@ -1385,6 +1385,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/analysis-tests/testData/resolve/contracts/contractFromOtherModule_samePackage.kt");
}
@Test
@TestMetadata("disabledFeature.kt")
public void testDisabledFeature() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/contracts/disabledFeature.kt");
}
@Test
@TestMetadata("genericContract.kt")
public void testGenericContract() throws Exception {
@@ -56,6 +56,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
FirTailrecFunctionChecker,
FirMemberFunctionsChecker,
FirDataObjectContentChecker,
ContractSyntaxV2FunctionChecker,
)
override val propertyCheckers: Set<FirPropertyChecker>
@@ -73,6 +74,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
FirDelegateUsesExtensionPropertyTypeParameterChecker,
FirTopLevelPropertiesChecker,
FirLocalExtensionPropertyChecker,
ContractSyntaxV2PropertyChecker,
)
override val backingFieldCheckers: Set<FirBackingFieldChecker>
@@ -0,0 +1,38 @@
/*
* 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.declaration
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.config.LanguageFeature
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.FirContractDescriptionOwner
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
object ContractSyntaxV2FunctionChecker : FirSimpleFunctionChecker() {
override fun check(declaration: FirSimpleFunction, context: CheckerContext, reporter: DiagnosticReporter) {
checkFeatureIsEnabled(declaration, context, reporter)
}
}
object ContractSyntaxV2PropertyChecker : FirPropertyChecker() {
override fun check(declaration: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) {
declaration.getter?.let { checkFeatureIsEnabled(it, context, reporter) }
declaration.setter?.let { checkFeatureIsEnabled(it, context, reporter) }
}
}
private fun checkFeatureIsEnabled(declaration: FirContractDescriptionOwner, context: CheckerContext, reporter: DiagnosticReporter) {
val source = declaration.contractDescription.source ?: return
if (source.elementType != KtNodeTypes.CONTRACT_EFFECT_LIST) return
val languageVersionSettings = context.languageVersionSettings
if (!languageVersionSettings.supportsFeature(LanguageFeature.ContractSyntaxV2)) {
reporter.reportOn(source, FirErrors.UNSUPPORTED_FEATURE, LanguageFeature.ContractSyntaxV2 to languageVersionSettings, context)
}
}
@@ -245,6 +245,7 @@ abstract class FirAbstractContractResolveTransformerDispatcher(
val legacyRawContractDescription = buildLegacyRawContractDescription {
this.contractCall = contractCall
this.source = contractDescription.source
}
owner.replaceContractDescription(legacyRawContractDescription)
@@ -1,3 +1,4 @@
// LANGUAGE: +ContractSyntaxV2
// !DIAGNOSTICS: -UNUSED_VARIABLE
import kotlin.contracts.*
@@ -21,4 +22,4 @@ fun bar(arg: Any?, block: () -> Int): Boolean contract [
return true
}
return false
}
}
@@ -1,3 +1,4 @@
// LANGUAGE: +ContractSyntaxV2
// !DIAGNOSTICS: -UNUSED_VARIABLE
import kotlin.contracts.*
@@ -21,4 +22,4 @@ fun bar(arg: Any?, block: () -> Int): Boolean contract <!UNSUPPORTED!>[
return true
}
return false
}
}
@@ -1,10 +1,11 @@
// LANGUAGE: +ContractSyntaxV2
import kotlin.contracts.*
fun calculateNumber(block: () -> Int): Int contract [
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
] = block()
fun <R> calculateResult(num: Int?, calculate: (Int?) -> R): R contract [
fun <R> calculateResult(num: Int?, calculate: (Int?) -> R): R contract <!WRONG_IMPLIES_CONDITION!>[
callsInPlace(calculate, InvocationKind.EXACTLY_ONCE),
returns() implies (num != null)
] = calculate(num)
]<!> = calculate(num)
@@ -1,3 +1,4 @@
// LANGUAGE: +ContractSyntaxV2
import kotlin.contracts.*
fun calculateNumber(block: () -> Int): Int contract <!UNSUPPORTED!>[
@@ -7,4 +8,4 @@ fun calculateNumber(block: () -> Int): Int contract <!UNSUPPORTED!>[
fun <R> calculateResult(num: Int?, calculate: (Int?) -> R): R contract <!UNSUPPORTED!>[
callsInPlace(calculate, InvocationKind.EXACTLY_ONCE),
returns() implies (num != null)
]<!> = calculate(num)
]<!> = calculate(num)
@@ -1,3 +1,4 @@
// LANGUAGE: +ContractSyntaxV2
import kotlin.contracts.*
class A {
@@ -15,4 +16,4 @@ class A {
fun f(arg: Int) = arg * arg
fun g(arg: Double) = arg / 2
}
}
@@ -1,3 +1,4 @@
// LANGUAGE: +ContractSyntaxV2
import kotlin.contracts.*
class A {
@@ -15,4 +16,4 @@ class A {
fun f(arg: Int) = arg * arg
fun g(arg: Double) = arg / 2
}
}
@@ -1,3 +1,4 @@
// LANGUAGE: +ContractSyntaxV2
import kotlin.contracts.*
fun printStr(str: String?) contract [
@@ -19,4 +20,4 @@ fun calculateNumber(block: () -> Int): Int contract [
] {
val num = block()
return num
}
}
@@ -1,3 +1,4 @@
// LANGUAGE: +ContractSyntaxV2
import kotlin.contracts.*
fun printStr(str: String?) contract <!UNSUPPORTED!>[
@@ -19,4 +20,4 @@ fun calculateNumber(block: () -> Int): Int contract <!UNSUPPORTED!>[
]<!> {
val num = block()
return num
}
}
@@ -325,6 +325,7 @@ enum class LanguageFeature(
CustomEqualsInValueClasses(sinceVersion = null, kind = OTHER), // KT-24874
InlineLateinit(sinceVersion = null, kind = OTHER), // KT-23814
EnableDfaWarningsInK2(sinceVersion = null, kind = OTHER), // KT-50965
ContractSyntaxV2(sinceVersion = null, kind = UNSTABLE_FEATURE), // KT-56127
;
init {