FIR: pass elvis expected type to lhs/rhs
This commit is contained in:
committed by
Mikhail Glukhikh
parent
41f56729f9
commit
8f2ad57f7a
@@ -587,8 +587,7 @@ class Fir2IrVisitor(
|
|||||||
fun irGetLhsValue(): IrGetValue =
|
fun irGetLhsValue(): IrGetValue =
|
||||||
IrGetValueImpl(startOffset, endOffset, irLhsVariable.type, irLhsVariable.symbol)
|
IrGetValueImpl(startOffset, endOffset, irLhsVariable.type, irLhsVariable.symbol)
|
||||||
|
|
||||||
// TODO: replace with .coneType
|
val originalType = firLhsVariable.returnTypeRef.coneType
|
||||||
val originalType = firLhsVariable.returnTypeRef.coneTypeUnsafe<ConeKotlinType>()
|
|
||||||
val notNullType = originalType.withNullability(ConeNullability.NOT_NULL)
|
val notNullType = originalType.withNullability(ConeNullability.NOT_NULL)
|
||||||
val irBranches = listOf(
|
val irBranches = listOf(
|
||||||
IrBranchImpl(
|
IrBranchImpl(
|
||||||
|
|||||||
+5
-2
@@ -216,9 +216,12 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirBodyResolveTran
|
|||||||
): CompositeTransformResult<FirStatement> {
|
): CompositeTransformResult<FirStatement> {
|
||||||
if (elvisExpression.calleeReference is FirResolvedNamedReference) return elvisExpression.compose()
|
if (elvisExpression.calleeReference is FirResolvedNamedReference) return elvisExpression.compose()
|
||||||
elvisExpression.transformAnnotations(transformer, data)
|
elvisExpression.transformAnnotations(transformer, data)
|
||||||
elvisExpression.transformLhs(transformer, ResolutionMode.ContextDependent)
|
val expectedArgumentType =
|
||||||
|
if (data is ResolutionMode.WithExpectedType && data.expectedType !is FirImplicitTypeRef) data
|
||||||
|
else ResolutionMode.ContextDependent
|
||||||
|
elvisExpression.transformLhs(transformer, expectedArgumentType)
|
||||||
dataFlowAnalyzer.exitElvisLhs(elvisExpression)
|
dataFlowAnalyzer.exitElvisLhs(elvisExpression)
|
||||||
elvisExpression.transformRhs(transformer, ResolutionMode.ContextDependent)
|
elvisExpression.transformRhs(transformer, expectedArgumentType)
|
||||||
|
|
||||||
val result = syntheticCallGenerator.generateCalleeForElvisExpression(elvisExpression, resolutionContext)?.let {
|
val result = syntheticCallGenerator.generateCalleeForElvisExpression(elvisExpression, resolutionContext)?.let {
|
||||||
callCompleter.completeCall(it, data.expectedType).result
|
callCompleter.completeCall(it, data.expectedType).result
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
|
|
||||||
interface PsiElement {
|
interface PsiElement {
|
||||||
fun <T: PsiElement> findChildByType(i: Int): T? =
|
fun <T: PsiElement> findChildByType(i: Int): T? =
|
||||||
if (i == 42) JetOperationReferenceExpression() as T else throw Exception()
|
if (i == 42) JetOperationReferenceExpression() as T else throw Exception()
|
||||||
|
|||||||
@@ -50,17 +50,17 @@ fun <T : Any?> test(value: T, value2: T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
val x5: Any = { // BLOCK
|
val x5: Any = { // BLOCK
|
||||||
val <elvis>: Int? = magic<Int?>()
|
val <elvis>: Any = magic<Any>()
|
||||||
when {
|
when {
|
||||||
EQEQ(arg0 = <elvis>, arg1 = null) -> 42
|
EQEQ(arg0 = <elvis>, arg1 = null) -> 42
|
||||||
else -> <elvis> /*as Int */
|
else -> <elvis>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val x6: Any = { // BLOCK
|
val x6: Any = { // BLOCK
|
||||||
val <elvis>: T = { // BLOCK
|
val <elvis>: Any = { // BLOCK
|
||||||
val <elvis>: T = value
|
val <elvis>: T = value
|
||||||
when {
|
when {
|
||||||
EQEQ(arg0 = <elvis>, arg1 = null) -> magic<T>()
|
EQEQ(arg0 = <elvis>, arg1 = null) -> magic<Any>()
|
||||||
else -> <elvis>
|
else -> <elvis>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -70,11 +70,11 @@ fun <T : Any?> test(value: T, value2: T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
val x7: Any = { // BLOCK
|
val x7: Any = { // BLOCK
|
||||||
val <elvis>: T = { // BLOCK
|
val <elvis>: Any = { // BLOCK
|
||||||
val <elvis>: T? = magic<T?>()
|
val <elvis>: Any = magic<Any>()
|
||||||
when {
|
when {
|
||||||
EQEQ(arg0 = <elvis>, arg1 = null) -> value
|
EQEQ(arg0 = <elvis>, arg1 = null) -> value
|
||||||
else -> <elvis> /*as T */
|
else -> <elvis>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
when {
|
when {
|
||||||
|
|||||||
+24
-26
@@ -96,68 +96,66 @@ FILE fqName:<root> fileName:/kt30796.kt
|
|||||||
if: CONST Boolean type=kotlin.Boolean value=true
|
if: CONST Boolean type=kotlin.Boolean value=true
|
||||||
then: GET_VAR 'val tmp_5: T of <root>.test [val] declared in <root>.test' type=T of <root>.test origin=null
|
then: GET_VAR 'val tmp_5: T of <root>.test [val] declared in <root>.test' type=T of <root>.test origin=null
|
||||||
VAR name:x5 type:kotlin.Any [val]
|
VAR name:x5 type:kotlin.Any [val]
|
||||||
BLOCK type=kotlin.Int origin=ELVIS
|
BLOCK type=kotlin.Any origin=ELVIS
|
||||||
VAR IR_TEMPORARY_VARIABLE name:tmp_7 type:kotlin.Int? [val]
|
VAR IR_TEMPORARY_VARIABLE name:tmp_7 type:kotlin.Any [val]
|
||||||
CALL 'public final fun magic <T> (): T of <root>.magic declared in <root>' type=kotlin.Int? origin=null
|
CALL 'public final fun magic <T> (): T of <root>.magic declared in <root>' type=kotlin.Any origin=null
|
||||||
<T>: kotlin.Int?
|
<T>: kotlin.Any
|
||||||
WHEN type=kotlin.Int origin=ELVIS
|
WHEN type=kotlin.Any origin=ELVIS
|
||||||
BRANCH
|
BRANCH
|
||||||
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
|
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
|
||||||
arg0: GET_VAR 'val tmp_7: kotlin.Int? [val] declared in <root>.test' type=kotlin.Int? origin=null
|
arg0: GET_VAR 'val tmp_7: kotlin.Any [val] declared in <root>.test' type=kotlin.Any origin=null
|
||||||
arg1: CONST Null type=kotlin.Nothing? value=null
|
arg1: CONST Null type=kotlin.Nothing? value=null
|
||||||
then: CONST Int type=kotlin.Int value=42
|
then: CONST Int type=kotlin.Int value=42
|
||||||
BRANCH
|
BRANCH
|
||||||
if: CONST Boolean type=kotlin.Boolean value=true
|
if: CONST Boolean type=kotlin.Boolean value=true
|
||||||
then: TYPE_OP type=kotlin.Int origin=IMPLICIT_CAST typeOperand=kotlin.Int
|
then: GET_VAR 'val tmp_7: kotlin.Any [val] declared in <root>.test' type=kotlin.Any origin=null
|
||||||
GET_VAR 'val tmp_7: kotlin.Int? [val] declared in <root>.test' type=kotlin.Int? origin=null
|
|
||||||
VAR name:x6 type:kotlin.Any [val]
|
VAR name:x6 type:kotlin.Any [val]
|
||||||
BLOCK type=kotlin.Any origin=ELVIS
|
BLOCK type=kotlin.Any origin=ELVIS
|
||||||
VAR IR_TEMPORARY_VARIABLE name:tmp_8 type:T of <root>.test [val]
|
VAR IR_TEMPORARY_VARIABLE name:tmp_8 type:kotlin.Any [val]
|
||||||
BLOCK type=T of <root>.test origin=ELVIS
|
BLOCK type=kotlin.Any origin=ELVIS
|
||||||
VAR IR_TEMPORARY_VARIABLE name:tmp_9 type:T of <root>.test [val]
|
VAR IR_TEMPORARY_VARIABLE name:tmp_9 type:T of <root>.test [val]
|
||||||
GET_VAR 'value: T of <root>.test declared in <root>.test' type=T of <root>.test origin=null
|
GET_VAR 'value: T of <root>.test declared in <root>.test' type=T of <root>.test origin=null
|
||||||
WHEN type=T of <root>.test origin=ELVIS
|
WHEN type=kotlin.Any origin=ELVIS
|
||||||
BRANCH
|
BRANCH
|
||||||
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
|
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
|
||||||
arg0: GET_VAR 'val tmp_9: T of <root>.test [val] declared in <root>.test' type=T of <root>.test origin=null
|
arg0: GET_VAR 'val tmp_9: T of <root>.test [val] declared in <root>.test' type=T of <root>.test origin=null
|
||||||
arg1: CONST Null type=kotlin.Nothing? value=null
|
arg1: CONST Null type=kotlin.Nothing? value=null
|
||||||
then: CALL 'public final fun magic <T> (): T of <root>.magic declared in <root>' type=T of <root>.test origin=null
|
then: CALL 'public final fun magic <T> (): T of <root>.magic declared in <root>' type=kotlin.Any origin=null
|
||||||
<T>: T of <root>.test
|
<T>: kotlin.Any
|
||||||
BRANCH
|
BRANCH
|
||||||
if: CONST Boolean type=kotlin.Boolean value=true
|
if: CONST Boolean type=kotlin.Boolean value=true
|
||||||
then: GET_VAR 'val tmp_9: T of <root>.test [val] declared in <root>.test' type=T of <root>.test origin=null
|
then: GET_VAR 'val tmp_9: T of <root>.test [val] declared in <root>.test' type=T of <root>.test origin=null
|
||||||
WHEN type=kotlin.Any origin=ELVIS
|
WHEN type=kotlin.Any origin=ELVIS
|
||||||
BRANCH
|
BRANCH
|
||||||
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
|
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
|
||||||
arg0: GET_VAR 'val tmp_8: T of <root>.test [val] declared in <root>.test' type=T of <root>.test origin=null
|
arg0: GET_VAR 'val tmp_8: kotlin.Any [val] declared in <root>.test' type=kotlin.Any origin=null
|
||||||
arg1: CONST Null type=kotlin.Nothing? value=null
|
arg1: CONST Null type=kotlin.Nothing? value=null
|
||||||
then: CONST Int type=kotlin.Int value=42
|
then: CONST Int type=kotlin.Int value=42
|
||||||
BRANCH
|
BRANCH
|
||||||
if: CONST Boolean type=kotlin.Boolean value=true
|
if: CONST Boolean type=kotlin.Boolean value=true
|
||||||
then: GET_VAR 'val tmp_8: T of <root>.test [val] declared in <root>.test' type=T of <root>.test origin=null
|
then: GET_VAR 'val tmp_8: kotlin.Any [val] declared in <root>.test' type=kotlin.Any origin=null
|
||||||
VAR name:x7 type:kotlin.Any [val]
|
VAR name:x7 type:kotlin.Any [val]
|
||||||
BLOCK type=kotlin.Any origin=ELVIS
|
BLOCK type=kotlin.Any origin=ELVIS
|
||||||
VAR IR_TEMPORARY_VARIABLE name:tmp_10 type:T of <root>.test [val]
|
VAR IR_TEMPORARY_VARIABLE name:tmp_10 type:kotlin.Any [val]
|
||||||
BLOCK type=T of <root>.test origin=ELVIS
|
BLOCK type=kotlin.Any origin=ELVIS
|
||||||
VAR IR_TEMPORARY_VARIABLE name:tmp_11 type:T of <root>.test? [val]
|
VAR IR_TEMPORARY_VARIABLE name:tmp_11 type:kotlin.Any [val]
|
||||||
CALL 'public final fun magic <T> (): T of <root>.magic declared in <root>' type=T of <root>.test? origin=null
|
CALL 'public final fun magic <T> (): T of <root>.magic declared in <root>' type=kotlin.Any origin=null
|
||||||
<T>: T of <root>.test?
|
<T>: kotlin.Any
|
||||||
WHEN type=T of <root>.test origin=ELVIS
|
WHEN type=kotlin.Any origin=ELVIS
|
||||||
BRANCH
|
BRANCH
|
||||||
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
|
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
|
||||||
arg0: GET_VAR 'val tmp_11: T of <root>.test? [val] declared in <root>.test' type=T of <root>.test? origin=null
|
arg0: GET_VAR 'val tmp_11: kotlin.Any [val] declared in <root>.test' type=kotlin.Any origin=null
|
||||||
arg1: CONST Null type=kotlin.Nothing? value=null
|
arg1: CONST Null type=kotlin.Nothing? value=null
|
||||||
then: GET_VAR 'value: T of <root>.test declared in <root>.test' type=T of <root>.test origin=null
|
then: GET_VAR 'value: T of <root>.test declared in <root>.test' type=T of <root>.test origin=null
|
||||||
BRANCH
|
BRANCH
|
||||||
if: CONST Boolean type=kotlin.Boolean value=true
|
if: CONST Boolean type=kotlin.Boolean value=true
|
||||||
then: TYPE_OP type=T of <root>.test origin=IMPLICIT_CAST typeOperand=T of <root>.test
|
then: GET_VAR 'val tmp_11: kotlin.Any [val] declared in <root>.test' type=kotlin.Any origin=null
|
||||||
GET_VAR 'val tmp_11: T of <root>.test? [val] declared in <root>.test' type=T of <root>.test? origin=null
|
|
||||||
WHEN type=kotlin.Any origin=ELVIS
|
WHEN type=kotlin.Any origin=ELVIS
|
||||||
BRANCH
|
BRANCH
|
||||||
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
|
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
|
||||||
arg0: GET_VAR 'val tmp_10: T of <root>.test [val] declared in <root>.test' type=T of <root>.test origin=null
|
arg0: GET_VAR 'val tmp_10: kotlin.Any [val] declared in <root>.test' type=kotlin.Any origin=null
|
||||||
arg1: CONST Null type=kotlin.Nothing? value=null
|
arg1: CONST Null type=kotlin.Nothing? value=null
|
||||||
then: CONST Int type=kotlin.Int value=42
|
then: CONST Int type=kotlin.Int value=42
|
||||||
BRANCH
|
BRANCH
|
||||||
if: CONST Boolean type=kotlin.Boolean value=true
|
if: CONST Boolean type=kotlin.Boolean value=true
|
||||||
then: GET_VAR 'val tmp_10: T of <root>.test [val] declared in <root>.test' type=T of <root>.test origin=null
|
then: GET_VAR 'val tmp_10: kotlin.Any [val] declared in <root>.test' type=kotlin.Any origin=null
|
||||||
|
|||||||
Reference in New Issue
Block a user