From c156dfe855db0cce7156fa21033c55a7647dd2d5 Mon Sep 17 00:00:00 2001 From: Nikolay Lunyak Date: Tue, 7 Mar 2023 13:41:29 +0200 Subject: [PATCH] [FIR] KT-56877: Allow checking types of containing classes in contracts --- .../transformers/contracts/ConeEffectExtractor.kt | 11 ++++++----- compiler/testData/diagnostics/tests/kt56877.fir.kt | 2 +- .../contracts/dsl/errors/accessToOuterThis.fir.kt | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/contracts/ConeEffectExtractor.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/contracts/ConeEffectExtractor.kt index c0f593a6084..d95a5098ca1 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/contracts/ConeEffectExtractor.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/contracts/ConeEffectExtractor.kt @@ -9,11 +9,9 @@ import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.contracts.description.* -import org.jetbrains.kotlin.fir.declarations.FirContractDescriptionOwner -import org.jetbrains.kotlin.fir.declarations.FirDeclaration -import org.jetbrains.kotlin.fir.declarations.FirProperty -import org.jetbrains.kotlin.fir.declarations.FirValueParameter +import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.expressions.* +import org.jetbrains.kotlin.fir.resolve.getContainingClass import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.coneType import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor @@ -156,7 +154,10 @@ class ConeEffectExtractor( data: Nothing? ): ConeContractDescriptionElement? { val declaration = thisReceiverExpression.calleeReference.boundSymbol?.fir ?: return null - return if (declaration == owner || owner.isAccessorOf(declaration)) { + val callableOwner = owner as? FirCallableDeclaration + val ownerHasReceiver = callableOwner?.receiverParameter != null + val ownerIsMemberOfDeclaration = callableOwner?.getContainingClass(session) == declaration + return if (declaration == owner || owner.isAccessorOf(declaration) || ownerIsMemberOfDeclaration && !ownerHasReceiver) { val type = thisReceiverExpression.typeRef.coneType toValueParameterReference(type, -1, "this") } else { diff --git a/compiler/testData/diagnostics/tests/kt56877.fir.kt b/compiler/testData/diagnostics/tests/kt56877.fir.kt index f73628ea24f..cb2afe36301 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 } 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 b28d5b62980..e7a79292ac9 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/accessToOuterThis.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/accessToOuterThis.fir.kt @@ -10,7 +10,7 @@ class Foo { inner class Bar { fun good() { contract { - returns() implies (this@Bar != null) + returns() implies (this@Bar != null) } }