Erase non-reified type parameters by-default when inlining.
Substitution of type arguments to non-reified type parameters may lead to accidental reification, which should not be done (see ^KT-60174 for examples). So, we should erase them, except the few cases. ^KT-60174: Fixed ^KT-60175: Fixed
This commit is contained in:
committed by
Space Team
parent
29ecc4d987
commit
f318b5969d
+19
-1
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrDoWhileLoopImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.transformStatement
|
||||
import org.jetbrains.kotlin.ir.types.isSubtypeOf
|
||||
import org.jetbrains.kotlin.ir.types.isUnit
|
||||
|
||||
// TODO migrate other usages and move this file to backend.jvm
|
||||
@@ -90,7 +91,24 @@ class ReturnableBlockTransformer(val context: CommonBackendContext, val containe
|
||||
val scopeSymbol = currentScope?.scope?.scopeOwnerSymbol ?: containerSymbol
|
||||
val builder = context.createIrBuilder(scopeSymbol!!)
|
||||
val variable by lazy {
|
||||
builder.scope.createTmpVariable(expression.type, "tmp\$ret\$${labelCnt++}", true)
|
||||
builder.scope.createTmpVariable(expression.type, "tmp\$ret\$${labelCnt++}", true).apply {
|
||||
// Consider the code:
|
||||
//
|
||||
// inline fun <T> myrun(block: () -> T) = block()
|
||||
// fun foo() = myrun L@{ if (false) return@L }
|
||||
//
|
||||
// Note that the block has execution path without explicit `Unit` return. That is why `variable` may be uninitialized
|
||||
// before its reading.
|
||||
// We worked it around that way: since explicit value return from `Unit` block is not obligatory, later in this lowering
|
||||
// we don't create `variable` reading if its type is known to be `Unit`.
|
||||
// On the other hand, despite the block in fact returns `Unit`, due to erasure of non-reified type parameters when inlining,
|
||||
// block's type in IR can be any superclass of `Unit`, e.g. `Any?`. Thus, the workaround does not work in that case.
|
||||
// Therefore, we should explicitly initialize `variable`.
|
||||
// It is safe even if block actually returns something, because in that case `Unit` initializer will be overwritten.
|
||||
if (!expression.type.isUnit() && context.irBuiltIns.unitType.isSubtypeOf(expression.type, context.typeSystem)) {
|
||||
initializer = builder.irUnit()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val loop by lazy {
|
||||
|
||||
+61
-15
@@ -5,12 +5,16 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.common.lower.inline
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.ir.Symbols
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent
|
||||
import org.jetbrains.kotlin.ir.declarations.IrTypeParametersContainer
|
||||
import org.jetbrains.kotlin.ir.declarations.copyAttributes
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
@@ -24,7 +28,8 @@ import org.jetbrains.kotlin.utils.memoryOptimizedMap
|
||||
|
||||
internal class DeepCopyIrTreeWithSymbolsForInliner(
|
||||
val typeArguments: Map<IrTypeParameterSymbol, IrType?>?,
|
||||
val parent: IrDeclarationParent?
|
||||
val parent: IrDeclarationParent?,
|
||||
defaultNonReifiedTypeParameterRemappingMode: NonReifiedTypeParameterRemappingMode,
|
||||
) {
|
||||
|
||||
fun copy(irElement: IrElement): IrElement {
|
||||
@@ -43,7 +48,8 @@ internal class DeepCopyIrTreeWithSymbolsForInliner(
|
||||
|
||||
private inner class InlinerTypeRemapper(
|
||||
val symbolRemapper: SymbolRemapper,
|
||||
val typeArguments: Map<IrTypeParameterSymbol, IrType?>?
|
||||
val typeArguments: Map<IrTypeParameterSymbol, IrType?>?,
|
||||
val defaultNonReifiedTypeParameterRemappingMode: NonReifiedTypeParameterRemappingMode,
|
||||
) : TypeRemapper {
|
||||
|
||||
override fun enterScope(irTypeParametersContainer: IrTypeParametersContainer) {}
|
||||
@@ -52,30 +58,36 @@ internal class DeepCopyIrTreeWithSymbolsForInliner(
|
||||
|
||||
private fun remapTypeArguments(
|
||||
arguments: List<IrTypeArgument>,
|
||||
erasedParameters: MutableSet<IrTypeParameterSymbol>?
|
||||
erasedParameters: MutableSet<IrTypeParameterSymbol>?,
|
||||
leaveNonReifiedAsIs: Boolean,
|
||||
) =
|
||||
arguments.memoryOptimizedMap { argument ->
|
||||
(argument as? IrTypeProjection)?.let { proj ->
|
||||
remapTypeAndOptionallyErase(proj.type, erasedParameters)?.let { newType ->
|
||||
remapType(proj.type, erasedParameters, leaveNonReifiedAsIs)?.let { newType ->
|
||||
makeTypeProjection(newType, proj.variance)
|
||||
} ?: IrStarProjectionImpl
|
||||
}
|
||||
?: argument
|
||||
}
|
||||
|
||||
override fun remapType(type: IrType) = remapTypeAndOptionallyErase(type, erase = false)
|
||||
override fun remapType(type: IrType) = remapType(type, defaultNonReifiedTypeParameterRemappingMode)
|
||||
|
||||
fun remapTypeAndOptionallyErase(type: IrType, erase: Boolean): IrType {
|
||||
val erasedParams = if (erase) mutableSetOf<IrTypeParameterSymbol>() else null
|
||||
return remapTypeAndOptionallyErase(type, erasedParams) ?: error("Cannot substitute type ${type.render()}")
|
||||
fun remapType(type: IrType, mode: NonReifiedTypeParameterRemappingMode): IrType {
|
||||
val erasedParams = if (mode == NonReifiedTypeParameterRemappingMode.ERASE) mutableSetOf<IrTypeParameterSymbol>() else null
|
||||
return remapType(type, erasedParams, mode == NonReifiedTypeParameterRemappingMode.LEAVE_AS_IS)
|
||||
?: error("Cannot substitute type ${type.render()}")
|
||||
}
|
||||
|
||||
private fun remapTypeAndOptionallyErase(type: IrType, erasedParameters: MutableSet<IrTypeParameterSymbol>?): IrType? {
|
||||
private fun remapType(type: IrType, erasedParameters: MutableSet<IrTypeParameterSymbol>?, leaveNonReifiedAsIs: Boolean): IrType? {
|
||||
if (type !is IrSimpleType) return type
|
||||
|
||||
val classifier = type.classifier
|
||||
val substitutedType = typeArguments?.get(classifier)
|
||||
|
||||
if (leaveNonReifiedAsIs && classifier is IrTypeParameterSymbol && !classifier.owner.isReified) {
|
||||
return type
|
||||
}
|
||||
|
||||
// Erase non-reified type parameter if asked to.
|
||||
if (erasedParameters != null && substitutedType != null && (classifier as? IrTypeParameterSymbol)?.owner?.isReified == false) {
|
||||
|
||||
@@ -94,7 +106,7 @@ internal class DeepCopyIrTreeWithSymbolsForInliner(
|
||||
val upperBound = superClass ?: superTypes.first()
|
||||
|
||||
// TODO: Think about how to reduce complexity from k^N to N^k
|
||||
val erasedUpperBound = remapTypeAndOptionallyErase(upperBound, erasedParameters)
|
||||
val erasedUpperBound = remapType(upperBound, erasedParameters, leaveNonReifiedAsIs)
|
||||
?: error("Cannot erase upperbound ${upperBound.render()}")
|
||||
|
||||
erasedParameters.remove(classifier)
|
||||
@@ -111,7 +123,7 @@ internal class DeepCopyIrTreeWithSymbolsForInliner(
|
||||
return type.buildSimpleType {
|
||||
kotlinType = null
|
||||
this.classifier = symbolRemapper.getReferencedClassifier(classifier)
|
||||
arguments = remapTypeArguments(type.arguments, erasedParameters)
|
||||
arguments = remapTypeArguments(type.arguments, erasedParameters, leaveNonReifiedAsIs)
|
||||
annotations = type.annotations.memoryOptimizedMap { it.transform(copier, null) as IrConstructorCall }
|
||||
}
|
||||
}
|
||||
@@ -136,16 +148,50 @@ internal class DeepCopyIrTreeWithSymbolsForInliner(
|
||||
}
|
||||
|
||||
private val symbolRemapper = SymbolRemapperImpl(NullDescriptorsRemapper)
|
||||
private val typeRemapper = InlinerTypeRemapper(symbolRemapper, typeArguments)
|
||||
private val typeRemapper = InlinerTypeRemapper(symbolRemapper, typeArguments, defaultNonReifiedTypeParameterRemappingMode)
|
||||
private val copier = object : DeepCopyIrTreeWithSymbols(symbolRemapper, typeRemapper) {
|
||||
private fun IrType.remapTypeAndErase() = typeRemapper.remapTypeAndOptionallyErase(this, erase = true)
|
||||
|
||||
private fun IrType.leaveNonReifiedAsIs() = typeRemapper.remapType(this, NonReifiedTypeParameterRemappingMode.LEAVE_AS_IS)
|
||||
|
||||
private fun IrType.substituteAll() = typeRemapper.remapType(this, NonReifiedTypeParameterRemappingMode.SUBSTITUTE)
|
||||
|
||||
private fun IrType.erase() = typeRemapper.remapType(this, NonReifiedTypeParameterRemappingMode.ERASE)
|
||||
|
||||
override fun visitClass(declaration: IrClass): IrClass {
|
||||
// Substitute type argument to make Class::genericSuperclass work as expected (see kt52417.kt)
|
||||
// Substitution to the super types does not lead to reification and therefore is safe
|
||||
return super.visitClass(declaration).apply {
|
||||
superTypes = declaration.superTypes.memoryOptimizedMap {
|
||||
it.substituteAll()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitCall(expression: IrCall): IrCall {
|
||||
if (!Symbols.isTypeOfIntrinsic(expression.symbol)) return super.visitCall(expression)
|
||||
// We should neither erase nor substitute non-reified type parameters in the `typeOf` call so that reflection is able
|
||||
// to create a proper KTypeParameter for it. See KT-60175, KT-30279.
|
||||
return IrCallImpl(
|
||||
expression.startOffset, expression.endOffset,
|
||||
expression.type,
|
||||
expression.symbol,
|
||||
expression.typeArgumentsCount,
|
||||
expression.valueArgumentsCount,
|
||||
expression.origin,
|
||||
expression.superQualifierSymbol
|
||||
).apply {
|
||||
for (i in 0 until typeArgumentsCount) {
|
||||
putTypeArgument(i, expression.getTypeArgument(i)?.leaveNonReifiedAsIs())
|
||||
}
|
||||
}.copyAttributes(expression)
|
||||
}
|
||||
|
||||
override fun visitTypeOperator(expression: IrTypeOperatorCall) =
|
||||
IrTypeOperatorCallImpl(
|
||||
expression.startOffset, expression.endOffset,
|
||||
expression.type.remapTypeAndErase(),
|
||||
expression.type.erase(),
|
||||
expression.operator,
|
||||
expression.typeOperand.remapTypeAndErase(),
|
||||
expression.typeOperand.erase(),
|
||||
expression.argument.transform()
|
||||
).copyAttributes(expression)
|
||||
}
|
||||
|
||||
+24
-67
@@ -52,18 +52,10 @@ interface InlineFunctionResolver {
|
||||
}
|
||||
}
|
||||
|
||||
fun IrFunction.isTopLevelInPackage(name: String, packageName: String): Boolean {
|
||||
if (name != this.name.asString()) return false
|
||||
|
||||
val containingDeclaration = parent as? IrPackageFragment ?: return false
|
||||
val packageFqName = containingDeclaration.packageFqName.asString()
|
||||
return packageName == packageFqName
|
||||
}
|
||||
|
||||
fun IrFunction.isBuiltInSuspendCoroutineUninterceptedOrReturn(): Boolean =
|
||||
isTopLevelInPackage(
|
||||
"suspendCoroutineUninterceptedOrReturn",
|
||||
StandardNames.COROUTINES_INTRINSICS_PACKAGE_FQ_NAME.asString()
|
||||
StandardNames.COROUTINES_INTRINSICS_PACKAGE_FQ_NAME
|
||||
)
|
||||
|
||||
open class InlineFunctionResolverReplacingCoroutineIntrinsics(open val context: CommonBackendContext) : InlineFunctionResolver {
|
||||
@@ -89,9 +81,8 @@ class FunctionInlining(
|
||||
private val insertAdditionalImplicitCasts: Boolean = false,
|
||||
private val alwaysCreateTemporaryVariablesForArguments: Boolean = false,
|
||||
private val regenerateInlinedAnonymousObjects: Boolean = false,
|
||||
private val inlineArgumentsWithTheirOriginalTypeAndOffset: Boolean = false,
|
||||
private val inlineArgumentsWithOriginalOffset: Boolean = false,
|
||||
private val allowExternalInlining: Boolean = false,
|
||||
private val useTypeParameterUpperBound: Boolean = false
|
||||
) : IrElementTransformerVoidWithContext(), BodyLoweringPass {
|
||||
private var containerScope: ScopeWithIr? = null
|
||||
|
||||
@@ -172,7 +163,7 @@ class FunctionInlining(
|
||||
(0 until callSite.typeArgumentsCount).associate {
|
||||
typeParameters[it].symbol to callSite.getTypeArgument(it)
|
||||
}
|
||||
DeepCopyIrTreeWithSymbolsForInliner(typeArguments, parent)
|
||||
DeepCopyIrTreeWithSymbolsForInliner(typeArguments, parent, NonReifiedTypeParameterRemappingMode.ERASE)
|
||||
}
|
||||
|
||||
val substituteMap = mutableMapOf<IrValueParameter, IrExpression>()
|
||||
@@ -317,7 +308,7 @@ class FunctionInlining(
|
||||
|
||||
private fun inlinePropertyReference(expression: IrCall, propertyReference: IrPropertyReference): IrExpression {
|
||||
val getterCall = IrCallImpl.fromSymbolOwner(
|
||||
expression.startOffset, expression.endOffset, expression.type, propertyReference.getter!!,
|
||||
expression.startOffset, expression.endOffset, propertyReference.getter!!.owner.returnType, propertyReference.getter!!,
|
||||
origin = INLINED_FUNCTION_REFERENCE
|
||||
)
|
||||
|
||||
@@ -327,14 +318,16 @@ class FunctionInlining(
|
||||
}
|
||||
|
||||
val receiverFromField = propertyReference.dispatchReceiver ?: propertyReference.extensionReceiver
|
||||
getterCall.dispatchReceiver = getterCall.symbol.owner.dispatchReceiverParameter?.let {
|
||||
receiverFromField ?: tryToGetArg(0)
|
||||
getterCall.dispatchReceiver = getterCall.symbol.owner.dispatchReceiverParameter?.let { dispatchReceiverParam ->
|
||||
val dispatchReceiverArgument = receiverFromField ?: tryToGetArg(0)
|
||||
dispatchReceiverArgument?.doImplicitCastIfNeededTo(dispatchReceiverParam.type)
|
||||
}
|
||||
getterCall.extensionReceiver = getterCall.symbol.owner.extensionReceiverParameter?.let {
|
||||
when (getterCall.symbol.owner.dispatchReceiverParameter) {
|
||||
getterCall.extensionReceiver = getterCall.symbol.owner.extensionReceiverParameter?.let { extensionReceiverParam ->
|
||||
val extensionReceiverArgument = when (getterCall.symbol.owner.dispatchReceiverParameter) {
|
||||
null -> receiverFromField ?: tryToGetArg(0)
|
||||
else -> tryToGetArg(if (receiverFromField != null) 0 else 1)
|
||||
}
|
||||
extensionReceiverArgument?.doImplicitCastIfNeededTo(extensionReceiverParam.type)
|
||||
}
|
||||
|
||||
return wrapInStubFunction(super.visitExpression(getterCall), expression, propertyReference)
|
||||
@@ -427,8 +420,8 @@ class FunctionInlining(
|
||||
is IrConstructor -> {
|
||||
val classTypeParametersCount = inlinedFunction.parentAsClass.typeParameters.size
|
||||
IrConstructorCallImpl.fromSymbolOwner(
|
||||
if (inlineArgumentsWithTheirOriginalTypeAndOffset) irFunctionReference.startOffset else irCall.startOffset,
|
||||
if (inlineArgumentsWithTheirOriginalTypeAndOffset) irFunctionReference.endOffset else irCall.endOffset,
|
||||
if (inlineArgumentsWithOriginalOffset) irFunctionReference.startOffset else irCall.startOffset,
|
||||
if (inlineArgumentsWithOriginalOffset) irFunctionReference.endOffset else irCall.endOffset,
|
||||
functionReferenceReturnType,
|
||||
inlinedFunction.symbol,
|
||||
classTypeParametersCount,
|
||||
@@ -437,8 +430,8 @@ class FunctionInlining(
|
||||
}
|
||||
is IrSimpleFunction ->
|
||||
IrCallImpl(
|
||||
if (inlineArgumentsWithTheirOriginalTypeAndOffset) irFunctionReference.startOffset else irCall.startOffset,
|
||||
if (inlineArgumentsWithTheirOriginalTypeAndOffset) irFunctionReference.endOffset else irCall.endOffset,
|
||||
if (inlineArgumentsWithOriginalOffset) irFunctionReference.startOffset else irCall.startOffset,
|
||||
if (inlineArgumentsWithOriginalOffset) irFunctionReference.endOffset else irCall.endOffset,
|
||||
functionReferenceReturnType,
|
||||
inlinedFunction.symbol,
|
||||
inlinedFunction.typeParameters.size,
|
||||
@@ -689,7 +682,9 @@ class FunctionInlining(
|
||||
startOffset = if (it.isDefaultArg) irExpression.startOffset else UNDEFINED_OFFSET,
|
||||
endOffset = if (it.isDefaultArg) irExpression.startOffset else UNDEFINED_OFFSET,
|
||||
irExpression = irExpression,
|
||||
irType = if (inlineArgumentsWithTheirOriginalTypeAndOffset) it.parameter.getOriginalType() else irExpression.type,
|
||||
// If original type of parameter is T, then `it.parameter.type` is T after substitution or erasure,
|
||||
// depending on whether T reified or not.
|
||||
irType = it.parameter.type,
|
||||
nameHint = callee.symbol.owner.name.asStringStripSpecialMarkers() + "_" + it.parameter.name.asStringStripSpecialMarkers(),
|
||||
isMutable = false
|
||||
)
|
||||
@@ -735,50 +730,6 @@ class FunctionInlining(
|
||||
return original.allParameters.singleOrNull { it.name == this.name && it.startOffset == this.startOffset } ?: this
|
||||
}
|
||||
|
||||
// In short this is needed for `kt44429` test. We need to get original generic type to trick type system on JVM backend.
|
||||
// Probably this it is relevant only for numeric types in JVM.
|
||||
private fun IrValueParameter.getOriginalType(): IrType {
|
||||
if (this.parent !is IrFunction) return type
|
||||
val copy = this.parent as IrFunction // contains substituted type parameters with corresponding type arguments
|
||||
val original = copy.originalFunction // contains original unsubstituted type parameters
|
||||
|
||||
// Note 1: the following method will replace super types fow the owner type parameter. So in every other IrSimpleType that
|
||||
// refers this type parameter we will see substituted values. This should not be a problem because earlier we replace all type
|
||||
// parameters with corresponding type arguments.
|
||||
// Note 2: this substitution can be dropped if we will learn how to copy IR function and leave its type parameters as they are.
|
||||
// But this sounds a little complicated.
|
||||
fun IrType.substituteSuperTypes(): IrType {
|
||||
val typeClassifier = this.classifierOrNull?.owner as? IrTypeParameter ?: return this
|
||||
typeClassifier.superTypes = original.typeParameters[typeClassifier.index].superTypes.map {
|
||||
val superTypeClassifier = it.classifierOrNull?.owner as? IrTypeParameter ?: return@map it
|
||||
copy.typeParameters[superTypeClassifier.index].defaultType.substituteSuperTypes()
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
fun IrValueParameter?.getTypeIfFromTypeParameter(): IrType? {
|
||||
val typeClassifier = this?.type?.classifierOrNull?.owner as? IrTypeParameter ?: return null
|
||||
if (typeClassifier.parent != this.parent) return null
|
||||
|
||||
// We take type parameter from copied callee and not from original because we need an actual copy. Without this copy,
|
||||
// in case of recursive call, we can get a situation there the same type parameter will be mapped on different type arguments.
|
||||
// (see compiler/testData/codegen/boxInline/complex/use.kt test file)
|
||||
val newTypeParameter = copy.typeParameters[typeClassifier.index].defaultType.substituteSuperTypes()
|
||||
return if (useTypeParameterUpperBound) typeClassifier.firstRealUpperBound().mergeNullability(type) else newTypeParameter
|
||||
}
|
||||
|
||||
return when (this) {
|
||||
copy.dispatchReceiverParameter -> original.dispatchReceiverParameter?.getTypeIfFromTypeParameter()
|
||||
?: copy.dispatchReceiverParameter!!.type
|
||||
copy.extensionReceiverParameter -> original.extensionReceiverParameter?.getTypeIfFromTypeParameter()
|
||||
?: copy.extensionReceiverParameter!!.type
|
||||
else -> copy.valueParameters.first { it == this }.let { valueParameter ->
|
||||
original.valueParameters.getOrNull(valueParameter.index)?.getTypeIfFromTypeParameter()
|
||||
?: valueParameter.type
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrTypeParameter?.firstRealUpperBound(): IrType {
|
||||
val queue = this?.superTypes?.toMutableList() ?: mutableListOf()
|
||||
|
||||
@@ -876,7 +827,9 @@ class FunctionInlining(
|
||||
irExpression = IrBlockImpl(
|
||||
if (isDefaultArg) variableInitializer.startOffset else UNDEFINED_OFFSET,
|
||||
if (isDefaultArg) variableInitializer.endOffset else UNDEFINED_OFFSET,
|
||||
if (inlineArgumentsWithTheirOriginalTypeAndOffset) parameter.getOriginalType() else variableInitializer.type,
|
||||
// If original type of parameter is T, then `parameter.type` is T after substitution or erasure,
|
||||
// depending on whether T reified or not.
|
||||
parameter.type
|
||||
).apply {
|
||||
statements.add(variableInitializer)
|
||||
},
|
||||
@@ -921,3 +874,7 @@ class FunctionInlining(
|
||||
val INLINED_FUNCTION_REFERENCE by IrStatementOriginImpl
|
||||
val INLINED_FUNCTION_ARGUMENTS by IrStatementOriginImpl
|
||||
val INLINED_FUNCTION_DEFAULT_ARGUMENTS by IrStatementOriginImpl
|
||||
|
||||
enum class NonReifiedTypeParameterRemappingMode {
|
||||
LEAVE_AS_IS, SUBSTITUTE, ERASE
|
||||
}
|
||||
@@ -213,10 +213,9 @@ private val functionInliningPhase = makeIrModulePhase(
|
||||
it,
|
||||
JsInlineFunctionResolver(it),
|
||||
it.innerClassesSupport,
|
||||
allowExternalInlining = true,
|
||||
useTypeParameterUpperBound = true,
|
||||
alwaysCreateTemporaryVariablesForArguments = true,
|
||||
inlineArgumentsWithTheirOriginalTypeAndOffset = true
|
||||
inlineArgumentsWithOriginalOffset = true,
|
||||
allowExternalInlining = true
|
||||
)
|
||||
},
|
||||
name = "FunctionInliningPhase",
|
||||
|
||||
+10
-2
@@ -259,6 +259,14 @@ private val returnableBlocksPhase = makeIrFilePhase(
|
||||
prerequisite = setOf(arrayConstructorPhase, assertionPhase, directInvokeLowering)
|
||||
)
|
||||
|
||||
private val singletonReferencesPhase = makeIrFilePhase(
|
||||
::SingletonReferencesLowering,
|
||||
name = "SingletonReferences",
|
||||
description = "Handle singleton references",
|
||||
// ReturnableBlock lowering may produce references to the `Unit` object
|
||||
prerequisite = setOf(returnableBlocksPhase)
|
||||
)
|
||||
|
||||
private val syntheticAccessorPhase = makeIrFilePhase(
|
||||
::SyntheticAccessorLowering,
|
||||
name = "SyntheticAccessor",
|
||||
@@ -287,7 +295,7 @@ internal val functionInliningPhase = makeIrModulePhase(
|
||||
innerClassesSupport = context.innerClassesSupport,
|
||||
alwaysCreateTemporaryVariablesForArguments = true,
|
||||
regenerateInlinedAnonymousObjects = true,
|
||||
inlineArgumentsWithTheirOriginalTypeAndOffset = true
|
||||
inlineArgumentsWithOriginalOffset = true
|
||||
)
|
||||
},
|
||||
name = "FunctionInliningPhase",
|
||||
@@ -367,10 +375,10 @@ private val jvmFilePhases = listOf(
|
||||
// makePatchParentsPhase(),
|
||||
|
||||
enumWhenPhase,
|
||||
singletonReferencesPhase,
|
||||
|
||||
assertionPhase,
|
||||
returnableBlocksPhase,
|
||||
singletonReferencesPhase,
|
||||
sharedVariablesPhase,
|
||||
localDeclarationsPhase,
|
||||
// makePatchParentsPhase(),
|
||||
|
||||
+1
-8
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.backend.jvm.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||
import org.jetbrains.kotlin.backend.common.pop
|
||||
import org.jetbrains.kotlin.backend.common.push
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
@@ -23,13 +22,7 @@ import org.jetbrains.kotlin.ir.types.classOrNull
|
||||
import org.jetbrains.kotlin.ir.util.isAnonymousObject
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
|
||||
internal val singletonReferencesPhase = makeIrFilePhase(
|
||||
::SingletonReferencesLowering,
|
||||
name = "SingletonReferences",
|
||||
description = "Handle singleton references"
|
||||
)
|
||||
|
||||
private class SingletonReferencesLowering(val context: JvmBackendContext) : FileLoweringPass, IrElementTransformerVoidWithContext() {
|
||||
internal class SingletonReferencesLowering(val context: JvmBackendContext) : FileLoweringPass, IrElementTransformerVoidWithContext() {
|
||||
private val constructingEnums = arrayListOf<IrDeclarationParent>()
|
||||
|
||||
override fun lower(irFile: IrFile) {
|
||||
|
||||
+2
-1
@@ -136,9 +136,10 @@ private val functionInliningPhase = makeCustomPhase<WasmBackendContext>(
|
||||
{ context, module ->
|
||||
FunctionInlining(
|
||||
context = context,
|
||||
innerClassesSupport = context.innerClassesSupport,
|
||||
inlineFunctionResolver = WasmInlineFunctionResolver(context),
|
||||
innerClassesSupport = context.innerClassesSupport,
|
||||
insertAdditionalImplicitCasts = true,
|
||||
alwaysCreateTemporaryVariablesForArguments = true
|
||||
).inline(module)
|
||||
module.patchDeclarationParents()
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user