From 78401b3ae09351bf66995baca185e44661c55b2b Mon Sep 17 00:00:00 2001 From: Tianyu Geng Date: Wed, 9 Jun 2021 17:53:56 -0700 Subject: [PATCH] FIR: add helper to check if a smartcast expressioin is stable --- .../kotlin/fir/backend/Fir2IrImplicitCastInserter.kt | 2 +- .../src/org/jetbrains/kotlin/fir/resolve/ScopeUtils.kt | 2 +- .../kotlin/fir/expressions/FirExpressionWithSmartcast.kt | 1 + .../fir/expressions/FirExpressionWithSmartcastToNull.kt | 1 + .../expressions/impl/FirExpressionWithSmartcastImpl.kt | 4 +++- .../impl/FirExpressionWithSmartcastToNullImpl.kt | 9 +++++++-- .../kotlin/fir/tree/generator/NodeConfigurator.kt | 1 + .../test/frontend/fir/handlers/FirDiagnosticsHandler.kt | 2 +- 8 files changed, 16 insertions(+), 6 deletions(-) diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrImplicitCastInserter.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrImplicitCastInserter.kt index a3ea30cacac..b1bb1771946 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrImplicitCastInserter.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrImplicitCastInserter.kt @@ -271,7 +271,7 @@ class Fir2IrImplicitCastInserter( } override fun visitExpressionWithSmartcast(expressionWithSmartcast: FirExpressionWithSmartcast, data: IrElement): IrExpression { - return if (expressionWithSmartcast.smartcastStability == SmartcastStability.STABLE_VALUE) { + return if (expressionWithSmartcast.isStable) { implicitCastOrExpression(data as IrExpression, expressionWithSmartcast.typeRef) } else { data as IrExpression diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ScopeUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ScopeUtils.kt index 47d6176ae67..771871a663d 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ScopeUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ScopeUtils.kt @@ -35,7 +35,7 @@ fun FirExpressionWithSmartcast.smartcastScope( ): FirTypeScope? { val smartcastType = smartcastType.coneType val smartcastScope = smartcastType.scope(useSiteSession, scopeSession, FakeOverrideTypeCalculator.DoNothing) - if (smartcastStability == SmartcastStability.STABLE_VALUE) { + if (isStable) { return smartcastScope } val originalScope = originalType.coneType.scope(useSiteSession, scopeSession, FakeOverrideTypeCalculator.DoNothing) diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirExpressionWithSmartcast.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirExpressionWithSmartcast.kt index dded469518b..733c3e7a8d9 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirExpressionWithSmartcast.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirExpressionWithSmartcast.kt @@ -33,6 +33,7 @@ abstract class FirExpressionWithSmartcast : FirQualifiedAccessExpression() { abstract val typesFromSmartCast: Collection abstract val originalType: FirTypeRef abstract val smartcastType: FirTypeRef + abstract val isStable: Boolean abstract val smartcastStability: SmartcastStability override fun accept(visitor: FirVisitor, data: D): R = visitor.visitExpressionWithSmartcast(this, data) diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirExpressionWithSmartcastToNull.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirExpressionWithSmartcastToNull.kt index 9181ab521fb..813e65a7538 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirExpressionWithSmartcastToNull.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirExpressionWithSmartcastToNull.kt @@ -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 abstract override val originalType: FirTypeRef diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/impl/FirExpressionWithSmartcastImpl.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/impl/FirExpressionWithSmartcastImpl.kt index 792c18878d5..25496b9e79e 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/impl/FirExpressionWithSmartcastImpl.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/impl/FirExpressionWithSmartcastImpl.kt @@ -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 transformChildren(transformer: FirTransformer, data: D): FirExpressionWithSmartcast { originalExpression = originalExpression.transformSingle(transformer, data) diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/impl/FirExpressionWithSmartcastToNullImpl.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/impl/FirExpressionWithSmartcastToNullImpl.kt index f9fe37f7e30..2d02bac758c 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/impl/FirExpressionWithSmartcastToNullImpl.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/impl/FirExpressionWithSmartcastToNullImpl.kt @@ -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 transformChildren(transformer: FirTransformer, data: D): FirExpressionWithSmartcastToNull { originalExpression = originalExpression.transformSingle(transformer, data) diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt index a3faf7e2ee0..addd4d1ff45 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt @@ -464,6 +464,7 @@ object NodeConfigurator : AbstractFieldConfigurator(FirTreeBuild +field("typesFromSmartCast", "Collection", null, customType = coneKotlinTypeType) +field("originalType", typeRef) +field("smartcastType", typeRef) + +booleanField("isStable") +smartcastStability } diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDiagnosticsHandler.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDiagnosticsHandler.kt index 6fe6e2bacc6..f81957c75c6 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDiagnosticsHandler.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDiagnosticsHandler.kt @@ -176,7 +176,7 @@ class FirDiagnosticsHandler(testServices: TestServices) : FirAnalysisHandler(tes diagnosedRangesToDiagnosticNames: Map> ): FirDiagnosticWithParameters1? = DebugInfoDiagnosticFactory1.EXPRESSION_TYPE.createDebugInfoDiagnostic(element, diagnosedRangesToDiagnosticNames) { - element.typeRef.renderAsString((element as? FirExpressionWithSmartcast)?.takeIf { it.smartcastStability == SmartcastStability.STABLE_VALUE }?.originalType) + element.typeRef.renderAsString((element as? FirExpressionWithSmartcast)?.takeIf { it.isStable }?.originalType) } private fun FirTypeRef.renderAsString(originalTypeRef: FirTypeRef?): String {