[FIR2IR] Don't build stub FirWhen for converting elvis expression

This commit is contained in:
Mikhail Glukhikh
2020-07-01 12:04:55 +03:00
committed by Dmitriy Novozhilov
parent 6229d2e215
commit 24c8eb43a2
@@ -38,10 +38,7 @@ import org.jetbrains.kotlin.fir.visitors.transformSingle
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.IrGeneratorContextInterface import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.builders.constFalse
import org.jetbrains.kotlin.ir.builders.constTrue
import org.jetbrains.kotlin.ir.builders.elseBranch
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
@@ -560,7 +557,7 @@ class Fir2IrVisitor(
override fun visitElvisCall(elvisCall: FirElvisCall, data: Any?): IrElement { override fun visitElvisCall(elvisCall: FirElvisCall, data: Any?): IrElement {
val subjectName = Name.special("<elvis>") val subjectName = Name.special("<elvis>")
val subjectVariable = buildProperty { val firSubjectVariable = buildProperty {
source = elvisCall.source source = elvisCall.source
session = this@Fir2IrVisitor.session session = this@Fir2IrVisitor.session
origin = FirDeclarationOrigin.Source origin = FirDeclarationOrigin.Source
@@ -572,55 +569,58 @@ class Fir2IrVisitor(
isLocal = true isLocal = true
status = FirDeclarationStatusImpl(Visibilities.LOCAL, Modality.FINAL) status = FirDeclarationStatusImpl(Visibilities.LOCAL, Modality.FINAL)
} }
val subjectVariable = firSubjectVariable.accept(this, null) as IrVariable
@OptIn(FirContractViolation::class) return conversionScope.withWhenSubject(subjectVariable) {
val ref = FirExpressionRef<FirWhenExpression>() elvisCall.convertWithOffsets { startOffset, endOffset ->
val subjectExpression = buildWhenSubjectExpression { val irBranches = listOf(
source = elvisCall.source IrBranchImpl(
whenRef = ref startOffset, endOffset, primitiveOp2(
} startOffset, endOffset, irBuiltIns.eqeqSymbol,
irBuiltIns.booleanType, IrStatementOrigin.EQEQ,
val whenExpression = buildWhenExpression { IrGetValueImpl(
source = elvisCall.source startOffset, endOffset,
this.subject = elvisCall.lhs subjectVariable.type,
this.subjectVariable = subjectVariable subjectVariable.symbol
branches += buildWhenBranch { ),
condition = buildOperatorCall { IrConstImpl(
operation = FirOperation.EQ startOffset, endOffset,
argumentList = buildBinaryArgumentList( irBuiltIns.nothingNType,
subjectExpression, buildConstExpression(null, FirConstKind.Null, null).apply { IrConstKind.Null,
replaceTypeRef(session.builtinTypes.nullableNothingType) value = null
)
),
convertToIrExpression(elvisCall.rhs)
),
buildWhenBranch {
condition = buildElseIfTrueCondition {}
var resultExpression = buildQualifiedAccessExpression {
calleeReference = buildResolvedNamedReference {
name = subjectVariable.name
resolvedSymbol = firSubjectVariable.symbol
}
typeRef = firSubjectVariable.returnTypeRef
} }
) // TODO: replace with .coneType
} val originalType = resultExpression.typeRef.coneTypeUnsafe<ConeKotlinType>()
result = buildSingleExpressionBlock(elvisCall.rhs) val notNullType = originalType.withNullability(ConeNullability.NOT_NULL)
if (notNullType != originalType) {
resultExpression = buildExpressionWithSmartcast {
originalExpression = resultExpression
typeRef = resultExpression.typeRef.resolvedTypeFromPrototype(notNullType)
typesFromSmartCast = setOf(notNullType)
}
}
result = buildSingleExpressionBlock(resultExpression)
}.toIrWhenBranch()
)
generateWhen(
startOffset, endOffset, IrStatementOrigin.ELVIS,
subjectVariable, irBranches, true,
elvisCall.typeRef
)
} }
branches += buildWhenBranch {
condition = buildElseIfTrueCondition {}
var resultExpression = buildQualifiedAccessExpression {
calleeReference = buildResolvedNamedReference {
name = subjectVariable.name
resolvedSymbol = subjectVariable.symbol
}
typeRef = subjectVariable.returnTypeRef
}
val originalType = resultExpression.typeRef.coneTypeUnsafe<ConeKotlinType>()
val notNullType = originalType.withNullability(ConeNullability.NOT_NULL)
if (notNullType != originalType) {
resultExpression = buildExpressionWithSmartcast {
originalExpression = resultExpression
typeRef = resultExpression.typeRef.resolvedTypeFromPrototype(notNullType)
typesFromSmartCast = setOf(notNullType)
}
}
result = buildSingleExpressionBlock(resultExpression)
}
typeRef = elvisCall.typeRef
isExhaustive = true
}.also {
ref.bind(it)
} }
return whenExpression.accept(this, data)
} }
override fun visitWhenExpression(whenExpression: FirWhenExpression, data: Any?): IrElement { override fun visitWhenExpression(whenExpression: FirWhenExpression, data: Any?): IrElement {
@@ -630,7 +630,6 @@ class Fir2IrVisitor(
KtNodeTypes.WHEN -> IrStatementOrigin.WHEN KtNodeTypes.WHEN -> IrStatementOrigin.WHEN
KtNodeTypes.IF -> IrStatementOrigin.IF KtNodeTypes.IF -> IrStatementOrigin.IF
KtNodeTypes.BINARY_EXPRESSION -> when ((psi as? KtBinaryExpression)?.operationToken) { KtNodeTypes.BINARY_EXPRESSION -> when ((psi as? KtBinaryExpression)?.operationToken) {
KtTokens.ELVIS -> IrStatementOrigin.ELVIS
KtTokens.OROR -> IrStatementOrigin.OROR KtTokens.OROR -> IrStatementOrigin.OROR
KtTokens.ANDAND -> IrStatementOrigin.ANDAND KtTokens.ANDAND -> IrStatementOrigin.ANDAND
else -> null else -> null