[FIR] Properly resolve declarations inside contract calls on CONTRACT phase
This commit is contained in:
committed by
Space Team
parent
01c6c7dc59
commit
9b7b517f43
+7
-6
@@ -29,14 +29,15 @@ internal class LLFirDesignatedContractsResolveTransformer(
|
|||||||
|
|
||||||
private val ideDeclarationTransformer = LLFirDeclarationTransformer(designation)
|
private val ideDeclarationTransformer = LLFirDeclarationTransformer(designation)
|
||||||
|
|
||||||
override val declarationsTransformer: FirDeclarationsResolveTransformer = object : FirDeclarationsContractResolveTransformer(this) {
|
override val contractDeclarationsTransformer: FirDeclarationsContractResolveTransformer
|
||||||
override fun transformDeclarationContent(firClass: FirClass, data: ResolutionMode) {
|
get() = object : FirDeclarationsContractResolveTransformer() {
|
||||||
ideDeclarationTransformer.transformDeclarationContent(this, firClass, data) {
|
override fun transformDeclarationContent(firClass: FirClass, data: ResolutionMode) {
|
||||||
super.transformDeclarationContent(firClass, data)
|
ideDeclarationTransformer.transformDeclarationContent(this, firClass, data) {
|
||||||
firClass
|
super.transformDeclarationContent(firClass, data)
|
||||||
|
firClass
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override fun transformDeclarationContent(declaration: FirDeclaration, data: ResolutionMode): FirDeclaration =
|
override fun transformDeclarationContent(declaration: FirDeclaration, data: ResolutionMode): FirDeclaration =
|
||||||
ideDeclarationTransformer.transformDeclarationContent(this, declaration, data) {
|
ideDeclarationTransformer.transformDeclarationContent(this, declaration, data) {
|
||||||
|
|||||||
+16
-4
@@ -48,6 +48,14 @@ abstract class FirAbstractContractResolveTransformerDispatcher(
|
|||||||
final override val expressionsTransformer: FirExpressionsResolveTransformer =
|
final override val expressionsTransformer: FirExpressionsResolveTransformer =
|
||||||
FirExpressionsResolveTransformer(this)
|
FirExpressionsResolveTransformer(this)
|
||||||
|
|
||||||
|
final override val declarationsTransformer: FirDeclarationsResolveTransformer
|
||||||
|
get() = if (contractMode) contractDeclarationsTransformer else regularDeclarationsTransformer
|
||||||
|
|
||||||
|
protected abstract val contractDeclarationsTransformer: FirDeclarationsContractResolveTransformer
|
||||||
|
private val regularDeclarationsTransformer = FirDeclarationsResolveTransformer(this)
|
||||||
|
|
||||||
|
private var contractMode = true
|
||||||
|
|
||||||
override fun transformAnnotation(annotation: FirAnnotation, data: ResolutionMode): FirStatement {
|
override fun transformAnnotation(annotation: FirAnnotation, data: ResolutionMode): FirStatement {
|
||||||
return annotation
|
return annotation
|
||||||
}
|
}
|
||||||
@@ -56,9 +64,8 @@ abstract class FirAbstractContractResolveTransformerDispatcher(
|
|||||||
return annotationCall
|
return annotationCall
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open class FirDeclarationsContractResolveTransformer(
|
protected open inner class FirDeclarationsContractResolveTransformer :
|
||||||
transformer: FirAbstractBodyResolveTransformerDispatcher
|
FirDeclarationsResolveTransformer(this@FirAbstractContractResolveTransformerDispatcher) {
|
||||||
) : FirDeclarationsResolveTransformer(transformer) {
|
|
||||||
override fun transformSimpleFunction(
|
override fun transformSimpleFunction(
|
||||||
simpleFunction: FirSimpleFunction,
|
simpleFunction: FirSimpleFunction,
|
||||||
data: ResolutionMode
|
data: ResolutionMode
|
||||||
@@ -136,7 +143,12 @@ abstract class FirAbstractContractResolveTransformerDispatcher(
|
|||||||
for (valueParameter in valueParameters) {
|
for (valueParameter in valueParameters) {
|
||||||
context.storeVariable(valueParameter, session)
|
context.storeVariable(valueParameter, session)
|
||||||
}
|
}
|
||||||
val contractCall = contractDescription.contractCall.transformSingle(transformer, ResolutionMode.ContextIndependent)
|
val contractCall = try {
|
||||||
|
contractMode = false
|
||||||
|
contractDescription.contractCall.transformSingle(transformer, ResolutionMode.ContextIndependent)
|
||||||
|
} finally {
|
||||||
|
contractMode = true
|
||||||
|
}
|
||||||
val resolvedId = contractCall.toResolvedCallableSymbol()?.callableId ?: return transformOwnerWithUnresolvedContract(owner)
|
val resolvedId = contractCall.toResolvedCallableSymbol()?.callableId ?: return transformOwnerWithUnresolvedContract(owner)
|
||||||
if (resolvedId != FirContractsDslNames.CONTRACT) return transformOwnerWithUnresolvedContract(owner)
|
if (resolvedId != FirContractsDslNames.CONTRACT) return transformOwnerWithUnresolvedContract(owner)
|
||||||
if (contractCall.arguments.size != 1) return transformOwnerOfErrorContract(owner)
|
if (contractCall.arguments.size != 1) return transformOwnerOfErrorContract(owner)
|
||||||
|
|||||||
+3
-3
@@ -9,7 +9,7 @@ import org.jetbrains.kotlin.fir.FirSession
|
|||||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.*
|
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.*
|
||||||
|
|
||||||
open class FirContractResolveTransformer(
|
class FirContractResolveTransformer(
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
scopeSession: ScopeSession,
|
scopeSession: ScopeSession,
|
||||||
outerBodyResolveContext: BodyResolveContext? = null
|
outerBodyResolveContext: BodyResolveContext? = null
|
||||||
@@ -18,6 +18,6 @@ open class FirContractResolveTransformer(
|
|||||||
scopeSession,
|
scopeSession,
|
||||||
outerBodyResolveContext,
|
outerBodyResolveContext,
|
||||||
) {
|
) {
|
||||||
final override val declarationsTransformer: FirDeclarationsResolveTransformer =
|
override val contractDeclarationsTransformer: FirDeclarationsContractResolveTransformer
|
||||||
FirDeclarationsContractResolveTransformer(this)
|
get() = FirDeclarationsContractResolveTransformer()
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@ fun whenInContract(x: Any?, boolean: Boolean) {
|
|||||||
|
|
||||||
fun forInContract(x: Any?) {
|
fun forInContract(x: Any?) {
|
||||||
contract {
|
contract {
|
||||||
for (i in <!HAS_NEXT_MISSING!>0..1<!>) {
|
for (i in 0..1) {
|
||||||
returns() implies (x is String)
|
returns() implies (x is String)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
-39
@@ -1,39 +0,0 @@
|
|||||||
// !OPT_IN: kotlin.contracts.ExperimentalContracts
|
|
||||||
// !LANGUAGE: +UseReturnsEffect
|
|
||||||
// Issue: KT-26386
|
|
||||||
|
|
||||||
fun myRun(block: () -> Unit) {
|
|
||||||
block()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun contract(block: () -> Unit) {
|
|
||||||
block()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun case_1(): Boolean? {
|
|
||||||
contract { case_1() }
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
fun case_2(): Boolean? {
|
|
||||||
contract { case_3() }
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
fun case_3(): Boolean? {
|
|
||||||
contract { case_2() }
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
fun case4() {
|
|
||||||
contract {
|
|
||||||
myRun {
|
|
||||||
val s: String
|
|
||||||
run {
|
|
||||||
<!UNRESOLVED_REFERENCE!>s<!> = "hello"
|
|
||||||
}
|
|
||||||
<!UNRESOLVED_REFERENCE!>s<!>.length
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// !OPT_IN: kotlin.contracts.ExperimentalContracts
|
// !OPT_IN: kotlin.contracts.ExperimentalContracts
|
||||||
// !LANGUAGE: +UseReturnsEffect
|
// !LANGUAGE: +UseReturnsEffect
|
||||||
// Issue: KT-26386
|
// Issue: KT-26386
|
||||||
|
|||||||
Reference in New Issue
Block a user