FIR: Make LHS of FirVariableAssignment a FirExpression

This way references can even be resolved for erroneous assignments
(e.g. function call, if expression, ... on LHS)

^KT-54648 Fixed
This commit is contained in:
Kirill Rakhman
2023-01-16 09:54:31 +01:00
committed by Space Team
parent e9b8d6db80
commit ace47c06a5
128 changed files with 950 additions and 935 deletions
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.coneTypeSafe
import org.jetbrains.kotlin.fir.expressions.explicitReceiver
@OptIn(DfaInternals::class)
class VariableStorageImpl(private val session: FirSession) : VariableStorage() {
@@ -92,7 +93,7 @@ class VariableStorageImpl(private val session: FirSession) : VariableStorage() {
}
private fun getIdentifierBySymbol(flow: Flow, symbol: FirBasedSymbol<*>, fir: FirElement): Identifier {
val expression = fir as? FirQualifiedAccess
val expression = fir as? FirQualifiedAccessExpression ?: (fir as? FirVariableAssignment)?.lValue as? FirQualifiedAccessExpression
// TODO: don't create receiver variables if not going to create the composed variable either?
return Identifier(
symbol,
@@ -104,10 +105,10 @@ class VariableStorageImpl(private val session: FirSession) : VariableStorage() {
private fun createReal(flow: Flow, identifier: Identifier, originalFir: FirElement, stability: PropertyStability): RealVariable {
val receiver: FirExpression?
val isThisReference: Boolean
val expression: FirQualifiedAccess? = when (originalFir) {
val expression: FirQualifiedAccessExpression? = when (originalFir) {
is FirQualifiedAccessExpression -> originalFir
is FirWhenSubjectExpression -> originalFir.whenRef.value.subject as? FirQualifiedAccessExpression
is FirVariableAssignment -> originalFir
is FirVariableAssignment -> originalFir.unwrapLValue()
else -> null
}
@@ -162,7 +163,7 @@ class VariableStorageImpl(private val session: FirSession) : VariableStorage() {
property.receiverParameter != null -> PropertyStability.PROPERTY_WITH_GETTER
property.getter.let { it != null && it !is FirDefaultPropertyAccessor } -> PropertyStability.PROPERTY_WITH_GETTER
property.modality != Modality.FINAL -> {
val dispatchReceiver = (originalFir.unwrapElement() as? FirQualifiedAccess)?.dispatchReceiver ?: return null
val dispatchReceiver = (originalFir.unwrapElement() as? FirQualifiedAccessExpression)?.dispatchReceiver ?: return null
val receiverType = dispatchReceiver.typeRef.coneTypeSafe<ConeClassLikeType>()?.fullyExpandedType(session) ?: return null
val receiverSymbol = receiverType.lookupTag.toSymbol(session) ?: return null
when (val receiverFir = receiverSymbol.fir) {
@@ -5,9 +5,7 @@
package org.jetbrains.kotlin.fir.resolve.dfa.cfg
import org.jetbrains.kotlin.fir.expressions.FirDoWhileLoop
import org.jetbrains.kotlin.fir.expressions.FirLoop
import org.jetbrains.kotlin.fir.expressions.FirWhileLoop
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.impl.FirElseIfTrueCondition
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.renderer.FirCallNoArgumentsRenderer
@@ -55,7 +53,7 @@ fun CFGNode<*>.render(): String =
CfgRenderer.renderAsCallableDeclarationString(fir)
}"
is VariableAssignmentNode -> "Assignment: ${CfgRenderer.renderElementAsString(fir.lValue)}"
is VariableAssignmentNode -> "Assignment: ${fir.calleeReference?.let(CfgRenderer::renderElementAsString)}"
is FunctionCallNode -> "Function call: ${CfgRenderer.renderElementAsString(fir)}"
is DelegatedConstructorCallNode -> "Delegated constructor call: ${CfgRenderer.renderElementAsString(fir)}"
is StringConcatenationCallNode -> "String concatenation call: ${CfgRenderer.renderElementAsString(fir)}"
@@ -40,10 +40,12 @@ val FirExpression.coneType: ConeKotlinType
val FirElement.symbol: FirBasedSymbol<*>?
get() = when (this) {
is FirResolvable -> symbol
is FirVariableAssignment -> unwrapLValue()?.symbol
is FirDeclaration -> symbol
is FirWhenSubjectExpression -> whenRef.value.subject?.symbol
is FirSafeCallExpression -> selector.symbol
is FirSmartCastExpression -> originalExpression.symbol
is FirDesugaredAssignmentValueReferenceExpression -> expressionRef.value.symbol
else -> null
}?.takeIf {
(this as? FirExpression)?.unwrapSmartcastExpression() is FirThisReceiverExpression ||
@@ -138,10 +138,6 @@ object ConeVariableExpectedError : ConeDiagnostic {
override val reason: String get() = "Variable expected"
}
class ConeValReassignmentError(val variable: FirVariableSymbol<*>) : ConeDiagnostic {
override val reason: String get() = "Re-assigning a val variable"
}
class ConeContractDescriptionError(override val reason: String) : ConeDiagnostic
class ConeIllegalAnnotationError(val name: Name) : ConeDiagnostic {