FIR: introduce FirExpressionWithSmartcastToNull
This new kind of expression encompasses the nullability of the original expression after null check (or equivalent `is Nothing?` check). Unlike FirExpressionWithSmartcast, this expression won't be materialized during conversion to backend IR. Also, Nothing? is discarded when computing the intersection of possible types from smartcast info. In that way, Nothing? is not used during resolution, while such smartcast info is stored in it (and the expression kind itself).
This commit is contained in:
committed by
TeamCityServer
parent
8da183e4f4
commit
8e10b5fdec
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.expressions
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.references.FirReference
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeProjection
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.visitors.*
|
||||
import org.jetbrains.kotlin.fir.FirImplementationDetail
|
||||
|
||||
/*
|
||||
* This file was generated automatically
|
||||
* DO NOT MODIFY IT MANUALLY
|
||||
*/
|
||||
|
||||
abstract class FirExpressionWithSmartcastToNull : FirExpressionWithSmartcast() {
|
||||
abstract override val source: FirSourceElement?
|
||||
abstract override val typeRef: FirTypeRef
|
||||
abstract override val annotations: List<FirAnnotationCall>
|
||||
abstract override val calleeReference: FirReference
|
||||
abstract override val typeArguments: List<FirTypeProjection>
|
||||
abstract override val explicitReceiver: FirExpression?
|
||||
abstract override val dispatchReceiver: FirExpression
|
||||
abstract override val extensionReceiver: FirExpression
|
||||
abstract override val originalExpression: FirQualifiedAccessExpression
|
||||
abstract override val typesFromSmartCast: Collection<ConeKotlinType>
|
||||
abstract override val originalType: FirTypeRef
|
||||
|
||||
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitExpressionWithSmartcastToNull(this, data)
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <E: FirElement, D> transform(transformer: FirTransformer<D>, data: D): E =
|
||||
transformer.transformExpressionWithSmartcastToNull(this, data) as E
|
||||
|
||||
@FirImplementationDetail
|
||||
abstract override fun replaceSource(newSource: FirSourceElement?)
|
||||
|
||||
abstract override fun replaceTypeRef(newTypeRef: FirTypeRef)
|
||||
|
||||
abstract override fun replaceCalleeReference(newCalleeReference: FirReference)
|
||||
|
||||
abstract override fun replaceTypeArguments(newTypeArguments: List<FirTypeProjection>)
|
||||
|
||||
abstract override fun replaceExplicitReceiver(newExplicitReceiver: FirExpression?)
|
||||
|
||||
abstract override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull
|
||||
|
||||
abstract override fun <D> transformCalleeReference(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull
|
||||
|
||||
abstract override fun <D> transformTypeArguments(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull
|
||||
|
||||
abstract override fun <D> transformExplicitReceiver(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull
|
||||
|
||||
abstract override fun <D> transformDispatchReceiver(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull
|
||||
|
||||
abstract override fun <D> transformExtensionReceiver(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull
|
||||
}
|
||||
@@ -91,6 +91,7 @@ import org.jetbrains.kotlin.fir.expressions.FirComponentCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess
|
||||
import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcastToNull
|
||||
import org.jetbrains.kotlin.fir.expressions.FirSafeCallExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirCheckedSafeCallSubject
|
||||
import org.jetbrains.kotlin.fir.expressions.FirGetClassCall
|
||||
@@ -480,6 +481,10 @@ abstract class FirTransformer<in D> : FirVisitor<FirElement, D>() {
|
||||
return transformElement(expressionWithSmartcast, data)
|
||||
}
|
||||
|
||||
open fun transformExpressionWithSmartcastToNull(expressionWithSmartcastToNull: FirExpressionWithSmartcastToNull, data: D): FirStatement {
|
||||
return transformElement(expressionWithSmartcastToNull, data)
|
||||
}
|
||||
|
||||
open fun transformSafeCallExpression(safeCallExpression: FirSafeCallExpression, data: D): FirStatement {
|
||||
return transformElement(safeCallExpression, data)
|
||||
}
|
||||
@@ -980,6 +985,10 @@ abstract class FirTransformer<in D> : FirVisitor<FirElement, D>() {
|
||||
return transformExpressionWithSmartcast(expressionWithSmartcast, data)
|
||||
}
|
||||
|
||||
final override fun visitExpressionWithSmartcastToNull(expressionWithSmartcastToNull: FirExpressionWithSmartcastToNull, data: D): FirStatement {
|
||||
return transformExpressionWithSmartcastToNull(expressionWithSmartcastToNull, data)
|
||||
}
|
||||
|
||||
final override fun visitSafeCallExpression(safeCallExpression: FirSafeCallExpression, data: D): FirStatement {
|
||||
return transformSafeCallExpression(safeCallExpression, data)
|
||||
}
|
||||
|
||||
@@ -91,6 +91,7 @@ import org.jetbrains.kotlin.fir.expressions.FirComponentCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess
|
||||
import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcastToNull
|
||||
import org.jetbrains.kotlin.fir.expressions.FirSafeCallExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirCheckedSafeCallSubject
|
||||
import org.jetbrains.kotlin.fir.expressions.FirGetClassCall
|
||||
@@ -309,6 +310,8 @@ abstract class FirVisitor<out R, in D> {
|
||||
|
||||
open fun visitExpressionWithSmartcast(expressionWithSmartcast: FirExpressionWithSmartcast, data: D): R = visitElement(expressionWithSmartcast, data)
|
||||
|
||||
open fun visitExpressionWithSmartcastToNull(expressionWithSmartcastToNull: FirExpressionWithSmartcastToNull, data: D): R = visitElement(expressionWithSmartcastToNull, data)
|
||||
|
||||
open fun visitSafeCallExpression(safeCallExpression: FirSafeCallExpression, data: D): R = visitElement(safeCallExpression, data)
|
||||
|
||||
open fun visitCheckedSafeCallSubject(checkedSafeCallSubject: FirCheckedSafeCallSubject, data: D): R = visitElement(checkedSafeCallSubject, data)
|
||||
|
||||
@@ -91,6 +91,7 @@ import org.jetbrains.kotlin.fir.expressions.FirComponentCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess
|
||||
import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcastToNull
|
||||
import org.jetbrains.kotlin.fir.expressions.FirSafeCallExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirCheckedSafeCallSubject
|
||||
import org.jetbrains.kotlin.fir.expressions.FirGetClassCall
|
||||
@@ -479,6 +480,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
|
||||
visitElement(expressionWithSmartcast)
|
||||
}
|
||||
|
||||
open fun visitExpressionWithSmartcastToNull(expressionWithSmartcastToNull: FirExpressionWithSmartcastToNull) {
|
||||
visitElement(expressionWithSmartcastToNull)
|
||||
}
|
||||
|
||||
open fun visitSafeCallExpression(safeCallExpression: FirSafeCallExpression) {
|
||||
visitElement(safeCallExpression)
|
||||
}
|
||||
@@ -979,6 +984,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
|
||||
visitExpressionWithSmartcast(expressionWithSmartcast)
|
||||
}
|
||||
|
||||
final override fun visitExpressionWithSmartcastToNull(expressionWithSmartcastToNull: FirExpressionWithSmartcastToNull, data: Nothing?) {
|
||||
visitExpressionWithSmartcastToNull(expressionWithSmartcastToNull)
|
||||
}
|
||||
|
||||
final override fun visitSafeCallExpression(safeCallExpression: FirSafeCallExpression, data: Nothing?) {
|
||||
visitSafeCallExpression(safeCallExpression)
|
||||
}
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.expressions.builder
|
||||
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcastToNull
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirExpressionWithSmartcastToNullImpl
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
|
||||
class FirExpressionWithSmartcastToNullBuilder {
|
||||
lateinit var originalExpression: FirQualifiedAccessExpression
|
||||
lateinit var typeRef: FirTypeRef
|
||||
lateinit var typesFromSmartCast: Collection<ConeKotlinType>
|
||||
|
||||
fun build(): FirExpressionWithSmartcastToNull {
|
||||
return FirExpressionWithSmartcastToNullImpl(originalExpression, typeRef, typesFromSmartCast)
|
||||
}
|
||||
}
|
||||
|
||||
inline fun buildExpressionWithSmartcastToNull(init: FirExpressionWithSmartcastToNullBuilder.() -> Unit): FirExpressionWithSmartcastToNull {
|
||||
return FirExpressionWithSmartcastToNullBuilder().apply(init).build()
|
||||
}
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
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.references.FirReference
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeProjection
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitor
|
||||
import org.jetbrains.kotlin.fir.visitors.transformSingle
|
||||
|
||||
class FirExpressionWithSmartcastToNullImpl(
|
||||
override var originalExpression: FirQualifiedAccessExpression,
|
||||
override val typeRef: FirTypeRef,
|
||||
override val typesFromSmartCast: Collection<ConeKotlinType>
|
||||
) : FirExpressionWithSmartcastToNull() {
|
||||
init {
|
||||
assert(originalExpression.typeRef is FirResolvedTypeRef)
|
||||
}
|
||||
|
||||
override val source: FirSourceElement? get() = originalExpression.source
|
||||
override val annotations: List<FirAnnotationCall> get() = originalExpression.annotations
|
||||
override val typeArguments: List<FirTypeProjection> get() = originalExpression.typeArguments
|
||||
override val explicitReceiver: FirExpression? get() = originalExpression.explicitReceiver
|
||||
override val dispatchReceiver: FirExpression get() = originalExpression.dispatchReceiver
|
||||
override val extensionReceiver: FirExpression get() = originalExpression.extensionReceiver
|
||||
override val calleeReference: FirReference get() = originalExpression.calleeReference
|
||||
override val originalType: FirTypeRef get() = originalExpression.typeRef
|
||||
|
||||
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull {
|
||||
originalExpression = originalExpression.transformSingle(transformer, data)
|
||||
return this
|
||||
}
|
||||
|
||||
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
|
||||
originalExpression.accept(visitor, data)
|
||||
}
|
||||
|
||||
override fun <D> transformCalleeReference(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull {
|
||||
throw IllegalStateException()
|
||||
}
|
||||
|
||||
override fun <D> transformExplicitReceiver(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull {
|
||||
throw IllegalStateException()
|
||||
}
|
||||
|
||||
override fun <D> transformDispatchReceiver(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull {
|
||||
throw IllegalStateException()
|
||||
}
|
||||
|
||||
override fun <D> transformExtensionReceiver(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull {
|
||||
throw IllegalStateException()
|
||||
}
|
||||
|
||||
override fun <D> transformTypeArguments(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull {
|
||||
throw IllegalStateException()
|
||||
}
|
||||
|
||||
override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull {
|
||||
throw IllegalStateException()
|
||||
}
|
||||
|
||||
override fun replaceTypeArguments(newTypeArguments: List<FirTypeProjection>) {
|
||||
throw IllegalStateException()
|
||||
}
|
||||
|
||||
override fun replaceCalleeReference(newCalleeReference: FirReference) {
|
||||
throw IllegalStateException()
|
||||
}
|
||||
|
||||
override fun replaceExplicitReceiver(newExplicitReceiver: FirExpression?) {
|
||||
throw IllegalStateException()
|
||||
}
|
||||
|
||||
override fun replaceTypeRef(newTypeRef: FirTypeRef) {}
|
||||
|
||||
@FirImplementationDetail
|
||||
override fun replaceSource(newSource: FirSourceElement?) {
|
||||
}
|
||||
}
|
||||
+1
@@ -108,6 +108,7 @@ object FirTreeBuilder : AbstractFirTreeBuilder() {
|
||||
val callableReferenceAccess = element("CallableReferenceAccess", Expression, qualifiedAccessExpression)
|
||||
val thisReceiverExpression = element("ThisReceiverExpression", Expression, qualifiedAccessExpression)
|
||||
val expressionWithSmartcast = element("ExpressionWithSmartcast", Expression, qualifiedAccessExpression)
|
||||
val expressionWithSmartcastToNull = element("ExpressionWithSmartcastToNull", Expression, expressionWithSmartcast)
|
||||
val safeCallExpression = element("SafeCallExpression", Expression, expression)
|
||||
val checkedSafeCallSubject = element("CheckedSafeCallSubject", Expression, expression)
|
||||
val getClassCall = element("GetClassCall", Expression, expression, call)
|
||||
|
||||
+1
@@ -156,6 +156,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
||||
impl(qualifiedAccessExpression)
|
||||
|
||||
noImpl(expressionWithSmartcast)
|
||||
noImpl(expressionWithSmartcastToNull)
|
||||
|
||||
impl(getClassCall) {
|
||||
default("argument") {
|
||||
|
||||
+6
@@ -459,6 +459,12 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
|
||||
+field("originalType", typeRef)
|
||||
}
|
||||
|
||||
expressionWithSmartcastToNull.configure {
|
||||
+field("originalExpression", qualifiedAccessExpression)
|
||||
+field("typesFromSmartCast", "Collection<ConeKotlinType>", null, customType = coneKotlinTypeType)
|
||||
+field("originalType", typeRef)
|
||||
}
|
||||
|
||||
safeCallExpression.configure {
|
||||
+field("receiver", expression).withTransform()
|
||||
// Special node that might be used as a reference to receiver of a safe call after null check
|
||||
|
||||
Reference in New Issue
Block a user