[FIR2IR] Simplify logic around annotationMode

#KT-58005 Fixed
This commit is contained in:
Ivan Kylchik
2023-04-28 18:01:40 +02:00
committed by Space Team
parent 59ea7717dd
commit 73cc73115e
10 changed files with 156 additions and 60 deletions
@@ -69,10 +69,24 @@ class Fir2IrVisitor(
private val operatorGenerator = OperatorExpressionGenerator(components, this, conversionScope)
private var _annotationMode: Boolean = false
public val annotationMode: Boolean
get() = _annotationMode
private fun FirTypeRef.toIrType(): IrType = with(typeConverter) { toIrType() }
private fun <T : IrDeclaration> applyParentFromStackTo(declaration: T): T = conversionScope.applyParentFromStackTo(declaration)
internal inline fun <T> withAnnotationMode(enableAnnotationMode: Boolean = true, block: () -> T): T {
val oldAnnotationMode = _annotationMode
_annotationMode = enableAnnotationMode
try {
return block()
} finally {
_annotationMode = oldAnnotationMode
}
}
override fun visitElement(element: FirElement, data: Any?): IrElement {
TODO("Should not be here: ${element::class} ${element.render()}")
}
@@ -412,33 +426,32 @@ class Fir2IrVisitor(
endOffset,
varargArgumentsExpression.typeRef.toIrType(),
varargArgumentsExpression.varargElementType.toIrType(),
varargArgumentsExpression.arguments.map { it.convertToIrVarargElement(annotationMode = false) }
varargArgumentsExpression.arguments.map { it.convertToIrVarargElement() }
)
}
}
private fun FirExpression.convertToIrVarargElement(annotationMode: Boolean): IrVarargElement =
private fun FirExpression.convertToIrVarargElement(): IrVarargElement =
if (this is FirSpreadArgumentExpression || this is FirNamedArgumentExpression && this.isSpread) {
IrSpreadElementImpl(
source?.startOffset ?: UNDEFINED_OFFSET,
source?.endOffset ?: UNDEFINED_OFFSET,
convertToIrExpression(this, annotationMode)
convertToIrExpression(this)
)
} else convertToIrExpression(this, annotationMode)
} else convertToIrExpression(this)
private fun convertToIrCall(functionCall: FirFunctionCall, annotationMode: Boolean): IrExpression {
private fun convertToIrCall(functionCall: FirFunctionCall): IrExpression {
if (functionCall.isCalleeDynamic &&
functionCall.calleeReference.name == OperatorNameConventions.SET &&
functionCall.calleeReference.source?.kind == KtFakeSourceElementKind.ArrayAccessNameReference
) {
return convertToIrArrayAccessDynamicCall(functionCall, annotationMode)
return convertToIrArrayAccessDynamicCall(functionCall)
}
return convertToIrCall(functionCall, annotationMode, dynamicOperator = null)
return convertToIrCall(functionCall, dynamicOperator = null)
}
private fun convertToIrCall(
functionCall: FirFunctionCall,
annotationMode: Boolean,
dynamicOperator: IrDynamicOperator?
): IrExpression {
val explicitReceiverExpression = convertToIrReceiverExpression(functionCall.explicitReceiver, functionCall.calleeReference)
@@ -446,21 +459,19 @@ class Fir2IrVisitor(
functionCall,
functionCall.typeRef,
explicitReceiverExpression,
annotationMode,
dynamicOperator
)
}
private fun convertToIrArrayAccessDynamicCall(functionCall: FirFunctionCall, annotationMode: Boolean): IrExpression {
private fun convertToIrArrayAccessDynamicCall(functionCall: FirFunctionCall): IrExpression {
val explicitReceiverExpression = convertToIrCall(
functionCall, annotationMode, dynamicOperator = IrDynamicOperator.ARRAY_ACCESS
functionCall, dynamicOperator = IrDynamicOperator.ARRAY_ACCESS
)
if (explicitReceiverExpression is IrDynamicOperatorExpression) {
explicitReceiverExpression.arguments.removeLast()
}
val result = callGenerator.convertToIrCall(
functionCall, functionCall.typeRef, explicitReceiverExpression,
annotationMode = annotationMode,
dynamicOperator = IrDynamicOperator.EQ
)
if (result is IrDynamicOperatorExpression) {
@@ -474,7 +485,7 @@ class Fir2IrVisitor(
}
override fun visitFunctionCall(functionCall: FirFunctionCall, data: Any?): IrExpression = whileAnalysing(session, functionCall) {
return convertToIrCall(functionCall = functionCall, annotationMode = false)
return convertToIrCall(functionCall = functionCall)
}
override fun visitSafeCallExpression(
@@ -521,13 +532,12 @@ class Fir2IrVisitor(
private fun convertQualifiedAccessExpression(
qualifiedAccessExpression: FirQualifiedAccessExpression,
annotationMode: Boolean = false
): IrExpression = whileAnalysing(session, qualifiedAccessExpression) {
val explicitReceiverExpression = convertToIrReceiverExpression(
qualifiedAccessExpression.explicitReceiver, qualifiedAccessExpression.calleeReference
)
return callGenerator.convertToIrCall(
qualifiedAccessExpression, qualifiedAccessExpression.typeRef, explicitReceiverExpression, annotationMode = annotationMode
qualifiedAccessExpression, qualifiedAccessExpression.typeRef, explicitReceiverExpression
)
}
@@ -678,7 +688,6 @@ class Fir2IrVisitor(
internal fun convertToIrExpression(
expression: FirExpression,
annotationMode: Boolean = false,
isDelegate: Boolean = false
): IrExpression {
return when (expression) {
@@ -691,20 +700,9 @@ class Fir2IrVisitor(
)
}
else -> {
val unwrappedExpression = expression.unwrapArgument()
if (annotationMode) {
when (unwrappedExpression) {
is FirFunctionCall -> convertToIrCall(unwrappedExpression, true)
is FirArrayOfCall -> convertToArrayOfCall(unwrappedExpression, true)
is FirCallableReferenceAccess -> convertCallableReferenceAccess(unwrappedExpression, isDelegate)
is FirQualifiedAccessExpression -> convertQualifiedAccessExpression(unwrappedExpression, true)
else -> expression.accept(this, null) as IrExpression
}
} else {
when (unwrappedExpression) {
is FirCallableReferenceAccess -> convertCallableReferenceAccess(unwrappedExpression, isDelegate)
else -> expression.accept(this, null) as IrExpression
}
when (val unwrappedExpression = expression.unwrapArgument()) {
is FirCallableReferenceAccess -> convertCallableReferenceAccess(unwrappedExpression, isDelegate)
else -> expression.accept(this, null) as IrExpression
}
}
}.let {
@@ -881,11 +879,10 @@ class Fir2IrVisitor(
qualifiedAccess,
qualifiedAccess.typeRef,
convertToIrReceiverExpression(receiverExpression, qualifiedAccess.calleeReference),
annotationMode = false
)
}
return callGenerator.convertToIrCall(
operationCall, operationCall.typeRef, explicitReceiverExpression, annotationMode = false
operationCall, operationCall.typeRef, explicitReceiverExpression
)
}
@@ -1364,7 +1361,7 @@ class Fir2IrVisitor(
classifierStorage.getIrClassSymbol(it)
}
private fun convertToArrayOfCall(arrayOfCall: FirArrayOfCall, annotationMode: Boolean): IrVararg {
private fun convertToArrayOfCall(arrayOfCall: FirArrayOfCall): IrVararg {
return arrayOfCall.convertWithOffsets { startOffset, endOffset ->
val arrayType = arrayOfCall.typeRef.toIrType()
val elementType = if (arrayOfCall.typeRef is FirResolvedTypeRef) {
@@ -1376,13 +1373,13 @@ class Fir2IrVisitor(
startOffset, endOffset,
type = arrayType,
varargElementType = elementType,
elements = arrayOfCall.arguments.map { it.convertToIrVarargElement(annotationMode) }
elements = arrayOfCall.arguments.map { it.convertToIrVarargElement() }
)
}
}
override fun visitArrayOfCall(arrayOfCall: FirArrayOfCall, data: Any?): IrElement = whileAnalysing(session, arrayOfCall) {
return convertToArrayOfCall(arrayOfCall, annotationMode = false)
return convertToArrayOfCall(arrayOfCall)
}
override fun visitAugmentedArraySetCall(
@@ -294,7 +294,6 @@ class CallAndReferenceGenerator(
type: IrType,
calleeReference: FirReference,
symbol: FirBasedSymbol<*>,
annotationMode: Boolean = false,
dynamicOperator: IrDynamicOperator? = null,
noArguments: Boolean = false,
): IrExpression {
@@ -332,14 +331,13 @@ class CallAndReferenceGenerator(
}
}
.applyTypeArguments(qualifiedAccess)
.applyCallArguments((qualifiedAccess as? FirCall)?.takeIf { !noArguments }, annotationMode)
.applyCallArguments((qualifiedAccess as? FirCall)?.takeIf { !noArguments })
}
fun convertToIrCall(
qualifiedAccess: FirQualifiedAccessExpression,
typeRef: FirTypeRef,
explicitReceiverExpression: IrExpression?,
annotationMode: Boolean = false,
dynamicOperator: IrDynamicOperator? = null,
variableAsFunctionMode: Boolean = false,
noArguments: Boolean = false
@@ -362,7 +360,6 @@ class CallAndReferenceGenerator(
type,
calleeReference,
firSymbol ?: error("Must have had a symbol"),
annotationMode,
dynamicOperator,
noArguments,
)
@@ -445,7 +442,7 @@ class CallAndReferenceGenerator(
}
}
is IrFieldSymbol -> if (annotationMode) {
is IrFieldSymbol -> if (visitor.annotationMode) {
val resolvedSymbol = calleeReference.toResolvedCallableSymbol() ?: error("should have resolvedSymbol")
val returnType = resolvedSymbol.resolvedReturnTypeRef.toIrType()
val firConstExpression = (resolvedSymbol.fir as FirVariable).initializer as? FirConstExpression<*>
@@ -474,7 +471,7 @@ class CallAndReferenceGenerator(
else -> generateErrorCallExpression(startOffset, endOffset, calleeReference, type)
}
}.applyTypeArguments(qualifiedAccess).applyReceivers(qualifiedAccess, convertedExplicitReceiver)
.applyCallArguments(qualifiedAccess, annotationMode)
.applyCallArguments(qualifiedAccess)
} catch (e: Throwable) {
throw IllegalStateException(
"Error while translating ${qualifiedAccess.render()} " +
@@ -647,7 +644,7 @@ class CallAndReferenceGenerator(
?.fullyExpandedType(session) as? ConeLookupTagBasedType
val type = coneType?.toIrType()
val symbol = type?.classifierOrNull
return annotation.convertWithOffsets { startOffset, endOffset ->
val irConstructorCall = annotation.convertWithOffsets { startOffset, endOffset ->
when (symbol) {
is IrClassSymbol -> {
val irClass = symbol.owner
@@ -694,7 +691,10 @@ class CallAndReferenceGenerator(
)
}
}
}.applyCallArguments(annotation.toAnnotationCall(), annotationMode = true)
}
return visitor.withAnnotationMode {
irConstructorCall.applyCallArguments(annotation.toAnnotationCall())
}
}
private fun FirAnnotation.toAnnotationCall(): FirAnnotationCall? {
@@ -779,7 +779,6 @@ class CallAndReferenceGenerator(
internal fun IrExpression.applyCallArguments(
statement: FirStatement?,
annotationMode: Boolean
): IrExpression {
val call = statement as? FirCall
return when (this) {
@@ -790,11 +789,10 @@ class CallAndReferenceGenerator(
if (argumentsCount <= valueArgumentsCount) {
apply {
val (valueParameters, argumentMapping, substitutor) = extractArgumentsMapping(call)
if (argumentMapping != null && (annotationMode || argumentMapping.isNotEmpty())) {
if (argumentMapping != null && (visitor.annotationMode || argumentMapping.isNotEmpty())) {
if (valueParameters != null) {
return applyArgumentsWithReorderingIfNeeded(
argumentMapping, valueParameters, substitutor, annotationMode,
contextReceiverCount,
argumentMapping, valueParameters, substitutor, contextReceiverCount,
)
}
}
@@ -828,12 +826,12 @@ class CallAndReferenceGenerator(
is IrDynamicOperatorExpression -> apply {
if (call == null) return@apply
val (valueParameters, argumentMapping, substitutor) = extractArgumentsMapping(call)
if (argumentMapping != null && (annotationMode || argumentMapping.isNotEmpty())) {
if (argumentMapping != null && (visitor.annotationMode || argumentMapping.isNotEmpty())) {
if (valueParameters != null) {
val dynamicCallVarargArgument = argumentMapping.keys.firstOrNull() as? FirVarargArgumentsExpression
?: error("Dynamic call must have a single vararg argument")
for (argument in dynamicCallVarargArgument.arguments) {
val irArgument = convertArgument(argument, null, substitutor, annotationMode)
val irArgument = convertArgument(argument, null, substitutor)
arguments.add(irArgument)
}
}
@@ -870,15 +868,14 @@ class CallAndReferenceGenerator(
argumentMapping: Map<FirExpression, FirValueParameter>,
valueParameters: List<FirValueParameter>,
substitutor: ConeSubstitutor,
annotationMode: Boolean,
contextReceiverCount: Int,
): IrExpression {
val converted = argumentMapping.entries.map { (argument, parameter) ->
parameter to convertArgument(argument, parameter, substitutor, annotationMode)
parameter to convertArgument(argument, parameter, substitutor)
}
// If none of the parameters have side effects, the evaluation order doesn't matter anyway.
// For annotations, this is always true, since arguments have to be compile-time constants.
if (!annotationMode && !converted.all { (_, irArgument) -> irArgument.hasNoSideEffects() } &&
if (!visitor.annotationMode && !converted.all { (_, irArgument) -> irArgument.hasNoSideEffects() } &&
needArgumentReordering(argumentMapping.values, valueParameters)
) {
return IrBlockImpl(startOffset, endOffset, type, IrStatementOrigin.ARGUMENTS_REORDERING_FOR_CALL).apply {
@@ -903,12 +900,12 @@ class CallAndReferenceGenerator(
for ((parameter, irArgument) in converted) {
putValueArgument(valueParameters.indexOf(parameter) + contextReceiverCount, irArgument)
}
if (annotationMode) {
if (visitor.annotationMode) {
for ((index, parameter) in valueParameters.withIndex()) {
if (parameter.isVararg && !argumentMapping.containsValue(parameter)) {
val defaultValue = parameter.defaultValue
val value = if (defaultValue != null) {
convertArgument(defaultValue, parameter, ConeSubstitutor.Empty, annotationMode = true)
convertArgument(defaultValue, parameter, ConeSubstitutor.Empty)
} else {
val elementType = parameter.returnTypeRef.toIrType()
IrVarargImpl(
@@ -945,9 +942,8 @@ class CallAndReferenceGenerator(
argument: FirExpression,
parameter: FirValueParameter?,
substitutor: ConeSubstitutor,
annotationMode: Boolean = false
): IrExpression {
var irArgument = visitor.convertToIrExpression(argument, annotationMode)
var irArgument = visitor.convertToIrExpression(argument)
if (parameter != null) {
with(visitor.implicitCastInserter) {
irArgument = irArgument.cast(argument, argument.typeRef, parameter.returnTypeRef)
@@ -111,7 +111,9 @@ internal class ClassMemberGenerator(
val irParameters = valueParameters.drop(firFunction.contextReceivers.size)
val annotationMode = containingClass?.classKind == ClassKind.ANNOTATION_CLASS && irFunction is IrConstructor
for ((valueParameter, firValueParameter) in irParameters.zip(firFunction.valueParameters)) {
valueParameter.setDefaultValue(firValueParameter, annotationMode)
visitor.withAnnotationMode(enableAnnotationMode = annotationMode) {
valueParameter.setDefaultValue(firValueParameter)
}
}
annotationGenerator.generate(irFunction, firFunction)
}
@@ -389,7 +391,7 @@ internal class ClassMemberGenerator(
}
with(callGenerator) {
declarationStorage.enterScope(irConstructorSymbol.owner)
val result = it.applyCallArguments(this@toIrDelegatingConstructorCall, annotationMode = false)
val result = it.applyCallArguments(this@toIrDelegatingConstructorCall)
declarationStorage.leaveScope(irConstructorSymbol.owner)
result
}
@@ -397,10 +399,10 @@ internal class ClassMemberGenerator(
}
}
private fun IrValueParameter.setDefaultValue(firValueParameter: FirValueParameter, annotationMode: Boolean) {
private fun IrValueParameter.setDefaultValue(firValueParameter: FirValueParameter) {
val firDefaultValue = firValueParameter.defaultValue
if (firDefaultValue != null) {
this.defaultValue = factory.createExpressionBody(visitor.convertToIrExpression(firDefaultValue, annotationMode))
this.defaultValue = factory.createExpressionBody(visitor.convertToIrExpression(firDefaultValue))
}
}
}
@@ -28351,6 +28351,12 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr
runTest("compiler/testData/codegen/box/involvesIrInterpreter/kt57313.kt");
}
@Test
@TestMetadata("kt58005.kt")
public void testKt58005() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/kt58005.kt");
}
@Test
@TestMetadata("longOperations.kt")
public void testLongOperations() throws Exception {
@@ -28351,6 +28351,12 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo
runTest("compiler/testData/codegen/box/involvesIrInterpreter/kt57313.kt");
}
@Test
@TestMetadata("kt58005.kt")
public void testKt58005() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/kt58005.kt");
}
@Test
@TestMetadata("longOperations.kt")
public void testLongOperations() throws Exception {
@@ -0,0 +1,66 @@
// TARGET_BACKEND: JVM
// FILE: ComponentScans.java
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ComponentScans {
ComponentScan[] value();
}
// FILE: ComponentScan.java
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
String[] a() default {};
String[] b() default {};
String[] c() default {};
}
// FILE: main.kt
@ComponentScans(
value = [
ComponentScan(
a = ["String" <!EVALUATED("StringA")!>+ "A"<!>],
c = ["String" <!EVALUATED("StringC")!>+ "C"<!>],
b = ["String" <!EVALUATED("StringB")!>+ "B"<!>],
)
]
)
class JavaTest
annotation class KtComponentScans(
val value: Array<KtComponentScan> = [],
)
annotation class KtComponentScan(
val a: Array<String> = [],
val b: Array<String> = [],
val c: Array<String> = [],
)
@ComponentScans(
value = [
ComponentScan(
a = ["String" <!EVALUATED("StringA")!>+ "A"<!>],
c = ["String" <!EVALUATED("StringC")!>+ "C"<!>],
b = ["String" <!EVALUATED("StringB")!>+ "B"<!>],
)
]
)
class KtTest
fun box(): String {
return "OK"
}
@@ -27211,6 +27211,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/kt57028.kt");
}
@Test
@TestMetadata("kt58005.kt")
public void testKt58005() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/kt58005.kt");
}
@Nested
@TestMetadata("compiler/testData/codegen/box/involvesIrInterpreter/intrinsicConst")
@TestDataPath("$PROJECT_ROOT")
@@ -28351,6 +28351,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/involvesIrInterpreter/kt57313.kt");
}
@Test
@TestMetadata("kt58005.kt")
public void testKt58005() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/kt58005.kt");
}
@Test
@TestMetadata("longOperations.kt")
public void testLongOperations() throws Exception {
@@ -28351,6 +28351,12 @@ public class IrBlackBoxCodegenWithIrInlinerTestGenerated extends AbstractIrBlack
runTest("compiler/testData/codegen/box/involvesIrInterpreter/kt57313.kt");
}
@Test
@TestMetadata("kt58005.kt")
public void testKt58005() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/kt58005.kt");
}
@Test
@TestMetadata("longOperations.kt")
public void testLongOperations() throws Exception {
@@ -22962,6 +22962,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/involvesIrInterpreter/kt57028.kt");
}
@TestMetadata("kt58005.kt")
public void testKt58005() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/kt58005.kt");
}
@TestMetadata("compiler/testData/codegen/box/involvesIrInterpreter/intrinsicConst")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)