diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonDeclarationCheckers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonDeclarationCheckers.kt index 03118666b62..a79f2a69903 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonDeclarationCheckers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonDeclarationCheckers.kt @@ -140,7 +140,6 @@ object CommonDeclarationCheckers : DeclarationCheckers() { override val controlFlowAnalyserCheckers: Set get() = setOf( FirCallsEffectAnalyzer, - FirReturnsImpliesAnalyzer, ) override val variableAssignmentCfaBasedCheckers: Set diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/ExtendedDeclarationCheckers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/ExtendedDeclarationCheckers.kt index 749478b60a2..f82c44737ee 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/ExtendedDeclarationCheckers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/ExtendedDeclarationCheckers.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers import org.jetbrains.kotlin.fir.analysis.cfa.AbstractFirPropertyInitializationChecker +import org.jetbrains.kotlin.fir.analysis.cfa.FirReturnsImpliesAnalyzer import org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker import org.jetbrains.kotlin.fir.analysis.checkers.declaration.* import org.jetbrains.kotlin.fir.analysis.checkers.extended.* @@ -36,6 +37,7 @@ object ExtendedDeclarationCheckers : DeclarationCheckers() { override val controlFlowAnalyserCheckers: Set get() = setOf( UnreachableCodeChecker, + FirReturnsImpliesAnalyzer, ) override val simpleFunctionCheckers: Set diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/accessToOuterThis.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/accessToOuterThis.fir.kt index e7a79292ac9..652522c39eb 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/accessToOuterThis.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/accessToOuterThis.fir.kt @@ -27,9 +27,9 @@ class Foo { } fun A?.goodWithReceiver() { - contract { + contract { returns() implies (this@goodWithReceiver != null) - } + } } fun A?.badWithReceiver() { diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/illegalConstructionInContractBlock.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/illegalConstructionInContractBlock.fir.kt index 3d144aab7bf..2c161732176 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/illegalConstructionInContractBlock.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/illegalConstructionInContractBlock.fir.kt @@ -48,8 +48,8 @@ fun doWhileInContract(x: Any?) { } fun localValInContract(x: Any?) { - contract { + contract { val y: Int = 42 returns() implies (x is String) - } + } } diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/typeReferences.1.3.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/typeReferences.1.3.fir.kt index c147aea1fa2..f12aef6c73e 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/typeReferences.1.3.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/typeReferences.1.3.fir.kt @@ -5,9 +5,9 @@ import kotlin.contracts.* inline fun referToReifiedGeneric(x: Any?) { - contract { + contract { returns() implies (x is T) - } + } } class Generic { @@ -19,15 +19,15 @@ class Generic { } fun referToSubstituted(x: Any?) { - contract { + contract { returns() implies (x is Generic) - } + } } fun referToSubstitutedWithStar(x: Any?) { - contract { + contract { returns() implies (x is Generic<*>) - } + } } typealias GenericString = Generic @@ -35,19 +35,19 @@ typealias FunctionalType = () -> Unit typealias SimpleType = Int fun referToAliasedGeneric(x: Any?) { - contract { + contract { returns() implies (x is GenericString) - } + } } fun referToAliasedFunctionType(x: Any?) { - contract { + contract { returns() implies (x is FunctionalType) - } + } } fun referToAliasedSimpleType(x: Any?) { - contract { + contract { returns() implies (x is SimpleType) - } + } } diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/typeReferences.1.4.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/typeReferences.1.4.fir.kt index 51e591c35a6..1ebbccf7666 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/typeReferences.1.4.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/typeReferences.1.4.fir.kt @@ -5,9 +5,9 @@ import kotlin.contracts.* inline fun referToReifiedGeneric(x: Any?) { - contract { + contract { returns() implies (x is T) - } + } } class Generic { @@ -19,15 +19,15 @@ class Generic { } fun referToSubstituted(x: Any?) { - contract { + contract { returns() implies (x is Generic) - } + } } fun referToSubstitutedWithStar(x: Any?) { - contract { + contract { returns() implies (x is Generic<*>) - } + } } typealias GenericString = Generic @@ -35,19 +35,19 @@ typealias FunctionalType = () -> Unit typealias SimpleType = Int fun referToAliasedGeneric(x: Any?) { - contract { + contract { returns() implies (x is GenericString) - } + } } fun referToAliasedFunctionType(x: Any?) { - contract { + contract { returns() implies (x is FunctionalType) - } + } } fun referToAliasedSimpleType(x: Any?) { - contract { + contract { returns() implies (x is SimpleType) - } + } } diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/kt45243.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/kt45243.fir.kt deleted file mode 100644 index 2d66e085662..00000000000 --- a/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/kt45243.fir.kt +++ /dev/null @@ -1,19 +0,0 @@ -// ISSUE: KT-45243 - -import kotlin.contracts.ExperimentalContracts -import kotlin.contracts.contract - -@ExperimentalContracts -fun assertNotNull(actual: T) { - contract { returns() implies (actual != null) } -} - -@ExperimentalContracts -fun test_1() { - assertNotNull { } -} - -@ExperimentalContracts -fun test_2() { - assertNotNull({ }) -} diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/kt45243.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/kt45243.kt index 3059fd542a4..5041c7ce9b4 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/kt45243.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/fromStdlib/kt45243.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // ISSUE: KT-45243 import kotlin.contracts.ExperimentalContracts diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/newSyntax/onelineFunctionsContractDescription.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/newSyntax/onelineFunctionsContractDescription.fir.kt index ac3159a381a..d5ec44dbfed 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/contracts/newSyntax/onelineFunctionsContractDescription.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/newSyntax/onelineFunctionsContractDescription.fir.kt @@ -5,7 +5,7 @@ fun calculateNumber(block: () -> Int): Int contract [ callsInPlace(block, InvocationKind.EXACTLY_ONCE) ] = block() -fun calculateResult(num: Int?, calculate: (Int?) -> R): R contract [ +fun calculateResult(num: Int?, calculate: (Int?) -> R): R contract [ callsInPlace(calculate, InvocationKind.EXACTLY_ONCE), returns() implies (num != null) -] = calculate(num) +] = calculate(num) diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/contractsOnMembers.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/contractsOnMembers.fir.kt index 1a38660d1ca..06dc6fcaa16 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/contractsOnMembers.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/contractsOnMembers.fir.kt @@ -17,7 +17,7 @@ open class Foo { } inline fun assertIs(value: Any) { - contract { returns() implies (value is T) } + contract { returns() implies (value is T) } } } diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/nullabilitySmartcastWhenNullability.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/nullabilitySmartcastWhenNullability.fir.kt index 13f8547f10b..9cb0a48acc3 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/nullabilitySmartcastWhenNullability.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/nullabilitySmartcastWhenNullability.fir.kt @@ -31,9 +31,9 @@ fun testNullWhenNull(x: Int?) { // NB. it is the same function as `nullWhenNull`, but annotations specifies other facet of the function behaviour fun notNullWhenNotNull (x: Int?): Int? { - contract { + contract { returns(null) implies (x == null) - } + } return x?.inc() } diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/equalsWithNullableBoolean.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/equalsWithNullableBoolean.fir.kt index 2ef7e9fed20..34b84dc870b 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/equalsWithNullableBoolean.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/equalsWithNullableBoolean.fir.kt @@ -5,9 +5,9 @@ import kotlin.contracts.* fun safeIsString(x: Any?): Boolean? { - contract { + contract { returns(true) implies (x is String) - } + } return x?.let { it is String } } diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/withSubjectNullableBoolean.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/withSubjectNullableBoolean.fir.kt index 58474f78e74..a970853d8e5 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/withSubjectNullableBoolean.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/withSubjectNullableBoolean.fir.kt @@ -5,9 +5,9 @@ import kotlin.contracts.* fun safeIsString(x: Any?): Boolean? { - contract { + contract { returns(true) implies (x is String) - } + } return x?.let { it is String } } diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/runners/AbstractFirDiagnosticTest.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/runners/AbstractFirDiagnosticTest.kt index c4fa6c1b8d2..6a7053fb9fb 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/runners/AbstractFirDiagnosticTest.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/runners/AbstractFirDiagnosticTest.kt @@ -193,7 +193,9 @@ fun TestConfigurationBuilder.baseFirDiagnosticTestConfiguration( forTestsMatching( "compiler/fir/analysis-tests/testData/resolve/extendedCheckers/*" or - "compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/*" + "compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/*" or + "compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/bad/returnsImplies/*" or + "compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/*" ) { defaultDirectives { +WITH_EXTENDED_CHECKERS diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/common/neg/1.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/common/neg/1.fir.kt index 9e2d5e9b021..95728ae9fd1 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/common/neg/1.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/common/neg/1.fir.kt @@ -28,12 +28,12 @@ inline fun case_1(value_1: Int?, block: () -> Unit): Boolean { // TESTCASE NUMBER: 2 inline fun T?.case_2(value_1: Int?, value_2: Any?, block: () -> Unit): Boolean? { - contract { + contract { callsInPlace(block, InvocationKind.AT_MOST_ONCE) returns(true) implies (value_1 == null && this@case_2 == null && value_2 !is Boolean?) returns(false) implies (value_2 is Boolean?) returns(null) implies ((value_1 != null || this@case_2 != null) && value_2 !is Boolean?) - } + } block() diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/8.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/8.fir.kt index c735bca2c36..785ef2b8757 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/8.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/8.fir.kt @@ -18,45 +18,45 @@ import kotlin.contracts.* // TESTCASE NUMBER: 3 fun T?.case_3(value_1: Int?, value_2: Boolean): Boolean { - contract { + contract { returns(true) implies (value_1 != null) returns(false) implies (value_1 == null && !value_2) returns(null) implies (value_1 == null && value_2) - } + } return value_1 == null } // TESTCASE NUMBER: 4 fun case_4(value_1: Number, block: (() -> Unit)?): Boolean? { - contract { + contract { returns(true) implies (block != null) returns(false) implies (value_1 is Int) returns(null) implies (block == null) - } + } return value_1 == null } // TESTCASE NUMBER: 5 fun String?.case_5(value_1: Number?): Boolean? { - contract { + contract { returns(true) implies (value_1 == null) returns(false) implies (this@case_5 == null) returnsNotNull() implies (value_1 is Int) - } + } return value_1 == null } // TESTCASE NUMBER: 6 fun T?.case_6(value_1: Number, value_2: String?): Boolean? { - contract { + contract { returns(true) implies (this@case_6 == null) returns(false) implies (value_1 is Int) returns(null) implies (this@case_6 is String) returnsNotNull() implies (value_2 == null) - } + } return value_1 == null } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/10.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/10.fir.kt index 0ee3d9aef45..5b7eebc891b 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/10.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/10.fir.kt @@ -25,7 +25,7 @@ fun case_1(value_1: Int?, value_2: Int? = 10): Boolean { // TESTCASE NUMBER: 2 fun case_2(value_1: Int? = 10, value_2: Int? = 10, value_3: Int? = 10): Boolean { - contract { returns(true) implies (value_2 != null) } + contract { returns(true) implies (value_2 != null) } return value_1 != null } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/14.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/14.fir.kt index e41d8b5f15f..32c899d473b 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/14.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/14.fir.kt @@ -27,27 +27,27 @@ fun case_1(value_1: Int?): Boolean? { // TESTCASE NUMBER: 2 fun case_2(value_1: Int?): Boolean { - contract { + contract { returns(false) implies (value_1 != null) - } + } return value_1 != null } // TESTCASE NUMBER: 3 fun case_3(value_1: Int?): Boolean? { - contract { + contract { returnsNotNull() implies (value_1 != null) - } + } return value_1 != null } // TESTCASE NUMBER: 4 fun case_4(value_1: Any?): Boolean { - contract { + contract { returnsNotNull() implies (value_1 is Number) - } + } return value_1 is Number } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/8.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/8.fir.kt index 267fce944b8..f2b71b9f7f4 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/8.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/8.fir.kt @@ -29,34 +29,34 @@ fun T?.case_3(value_1: Int?, value_2: Boolean): Boolean { // TESTCASE NUMBER: 4 fun case_4(value_1: Number, block: (() -> Unit)?): Boolean? { - contract { + contract { returns(true) implies (value_1 is Int) returns(false) implies (block == null) returns(null) implies (block != null) - } + } return value_1 == null } // TESTCASE NUMBER: 5 fun String?.case_5(value_1: Number?): Boolean? { - contract { + contract { returns(true) implies (value_1 != null) returns(false) implies (value_1 is Int) returnsNotNull() implies (this@case_5 != null) - } + } return value_1 == null } // TESTCASE NUMBER: 6 fun T?.case_6(value_1: Number, value_2: String?): Boolean? { - contract { + contract { returns(true) implies (this@case_6 != null) returns(false) implies (this@case_6 is String) returns(null) implies (value_1 is Int) returnsNotNull() implies (value_2 != null) - } + } return value_1 == null } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/pos/1.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/pos/1.fir.kt deleted file mode 100644 index 1b0e478854a..00000000000 --- a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/pos/1.fir.kt +++ /dev/null @@ -1,39 +0,0 @@ -// !OPT_IN: kotlin.contracts.ExperimentalContracts - -/* - * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (POSITIVE) - * - * SECTIONS: contracts, declarations, contractBuilder, common - * NUMBER: 1 - * DESCRIPTION: Functions with simple contracts. - */ - -import kotlin.contracts.* - -// TESTCASE NUMBER: 1 -inline fun case_1(block: () -> Unit) { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return block() -} - -// TESTCASE NUMBER: 2 -inline fun case_2(value_1: Int?, block: () -> Unit): Boolean { - contract { - callsInPlace(block, InvocationKind.EXACTLY_ONCE) - returns(true) implies (value_1 != null) - } - block() - return value_1 != null -} - -// TESTCASE NUMBER: 3 -inline fun T?.case_3(value_1: Int?, value_2: Boolean, value_3: Int?, block: () -> Unit): Boolean? { - contract { - callsInPlace(block, InvocationKind.EXACTLY_ONCE) - returns(true) implies (value_1 != null) - returns(false) implies (!value_2) - returnsNotNull() implies (this@case_3 != null && value_3 != null) - } - block() - return value_1 != null -} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/pos/1.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/pos/1.kt index bbc1490fcfa..c25b0f59b21 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/pos/1.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/pos/1.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !OPT_IN: kotlin.contracts.ExperimentalContracts /*