From c7a71fec177d31cf3c7fab756cc0687d6a48feae Mon Sep 17 00:00:00 2001 From: Nikolay Lunyak Date: Tue, 7 Mar 2023 13:27:44 +0200 Subject: [PATCH] [FIR] KT-56877: Allow referencing implicit receivers in class contracts --- .../body/resolve/BodyResolveContext.kt | 6 --- ...actContractResolveTransformerDispatcher.kt | 2 +- .../testData/diagnostics/tests/kt56877.fir.kt | 4 +- .../dsl/callUsualContractFunction.fir.kt | 42 ------------------- .../dsl/callUsualContractFunction.kt | 1 + .../dsl/errors/accessToOuterThis.fir.kt | 6 +-- .../dsl/errors/referenceToProperty.1.3.fir.kt | 2 +- .../dsl/errors/referenceToProperty.1.4.fir.kt | 4 +- .../contractBuilder/common/neg/6.fir.kt | 14 +++---- .../contractFunction/neg/2.fir.kt | 6 +-- 10 files changed, 20 insertions(+), 67 deletions(-) delete mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/callUsualContractFunction.fir.kt diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt index 248e9735372..395ca3b73d0 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt @@ -382,15 +382,9 @@ class BodyResolveContext( fun withRegularClass( regularClass: FirRegularClass, holder: SessionHolder, - forContracts: Boolean = false, f: () -> T ): T { storeClassIfNotNested(regularClass, holder.session) - if (forContracts) { - return withTypeParametersOf(regularClass) { - withContainerClass(regularClass, f) - } - } return withTowerDataModeCleanup { if (!regularClass.isInner && containerIfAny is FirRegularClass) { towerDataMode = if (regularClass.isCompanion) { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/contracts/FirAbstractContractResolveTransformerDispatcher.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/contracts/FirAbstractContractResolveTransformerDispatcher.kt index eb344229607..58864c97531 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/contracts/FirAbstractContractResolveTransformerDispatcher.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/contracts/FirAbstractContractResolveTransformerDispatcher.kt @@ -254,7 +254,7 @@ abstract class FirAbstractContractResolveTransformerDispatcher( } override fun transformRegularClass(regularClass: FirRegularClass, data: ResolutionMode): FirStatement { - context.withRegularClass(regularClass, components, forContracts = true) { + context.withRegularClass(regularClass, components) { transformDeclarationContent(regularClass, data) } return regularClass diff --git a/compiler/testData/diagnostics/tests/kt56877.fir.kt b/compiler/testData/diagnostics/tests/kt56877.fir.kt index f114be89e65..f73628ea24f 100644 --- a/compiler/testData/diagnostics/tests/kt56877.fir.kt +++ b/compiler/testData/diagnostics/tests/kt56877.fir.kt @@ -9,7 +9,7 @@ open class Result { fun isSuccess1(): Boolean { contract { - returns(true) implies (this@Result is Success) + returns(true) implies (this@Result is Success) } return this@Result is Success } @@ -18,7 +18,7 @@ open class Result { contract { // implicit type ref // ERROR CLASS: Cannot calculate return type during full-body resolution (local class/object?) - returns(true) implies (this@Result.someProperty == 10) + returns(true) implies (this@Result.someProperty == 10) } return this@Result.someProperty == 10 } diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/callUsualContractFunction.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/callUsualContractFunction.fir.kt deleted file mode 100644 index 4ccdc7ee1a2..00000000000 --- a/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/callUsualContractFunction.fir.kt +++ /dev/null @@ -1,42 +0,0 @@ -// !DIAGNOSTICS: -UNUSED_PARAMETER - -package my - -// Accepts block, can't be distinguished from kotlin.contract without resolve -fun contract(block: () -> Unit) {} - -// Accepts int, potentially can be distinguished from kotlin.contract by PSI, -// but as of Kotlin 1.3.0, we don't do that -fun contract(i: Int) {} - -fun doStuff() {} - -class SomeClass { - - fun contract() {} - - fun callMemberContractWithThis() { - this.contract() - } - - fun callMemberContractWithoutThis() { - contract() - } - - fun callTopLevelSamePsiInMember() { - contract { } - } -} - -fun callTopLevelSamePsi() { - contract { } -} - -fun callTopLevelDifferentPsi() { - contract(42) -} - -fun callTopLevelSamePsiNotFirstStatement() { - doStuff() - contract { } -} diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/callUsualContractFunction.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/callUsualContractFunction.kt index 1c03aa81914..6dc12919cc4 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/callUsualContractFunction.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/callUsualContractFunction.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -UNUSED_PARAMETER package my 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 c830fd148fa..b28d5b62980 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/accessToOuterThis.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/accessToOuterThis.fir.kt @@ -10,13 +10,13 @@ class Foo { inner class Bar { fun good() { contract { - returns() implies (this@Bar != null) + returns() implies (this@Bar != null) } } fun badOuter() { contract { - returns() implies (this@Foo != null) + returns() implies (this@Foo != null) } } @@ -34,7 +34,7 @@ class Foo { fun A?.badWithReceiver() { contract { - returns() implies (this@Bar != null) + returns() implies (this@Bar != null) } } } diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/referenceToProperty.1.3.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/referenceToProperty.1.3.fir.kt index 30531f58ea5..fb2697c3cee 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/referenceToProperty.1.3.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/referenceToProperty.1.3.fir.kt @@ -7,7 +7,7 @@ import kotlin.contracts.* class Foo(val x: Int?) { fun isXNull(): Boolean { contract { - returns(false) implies (x != null) + returns(false) implies (x != null) } return x != null } diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/referenceToProperty.1.4.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/referenceToProperty.1.4.fir.kt index 0fb4a51a3dd..2d8e946868f 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/referenceToProperty.1.4.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/referenceToProperty.1.4.fir.kt @@ -7,8 +7,8 @@ import kotlin.contracts.* class Foo(val x: Int?) { fun isXNull(): Boolean { contract { - returns(false) implies (x != null) + returns(false) implies (x != null) } return x != null } -} \ No newline at end of file +} diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/6.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/6.fir.kt index ffec00815ab..a2dee8ecb31 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/6.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/6.fir.kt @@ -11,16 +11,16 @@ object case_1 { private const val value_3 = false fun case_1_1(): Boolean? { - contract { returnsNotNull() implies (value_1) } + contract { returnsNotNull() implies (value_1) } return if (value_1) true else null } fun case_1_2(): Boolean? { - contract { returns(null) implies (value_2) } + contract { returns(null) implies (value_2) } return if (value_2) null else true } fun case_1_3(): Boolean { - contract { returns(true) implies (value_3) } + contract { returns(true) implies (value_3) } return value_3 } } @@ -42,22 +42,22 @@ class case_2(value_5: Boolean, val value_1: Boolean) { } fun case_2_2(): Boolean? { - contract { returns(null) implies (value_1) } + contract { returns(null) implies (value_1) } return if (value_1) null else true } fun case_2_3(): Boolean { - contract { returns(true) implies (value_2) } + contract { returns(true) implies (value_2) } return value_2 } fun case_2_4(): Boolean { - contract { returns(false) implies (value_3) } + contract { returns(false) implies (value_3) } return !(value_3) } inline fun K.case_2_5(): Boolean? { - contract { returnsNotNull() implies (value_4) } + contract { returnsNotNull() implies (value_4) } return if (value_4) true else null } } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractFunction/neg/2.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractFunction/neg/2.fir.kt index 4e145c98140..e073cc751d2 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractFunction/neg/2.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractFunction/neg/2.fir.kt @@ -32,7 +32,7 @@ fun case_2() { class case_4 : ClassLevel3() { fun T.case_4_1(): Boolean { - contract { returns(false) implies (this@case_4 !is ClassLevel1) } + contract { returns(false) implies (this@case_4 !is ClassLevel1) } return this == null } @@ -60,12 +60,12 @@ class case_4 : ClassLevel3() { class case_5 : ClassLevel5() { inner class case_5_1 { fun K.case_5_1_1() { - contract { returns() implies (this@case_5_1 !is ClassLevel1 && this@case_5_1 != null || this@case_5 is ClassLevel1 && this@case_5_1_1 is Float) } + contract { returns() implies (this@case_5_1 !is ClassLevel1 && this@case_5_1 != null || this@case_5 is ClassLevel1 && this@case_5_1_1 is Float) } if (!(this@case_5_1 !is ClassLevel1 && this@case_5_1 != null || this@case_5 is ClassLevel1 && this is Float)) throw Exception() } fun case_5_1_2() { - contract { returns() implies (this@case_5_1 !is ClassLevel1 || this@case_5 is ClassLevel1 || this@case_5_1 == null) } + contract { returns() implies (this@case_5_1 !is ClassLevel1 || this@case_5 is ClassLevel1 || this@case_5_1 == null) } if (!(this@case_5_1 !is ClassLevel1 || this@case_5 is ClassLevel1 || this@case_5_1 == null)) throw Exception() } }