FIR: add helper to check if a smartcast expressioin is stable

This commit is contained in:
Tianyu Geng
2021-06-09 17:53:56 -07:00
committed by TeamCityServer
parent 3c8693758b
commit 78401b3ae0
8 changed files with 16 additions and 6 deletions
@@ -33,6 +33,7 @@ abstract class FirExpressionWithSmartcast : FirQualifiedAccessExpression() {
abstract val typesFromSmartCast: Collection<ConeKotlinType>
abstract val originalType: FirTypeRef
abstract val smartcastType: FirTypeRef
abstract val isStable: Boolean
abstract val smartcastStability: SmartcastStability
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitExpressionWithSmartcast(this, data)
@@ -29,6 +29,7 @@ abstract class FirExpressionWithSmartcastToNull : FirExpressionWithSmartcast() {
abstract override val explicitReceiver: FirExpression?
abstract override val dispatchReceiver: FirExpression
abstract override val extensionReceiver: FirExpression
abstract override val isStable: Boolean
abstract override val originalExpression: FirQualifiedAccessExpression
abstract override val typesFromSmartCast: Collection<ConeKotlinType>
abstract override val originalType: FirTypeRef
@@ -39,10 +39,12 @@ internal class FirExpressionWithSmartcastImpl(
override val extensionReceiver: FirExpression get() = originalExpression.extensionReceiver
override val calleeReference: FirReference get() = originalExpression.calleeReference
override val originalType: FirTypeRef get() = originalExpression.typeRef
override val isStable: Boolean get() = smartcastStability == SmartcastStability.STABLE_VALUE
// A FirExpressionWithSmartcast is only an effective smartcast if `smartcastStability == SmartcastStability.STABLE_VALUE`. Otherwise,
// it's the same as the `originalExpression` under the hood. The reason we still create such a smartcast expression is for diagnostics
// purpose only.
override val typeRef: FirTypeRef get() = if (smartcastStability == SmartcastStability.STABLE_VALUE) smartcastType else originalType
override val typeRef: FirTypeRef get() = if (isStable) smartcastType else originalType
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcast {
originalExpression = originalExpression.transformSingle(transformer, data)
@@ -7,7 +7,10 @@ package org.jetbrains.kotlin.fir.expressions.impl
import org.jetbrains.kotlin.fir.FirImplementationDetail
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcastToNull
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.references.FirReference
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
@@ -34,12 +37,14 @@ class FirExpressionWithSmartcastToNullImpl(
override val explicitReceiver: FirExpression? get() = originalExpression.explicitReceiver
override val dispatchReceiver: FirExpression get() = originalExpression.dispatchReceiver
override val extensionReceiver: FirExpression get() = originalExpression.extensionReceiver
override val isStable: Boolean get() = smartcastStability == SmartcastStability.STABLE_VALUE
override val calleeReference: FirReference get() = originalExpression.calleeReference
override val originalType: FirTypeRef get() = originalExpression.typeRef
// A FirExpressionWithSmartcast is only an effective smartcast if `smartcastStability == SmartcastStability.STABLE_VALUE`. Otherwise,
// it's the same as the `originalExpression` under the hood. The reason we still create such a smartcast expression is for diagnostics
// purpose only.
override val typeRef: FirTypeRef get() = if (smartcastStability == SmartcastStability.STABLE_VALUE) smartcastType else originalType
override val typeRef: FirTypeRef get() = if (isStable) smartcastType else originalType
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull {
originalExpression = originalExpression.transformSingle(transformer, data)
@@ -464,6 +464,7 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
+field("typesFromSmartCast", "Collection<ConeKotlinType>", null, customType = coneKotlinTypeType)
+field("originalType", typeRef)
+field("smartcastType", typeRef)
+booleanField("isStable")
+smartcastStability
}