[FIR] Let prefix inc/dec call getter twice for compatibility with K1
#KT-57179 Fixed
This commit is contained in:
committed by
Space Team
parent
fea344faa4
commit
45d2424ad8
+12
@@ -711,6 +711,18 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir
|
||||
runTest("compiler/testData/diagnostics/tests/PackageQualified.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("prefixIncReturnType.kt")
|
||||
public void testPrefixIncReturnType() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/prefixIncReturnType.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("prefixIncSmartCast.kt")
|
||||
public void testPrefixIncSmartCast() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/prefixIncSmartCast.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("PrimaryConstructors.kt")
|
||||
public void testPrimaryConstructors() throws Exception {
|
||||
|
||||
+12
@@ -711,6 +711,18 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia
|
||||
runTest("compiler/testData/diagnostics/tests/PackageQualified.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("prefixIncReturnType.kt")
|
||||
public void testPrefixIncReturnType() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/prefixIncReturnType.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("prefixIncSmartCast.kt")
|
||||
public void testPrefixIncSmartCast() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/prefixIncSmartCast.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("PrimaryConstructors.kt")
|
||||
public void testPrimaryConstructors() throws Exception {
|
||||
|
||||
+6
@@ -141,6 +141,12 @@ class ErrorNodeDiagnosticCollectorComponent(
|
||||
// See FirForLoopChecker
|
||||
return
|
||||
}
|
||||
|
||||
// Prefix inc/dec on array access will have two calls to .get(...), don't report for the second one.
|
||||
if (source.kind == KtFakeSourceElementKind.DesugaredPrefixSecondGetReference) {
|
||||
return
|
||||
}
|
||||
|
||||
for (coneDiagnostic in diagnostic.toFirDiagnostics(session, source, qualifiedAccessSource)) {
|
||||
reporter.report(coneDiagnostic, context)
|
||||
}
|
||||
|
||||
@@ -653,6 +653,13 @@ class Fir2IrVisitor(
|
||||
return callGenerator.convertToIrSetCall(variableAssignment, explicitReceiverExpression)
|
||||
}
|
||||
|
||||
override fun visitDesugaredAssignmentValueReferenceExpression(
|
||||
desugaredAssignmentValueReferenceExpression: FirDesugaredAssignmentValueReferenceExpression,
|
||||
data: Any?
|
||||
): IrElement {
|
||||
return desugaredAssignmentValueReferenceExpression.expressionRef.value.accept(this, null)
|
||||
}
|
||||
|
||||
override fun <T> visitConstExpression(constExpression: FirConstExpression<T>, data: Any?): IrElement {
|
||||
return constExpression.toIrConst(constExpression.typeRef.toIrType())
|
||||
}
|
||||
|
||||
-18
@@ -26933,12 +26933,6 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr
|
||||
runTest("compiler/testData/codegen/box/intrinsics/prefixIncDec.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("prefixIncDecFir.kt")
|
||||
public void testPrefixIncDecFir() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/intrinsics/prefixIncDecFir.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("rangeFromCollection.kt")
|
||||
public void testRangeFromCollection() throws Exception {
|
||||
@@ -49309,24 +49303,12 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr
|
||||
runTest("compiler/testData/codegen/box/statics/incInClassObject.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("incInClassObjectFir.kt")
|
||||
public void testIncInClassObjectFir() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/statics/incInClassObjectFir.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("incInObject.kt")
|
||||
public void testIncInObject() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/statics/incInObject.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("incInObjectFir.kt")
|
||||
public void testIncInObjectFir() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/statics/incInObjectFir.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inheritedPropertyInClassObject.kt")
|
||||
public void testInheritedPropertyInClassObject() throws Exception {
|
||||
|
||||
-18
@@ -26933,12 +26933,6 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo
|
||||
runTest("compiler/testData/codegen/box/intrinsics/prefixIncDec.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("prefixIncDecFir.kt")
|
||||
public void testPrefixIncDecFir() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/intrinsics/prefixIncDecFir.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("rangeFromCollection.kt")
|
||||
public void testRangeFromCollection() throws Exception {
|
||||
@@ -49309,24 +49303,12 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo
|
||||
runTest("compiler/testData/codegen/box/statics/incInClassObject.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("incInClassObjectFir.kt")
|
||||
public void testIncInClassObjectFir() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/statics/incInClassObjectFir.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("incInObject.kt")
|
||||
public void testIncInObject() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/statics/incInObject.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("incInObjectFir.kt")
|
||||
public void testIncInObjectFir() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/statics/incInObjectFir.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inheritedPropertyInClassObject.kt")
|
||||
public void testInheritedPropertyInClassObject() throws Exception {
|
||||
|
||||
Vendored
+12
-18
@@ -54,44 +54,38 @@ FILE: safeCallsWithUnaryOperators.kt
|
||||
a#?.{ {
|
||||
lval <array>: <implicit> = $subj$.b#
|
||||
lval <index_0>: <implicit> = IntegerLiteral(0)
|
||||
lval <unary-result>: <implicit> = R|<local>/<array>|.get#(R|<local>/<index_0>|).inc#()
|
||||
R|<local>/<array>|.set#(R|<local>/<index_0>|, R|<local>/<unary-result>|)
|
||||
R|<local>/<unary-result>|
|
||||
R|<local>/<array>|.set#(R|<local>/<index_0>|, R|<local>/<array>|.get#(R|<local>/<index_0>|).inc#())
|
||||
R|<local>/<array>|.get#(R|<local>/<index_0>|)
|
||||
}
|
||||
}
|
||||
a#?.{ $subj$.b# }?.{ {
|
||||
lval <array>: <implicit> = $subj$.c#
|
||||
lval <index_0>: <implicit> = IntegerLiteral(0)
|
||||
lval <unary-result>: <implicit> = R|<local>/<array>|.get#(R|<local>/<index_0>|).inc#()
|
||||
R|<local>/<array>|.set#(R|<local>/<index_0>|, R|<local>/<unary-result>|)
|
||||
R|<local>/<unary-result>|
|
||||
R|<local>/<array>|.set#(R|<local>/<index_0>|, R|<local>/<array>|.get#(R|<local>/<index_0>|).inc#())
|
||||
R|<local>/<array>|.get#(R|<local>/<index_0>|)
|
||||
}
|
||||
}
|
||||
lval <array>: <implicit> = a#?.{ $subj$.b# }.c#
|
||||
lval <index_0>: <implicit> = IntegerLiteral(0)
|
||||
lval <unary-result>: <implicit> = R|<local>/<array>|.get#(R|<local>/<index_0>|).inc#()
|
||||
R|<local>/<array>|.set#(R|<local>/<index_0>|, R|<local>/<unary-result>|)
|
||||
R|<local>/<unary-result>|
|
||||
R|<local>/<array>|.set#(R|<local>/<index_0>|, R|<local>/<array>|.get#(R|<local>/<index_0>|).inc#())
|
||||
R|<local>/<array>|.get#(R|<local>/<index_0>|)
|
||||
a#?.{ {
|
||||
lval <array>: <implicit> = $subj$.b#.get#(IntegerLiteral(0))
|
||||
lval <index_0>: <implicit> = IntegerLiteral(0)
|
||||
lval <unary-result>: <implicit> = R|<local>/<array>|.get#(R|<local>/<index_0>|).inc#()
|
||||
R|<local>/<array>|.set#(R|<local>/<index_0>|, R|<local>/<unary-result>|)
|
||||
R|<local>/<unary-result>|
|
||||
R|<local>/<array>|.set#(R|<local>/<index_0>|, R|<local>/<array>|.get#(R|<local>/<index_0>|).inc#())
|
||||
R|<local>/<array>|.get#(R|<local>/<index_0>|)
|
||||
}
|
||||
}
|
||||
a#?.{ $subj$.b# }?.{ {
|
||||
lval <array>: <implicit> = $subj$.c#.get#(IntegerLiteral(0))
|
||||
lval <index_0>: <implicit> = IntegerLiteral(0)
|
||||
lval <unary-result>: <implicit> = R|<local>/<array>|.get#(R|<local>/<index_0>|).inc#()
|
||||
R|<local>/<array>|.set#(R|<local>/<index_0>|, R|<local>/<unary-result>|)
|
||||
R|<local>/<unary-result>|
|
||||
R|<local>/<array>|.set#(R|<local>/<index_0>|, R|<local>/<array>|.get#(R|<local>/<index_0>|).inc#())
|
||||
R|<local>/<array>|.get#(R|<local>/<index_0>|)
|
||||
}
|
||||
}
|
||||
lval <array>: <implicit> = a#?.{ $subj$.b# }.c#.get#(IntegerLiteral(0))
|
||||
lval <index_0>: <implicit> = IntegerLiteral(0)
|
||||
lval <unary-result>: <implicit> = R|<local>/<array>|.get#(R|<local>/<index_0>|).inc#()
|
||||
R|<local>/<array>|.set#(R|<local>/<index_0>|, R|<local>/<unary-result>|)
|
||||
R|<local>/<unary-result>|
|
||||
R|<local>/<array>|.set#(R|<local>/<index_0>|, R|<local>/<array>|.get#(R|<local>/<index_0>|).inc#())
|
||||
R|<local>/<array>|.get#(R|<local>/<index_0>|)
|
||||
++a#?.{ $subj$.b# }.d#()
|
||||
}
|
||||
|
||||
@@ -37,9 +37,8 @@ FILE: unary.kt
|
||||
lval x2: <implicit> = {
|
||||
lval <array>: <implicit> = arr#
|
||||
lval <index_0>: <implicit> = IntegerLiteral(1)
|
||||
lval <unary-result>: <implicit> = R|<local>/<array>|.get#(R|<local>/<index_0>|).inc#()
|
||||
R|<local>/<array>|.set#(R|<local>/<index_0>|, R|<local>/<unary-result>|)
|
||||
R|<local>/<unary-result>|
|
||||
R|<local>/<array>|.set#(R|<local>/<index_0>|, R|<local>/<array>|.get#(R|<local>/<index_0>|).inc#())
|
||||
R|<local>/<array>|.get#(R|<local>/<index_0>|)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -64,9 +63,8 @@ FILE: unary.kt
|
||||
lval x2: <implicit> = {
|
||||
lval <array>: <implicit> = y#.arr#
|
||||
lval <index_0>: <implicit> = IntegerLiteral(1)
|
||||
lval <unary-result>: <implicit> = R|<local>/<array>|.get#(R|<local>/<index_0>|).inc#()
|
||||
R|<local>/<array>|.set#(R|<local>/<index_0>|, R|<local>/<unary-result>|)
|
||||
R|<local>/<unary-result>|
|
||||
R|<local>/<array>|.set#(R|<local>/<index_0>|, R|<local>/<array>|.get#(R|<local>/<index_0>|).inc#())
|
||||
R|<local>/<array>|.get#(R|<local>/<index_0>|)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+61
-143
@@ -471,32 +471,6 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* given:
|
||||
* receiver++
|
||||
*
|
||||
* result:
|
||||
* {
|
||||
* val <unary> = receiver
|
||||
* receiver = <unary>.inc()
|
||||
* ^<unary>
|
||||
* }
|
||||
*
|
||||
* given:
|
||||
* ++receiver
|
||||
*
|
||||
* result:
|
||||
* {
|
||||
* val <unary-result> = receiver.inc()
|
||||
* receiver = <unary-result>
|
||||
* ^<unary-result>
|
||||
* }
|
||||
*
|
||||
*/
|
||||
|
||||
// TODO:
|
||||
// 1. Support receiver capturing for `a?.b++` (elementType == SAFE_ACCESS_EXPRESSION).
|
||||
// 2. Add box test cases for #1 where receiver expression has side effects.
|
||||
fun generateIncrementOrDecrementBlock(
|
||||
// Used to obtain source-element or text
|
||||
wholeExpression: T,
|
||||
@@ -532,91 +506,6 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* given:
|
||||
* receiver++
|
||||
*
|
||||
* result:
|
||||
* {
|
||||
* val <unary> = receiver
|
||||
* val resultVar = <unary>.inc()
|
||||
* appendAssignment(resultVar)
|
||||
* ^<unary>
|
||||
* }
|
||||
*
|
||||
* given:
|
||||
* ++receiver
|
||||
*
|
||||
* result:
|
||||
* {
|
||||
* val <unary-result> = receiver.inc()
|
||||
* val resultVar = <unary-result>
|
||||
* appendAssignment(resultVar)
|
||||
* ^<unary-result>
|
||||
* }
|
||||
*
|
||||
*/
|
||||
private fun FirBlockBuilder.putIncrementOrDecrementStatements(
|
||||
receiver: FirExpression,
|
||||
operationReference: T?,
|
||||
callName: Name, // 'inc' or 'dec'
|
||||
prefix: Boolean,
|
||||
nameIfSimpleReference: Name?, // 'b' if whole expression is simple `b++` or `a.b++`, but not `a[1]++`
|
||||
desugaredSource: KtSourceElement?,
|
||||
appendAssignment: FirBlockBuilder.(resultInitializer: FirExpression, resultVar: FirVariable) -> Unit
|
||||
) {
|
||||
// initialValueVar is only used for postfix increment/decrement (stores the argument value before increment/decrement).
|
||||
val initialValueVar = generateTemporaryVariable(
|
||||
baseModuleData,
|
||||
desugaredSource,
|
||||
SpecialNames.UNARY,
|
||||
receiver
|
||||
)
|
||||
|
||||
// resultInitializer is the expression for `argument.inc()`
|
||||
val resultInitializer = buildFunctionCall {
|
||||
source = desugaredSource
|
||||
calleeReference = buildSimpleNamedReference {
|
||||
val kind = if (prefix) {
|
||||
KtFakeSourceElementKind.DesugaredPrefixNameReference
|
||||
} else {
|
||||
KtFakeSourceElementKind.DesugaredPostfixNameReference
|
||||
}
|
||||
source = operationReference?.toFirSourceElement(kind)
|
||||
name = callName
|
||||
}
|
||||
explicitReceiver = if (prefix) {
|
||||
receiver
|
||||
} else {
|
||||
generateResolvedAccessExpression(desugaredSource, initialValueVar)
|
||||
}
|
||||
origin = FirFunctionCallOrigin.Operator
|
||||
}
|
||||
|
||||
// resultVar is only used for prefix increment/decrement.
|
||||
val resultVar = generateTemporaryVariable(
|
||||
baseModuleData,
|
||||
desugaredSource,
|
||||
SpecialNames.UNARY_RESULT,
|
||||
resultInitializer
|
||||
)
|
||||
|
||||
if (prefix) {
|
||||
if (nameIfSimpleReference != null) {
|
||||
appendAssignment(resultInitializer, resultVar)
|
||||
statements += generateAccessExpression(desugaredSource, desugaredSource, nameIfSimpleReference)
|
||||
} else {
|
||||
statements += resultVar
|
||||
appendAssignment(resultInitializer, resultVar)
|
||||
statements += generateResolvedAccessExpression(desugaredSource, resultVar)
|
||||
}
|
||||
} else {
|
||||
statements += initialValueVar
|
||||
appendAssignment(resultInitializer, resultVar)
|
||||
statements += generateResolvedAccessExpression(desugaredSource, initialValueVar)
|
||||
}
|
||||
}
|
||||
|
||||
private fun T?.unwrap(): T? {
|
||||
// NOTE: By removing surrounding parentheses and labels, FirLabels will NOT be created for those labels.
|
||||
// This should be fine since the label is meaningless and unusable for a ++/-- argument or assignment LHS.
|
||||
@@ -653,9 +542,8 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
|
||||
* val <array> = a
|
||||
* val <index0> = b
|
||||
* val <index1> = c
|
||||
* val <unary-result> = <array>.get(b, c).inc()
|
||||
* <array>.set(b, c, <unary-result>)
|
||||
* ^<unary-result>
|
||||
* <array>.set(b, c, <array>.get(b, c).inc())
|
||||
* ^<array>.get(b, c)
|
||||
* }
|
||||
*
|
||||
*/
|
||||
@@ -668,7 +556,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
|
||||
convert: T.() -> FirExpression
|
||||
): FirExpression {
|
||||
val array = receiver.arrayExpression
|
||||
return buildBlockProbablyUnderSafeCall(
|
||||
return buildBlockPossiblyUnderSafeCall(
|
||||
array, convert, receiver.toFirSourceElement(),
|
||||
) { arrayReceiver ->
|
||||
val baseSource = wholeExpression?.toFirSourceElement()
|
||||
@@ -694,44 +582,74 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
|
||||
).also { statements += it }
|
||||
}
|
||||
|
||||
val firArgument = buildFunctionCall {
|
||||
source = desugaredSource
|
||||
calleeReference = buildSimpleNamedReference {
|
||||
source = receiver?.toFirSourceElement(KtFakeSourceElementKind.ArrayAccessNameReference)
|
||||
name = OperatorNameConventions.GET
|
||||
}
|
||||
explicitReceiver = generateResolvedAccessExpression(arrayVariable.source, arrayVariable)
|
||||
argumentList = buildArgumentList {
|
||||
for (indexVar in indexVariables) {
|
||||
arguments += generateResolvedAccessExpression(indexVar.source, indexVar)
|
||||
}
|
||||
}
|
||||
origin = FirFunctionCallOrigin.Operator
|
||||
}
|
||||
|
||||
putIncrementOrDecrementStatements(
|
||||
firArgument, operationReference, callName, prefix,
|
||||
nameIfSimpleReference = null, desugaredSource
|
||||
) { resultInitializer: FirExpression, resultVar: FirVariable ->
|
||||
statements += buildFunctionCall {
|
||||
fun buildGetCall(referenceSourceKind: KtFakeSourceElementKind = KtFakeSourceElementKind.ArrayAccessNameReference) =
|
||||
buildFunctionCall {
|
||||
source = desugaredSource
|
||||
calleeReference = buildSimpleNamedReference {
|
||||
source = receiver.toFirSourceElement()
|
||||
name = OperatorNameConventions.SET
|
||||
source = receiver?.toFirSourceElement(referenceSourceKind)
|
||||
name = OperatorNameConventions.GET
|
||||
}
|
||||
explicitReceiver = generateResolvedAccessExpression(arrayVariable.source, arrayVariable)
|
||||
argumentList = buildArgumentList {
|
||||
for (indexVar in indexVariables) {
|
||||
arguments += generateResolvedAccessExpression(indexVar.source, indexVar)
|
||||
}
|
||||
arguments += if (prefix) {
|
||||
generateResolvedAccessExpression(source, resultVar)
|
||||
} else {
|
||||
resultInitializer
|
||||
}
|
||||
}
|
||||
origin = FirFunctionCallOrigin.Operator
|
||||
}
|
||||
|
||||
fun buildSetCall(argumentExpression: FirExpression) = buildFunctionCall {
|
||||
source = desugaredSource
|
||||
calleeReference = buildSimpleNamedReference {
|
||||
source = receiver.toFirSourceElement()
|
||||
name = OperatorNameConventions.SET
|
||||
}
|
||||
explicitReceiver = generateResolvedAccessExpression(arrayVariable.source, arrayVariable)
|
||||
argumentList = buildArgumentList {
|
||||
for (indexVar in indexVariables) {
|
||||
arguments += generateResolvedAccessExpression(indexVar.source, indexVar)
|
||||
}
|
||||
arguments += argumentExpression
|
||||
}
|
||||
origin = FirFunctionCallOrigin.Operator
|
||||
}
|
||||
|
||||
fun buildIncDecCall(kind: KtFakeSourceElementKind, receiver: FirExpression) = buildFunctionCall {
|
||||
source = desugaredSource
|
||||
calleeReference = buildSimpleNamedReference {
|
||||
source = operationReference?.toFirSourceElement(kind)
|
||||
name = callName
|
||||
}
|
||||
explicitReceiver = receiver
|
||||
origin = FirFunctionCallOrigin.Operator
|
||||
}
|
||||
|
||||
if (prefix) {
|
||||
statements += buildSetCall(
|
||||
buildIncDecCall(
|
||||
KtFakeSourceElementKind.DesugaredPrefixNameReference,
|
||||
buildGetCall()
|
||||
)
|
||||
)
|
||||
|
||||
statements += buildGetCall(KtFakeSourceElementKind.DesugaredPrefixSecondGetReference)
|
||||
} else {
|
||||
val initialValueVar = generateTemporaryVariable(
|
||||
baseModuleData,
|
||||
desugaredSource,
|
||||
SpecialNames.UNARY,
|
||||
buildGetCall()
|
||||
)
|
||||
|
||||
statements += initialValueVar
|
||||
|
||||
statements += buildSetCall(
|
||||
buildIncDecCall(
|
||||
KtFakeSourceElementKind.DesugaredPostfixNameReference,
|
||||
generateResolvedAccessExpression(desugaredSource, initialValueVar)
|
||||
)
|
||||
)
|
||||
statements += generateResolvedAccessExpression(desugaredSource, initialValueVar)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -741,7 +659,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
|
||||
// a?.{ val receiver = $subj$.f() ... } where `...` is generated by `init(FIR<$subj$.f()>)`
|
||||
//
|
||||
// Otherwise just returns buildBlock { init(FIR<receiver>)) }
|
||||
private fun buildBlockProbablyUnderSafeCall(
|
||||
private fun buildBlockPossiblyUnderSafeCall(
|
||||
receiver: T?,
|
||||
convert: T.() -> FirExpression,
|
||||
sourceElementForError: KtSourceElement?,
|
||||
|
||||
@@ -391,6 +391,16 @@ fun BodyResolveComponents.transformWhenSubjectExpressionUsingSmartcastInfo(
|
||||
return builder.build()
|
||||
}
|
||||
|
||||
fun BodyResolveComponents.transformDesugaredAssignmentValueUsingSmartcastInfo(
|
||||
expression: FirDesugaredAssignmentValueReferenceExpression
|
||||
): FirExpression {
|
||||
val (stability, typesFromSmartCast) = dataFlowAnalyzer.getTypeUsingSmartcastInfo(expression.expressionRef.value) ?: return expression
|
||||
val builder = transformExpressionUsingSmartcastInfo(
|
||||
expression, stability, typesFromSmartCast
|
||||
) ?: return expression
|
||||
return builder.build()
|
||||
}
|
||||
|
||||
private val ConeKotlinType.isKindOfNothing
|
||||
get() = lowerBoundIfFlexible().let { it.isNothing || it.isNullableNothing }
|
||||
|
||||
|
||||
+10
-20
@@ -750,26 +750,16 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
|
||||
}
|
||||
|
||||
if (incrementDecrementExpression.isPrefix) {
|
||||
val targetProperty = expression.calleeReference?.toResolvedPropertySymbol()?.fir
|
||||
val operatorCall = buildAndResolveOperatorCall(expression)
|
||||
|
||||
// Special case for prefix inc/dec on local variable without delegate where unary-result variable generation is skipped.
|
||||
if (targetProperty?.isLocal == true && targetProperty.delegate == null) {
|
||||
// a = a.inc()
|
||||
statements += buildAndResolveVariableAssignment(operatorCall)
|
||||
// ^a
|
||||
statements += targetProperty.toQualifiedAccess(fakeSource = desugaredSource, typeRef = noExpectedType)
|
||||
// If inc() returns a subtype of its receiver type, the variable access should be smart-casted.
|
||||
.transform<FirStatement, ResolutionMode>(transformer, withExpectedType(operatorCall.typeRef.coneType))
|
||||
} else {
|
||||
val unaryResultVariable = generateTemporaryVariable(SpecialNames.UNARY_RESULT, operatorCall)
|
||||
|
||||
// val <unary-result> = a.inc()
|
||||
statements += unaryResultVariable
|
||||
// a = <unary-result>
|
||||
statements += buildAndResolveVariableAssignment(unaryResultVariable.toQualifiedAccess(fakeSource = desugaredSource))
|
||||
// ^<unary-result>
|
||||
statements += unaryResultVariable.toQualifiedAccess(fakeSource = desugaredSource)
|
||||
// a = a.inc()
|
||||
statements += buildAndResolveVariableAssignment(buildAndResolveOperatorCall(expression))
|
||||
// ^a
|
||||
statements += buildDesugaredAssignmentValueReferenceExpression {
|
||||
source = ((expression as? FirErrorExpression)?.expression ?: expression).source
|
||||
?.fakeElement(KtFakeSourceElementKind.DesugaredIncrementOrDecrement)
|
||||
expressionRef = FirExpressionRef<FirExpression>().apply { bind(expression.unwrapSmartcastExpression()) }
|
||||
}.let {
|
||||
it.transform<FirStatement, ResolutionMode>(transformer, ResolutionMode.ContextIndependent)
|
||||
components.transformDesugaredAssignmentValueUsingSmartcastInfo(it)
|
||||
}
|
||||
} else {
|
||||
val unaryVariable = generateTemporaryVariable(SpecialNames.UNARY, expression)
|
||||
|
||||
Reference in New Issue
Block a user