PSI2IR: do not generate when subjects multiple times
`in x` is represented as `<subject expression> in x` in psi, so generating the entire call and then replacing the argument with a read of a temporary results in redundant regenerations of the subject. #KT-42054 Fixed #KT-42455 Fixed
This commit is contained in:
Generated
+5
@@ -5667,6 +5667,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/controlStructures/kt416.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt42455.kt")
|
||||
public void testKt42455() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/controlStructures/kt42455.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt513.kt")
|
||||
public void testKt513() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/controlStructures/kt513.kt");
|
||||
|
||||
+9
-11
@@ -473,13 +473,19 @@ fun Generator.getSuperQualifier(resolvedCall: ResolvedCall<*>): ClassDescriptor?
|
||||
return getOrFail(BindingContext.REFERENCE_TARGET, superCallExpression.instanceReference) as ClassDescriptor
|
||||
}
|
||||
|
||||
fun StatementGenerator.pregenerateCall(resolvedCall: ResolvedCall<*>): CallBuilder {
|
||||
fun StatementGenerator.pregenerateCall(resolvedCall: ResolvedCall<*>): CallBuilder =
|
||||
pregenerateCallUsing(resolvedCall) { generateExpression(it) }
|
||||
|
||||
fun StatementGenerator.pregenerateCallUsing(
|
||||
resolvedCall: ResolvedCall<*>,
|
||||
generateArgumentExpression: (KtExpression) -> IrExpression?
|
||||
): CallBuilder {
|
||||
if (resolvedCall.isExtensionInvokeCall()) {
|
||||
return pregenerateExtensionInvokeCall(resolvedCall)
|
||||
}
|
||||
|
||||
val call = pregenerateCallReceivers(resolvedCall)
|
||||
pregenerateValueArguments(call, resolvedCall)
|
||||
pregenerateValueArgumentsUsing(call, resolvedCall, generateArgumentExpression)
|
||||
generateSamConversionForValueArgumentsIfRequired(call, resolvedCall)
|
||||
return call
|
||||
}
|
||||
|
||||
@@ -562,14 +568,6 @@ private fun ResolvedCall<*>.isExtensionInvokeCall(): Boolean {
|
||||
return extensionReceiver != null
|
||||
}
|
||||
|
||||
private fun StatementGenerator.pregenerateValueArguments(call: CallBuilder, resolvedCall: ResolvedCall<*>) {
|
||||
pregenerateValueArgumentsUsing(call, resolvedCall) {
|
||||
generateExpression(it)
|
||||
}
|
||||
|
||||
generateSamConversionForValueArgumentsIfRequired(call, resolvedCall)
|
||||
}
|
||||
|
||||
fun StatementGenerator.generateSamConversionForValueArgumentsIfRequired(call: CallBuilder, resolvedCall: ResolvedCall<*>) {
|
||||
val samConversion = context.extensions.samConversion
|
||||
|
||||
|
||||
+10
-6
@@ -113,7 +113,7 @@ class BranchingExpressionGenerator(statementGenerator: StatementGenerator) : Sta
|
||||
for (ktCondition in ktEntry.conditions) {
|
||||
val irCondition =
|
||||
if (irSubject != null)
|
||||
generateWhenConditionWithSubject(ktCondition, irSubject)
|
||||
generateWhenConditionWithSubject(ktCondition, irSubject, expression.subjectExpression)
|
||||
else
|
||||
generateWhenConditionNoSubject(ktCondition)
|
||||
irBranchCondition = irBranchCondition?.let { context.whenComma(it, irCondition) } ?: irCondition
|
||||
@@ -190,12 +190,14 @@ class BranchingExpressionGenerator(statementGenerator: StatementGenerator) : Sta
|
||||
private fun generateWhenConditionNoSubject(ktCondition: KtWhenCondition): IrExpression =
|
||||
(ktCondition as KtWhenConditionWithExpression).expression!!.genExpr()
|
||||
|
||||
private fun generateWhenConditionWithSubject(ktCondition: KtWhenCondition, irSubject: IrVariable): IrExpression {
|
||||
private fun generateWhenConditionWithSubject(
|
||||
ktCondition: KtWhenCondition, irSubject: IrVariable, ktSubject: KtExpression?
|
||||
): IrExpression {
|
||||
return when (ktCondition) {
|
||||
is KtWhenConditionWithExpression ->
|
||||
generateEqualsCondition(irSubject, ktCondition)
|
||||
is KtWhenConditionInRange ->
|
||||
generateInRangeCondition(irSubject, ktCondition)
|
||||
generateInCondition(irSubject, ktCondition, ktSubject)
|
||||
is KtWhenConditionIsPattern ->
|
||||
generateIsPatternCondition(irSubject, ktCondition)
|
||||
else ->
|
||||
@@ -227,11 +229,13 @@ class BranchingExpressionGenerator(statementGenerator: StatementGenerator) : Sta
|
||||
irInstanceOf
|
||||
}
|
||||
|
||||
private fun generateInRangeCondition(irSubject: IrVariable, ktCondition: KtWhenConditionInRange): IrExpression {
|
||||
val inCall = statementGenerator.pregenerateCall(getResolvedCall(ktCondition.operationReference)!!)
|
||||
private fun generateInCondition(irSubject: IrVariable, ktCondition: KtWhenConditionInRange, ktSubject: KtExpression?): IrExpression {
|
||||
val startOffset = ktCondition.startOffsetSkippingComments
|
||||
val endOffset = ktCondition.endOffset
|
||||
inCall.irValueArgumentsByIndex[0] = irSubject.loadAt(startOffset, startOffset)
|
||||
val inCall = statementGenerator.pregenerateCallUsing(getResolvedCall(ktCondition.operationReference)!!) {
|
||||
// In a `when` with a subject, `in x` is represented as `x.contains(<reference to subject expression>)`.
|
||||
if (it === ktSubject) irSubject.loadAt(startOffset, startOffset) else statementGenerator.generateExpression(it)
|
||||
}
|
||||
val inOperator = getInfixOperator(ktCondition.operationReference.getReferencedNameElementType())
|
||||
val irInCall = CallGenerator(statementGenerator).generateCall(ktCondition, inCall, inOperator)
|
||||
return when (inOperator) {
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
// WITH_RUNTIME
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
fun box(): String {
|
||||
val xs = listOf(1, 2, 3)
|
||||
return when (xs.first { it > 1 }) {
|
||||
in xs -> "OK"
|
||||
else -> "fail"
|
||||
}
|
||||
}
|
||||
+5
@@ -5702,6 +5702,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/controlStructures/kt416.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt42455.kt")
|
||||
public void testKt42455() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/controlStructures/kt42455.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt513.kt")
|
||||
public void testKt513() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/controlStructures/kt513.kt");
|
||||
|
||||
+5
@@ -5702,6 +5702,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/controlStructures/kt416.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt42455.kt")
|
||||
public void testKt42455() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/controlStructures/kt42455.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt513.kt")
|
||||
public void testKt513() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/controlStructures/kt513.kt");
|
||||
|
||||
+5
@@ -5667,6 +5667,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/controlStructures/kt416.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt42455.kt")
|
||||
public void testKt42455() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/controlStructures/kt42455.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt513.kt")
|
||||
public void testKt513() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/controlStructures/kt513.kt");
|
||||
|
||||
Generated
+5
@@ -4572,6 +4572,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
|
||||
runTest("compiler/testData/codegen/box/controlStructures/kt416.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt42455.kt")
|
||||
public void testKt42455() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/controlStructures/kt42455.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt513.kt")
|
||||
public void testKt513() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/controlStructures/kt513.kt");
|
||||
|
||||
Generated
+5
@@ -4572,6 +4572,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/controlStructures/kt416.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt42455.kt")
|
||||
public void testKt42455() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/controlStructures/kt42455.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt513.kt")
|
||||
public void testKt513() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/controlStructures/kt513.kt");
|
||||
|
||||
+5
@@ -4572,6 +4572,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/controlStructures/kt416.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt42455.kt")
|
||||
public void testKt42455() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/controlStructures/kt42455.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt513.kt")
|
||||
public void testKt513() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/controlStructures/kt513.kt");
|
||||
|
||||
Reference in New Issue
Block a user