[IR] Unify MFVC bridge redirection, fix related bugs, support MFVC overriding functions with default parameters
#KT-1179
This commit is contained in:
committed by
Space Team
parent
384ed9cc9e
commit
bf5fa61ffb
+6
@@ -52095,6 +52095,12 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr
|
|||||||
runTest("compiler/testData/codegen/box/valueClasses/mutableSharedMfvcVar.kt");
|
runTest("compiler/testData/codegen/box/valueClasses/mutableSharedMfvcVar.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("nothingAsParameterType.kt")
|
||||||
|
public void testNothingAsParameterType() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/valueClasses/nothingAsParameterType.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("overrideFunctionWithDefaultParameter.kt")
|
@TestMetadata("overrideFunctionWithDefaultParameter.kt")
|
||||||
public void testOverrideFunctionWithDefaultParameter() throws Exception {
|
public void testOverrideFunctionWithDefaultParameter() throws Exception {
|
||||||
|
|||||||
+6
@@ -52095,6 +52095,12 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo
|
|||||||
runTest("compiler/testData/codegen/box/valueClasses/mutableSharedMfvcVar.kt");
|
runTest("compiler/testData/codegen/box/valueClasses/mutableSharedMfvcVar.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("nothingAsParameterType.kt")
|
||||||
|
public void testNothingAsParameterType() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/valueClasses/nothingAsParameterType.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("overrideFunctionWithDefaultParameter.kt")
|
@TestMetadata("overrideFunctionWithDefaultParameter.kt")
|
||||||
public void testOverrideFunctionWithDefaultParameter() throws Exception {
|
public void testOverrideFunctionWithDefaultParameter() throws Exception {
|
||||||
|
|||||||
+85
-64
@@ -5,11 +5,10 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.common.lower
|
package org.jetbrains.kotlin.backend.common.lower
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
|
import org.jetbrains.kotlin.backend.common.*
|
||||||
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
|
||||||
import org.jetbrains.kotlin.backend.common.DeclarationTransformer
|
|
||||||
import org.jetbrains.kotlin.backend.common.descriptors.synthesizedString
|
import org.jetbrains.kotlin.backend.common.descriptors.synthesizedString
|
||||||
import org.jetbrains.kotlin.backend.common.ir.ValueRemapper
|
import org.jetbrains.kotlin.backend.common.ir.ValueRemapper
|
||||||
|
import org.jetbrains.kotlin.backend.common.lower.isMovedReceiver
|
||||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
import org.jetbrains.kotlin.ir.builders.*
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
@@ -30,6 +29,7 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
|||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
import org.jetbrains.kotlin.utils.memoryOptimizedPlus
|
import org.jetbrains.kotlin.utils.memoryOptimizedPlus
|
||||||
|
import org.jetbrains.kotlin.backend.common.lower.isMovedReceiver as isMovedReceiverImpl
|
||||||
|
|
||||||
// TODO: fix expect/actual default parameters
|
// TODO: fix expect/actual default parameters
|
||||||
|
|
||||||
@@ -263,8 +263,11 @@ open class DefaultParameterInjector<TContext : CommonBackendContext>(
|
|||||||
protected val forceSetOverrideSymbols: Boolean = true,
|
protected val forceSetOverrideSymbols: Boolean = true,
|
||||||
) : IrElementTransformerVoid(), BodyLoweringPass {
|
) : IrElementTransformerVoid(), BodyLoweringPass {
|
||||||
|
|
||||||
|
private val declarationStack = mutableListOf<IrDeclaration>()
|
||||||
override fun lower(irBody: IrBody, container: IrDeclaration) {
|
override fun lower(irBody: IrBody, container: IrDeclaration) {
|
||||||
|
declarationStack.push(container)
|
||||||
irBody.transformChildrenVoid(this)
|
irBody.transformChildrenVoid(this)
|
||||||
|
declarationStack.pop()
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun shouldReplaceWithSyntheticFunction(functionAccess: IrFunctionAccessExpression): Boolean {
|
protected open fun shouldReplaceWithSyntheticFunction(functionAccess: IrFunctionAccessExpression): Boolean {
|
||||||
@@ -275,50 +278,44 @@ open class DefaultParameterInjector<TContext : CommonBackendContext>(
|
|||||||
if (!shouldReplaceWithSyntheticFunction(expression))
|
if (!shouldReplaceWithSyntheticFunction(expression))
|
||||||
return expression
|
return expression
|
||||||
|
|
||||||
val (symbol, params) = parametersForCall(expression) ?: return expression
|
val symbol = createStubFunction(expression) ?: return expression
|
||||||
for (i in 0 until expression.typeArgumentsCount) {
|
for (i in 0 until expression.typeArgumentsCount) {
|
||||||
log { "$symbol[$i]: ${expression.getTypeArgument(i)}" }
|
log { "$symbol[$i]: ${expression.getTypeArgument(i)}" }
|
||||||
}
|
}
|
||||||
symbol.owner.typeParameters.forEach { log { "${symbol.owner}[${it.index}] : $it" } }
|
val stubFunction = symbol.owner
|
||||||
|
stubFunction.typeParameters.forEach { log { "$stubFunction[${it.index}] : $it" } }
|
||||||
|
|
||||||
val isStatic = isStatic(expression.symbol.owner)
|
val declaration = expression.symbol.owner
|
||||||
|
val currentDeclaration = declarationStack.last()
|
||||||
val newCall = builder(symbol).apply {
|
return context.createIrBuilder(
|
||||||
copyTypeArgumentsFrom(expression)
|
currentDeclaration.symbol, startOffset = expression.startOffset, endOffset = expression.endOffset
|
||||||
|
).irBlock {
|
||||||
var receivers = 0
|
val newCall = builder(symbol).apply {
|
||||||
|
val offset = if (needsTypeArgumentOffset(declaration)) declaration.parentAsClass.typeParameters.size else 0
|
||||||
if (isStatic) {
|
for (i in 0 until typeArgumentsCount) {
|
||||||
if (symbol.owner.dispatchReceiverParameter != null) {
|
putTypeArgument(i, expression.getTypeArgument(i + offset))
|
||||||
dispatchReceiver = params[receivers++]
|
|
||||||
}
|
}
|
||||||
if (symbol.owner.extensionReceiverParameter != null) {
|
val parameter2arguments = argumentsForCall(expression, stubFunction)
|
||||||
extensionReceiver = params[receivers++]
|
|
||||||
|
for ((parameter, argument) in parameter2arguments) {
|
||||||
|
when (parameter) {
|
||||||
|
stubFunction.dispatchReceiverParameter -> log { "call::dispatch@: ${ir2string(argument)}" }
|
||||||
|
stubFunction.extensionReceiverParameter -> log { "call::extension@: ${ir2string(argument)}" }
|
||||||
|
else -> log { "call::params@$${parameter.index}/${parameter.name}: ${ir2string(argument)}" }
|
||||||
|
}
|
||||||
|
if (argument != null) {
|
||||||
|
putArgument(parameter, argument)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
dispatchReceiver = expression.dispatchReceiver
|
|
||||||
extensionReceiver = expression.extensionReceiver
|
|
||||||
}
|
}
|
||||||
|
|
||||||
params.drop(receivers).forEachIndexed { i, value ->
|
+irCastIfNeeded(newCall, expression.type)
|
||||||
log { "call::params@$i/${symbol.owner.valueParameters[i].name}: ${ir2string(value)}" }
|
}.unwrapBlock()
|
||||||
putValueArgument(i, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
log { "call::extension@: ${ir2string(expression.extensionReceiver)}" }
|
|
||||||
log { "call::dispatch@: ${ir2string(expression.dispatchReceiver)}" }
|
|
||||||
}
|
|
||||||
|
|
||||||
return newCall.takeIf { it.type == expression.type } ?: IrTypeOperatorCallImpl(
|
|
||||||
startOffset = newCall.startOffset,
|
|
||||||
endOffset = newCall.endOffset,
|
|
||||||
type = expression.type,
|
|
||||||
operator = IrTypeOperator.IMPLICIT_CAST,
|
|
||||||
typeOperand = expression.type,
|
|
||||||
argument = newCall
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun needsTypeArgumentOffset(declaration: IrFunction) =
|
||||||
|
isStatic(declaration) && declaration.parentAsClass.isMultiFieldValueClass && declaration is IrSimpleFunction
|
||||||
|
|
||||||
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression {
|
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression {
|
||||||
expression.transformChildrenVoid()
|
expression.transformChildrenVoid()
|
||||||
return visitFunctionAccessExpression(expression) {
|
return visitFunctionAccessExpression(expression) {
|
||||||
@@ -362,11 +359,13 @@ open class DefaultParameterInjector<TContext : CommonBackendContext>(
|
|||||||
|
|
||||||
override fun visitCall(expression: IrCall): IrExpression {
|
override fun visitCall(expression: IrCall): IrExpression {
|
||||||
expression.transformChildrenVoid()
|
expression.transformChildrenVoid()
|
||||||
|
val declaration = expression.symbol.owner
|
||||||
|
val typeParametersToRemove = if (needsTypeArgumentOffset(declaration)) declaration.parentAsClass.typeParameters.size else 0
|
||||||
with(expression) {
|
with(expression) {
|
||||||
return visitFunctionAccessExpression(expression) {
|
return visitFunctionAccessExpression(expression) {
|
||||||
IrCallImpl(
|
IrCallImpl(
|
||||||
startOffset, endOffset, (it as IrSimpleFunctionSymbol).owner.returnType, it,
|
startOffset, endOffset, (it as IrSimpleFunctionSymbol).owner.returnType, it,
|
||||||
typeArgumentsCount = typeArgumentsCount,
|
typeArgumentsCount = typeArgumentsCount - typeParametersToRemove,
|
||||||
valueArgumentsCount = it.owner.valueParameters.size,
|
valueArgumentsCount = it.owner.valueParameters.size,
|
||||||
origin = LoweredStatementOrigins.DEFAULT_DISPATCH_CALL,
|
origin = LoweredStatementOrigins.DEFAULT_DISPATCH_CALL,
|
||||||
superQualifierSymbol = superQualifierSymbol
|
superQualifierSymbol = superQualifierSymbol
|
||||||
@@ -375,9 +374,7 @@ open class DefaultParameterInjector<TContext : CommonBackendContext>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open protected fun parametersForCall(expression: IrFunctionAccessExpression): Pair<IrFunctionSymbol, List<IrExpression?>>? {
|
private fun createStubFunction(expression: IrFunctionAccessExpression): IrFunctionSymbol? {
|
||||||
val startOffset = expression.startOffset
|
|
||||||
val endOffset = expression.endOffset
|
|
||||||
val declaration = expression.symbol.owner
|
val declaration = expression.symbol.owner
|
||||||
|
|
||||||
// We *have* to find the actual function here since on the JVM, a default stub for a function implemented
|
// We *have* to find the actual function here since on the JVM, a default stub for a function implemented
|
||||||
@@ -396,8 +393,14 @@ open class DefaultParameterInjector<TContext : CommonBackendContext>(
|
|||||||
baseFunction.copyAnnotations(),
|
baseFunction.copyAnnotations(),
|
||||||
)
|
)
|
||||||
} ?: return null
|
} ?: return null
|
||||||
|
|
||||||
log { "$declaration -> $stubFunction" }
|
log { "$declaration -> $stubFunction" }
|
||||||
|
return stubFunction.symbol
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun IrBlockBuilder.argumentsForCall(expression: IrFunctionAccessExpression, stubFunction: IrFunction): Map<IrValueParameter, IrExpression?> {
|
||||||
|
val startOffset = expression.startOffset
|
||||||
|
val endOffset = expression.endOffset
|
||||||
|
val declaration = expression.symbol.owner
|
||||||
|
|
||||||
val realArgumentsNumber = declaration.valueParameters.filterNot { it.isMovedReceiver() }.size
|
val realArgumentsNumber = declaration.valueParameters.filterNot { it.isMovedReceiver() }.size
|
||||||
val maskValues = IntArray((realArgumentsNumber + 31) / 32)
|
val maskValues = IntArray((realArgumentsNumber + 31) / 32)
|
||||||
@@ -408,32 +411,48 @@ open class DefaultParameterInjector<TContext : CommonBackendContext>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
var sourceParameterIndex = -1
|
var sourceParameterIndex = -1
|
||||||
val valueParametersPrefix =
|
return buildMap {
|
||||||
if (isStatic(declaration))
|
val valueParametersPrefix: List<IrValueParameter> = if (isStatic(declaration)) {
|
||||||
listOfNotNull(stubFunction.dispatchReceiverParameter, stubFunction.extensionReceiverParameter)
|
listOfNotNull(stubFunction.dispatchReceiverParameter, stubFunction.extensionReceiverParameter)
|
||||||
else emptyList()
|
} else {
|
||||||
return stubFunction.symbol to (valueParametersPrefix + stubFunction.valueParameters).mapIndexed { i, parameter ->
|
stubFunction.dispatchReceiverParameter?.let { put(it, expression.dispatchReceiver) }
|
||||||
if (!parameter.isMovedReceiver() && parameter != stubFunction.dispatchReceiverParameter && parameter != stubFunction.extensionReceiverParameter) {
|
stubFunction.extensionReceiverParameter?.let { put(it, expression.extensionReceiver) }
|
||||||
++sourceParameterIndex
|
listOf()
|
||||||
}
|
}
|
||||||
when {
|
for ((i, parameter) in (valueParametersPrefix + stubFunction.valueParameters).withIndex()) {
|
||||||
sourceParameterIndex >= realArgumentsNumber + maskValues.size -> IrConstImpl.constNull(startOffset, endOffset, parameter.type)
|
if (!parameter.isMovedReceiver() && parameter != stubFunction.dispatchReceiverParameter && parameter != stubFunction.extensionReceiverParameter) {
|
||||||
sourceParameterIndex >= realArgumentsNumber -> IrConstImpl.int(startOffset, endOffset, parameter.type, maskValues[sourceParameterIndex - realArgumentsNumber])
|
++sourceParameterIndex
|
||||||
else -> {
|
}
|
||||||
val valueArgument = expression.getValueArgument(i)
|
val newArgument = when {
|
||||||
if (valueArgument == null) {
|
sourceParameterIndex >= realArgumentsNumber + maskValues.size -> IrConstImpl.constNull(
|
||||||
maskValues[sourceParameterIndex / 32] = maskValues[sourceParameterIndex / 32] or (1 shl (sourceParameterIndex % 32))
|
startOffset,
|
||||||
}
|
endOffset,
|
||||||
valueArgument ?: nullConst(startOffset, endOffset, parameter)?.let {
|
parameter.type
|
||||||
IrCompositeImpl(
|
)
|
||||||
expression.startOffset,
|
sourceParameterIndex >= realArgumentsNumber -> IrConstImpl.int(
|
||||||
expression.endOffset,
|
startOffset,
|
||||||
parameter.type,
|
endOffset,
|
||||||
IrStatementOrigin.DEFAULT_VALUE,
|
parameter.type,
|
||||||
listOf(it)
|
maskValues[sourceParameterIndex - realArgumentsNumber]
|
||||||
)
|
)
|
||||||
|
else -> {
|
||||||
|
val valueArgument = expression.getValueArgument(i)
|
||||||
|
if (valueArgument == null) {
|
||||||
|
maskValues[sourceParameterIndex / 32] =
|
||||||
|
maskValues[sourceParameterIndex / 32] or (1 shl (sourceParameterIndex % 32))
|
||||||
|
}
|
||||||
|
valueArgument ?: nullConst(startOffset, endOffset, parameter)?.let {
|
||||||
|
IrCompositeImpl(
|
||||||
|
expression.startOffset,
|
||||||
|
expression.endOffset,
|
||||||
|
parameter.type,
|
||||||
|
IrStatementOrigin.DEFAULT_VALUE,
|
||||||
|
listOf(it)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
put(parameter, newArgument)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -455,6 +474,8 @@ open class DefaultParameterInjector<TContext : CommonBackendContext>(
|
|||||||
protected open fun isStatic(function: IrFunction): Boolean = false
|
protected open fun isStatic(function: IrFunction): Boolean = false
|
||||||
|
|
||||||
private fun log(msg: () -> String) = context.log { "DEFAULT-INJECTOR: ${msg()}" }
|
private fun log(msg: () -> String) = context.log { "DEFAULT-INJECTOR: ${msg()}" }
|
||||||
|
|
||||||
|
protected fun IrValueParameter.isMovedReceiver() = isMovedReceiverImpl()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove default argument initializers.
|
// Remove default argument initializers.
|
||||||
|
|||||||
+2
-1
@@ -374,6 +374,7 @@ class InlineClassLowering(val context: CommonBackendContext) {
|
|||||||
function.parent,
|
function.parent,
|
||||||
function.toInlineClassImplementationName(),
|
function.toInlineClassImplementationName(),
|
||||||
function,
|
function,
|
||||||
typeParametersFromContext = extractTypeParameters(function.parentAsClass)
|
typeParametersFromContext = extractTypeParameters(function.parentAsClass),
|
||||||
|
remapMultiFieldValueClassStructure = context::remapMultiFieldValueClassStructure
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-21
@@ -5,14 +5,15 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.ir.backend.js.lower
|
package org.jetbrains.kotlin.ir.backend.js.lower
|
||||||
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
|
||||||
import org.jetbrains.kotlin.backend.common.lower.DefaultParameterInjector
|
import org.jetbrains.kotlin.backend.common.lower.DefaultParameterInjector
|
||||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||||
import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin
|
import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.ir.backend.js.JsStatementOrigins
|
import org.jetbrains.kotlin.ir.backend.js.JsStatementOrigins
|
||||||
import org.jetbrains.kotlin.ir.backend.js.export.isExported
|
import org.jetbrains.kotlin.ir.backend.js.export.isExported
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.getVoid
|
import org.jetbrains.kotlin.ir.backend.js.utils.getVoid
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.jsConstructorReference
|
import org.jetbrains.kotlin.ir.backend.js.utils.jsConstructorReference
|
||||||
|
import org.jetbrains.kotlin.ir.builders.IrBlockBuilder
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
|
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||||
@@ -20,8 +21,6 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression
|
|||||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
|
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
|
||||||
import org.jetbrains.kotlin.ir.util.copyAnnotations
|
|
||||||
import org.jetbrains.kotlin.ir.util.isTopLevel
|
import org.jetbrains.kotlin.ir.util.isTopLevel
|
||||||
import org.jetbrains.kotlin.ir.util.isVararg
|
import org.jetbrains.kotlin.ir.util.isVararg
|
||||||
|
|
||||||
@@ -48,32 +47,24 @@ class JsDefaultParameterInjector(context: JsIrBackendContext) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun parametersForCall(expression: IrFunctionAccessExpression): Pair<IrFunctionSymbol, List<IrExpression?>>? {
|
override fun IrBlockBuilder.argumentsForCall(expression: IrFunctionAccessExpression, stubFunction: IrFunction): Map<IrValueParameter, IrExpression?> {
|
||||||
val startOffset = expression.startOffset
|
val startOffset = expression.startOffset
|
||||||
val endOffset = expression.endOffset
|
val endOffset = expression.endOffset
|
||||||
val declaration = expression.symbol.owner
|
|
||||||
|
|
||||||
val stubFunction = factory.findBaseFunctionWithDefaultArgumentsFor(declaration, skipInline, skipExternalMethods)?.let {
|
return buildMap {
|
||||||
factory.generateDefaultsFunction(
|
stubFunction.dispatchReceiverParameter?.let { put(it, expression.dispatchReceiver) }
|
||||||
it,
|
stubFunction.extensionReceiverParameter?.let { put(it, expression.extensionReceiver) }
|
||||||
skipInline,
|
|
||||||
skipExternalMethods,
|
|
||||||
forceSetOverrideSymbols,
|
|
||||||
defaultArgumentStubVisibility(declaration),
|
|
||||||
useConstructorMarker(declaration),
|
|
||||||
it.copyAnnotations(),
|
|
||||||
)
|
|
||||||
} ?: return null
|
|
||||||
|
|
||||||
return stubFunction.symbol to buildList {
|
|
||||||
for (i in 0 until expression.valueArgumentsCount) {
|
for (i in 0 until expression.valueArgumentsCount) {
|
||||||
val declaredParameter = stubFunction.valueParameters[i]
|
val declaredParameter = stubFunction.valueParameters[i]
|
||||||
val actualParameter = expression.getValueArgument(i)
|
val actualArgument = expression.getValueArgument(i)
|
||||||
add(actualParameter ?: nullConst(startOffset, endOffset, declaredParameter))
|
put(declaredParameter, actualArgument ?: nullConst(startOffset, endOffset, declaredParameter))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expression is IrCall && stubFunction.hasSuperContextParameter()) {
|
if (expression is IrCall && stubFunction.hasSuperContextParameter()) {
|
||||||
add(expression.superQualifierSymbol?.prototypeOf() ?: context.getVoid())
|
put(
|
||||||
|
stubFunction.valueParameters[expression.valueArgumentsCount],
|
||||||
|
expression.superQualifierSymbol?.prototypeOf() ?: this@JsDefaultParameterInjector.context.getVoid()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -226,7 +226,8 @@ private class AddContinuationLowering(context: JvmBackendContext) : SuspendLower
|
|||||||
JavaDescriptorVisibilities.PACKAGE_VISIBILITY,
|
JavaDescriptorVisibilities.PACKAGE_VISIBILITY,
|
||||||
isFakeOverride = false,
|
isFakeOverride = false,
|
||||||
copyMetadata = false,
|
copyMetadata = false,
|
||||||
typeParametersFromContext = extractTypeParameters(irFunction.parentAsClass)
|
typeParametersFromContext = extractTypeParameters(irFunction.parentAsClass),
|
||||||
|
remapMultiFieldValueClassStructure = context::remapMultiFieldValueClassStructure
|
||||||
)
|
)
|
||||||
static.body = irFunction.moveBodyTo(static)
|
static.body = irFunction.moveBodyTo(static)
|
||||||
// Fixup dispatch parameter to outer class
|
// Fixup dispatch parameter to outer class
|
||||||
|
|||||||
+28
-110
@@ -10,9 +10,10 @@ import org.jetbrains.kotlin.backend.common.lower.SpecialMethodWithDefaultInfo
|
|||||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||||
import org.jetbrains.kotlin.backend.common.lower.irNot
|
import org.jetbrains.kotlin.backend.common.lower.irNot
|
||||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||||
import org.jetbrains.kotlin.backend.jvm.*
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
import org.jetbrains.kotlin.backend.jvm.MemoizedMultiFieldValueClassReplacements.RemappedParameter.MultiFieldValueClassMapping
|
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.backend.jvm.MemoizedMultiFieldValueClassReplacements.RemappedParameter.RegularMapping
|
import org.jetbrains.kotlin.backend.jvm.MemoizedMultiFieldValueClassReplacements
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.SpecialBridge
|
||||||
import org.jetbrains.kotlin.backend.jvm.ir.*
|
import org.jetbrains.kotlin.backend.jvm.ir.*
|
||||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||||
@@ -24,7 +25,10 @@ import org.jetbrains.kotlin.ir.declarations.*
|
|||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.*
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
|
import org.jetbrains.kotlin.ir.types.isNullable
|
||||||
|
import org.jetbrains.kotlin.ir.types.isPrimitiveType
|
||||||
|
import org.jetbrains.kotlin.ir.types.makeNullable
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
@@ -598,22 +602,20 @@ internal class BridgeLowering(val context: JvmBackendContext) : FileLoweringPass
|
|||||||
bridge: IrSimpleFunction,
|
bridge: IrSimpleFunction,
|
||||||
target: IrSimpleFunction,
|
target: IrSimpleFunction,
|
||||||
superQualifierSymbol: IrClassSymbol? = null
|
superQualifierSymbol: IrClassSymbol? = null
|
||||||
) =
|
) = irCastIfNeeded(irBlock {
|
||||||
irCastIfNeeded(irBlock {
|
+irReturn(irCall(target, origin = IrStatementOrigin.BRIDGE_DELEGATION, superQualifierSymbol = superQualifierSymbol).apply {
|
||||||
+irReturn(irCall(target, origin = IrStatementOrigin.BRIDGE_DELEGATION, superQualifierSymbol = superQualifierSymbol).apply {
|
if (getStructure(target) == null && getStructure(bridge) == null) {
|
||||||
|
for ((param, targetParam) in bridge.explicitParameters.zip(target.explicitParameters)) {
|
||||||
val targetStructure = getStructure(target)
|
val argument = irGet(param).let { argument ->
|
||||||
val bridgeStructure = getStructure(bridge)
|
if (param == bridge.dispatchReceiverParameter) argument else irCastIfNeeded(argument, targetParam.type.upperBound)
|
||||||
|
|
||||||
if (targetStructure == null && bridgeStructure == null) {
|
|
||||||
for ((param, targetParam) in bridge.explicitParameters.zip(target.explicitParameters)) {
|
|
||||||
putArgument(targetParam, irGetOrCast(bridge, param, targetParam))
|
|
||||||
}
|
}
|
||||||
} else {
|
putArgument(targetParam, argument)
|
||||||
this@irBlock.addBoxedAndUnboxedMfvcArguments(targetStructure, bridgeStructure, target, bridge, this)
|
|
||||||
}
|
}
|
||||||
})
|
} else {
|
||||||
}.unwrapBlock(), bridge.returnType.upperBound)
|
this@irBlock.addBoxedAndUnboxedMfvcArguments(target, bridge, this)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}.unwrapBlock(), bridge.returnType.upperBound)
|
||||||
|
|
||||||
private fun getStructure(function: IrSimpleFunction): List<MemoizedMultiFieldValueClassReplacements.RemappedParameter>? {
|
private fun getStructure(function: IrSimpleFunction): List<MemoizedMultiFieldValueClassReplacements.RemappedParameter>? {
|
||||||
val structure = context.multiFieldValueClassReplacements.bindingNewFunctionToParameterTemplateStructure[function] ?: return null
|
val structure = context.multiFieldValueClassReplacements.bindingNewFunctionToParameterTemplateStructure[function] ?: return null
|
||||||
@@ -625,106 +627,22 @@ internal class BridgeLowering(val context: JvmBackendContext) : FileLoweringPass
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun IrBlockBuilder.addBoxedAndUnboxedMfvcArguments(
|
private fun IrBlockBuilder.addBoxedAndUnboxedMfvcArguments(
|
||||||
targetStructure: List<MemoizedMultiFieldValueClassReplacements.RemappedParameter>?,
|
|
||||||
bridgeStructure: List<MemoizedMultiFieldValueClassReplacements.RemappedParameter>?,
|
|
||||||
target: IrSimpleFunction,
|
target: IrSimpleFunction,
|
||||||
bridge: IrSimpleFunction,
|
bridge: IrSimpleFunction,
|
||||||
irCall: IrCall
|
irCall: IrCall
|
||||||
) {
|
) {
|
||||||
require(
|
val parameters2arguments = this@BridgeLowering.context.multiFieldValueClassReplacements
|
||||||
targetStructure == null || bridgeStructure == null ||
|
.mapFunctionMfvcStructures(this, target, bridge) { sourceParameter, targetParameterType ->
|
||||||
bridgeStructure.size == targetStructure.size &&
|
if (sourceParameter == bridge.dispatchReceiverParameter) irGet(sourceParameter)
|
||||||
(targetStructure zip bridgeStructure).none { (targetParameter, bridgeParameter) ->
|
else irCastIfNeeded(irGet(sourceParameter), targetParameterType)
|
||||||
targetParameter is MultiFieldValueClassMapping && bridgeParameter is MultiFieldValueClassMapping &&
|
}
|
||||||
targetParameter.rootMfvcNode != bridgeParameter.rootMfvcNode
|
for ((parameter, argument) in parameters2arguments) {
|
||||||
}
|
if (argument != null) {
|
||||||
) { "Incompatible structures: $bridgeStructure and $targetStructure" }
|
irCall.putArgument(parameter, argument)
|
||||||
|
|
||||||
val targetExplicitParameters = target.explicitParameters
|
|
||||||
val bridgeExplicitParameters = bridge.explicitParameters
|
|
||||||
var targetIndex = 0
|
|
||||||
var bridgeIndex = 0
|
|
||||||
var structureIndex = 0
|
|
||||||
while (targetIndex < targetExplicitParameters.size && bridgeIndex < bridgeExplicitParameters.size) {
|
|
||||||
val targetRemappedParameter = targetStructure?.get(structureIndex)
|
|
||||||
val bridgeRemappedParameter = bridgeStructure?.get(structureIndex)
|
|
||||||
when (targetRemappedParameter) {
|
|
||||||
is MultiFieldValueClassMapping -> when (bridgeRemappedParameter) {
|
|
||||||
is MultiFieldValueClassMapping -> {
|
|
||||||
require(bridgeRemappedParameter.rootMfvcNode == targetRemappedParameter.rootMfvcNode) {
|
|
||||||
"Incompatible parameters: $bridgeRemappedParameter, $targetRemappedParameter"
|
|
||||||
}
|
|
||||||
repeat(bridgeRemappedParameter.valueParameters.size) {
|
|
||||||
val bridgeParameter = bridgeExplicitParameters[bridgeIndex++]
|
|
||||||
val targetParameter = targetExplicitParameters[targetIndex++]
|
|
||||||
irCall.putArgument(targetParameter, irGetOrCast(bridge, bridgeParameter, targetParameter))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
is RegularMapping, null -> {
|
|
||||||
val bridgeParameter = bridgeExplicitParameters[bridgeIndex++]
|
|
||||||
val targetParameterType = targetRemappedParameter.rootMfvcNode.mfvc.defaultType
|
|
||||||
val instance = targetRemappedParameter.rootMfvcNode.createInstanceFromBox(
|
|
||||||
this,
|
|
||||||
irCastIfNeeded(irGet(bridgeParameter), targetParameterType),
|
|
||||||
AccessType.ChooseEffective
|
|
||||||
) { error("Not applicable") }
|
|
||||||
val newArguments = instance.makeFlattenedGetterExpressions(this, bridge.parentAsClass, registerPossibleExtraBoxCreation = {})
|
|
||||||
for (newArgument in newArguments) {
|
|
||||||
irCall.putArgument(targetExplicitParameters[targetIndex++], newArgument)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
is RegularMapping, null -> {
|
|
||||||
val targetParameter = targetExplicitParameters[targetIndex]
|
|
||||||
when (bridgeRemappedParameter) {
|
|
||||||
is MultiFieldValueClassMapping -> {
|
|
||||||
val valueArguments = List(bridgeRemappedParameter.rootMfvcNode.leavesCount) {
|
|
||||||
irGet(bridgeExplicitParameters[bridgeIndex++])
|
|
||||||
}
|
|
||||||
val boxCall = bridgeRemappedParameter.rootMfvcNode.makeBoxedExpression(
|
|
||||||
this, bridgeRemappedParameter.typeArguments, valueArguments, registerPossibleExtraBoxCreation = {}
|
|
||||||
)
|
|
||||||
irCall.putArgument(targetParameter, irCastIfNeeded(boxCall, targetParameter.type.upperBound))
|
|
||||||
}
|
|
||||||
|
|
||||||
is RegularMapping, null -> {
|
|
||||||
val bridgeParameter = bridgeExplicitParameters[bridgeIndex++]
|
|
||||||
irCall.putArgument(targetParameter, irGetOrCast(bridge, bridgeParameter, targetParameter))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
targetIndex++
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
structureIndex++
|
|
||||||
}
|
|
||||||
require(targetIndex == targetExplicitParameters.size && bridgeIndex == bridgeExplicitParameters.size) {
|
|
||||||
"Incorrect bridge:\n${bridge.dump()}\n\nfor target\n${target.dump()}"
|
|
||||||
}
|
|
||||||
require((targetStructure == null || structureIndex == targetStructure.size)) {
|
|
||||||
"Invalid structure index $structureIndex for $targetStructure"
|
|
||||||
}
|
|
||||||
require((bridgeStructure == null || structureIndex == bridgeStructure.size)) {
|
|
||||||
"Invalid structure index $structureIndex for $bridgeStructure"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrBuilderWithScope.irGetOrCast(
|
|
||||||
bridge: IrSimpleFunction,
|
|
||||||
bridgeParameter: IrValueParameter,
|
|
||||||
targetParameter: IrValueParameter
|
|
||||||
) =
|
|
||||||
irGet(bridgeParameter).let { argument ->
|
|
||||||
if (bridgeParameter == bridge.dispatchReceiverParameter)
|
|
||||||
argument
|
|
||||||
else
|
|
||||||
irCastIfNeeded(argument, targetParameter.type.upperBound)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun IrBuilderWithScope.irCastIfNeeded(expression: IrExpression, to: IrType): IrExpression =
|
|
||||||
if (expression.type == to || to.isAny() || to.isNullableAny()) expression else irImplicitCast(expression, to)
|
|
||||||
|
|
||||||
private val IrFunction.jvmMethod: Method
|
private val IrFunction.jvmMethod: Method
|
||||||
get() = context.bridgeLoweringCache.computeJvmMethod(this)
|
get() = context.bridgeLoweringCache.computeJvmMethod(this)
|
||||||
}
|
}
|
||||||
|
|||||||
+21
-59
@@ -12,26 +12,20 @@ import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
|||||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.backend.jvm.MemoizedMultiFieldValueClassReplacements.RemappedParameter.MultiFieldValueClassMapping
|
|
||||||
import org.jetbrains.kotlin.backend.jvm.MemoizedMultiFieldValueClassReplacements.RemappedParameter.RegularMapping
|
|
||||||
import org.jetbrains.kotlin.backend.jvm.fullValueParameterList
|
|
||||||
import org.jetbrains.kotlin.backend.jvm.ir.*
|
import org.jetbrains.kotlin.backend.jvm.ir.*
|
||||||
import org.jetbrains.kotlin.backend.jvm.makeBoxedExpression
|
|
||||||
import org.jetbrains.kotlin.builtins.StandardNames
|
import org.jetbrains.kotlin.builtins.StandardNames
|
||||||
import org.jetbrains.kotlin.config.JvmDefaultMode
|
import org.jetbrains.kotlin.config.JvmDefaultMode
|
||||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.descriptors.deserialization.PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME
|
import org.jetbrains.kotlin.descriptors.deserialization.PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.builders.irBlockBody
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
import org.jetbrains.kotlin.ir.builders.irCall
|
|
||||||
import org.jetbrains.kotlin.ir.builders.irGet
|
|
||||||
import org.jetbrains.kotlin.ir.builders.irReturn
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
|
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.putArgument
|
||||||
import org.jetbrains.kotlin.ir.types.IrType
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.*
|
import org.jetbrains.kotlin.ir.visitors.*
|
||||||
@@ -96,59 +90,27 @@ private class InheritedDefaultMethodsOnClassesLowering(val context: JvmBackendCo
|
|||||||
val classStartOffset = classOverride.parentAsClass.startOffset
|
val classStartOffset = classOverride.parentAsClass.startOffset
|
||||||
val backendContext = context
|
val backendContext = context
|
||||||
context.createIrBuilder(irFunction.symbol, classStartOffset, classStartOffset).apply {
|
context.createIrBuilder(irFunction.symbol, classStartOffset, classStartOffset).apply {
|
||||||
irFunction.body = irBlockBody {
|
irFunction.body = irExprBody(irBlock {
|
||||||
+irReturn(
|
val parameter2arguments = backendContext.multiFieldValueClassReplacements
|
||||||
irCall(defaultImplFun.symbol, irFunction.returnType).apply {
|
.mapFunctionMfvcStructures(this, defaultImplFun, irFunction) { sourceParameter, _ ->
|
||||||
superMethod.parentAsClass.typeParameters.forEachIndexed { index, _ ->
|
irGet(sourceParameter).let {
|
||||||
putTypeArgument(index, createPlaceholderAnyNType(context.irBuiltIns))
|
if (sourceParameter != irFunction.dispatchReceiverParameter) it
|
||||||
}
|
else it.reinterpretAsDispatchReceiverOfType(superClassType)
|
||||||
passTypeArgumentsFrom(irFunction, offset = superMethod.parentAsClass.typeParameters.size)
|
|
||||||
|
|
||||||
irFunction.dispatchReceiverParameter?.let {
|
|
||||||
putValueArgument(0, irGet(it).reinterpretAsDispatchReceiverOfType(superClassType))
|
|
||||||
}
|
|
||||||
val bindingNewFunctionToParameterTemplateStructure = backendContext.multiFieldValueClassReplacements
|
|
||||||
.bindingNewFunctionToParameterTemplateStructure
|
|
||||||
val structure = bindingNewFunctionToParameterTemplateStructure[classOverride]?.let { structure ->
|
|
||||||
require(structure.sumOf { it.valueParameters.size } == classOverride.explicitParametersCount) {
|
|
||||||
"Bad parameters structure: $structure"
|
|
||||||
}
|
|
||||||
if (defaultImplFun.explicitParametersCount == irFunction.explicitParametersCount) {
|
|
||||||
null
|
|
||||||
} else {
|
|
||||||
require(structure.size == defaultImplFun.explicitParametersCount) { "Bad parameters structure: $structure" }
|
|
||||||
structure
|
|
||||||
}
|
|
||||||
}
|
|
||||||
require(structure == null || structure.first() is RegularMapping) {
|
|
||||||
"Dispatch receiver for method replacement cannot be flattened"
|
|
||||||
}
|
|
||||||
val sourceFullValueParameterList = irFunction.fullValueParameterList
|
|
||||||
if (structure == null) {
|
|
||||||
for ((index, parameter) in sourceFullValueParameterList.withIndex()) {
|
|
||||||
putValueArgument(1 + index, irGet(parameter))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
var flattenedIndex = 0
|
|
||||||
for (i in 1 until structure.size) {
|
|
||||||
when (val remappedParameter = structure[i]) {
|
|
||||||
is MultiFieldValueClassMapping -> {
|
|
||||||
val valueArguments = remappedParameter.valueParameters.indices.map {
|
|
||||||
irGet(sourceFullValueParameterList[flattenedIndex++])
|
|
||||||
}
|
|
||||||
val boxedExpression = remappedParameter.rootMfvcNode.makeBoxedExpression(
|
|
||||||
this@irBlockBody, remappedParameter.typeArguments, valueArguments, registerPossibleExtraBoxCreation = {}
|
|
||||||
)
|
|
||||||
putValueArgument(i, boxedExpression)
|
|
||||||
}
|
|
||||||
|
|
||||||
is RegularMapping -> putValueArgument(i, irGet(sourceFullValueParameterList[flattenedIndex++]))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
+irCall(defaultImplFun.symbol, irFunction.returnType).apply {
|
||||||
}
|
for (index in superMethod.parentAsClass.typeParameters.indices) {
|
||||||
|
putTypeArgument(index, createPlaceholderAnyNType(context.irBuiltIns))
|
||||||
|
}
|
||||||
|
passTypeArgumentsFrom(irFunction, offset = superMethod.parentAsClass.typeParameters.size)
|
||||||
|
|
||||||
|
for ((parameter, argument) in parameter2arguments) {
|
||||||
|
if (argument != null) {
|
||||||
|
putArgument(parameter, argument)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return irFunction
|
return irFunction
|
||||||
|
|||||||
+60
@@ -10,11 +10,18 @@ import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
|||||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.backend.jvm.ir.defaultValue
|
import org.jetbrains.kotlin.backend.jvm.ir.defaultValue
|
||||||
import org.jetbrains.kotlin.backend.jvm.ir.getJvmVisibilityOfDefaultArgumentStub
|
import org.jetbrains.kotlin.backend.jvm.ir.getJvmVisibilityOfDefaultArgumentStub
|
||||||
|
import org.jetbrains.kotlin.ir.builders.IrBlockBuilder
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
|
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||||
import org.jetbrains.kotlin.ir.types.IrType
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
|
import org.jetbrains.kotlin.ir.util.explicitParametersCount
|
||||||
|
import org.jetbrains.kotlin.ir.util.render
|
||||||
|
|
||||||
class JvmDefaultParameterInjector(context: JvmBackendContext) : DefaultParameterInjector<JvmBackendContext>(
|
class JvmDefaultParameterInjector(context: JvmBackendContext) : DefaultParameterInjector<JvmBackendContext>(
|
||||||
context = context,
|
context = context,
|
||||||
@@ -40,4 +47,57 @@ class JvmDefaultParameterInjector(context: JvmBackendContext) : DefaultParameter
|
|||||||
override fun isStatic(function: IrFunction): Boolean =
|
override fun isStatic(function: IrFunction): Boolean =
|
||||||
function.origin == JvmLoweredDeclarationOrigin.STATIC_INLINE_CLASS_REPLACEMENT ||
|
function.origin == JvmLoweredDeclarationOrigin.STATIC_INLINE_CLASS_REPLACEMENT ||
|
||||||
function.origin == JvmLoweredDeclarationOrigin.STATIC_MULTI_FIELD_VALUE_CLASS_REPLACEMENT
|
function.origin == JvmLoweredDeclarationOrigin.STATIC_MULTI_FIELD_VALUE_CLASS_REPLACEMENT
|
||||||
|
|
||||||
|
|
||||||
|
override fun IrBlockBuilder.argumentsForCall(
|
||||||
|
expression: IrFunctionAccessExpression, stubFunction: IrFunction
|
||||||
|
): Map<IrValueParameter, IrExpression?> {
|
||||||
|
val startOffset = expression.startOffset
|
||||||
|
val endOffset = expression.endOffset
|
||||||
|
val declaration = expression.symbol.owner
|
||||||
|
|
||||||
|
val realArgumentsNumber = declaration.valueParameters.filterNot { it.isMovedReceiver() }.size
|
||||||
|
val maskValues = IntArray((realArgumentsNumber + 31) / 32)
|
||||||
|
|
||||||
|
val oldArguments: Map<IrValueParameter, IrExpression?> = buildMap {
|
||||||
|
declaration.dispatchReceiverParameter?.let { put(it, expression.dispatchReceiver) }
|
||||||
|
declaration.extensionReceiverParameter?.let { put(it, expression.extensionReceiver) }
|
||||||
|
putAll(declaration.valueParameters.mapIndexed { index, parameter -> parameter to expression.getValueArgument(index) })
|
||||||
|
}
|
||||||
|
|
||||||
|
val indexes = declaration.valueParameters.filterNot { it.isMovedReceiver() }.withIndex().associate { it.value to it.index }
|
||||||
|
val mainArguments = this@JvmDefaultParameterInjector.context.multiFieldValueClassReplacements
|
||||||
|
.mapFunctionMfvcStructures(this, stubFunction, declaration) { sourceParameter: IrValueParameter, targetParameterType: IrType ->
|
||||||
|
val valueArgument = oldArguments[sourceParameter]
|
||||||
|
if (valueArgument == null) {
|
||||||
|
val index = indexes[sourceParameter]!!
|
||||||
|
maskValues[index / 32] = maskValues[index / 32] or (1 shl (index % 32))
|
||||||
|
}
|
||||||
|
valueArgument ?: IrCompositeImpl(
|
||||||
|
expression.startOffset,
|
||||||
|
expression.endOffset,
|
||||||
|
targetParameterType,
|
||||||
|
IrStatementOrigin.DEFAULT_VALUE,
|
||||||
|
listOf(nullConst(startOffset, endOffset, targetParameterType))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
assert(stubFunction.explicitParametersCount - mainArguments.size - maskValues.size in listOf(0, 1)) {
|
||||||
|
"argument count mismatch: expected $realArgumentsNumber arguments + ${maskValues.size} masks + optional handler/marker, " +
|
||||||
|
"got ${stubFunction.explicitParametersCount} total in ${stubFunction.render()}"
|
||||||
|
}
|
||||||
|
|
||||||
|
return buildMap {
|
||||||
|
putAll(mainArguments)
|
||||||
|
val restParameters = stubFunction.valueParameters.filterNot { it in mainArguments }
|
||||||
|
for ((maskParameter, maskValue) in restParameters zip maskValues.asList()) {
|
||||||
|
put(maskParameter, IrConstImpl.int(startOffset, endOffset, maskParameter.type, maskValue))
|
||||||
|
}
|
||||||
|
if (restParameters.size > maskValues.size) {
|
||||||
|
val lastParameter = restParameters.last()
|
||||||
|
put(lastParameter, IrConstImpl.constNull(startOffset, endOffset, lastParameter.type))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+52
-121
@@ -518,15 +518,21 @@ internal class JvmMultiFieldValueClassLowering(
|
|||||||
name = mangledName
|
name = mangledName
|
||||||
returnType = source.returnType
|
returnType = source.returnType
|
||||||
}.apply {
|
}.apply {
|
||||||
val isAnyOverriddenReplaced = replacement.overriddenSymbols.any {
|
val implementationStructure = if (isFakeOverride) {
|
||||||
it.owner in replacements.bindingNewFunctionToParameterTemplateStructure
|
val superDeclaration = replacement.allOverridden().singleOrNull { it.body != null }
|
||||||
|
?: error("${this.render()} is fake override and has no implementation")
|
||||||
|
replacements.bindingNewFunctionToParameterTemplateStructure[superDeclaration]
|
||||||
|
?: superDeclaration.explicitParameters.map { RegularMapping(it) }
|
||||||
|
} else {
|
||||||
|
replacements.bindingNewFunctionToParameterTemplateStructure[replacement]
|
||||||
|
?: error("${replacement.render()} must have MFVC structure")
|
||||||
}
|
}
|
||||||
if (source.parentAsClass.isMultiFieldValueClass && isAnyOverriddenReplaced) {
|
copyTypeParametersFrom(source) // without static type parameters
|
||||||
copyTypeParametersFrom(source) // without static type parameters
|
val substitutionMap = makeTypeParameterSubstitutionMap(source, this)
|
||||||
val substitutionMap = makeTypeParameterSubstitutionMap(source, this)
|
dispatchReceiverParameter = source.dispatchReceiverParameter!!.let { // source!!!
|
||||||
dispatchReceiverParameter = source.dispatchReceiverParameter!!.let { // source!!!
|
it.copyTo(this, type = it.type.substitute(substitutionMap))
|
||||||
it.copyTo(this, type = it.type.substitute(substitutionMap))
|
}
|
||||||
}
|
if ((source.parent as? IrClass)?.isMultiFieldValueClass == true) {
|
||||||
require(replacement.dispatchReceiverParameter == null) {
|
require(replacement.dispatchReceiverParameter == null) {
|
||||||
"""
|
"""
|
||||||
Ambiguous receivers:
|
Ambiguous receivers:
|
||||||
@@ -534,19 +540,32 @@ internal class JvmMultiFieldValueClassLowering(
|
|||||||
${replacement.dispatchReceiverParameter!!.render()}
|
${replacement.dispatchReceiverParameter!!.render()}
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
}
|
}
|
||||||
require(replacement.extensionReceiverParameter == null) {
|
|
||||||
"Static replacement must have no extension receiver but ${replacement.extensionReceiverParameter!!.render()} found"
|
|
||||||
}
|
|
||||||
val replacementStructure = replacements.bindingNewFunctionToParameterTemplateStructure[replacement]!!
|
|
||||||
val offset = replacementStructure[0].valueParameters.size
|
|
||||||
valueParameters = replacement.valueParameters.drop(offset).map {
|
|
||||||
it.copyTo(this, type = it.type.substitute(substitutionMap), index = it.index - offset)
|
|
||||||
}
|
|
||||||
val parametersMapping = (replacement.valueParameters.drop(offset) zip valueParameters).toMap()
|
|
||||||
context.remapMultiFieldValueClassStructure(replacement, this, parametersMapping)
|
|
||||||
} else {
|
|
||||||
copyParameterDeclarationsFrom(source)
|
|
||||||
}
|
}
|
||||||
|
require(replacement.extensionReceiverParameter == null) {
|
||||||
|
"Static replacement must have no extension receiver but ${replacement.extensionReceiverParameter!!.render()} found"
|
||||||
|
}
|
||||||
|
val structure = buildList(implementationStructure.size) {
|
||||||
|
var valueParameterIndex = 0
|
||||||
|
add(RegularMapping(dispatchReceiverParameter!!))
|
||||||
|
val valueParametersAsMutableList = mutableListOf<IrValueParameter>()
|
||||||
|
for (expectedParameterStructure in implementationStructure.asSequence().drop(this.size)) {
|
||||||
|
fun IrValueParameter.copy() =
|
||||||
|
copyTo(this@apply, type = type.substitute(substitutionMap), index = valueParameterIndex++)
|
||||||
|
|
||||||
|
val parameterStructure = when (expectedParameterStructure) {
|
||||||
|
is RegularMapping -> RegularMapping(expectedParameterStructure.valueParameter.copy())
|
||||||
|
is MultiFieldValueClassMapping -> MultiFieldValueClassMapping(
|
||||||
|
expectedParameterStructure.rootMfvcNode,
|
||||||
|
substitutionMap,
|
||||||
|
expectedParameterStructure.valueParameters.map { it.copy() }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
add(parameterStructure)
|
||||||
|
valueParametersAsMutableList.addAll(parameterStructure.valueParameters)
|
||||||
|
}
|
||||||
|
valueParameters = valueParametersAsMutableList
|
||||||
|
}
|
||||||
|
replacements.bindingNewFunctionToParameterTemplateStructure[this] = structure
|
||||||
annotations = source.annotations
|
annotations = source.annotations
|
||||||
parent = source.parent
|
parent = source.parent
|
||||||
// We need to ensure that this bridge has the same attribute owner as its static inline class replacement, since this
|
// We need to ensure that this bridge has the same attribute owner as its static inline class replacement, since this
|
||||||
@@ -557,110 +576,17 @@ internal class JvmMultiFieldValueClassLowering(
|
|||||||
|
|
||||||
override fun createBridgeBody(source: IrSimpleFunction, target: IrSimpleFunction, original: IrFunction, inverted: Boolean) {
|
override fun createBridgeBody(source: IrSimpleFunction, target: IrSimpleFunction, original: IrFunction, inverted: Boolean) {
|
||||||
allScopes.push(createScope(source))
|
allScopes.push(createScope(source))
|
||||||
source.body = context.createJvmIrBuilder(source.symbol).run {
|
source.body = with(context.createJvmIrBuilder(source.symbol)) {
|
||||||
val sourceExplicitParameters = source.explicitParameters
|
|
||||||
val targetExplicitParameters = target.explicitParameters
|
|
||||||
irExprBody(irBlock {
|
irExprBody(irBlock {
|
||||||
|
val parameters2arguments = replacements.mapFunctionMfvcStructures(this, target, source) { sourceParameter, _ ->
|
||||||
|
irGet(sourceParameter)
|
||||||
|
}
|
||||||
+irReturn(irCall(target).apply {
|
+irReturn(irCall(target).apply {
|
||||||
passTypeArgumentsWithOffsets(target, source) { source.typeParameters[it].defaultType }
|
passTypeArgumentsWithOffsets(target, source) { source.typeParameters[it].defaultType }
|
||||||
val sourceStructure: List<RemappedParameter>? = replacements.bindingNewFunctionToParameterTemplateStructure[source]
|
for ((parameter, argument) in parameters2arguments) {
|
||||||
val targetStructure: List<RemappedParameter>? = replacements.bindingNewFunctionToParameterTemplateStructure[target]
|
if (argument != null) {
|
||||||
val errorMessage = {
|
putArgument(parameter, argument)
|
||||||
"""
|
|
||||||
Incompatible structures for
|
|
||||||
Source: $sourceStructure
|
|
||||||
${source.render()}
|
|
||||||
Target: $targetStructure
|
|
||||||
${target.render()}
|
|
||||||
""".trimIndent()
|
|
||||||
}
|
|
||||||
when (targetStructure) {
|
|
||||||
null -> when (sourceStructure) {
|
|
||||||
null -> require(targetExplicitParameters.size == sourceExplicitParameters.size, errorMessage)
|
|
||||||
else -> {
|
|
||||||
require(targetExplicitParameters.size == sourceStructure.size, errorMessage)
|
|
||||||
require(sourceExplicitParameters.size == sourceStructure.sumOf { it.valueParameters.size }, errorMessage)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> when (sourceStructure) {
|
|
||||||
null -> {
|
|
||||||
require(targetStructure.size == sourceExplicitParameters.size, errorMessage)
|
|
||||||
require(targetStructure.sumOf { it.valueParameters.size } == targetExplicitParameters.size, errorMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> {
|
|
||||||
require(targetStructure.size == sourceStructure.size, errorMessage)
|
|
||||||
require(sourceStructure.sumOf { it.valueParameters.size } == sourceExplicitParameters.size, errorMessage)
|
|
||||||
require(targetStructure.sumOf { it.valueParameters.size } == targetExplicitParameters.size, errorMessage)
|
|
||||||
require((targetStructure zip sourceStructure).none { (t, s) ->
|
|
||||||
t is MultiFieldValueClassMapping && s is MultiFieldValueClassMapping && t.rootMfvcNode != s.rootMfvcNode
|
|
||||||
}, errorMessage)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val structuresSizes = sourceStructure?.size ?: targetStructure?.size ?: targetExplicitParameters.size
|
|
||||||
var flattenedSourceIndex = 0
|
|
||||||
var flattenedTargetIndex = 0
|
|
||||||
for (i in 0 until structuresSizes) {
|
|
||||||
val remappedSourceParameter = sourceStructure?.get(i)
|
|
||||||
val remappedTargetParameter = targetStructure?.get(i)
|
|
||||||
when (remappedSourceParameter) {
|
|
||||||
is MultiFieldValueClassMapping -> {
|
|
||||||
when (remappedTargetParameter) {
|
|
||||||
is MultiFieldValueClassMapping -> {
|
|
||||||
require(remappedTargetParameter.valueParameters.size == remappedSourceParameter.valueParameters.size) {
|
|
||||||
"Incompatible structures: $remappedTargetParameter, $remappedSourceParameter"
|
|
||||||
}
|
|
||||||
repeat(remappedTargetParameter.valueParameters.size) {
|
|
||||||
putArgument(
|
|
||||||
targetExplicitParameters[flattenedTargetIndex++],
|
|
||||||
irGet(sourceExplicitParameters[flattenedSourceIndex++])
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
is RegularMapping, null -> {
|
|
||||||
val valueArguments = sourceExplicitParameters
|
|
||||||
.slice(flattenedSourceIndex until flattenedSourceIndex + remappedSourceParameter.valueParameters.size)
|
|
||||||
.map { irGet(it) }
|
|
||||||
val targetParameter = targetExplicitParameters[flattenedTargetIndex++]
|
|
||||||
val boxedExpression = remappedSourceParameter.rootMfvcNode.makeBoxedExpression(
|
|
||||||
this@irBlock,
|
|
||||||
remappedSourceParameter.typeArguments,
|
|
||||||
valueArguments,
|
|
||||||
::registerPossibleExtraBoxUsage
|
|
||||||
)
|
|
||||||
putArgument(targetParameter, boxedExpression)
|
|
||||||
.also { flattenedSourceIndex += remappedSourceParameter.valueParameters.size }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
is RegularMapping, null -> when (remappedTargetParameter) {
|
|
||||||
is MultiFieldValueClassMapping -> {
|
|
||||||
val receiver = sourceExplicitParameters[flattenedSourceIndex++]
|
|
||||||
val rootNode = remappedTargetParameter.rootMfvcNode
|
|
||||||
val instance = rootNode.createInstanceFromBox(
|
|
||||||
this@irBlock, irGet(receiver), AccessType.ChooseEffective, ::variablesSaver,
|
|
||||||
)
|
|
||||||
val flattenedExpressions = instance.makeFlattenedGetterExpressions(
|
|
||||||
this@irBlock, irCurrentClass, ::registerPossibleExtraBoxUsage
|
|
||||||
)
|
|
||||||
for (expression in flattenedExpressions) {
|
|
||||||
putArgument(targetExplicitParameters[flattenedTargetIndex++], expression)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> putArgument(
|
|
||||||
targetExplicitParameters[flattenedTargetIndex++],
|
|
||||||
irGet(sourceExplicitParameters[flattenedSourceIndex++])
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
require(flattenedTargetIndex == targetExplicitParameters.size && flattenedSourceIndex == sourceExplicitParameters.size) {
|
|
||||||
"Incorrect source:\n${source.dump()}\n\nfor target\n${target.dump()}"
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -1076,7 +1002,9 @@ internal class JvmMultiFieldValueClassLowering(
|
|||||||
originalFunction: IrFunction,
|
originalFunction: IrFunction,
|
||||||
original: IrMemberAccessExpression<*>,
|
original: IrMemberAccessExpression<*>,
|
||||||
replacement: IrFunction,
|
replacement: IrFunction,
|
||||||
makeMemberAccessExpression: (IrFunctionSymbol) -> IrMemberAccessExpression<*> = ::irCall,
|
makeMemberAccessExpression: (IrFunctionSymbol) -> IrMemberAccessExpression<*> = { callee: IrFunctionSymbol ->
|
||||||
|
irCall(callee.owner, superQualifierSymbol = (original as? IrCall)?.superQualifierSymbol)
|
||||||
|
},
|
||||||
): IrMemberAccessExpression<*> {
|
): IrMemberAccessExpression<*> {
|
||||||
val parameter2expression = typedArgumentList(originalFunction, original)
|
val parameter2expression = typedArgumentList(originalFunction, original)
|
||||||
val structure = replacements.bindingOldFunctionToParameterTemplateStructure[originalFunction]!!
|
val structure = replacements.bindingOldFunctionToParameterTemplateStructure[originalFunction]!!
|
||||||
@@ -1302,6 +1230,9 @@ internal class JvmMultiFieldValueClassLowering(
|
|||||||
if (expression is IrConstructorCall) expression.symbol.owner.constructedClass else expression.type.erasedUpperBound
|
if (expression is IrConstructorCall) expression.symbol.owner.constructedClass else expression.type.erasedUpperBound
|
||||||
)
|
)
|
||||||
val type = if (expression is IrConstructorCall) expression.symbol.owner.constructedClass.defaultType else expression.type
|
val type = if (expression is IrConstructorCall) expression.symbol.owner.constructedClass.defaultType else expression.type
|
||||||
|
if (type == context.irBuiltIns.nothingType) {
|
||||||
|
return flattenExpressionTo(irImplicitCast(expression, instance.type), instance)
|
||||||
|
}
|
||||||
val lowering = this@JvmMultiFieldValueClassLowering
|
val lowering = this@JvmMultiFieldValueClassLowering
|
||||||
if (rootNode == null || !type.needsMfvcFlattening() || instance.size == 1) {
|
if (rootNode == null || !type.needsMfvcFlattening() || instance.size == 1) {
|
||||||
require(instance.size == 1) { "Required 1 variable/field to store regular value but got ${instance.size}" }
|
require(instance.size == 1) { "Required 1 variable/field to store regular value but got ${instance.size}" }
|
||||||
|
|||||||
+1
-1
@@ -211,7 +211,7 @@ internal abstract class JvmValueClassAbstractLowering(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// Update the overridden symbols to point to their inline class replacements
|
// Update the overridden symbols to point to their value class replacements
|
||||||
bridgeFunction.overriddenSymbols = replacement.overriddenSymbols
|
bridgeFunction.overriddenSymbols = replacement.overriddenSymbols
|
||||||
|
|
||||||
// Replace the function body with a wrapper
|
// Replace the function body with a wrapper
|
||||||
|
|||||||
+6
-1
@@ -80,6 +80,11 @@ private class StaticDefaultFunctionLowering(val context: JvmBackendContext) : Ir
|
|||||||
|
|
||||||
private fun getStaticFunctionWithReceivers(function: IrSimpleFunction): IrSimpleFunction =
|
private fun getStaticFunctionWithReceivers(function: IrSimpleFunction): IrSimpleFunction =
|
||||||
context.staticDefaultStubs.getOrPut(function.symbol) {
|
context.staticDefaultStubs.getOrPut(function.symbol) {
|
||||||
context.irFactory.createStaticFunctionWithReceivers(function.parent, function.name, function)
|
context.irFactory.createStaticFunctionWithReceivers(
|
||||||
|
function.parent,
|
||||||
|
function.name,
|
||||||
|
function,
|
||||||
|
remapMultiFieldValueClassStructure = context::remapMultiFieldValueClassStructure
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -220,7 +220,8 @@ class JvmCachedDeclarations(
|
|||||||
modality = Modality.OPEN,
|
modality = Modality.OPEN,
|
||||||
visibility = defaultImplsVisibility,
|
visibility = defaultImplsVisibility,
|
||||||
isFakeOverride = false,
|
isFakeOverride = false,
|
||||||
typeParametersFromContext = parent.typeParameters
|
typeParametersFromContext = parent.typeParameters,
|
||||||
|
remapMultiFieldValueClassStructure = context::remapMultiFieldValueClassStructure
|
||||||
).also {
|
).also {
|
||||||
it.copyCorrespondingPropertyFrom(interfaceFun)
|
it.copyCorrespondingPropertyFrom(interfaceFun)
|
||||||
|
|
||||||
@@ -257,7 +258,6 @@ class JvmCachedDeclarations(
|
|||||||
defaultImplsRedirections.getOrPut(fakeOverride) {
|
defaultImplsRedirections.getOrPut(fakeOverride) {
|
||||||
assert(fakeOverride.isFakeOverride)
|
assert(fakeOverride.isFakeOverride)
|
||||||
val irClass = fakeOverride.parentAsClass
|
val irClass = fakeOverride.parentAsClass
|
||||||
val mfvcReplacementStructure = context.multiFieldValueClassReplacements.bindingNewFunctionToParameterTemplateStructure
|
|
||||||
val redirectFunction = context.irFactory.buildFun {
|
val redirectFunction = context.irFactory.buildFun {
|
||||||
origin = JvmLoweredDeclarationOrigin.SUPER_INTERFACE_METHOD_BRIDGE
|
origin = JvmLoweredDeclarationOrigin.SUPER_INTERFACE_METHOD_BRIDGE
|
||||||
name = fakeOverride.name
|
name = fakeOverride.name
|
||||||
@@ -282,7 +282,7 @@ class JvmCachedDeclarations(
|
|||||||
annotations = fakeOverride.annotations
|
annotations = fakeOverride.annotations
|
||||||
copyCorrespondingPropertyFrom(fakeOverride)
|
copyCorrespondingPropertyFrom(fakeOverride)
|
||||||
}
|
}
|
||||||
mfvcReplacementStructure[fakeOverride]?.let { mfvcReplacementStructure[redirectFunction] = it }
|
context.remapMultiFieldValueClassStructure(fakeOverride, redirectFunction, parametersMappingOrNull = null)
|
||||||
redirectFunction
|
redirectFunction
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+114
-2
@@ -5,23 +5,32 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.jvm
|
package org.jetbrains.kotlin.backend.jvm
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.lower.parents
|
||||||
import org.jetbrains.kotlin.backend.jvm.MemoizedMultiFieldValueClassReplacements.RemappedParameter.MultiFieldValueClassMapping
|
import org.jetbrains.kotlin.backend.jvm.MemoizedMultiFieldValueClassReplacements.RemappedParameter.MultiFieldValueClassMapping
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.MemoizedMultiFieldValueClassReplacements.RemappedParameter.RegularMapping
|
||||||
import org.jetbrains.kotlin.backend.jvm.ir.*
|
import org.jetbrains.kotlin.backend.jvm.ir.*
|
||||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||||
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
|
import org.jetbrains.kotlin.ir.builders.IrBlockBuilder
|
||||||
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
|
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
|
||||||
import org.jetbrains.kotlin.ir.builders.declarations.buildConstructor
|
import org.jetbrains.kotlin.ir.builders.declarations.buildConstructor
|
||||||
|
import org.jetbrains.kotlin.ir.builders.irComposite
|
||||||
import org.jetbrains.kotlin.ir.builders.irExprBody
|
import org.jetbrains.kotlin.ir.builders.irExprBody
|
||||||
import org.jetbrains.kotlin.ir.builders.irGet
|
import org.jetbrains.kotlin.ir.builders.irGet
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrComposite
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrStatementOriginImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||||
import org.jetbrains.kotlin.ir.types.IrType
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
import org.jetbrains.kotlin.ir.types.defaultType
|
import org.jetbrains.kotlin.ir.types.defaultType
|
||||||
|
import org.jetbrains.kotlin.ir.types.isNothing
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.InlineClassDescriptorResolver
|
import org.jetbrains.kotlin.resolve.InlineClassDescriptorResolver
|
||||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -43,7 +52,7 @@ class MemoizedMultiFieldValueClassReplacements(
|
|||||||
originWhenFlattened: IrDeclarationOrigin,
|
originWhenFlattened: IrDeclarationOrigin,
|
||||||
): RemappedParameter {
|
): RemappedParameter {
|
||||||
val oldParam = this
|
val oldParam = this
|
||||||
if (!type.needsMfvcFlattening()) return RemappedParameter.RegularMapping(
|
if (!type.needsMfvcFlattening()) return RegularMapping(
|
||||||
targetFunction.addValueParameter {
|
targetFunction.addValueParameter {
|
||||||
updateFrom(oldParam)
|
updateFrom(oldParam)
|
||||||
this.name = oldParam.name
|
this.name = oldParam.name
|
||||||
@@ -238,7 +247,7 @@ class MemoizedMultiFieldValueClassReplacements(
|
|||||||
dispatchReceiverParameter = function.dispatchReceiverParameter?.copyTo(this, index = -1)
|
dispatchReceiverParameter = function.dispatchReceiverParameter?.copyTo(this, index = -1)
|
||||||
val newFlattenedParameters = makeAndAddGroupedValueParametersFrom(function, includeDispatcherReceiver = false, mapOf(), this)
|
val newFlattenedParameters = makeAndAddGroupedValueParametersFrom(function, includeDispatcherReceiver = false, mapOf(), this)
|
||||||
val receiver = dispatchReceiverParameter
|
val receiver = dispatchReceiverParameter
|
||||||
return if (receiver != null) listOf(RemappedParameter.RegularMapping(receiver)) + newFlattenedParameters else newFlattenedParameters
|
return if (receiver != null) listOf(RegularMapping(receiver)) + newFlattenedParameters else newFlattenedParameters
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -369,4 +378,107 @@ class MemoizedMultiFieldValueClassReplacements(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val IrProperty.backingFieldIfNotToRemove get() = backingField?.takeUnless { it in getFieldsToRemove(this.parentAsClass) }
|
private val IrProperty.backingFieldIfNotToRemove get() = backingField?.takeUnless { it in getFieldsToRemove(this.parentAsClass) }
|
||||||
|
|
||||||
|
@Suppress("ClassName")
|
||||||
|
private object FLATTENED_NOTHING_DEFAULT_VALUE : IrStatementOriginImpl("FLATTENED_NOTHING_DEFAULT_VALUE")
|
||||||
|
|
||||||
|
fun mapFunctionMfvcStructures(
|
||||||
|
irBuilder: IrBlockBuilder,
|
||||||
|
targetFunction: IrFunction,
|
||||||
|
sourceFunction: IrFunction,
|
||||||
|
getArgument: (sourceParameter: IrValueParameter, targetParameterType: IrType) -> IrExpression?
|
||||||
|
): Map<IrValueParameter, IrExpression?> {
|
||||||
|
val targetStructure = bindingNewFunctionToParameterTemplateStructure[targetFunction]
|
||||||
|
?: targetFunction.explicitParameters.map { RegularMapping(it) }
|
||||||
|
val sourceStructure = bindingNewFunctionToParameterTemplateStructure[sourceFunction]
|
||||||
|
?: sourceFunction.explicitParameters.map { RegularMapping(it) }
|
||||||
|
verifyStructureCompatibility(targetStructure, sourceStructure)
|
||||||
|
return buildMap {
|
||||||
|
for ((targetParameterStructure, sourceParameterStructure) in targetStructure zip sourceStructure) {
|
||||||
|
when (targetParameterStructure) {
|
||||||
|
is RegularMapping -> when (sourceParameterStructure) {
|
||||||
|
is RegularMapping -> put(
|
||||||
|
targetParameterStructure.valueParameter,
|
||||||
|
getArgument(sourceParameterStructure.valueParameter, targetParameterStructure.valueParameter.type)
|
||||||
|
)
|
||||||
|
is MultiFieldValueClassMapping -> {
|
||||||
|
val valueArguments = sourceParameterStructure.valueParameters.map {
|
||||||
|
getArgument(it, it.type) ?: error("Expected an argument for $sourceParameterStructure")
|
||||||
|
}
|
||||||
|
val newArgument =
|
||||||
|
if (valueArguments.all { it is IrComposite && it.origin == FLATTENED_NOTHING_DEFAULT_VALUE }) {
|
||||||
|
(valueArguments[0] as IrComposite).statements[0] as IrExpression
|
||||||
|
} else {
|
||||||
|
sourceParameterStructure.rootMfvcNode.makeBoxedExpression(
|
||||||
|
irBuilder,
|
||||||
|
sourceParameterStructure.typeArguments,
|
||||||
|
valueArguments,
|
||||||
|
registerPossibleExtraBoxCreation = {}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
put(targetParameterStructure.valueParameter, newArgument)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is MultiFieldValueClassMapping -> when (sourceParameterStructure) {
|
||||||
|
is RegularMapping -> with(irBuilder) {
|
||||||
|
val argument = getArgument(sourceParameterStructure.valueParameter, targetParameterStructure.boxedType)
|
||||||
|
?: error("Expected an argument for $sourceParameterStructure")
|
||||||
|
if (sourceParameterStructure.valueParameter.type.isNothing()) {
|
||||||
|
for ((index, parameter) in targetParameterStructure.valueParameters.withIndex()) {
|
||||||
|
put(parameter, irComposite(origin = FLATTENED_NOTHING_DEFAULT_VALUE) {
|
||||||
|
if (index == 0) +argument
|
||||||
|
+parameter.type.defaultValue(
|
||||||
|
UNDEFINED_OFFSET, UNDEFINED_OFFSET, this@MemoizedMultiFieldValueClassReplacements.context
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val instance = targetParameterStructure.rootMfvcNode.createInstanceFromBox(
|
||||||
|
scope = this,
|
||||||
|
receiver = argument,
|
||||||
|
accessType = AccessType.ChooseEffective,
|
||||||
|
saveVariable = { +it }
|
||||||
|
)
|
||||||
|
val arguments = instance.makeFlattenedGetterExpressions(
|
||||||
|
this, sourceFunction.parents.firstIsInstance<IrClass>(), registerPossibleExtraBoxCreation = {}
|
||||||
|
)
|
||||||
|
for ((targetParameter, expression) in targetParameterStructure.valueParameters zip arguments) {
|
||||||
|
put(targetParameter, expression)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is MultiFieldValueClassMapping -> {
|
||||||
|
for ((sourceParameter, targetParameter) in sourceParameterStructure.valueParameters zip targetParameterStructure.valueParameters) {
|
||||||
|
put(targetParameter, getArgument(sourceParameter, targetParameter.type))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalStdlibApi::class)
|
||||||
|
private fun verifyStructureCompatibility(
|
||||||
|
targetStructure: List<RemappedParameter>,
|
||||||
|
sourceStructure: List<RemappedParameter>
|
||||||
|
) {
|
||||||
|
for ((targetParameterStructure, sourceParameterStructure) in targetStructure zip sourceStructure) {
|
||||||
|
if (targetParameterStructure is MultiFieldValueClassMapping && sourceParameterStructure is MultiFieldValueClassMapping) {
|
||||||
|
require(targetParameterStructure.rootMfvcNode.mfvc.classId == sourceParameterStructure.rootMfvcNode.mfvc.classId) {
|
||||||
|
"Incompatible parameter structures:\n$targetParameterStructure inside $targetStructure\n$sourceParameterStructure inside $sourceStructure"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (extraParameterStructure in targetStructure.slice(sourceStructure.size..<targetStructure.size)) {
|
||||||
|
require(extraParameterStructure is RegularMapping && extraParameterStructure.valueParameter.origin != IrDeclarationOrigin.DEFINED) {
|
||||||
|
"Unexpected target MFVC parameter structure:\n$extraParameterStructure inside $targetStructure"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (extraParameterStructure in sourceStructure.slice(targetStructure.size..<sourceStructure.size)) {
|
||||||
|
require(extraParameterStructure is RegularMapping && extraParameterStructure.valueParameter.origin != IrDeclarationOrigin.DEFINED) {
|
||||||
|
"Unexpected source MFVC parameter structure:\n$extraParameterStructure inside $sourceStructure"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,10 +27,16 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
|
|
||||||
typealias TypeArguments = Map<IrTypeParameterSymbol, IrType>
|
typealias TypeArguments = Map<IrTypeParameterSymbol, IrType>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instance-agnostic tree node describing structure of multi-field value class
|
||||||
|
*/
|
||||||
sealed interface MfvcNode {
|
sealed interface MfvcNode {
|
||||||
val type: IrType
|
val type: IrType
|
||||||
val leavesCount: Int
|
val leavesCount: Int
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create instance-specific [ReceiverBasedMfvcNodeInstance] from instance-agnostic [MfvcNode] using a boxed [receiver] as data source.
|
||||||
|
*/
|
||||||
fun createInstanceFromBox(
|
fun createInstanceFromBox(
|
||||||
scope: IrBlockBuilder,
|
scope: IrBlockBuilder,
|
||||||
typeArguments: TypeArguments,
|
typeArguments: TypeArguments,
|
||||||
@@ -40,6 +46,9 @@ sealed interface MfvcNode {
|
|||||||
): ReceiverBasedMfvcNodeInstance
|
): ReceiverBasedMfvcNodeInstance
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create instance-specific [ReceiverBasedMfvcNodeInstance] from instance-agnostic [MfvcNode] using a boxed [receiver] as data source.
|
||||||
|
*/
|
||||||
fun MfvcNode.createInstanceFromBox(
|
fun MfvcNode.createInstanceFromBox(
|
||||||
scope: IrBlockBuilder,
|
scope: IrBlockBuilder,
|
||||||
receiver: IrExpression,
|
receiver: IrExpression,
|
||||||
@@ -48,10 +57,16 @@ fun MfvcNode.createInstanceFromBox(
|
|||||||
) =
|
) =
|
||||||
createInstanceFromBox(scope, makeTypeArgumentsFromType(receiver.type as IrSimpleType), receiver, accessType, saveVariable)
|
createInstanceFromBox(scope, makeTypeArgumentsFromType(receiver.type as IrSimpleType), receiver, accessType, saveVariable)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create instance-specific [ValueDeclarationMfvcNodeInstance] from instance-agnostic [MfvcNode] using new flattened variables as data source.
|
||||||
|
*/
|
||||||
fun MfvcNode.createInstanceFromValueDeclarationsAndBoxType(
|
fun MfvcNode.createInstanceFromValueDeclarationsAndBoxType(
|
||||||
scope: IrBuilderWithScope, type: IrSimpleType, name: Name, saveVariable: (IrVariable) -> Unit, isVar: Boolean
|
scope: IrBuilderWithScope, type: IrSimpleType, name: Name, saveVariable: (IrVariable) -> Unit, isVar: Boolean
|
||||||
): ValueDeclarationMfvcNodeInstance = createInstanceFromValueDeclarations(scope, makeTypeArgumentsFromType(type), name, saveVariable, isVar)
|
): ValueDeclarationMfvcNodeInstance = createInstanceFromValueDeclarations(scope, makeTypeArgumentsFromType(type), name, saveVariable, isVar)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create instance-specific [ValueDeclarationMfvcNodeInstance] from instance-agnostic [MfvcNode] using new flattened variables as data source.
|
||||||
|
*/
|
||||||
fun MfvcNode.createInstanceFromValueDeclarations(
|
fun MfvcNode.createInstanceFromValueDeclarations(
|
||||||
scope: IrBuilderWithScope, typeArguments: TypeArguments, name: Name, saveVariable: (IrVariable) -> Unit, isVar: Boolean
|
scope: IrBuilderWithScope, typeArguments: TypeArguments, name: Name, saveVariable: (IrVariable) -> Unit, isVar: Boolean
|
||||||
): ValueDeclarationMfvcNodeInstance {
|
): ValueDeclarationMfvcNodeInstance {
|
||||||
@@ -67,6 +82,9 @@ fun MfvcNode.createInstanceFromValueDeclarations(
|
|||||||
return ValueDeclarationMfvcNodeInstance(this, typeArguments, valueDeclarations)
|
return ValueDeclarationMfvcNodeInstance(this, typeArguments, valueDeclarations)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create instance-specific [ValueDeclarationMfvcNodeInstance] from instance-agnostic [MfvcNode] using flattened [fieldValues] as data source.
|
||||||
|
*/
|
||||||
fun MfvcNode.createInstanceFromValueDeclarationsAndBoxType(
|
fun MfvcNode.createInstanceFromValueDeclarationsAndBoxType(
|
||||||
type: IrSimpleType, fieldValues: List<IrValueDeclaration>
|
type: IrSimpleType, fieldValues: List<IrValueDeclaration>
|
||||||
): ValueDeclarationMfvcNodeInstance =
|
): ValueDeclarationMfvcNodeInstance =
|
||||||
@@ -83,19 +101,41 @@ fun makeTypeArgumentsFromType(type: IrSimpleType): TypeArguments {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Non-root [MfvcNode]. It contains an unbox method and a name.
|
||||||
|
*/
|
||||||
sealed interface NameableMfvcNode : MfvcNode {
|
sealed interface NameableMfvcNode : MfvcNode {
|
||||||
val namedNodeImpl: NameableMfvcNodeImpl
|
val namedNodeImpl: NameableMfvcNodeImpl
|
||||||
val hasPureUnboxMethod: Boolean
|
val hasPureUnboxMethod: Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of names of the root node of the [NameableMfvcNode] up to the node.
|
||||||
|
*/
|
||||||
val NameableMfvcNode.nameParts: List<Name>
|
val NameableMfvcNode.nameParts: List<Name>
|
||||||
get() = namedNodeImpl.nameParts
|
get() = namedNodeImpl.nameParts
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The last [nameParts] which distinguishes the [NameableMfvcNode] from its parent.
|
||||||
|
*/
|
||||||
val NameableMfvcNode.name: Name
|
val NameableMfvcNode.name: Name
|
||||||
get() = nameParts.last()
|
get() = nameParts.last()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unbox method of the [NameableMfvcNode].
|
||||||
|
*/
|
||||||
val NameableMfvcNode.unboxMethod: IrSimpleFunction
|
val NameableMfvcNode.unboxMethod: IrSimpleFunction
|
||||||
get() = namedNodeImpl.unboxMethod
|
get() = namedNodeImpl.unboxMethod
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An unbox function or getter function method name of the [NameableMfvcNode].
|
||||||
|
*/
|
||||||
val NameableMfvcNode.fullMethodName: Name
|
val NameableMfvcNode.fullMethodName: Name
|
||||||
get() = namedNodeImpl.fullMethodName
|
get() = namedNodeImpl.fullMethodName
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A field name corresponding to the [NameableMfvcNode].
|
||||||
|
*/
|
||||||
val NameableMfvcNode.fullFieldName: Name
|
val NameableMfvcNode.fullFieldName: Name
|
||||||
get() = namedNodeImpl.fullFieldName
|
get() = namedNodeImpl.fullFieldName
|
||||||
|
|
||||||
@@ -138,7 +178,9 @@ fun MfvcNode.getSubnodeAndIndices(name: Name): Pair<NameableMfvcNode, IntRange>?
|
|||||||
val indices = subnodeIndices[node] ?: error("existing node without indices")
|
val indices = subnodeIndices[node] ?: error("existing node without indices")
|
||||||
return node to indices
|
return node to indices
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Non-leaf [MfvcNode]. It contains a box method and children.
|
||||||
|
*/
|
||||||
sealed class MfvcNodeWithSubnodes(val subnodes: List<NameableMfvcNode>) : MfvcNode {
|
sealed class MfvcNodeWithSubnodes(val subnodes: List<NameableMfvcNode>) : MfvcNode {
|
||||||
abstract override val type: IrSimpleType
|
abstract override val type: IrSimpleType
|
||||||
abstract val boxMethod: IrSimpleFunction
|
abstract val boxMethod: IrSimpleFunction
|
||||||
@@ -159,6 +201,9 @@ sealed class MfvcNodeWithSubnodes(val subnodes: List<NameableMfvcNode>) : MfvcNo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get child by [name].
|
||||||
|
*/
|
||||||
operator fun get(name: Name): NameableMfvcNode? = mapping[name]
|
operator fun get(name: Name): NameableMfvcNode? = mapping[name]
|
||||||
|
|
||||||
val leaves: List<LeafMfvcNode> = subnodes.leaves
|
val leaves: List<LeafMfvcNode> = subnodes.leaves
|
||||||
@@ -178,6 +223,9 @@ sealed class MfvcNodeWithSubnodes(val subnodes: List<NameableMfvcNode>) : MfvcNo
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a box expression for the given [MfvcNodeWithSubnodes] by calling box methods with the given [typeArguments] and [valueArguments].
|
||||||
|
*/
|
||||||
fun MfvcNodeWithSubnodes.makeBoxedExpression(
|
fun MfvcNodeWithSubnodes.makeBoxedExpression(
|
||||||
scope: IrBuilderWithScope,
|
scope: IrBuilderWithScope,
|
||||||
typeArguments: TypeArguments,
|
typeArguments: TypeArguments,
|
||||||
@@ -195,6 +243,9 @@ fun MfvcNodeWithSubnodes.makeBoxedExpression(
|
|||||||
registerPossibleExtraBoxCreation()
|
registerPossibleExtraBoxCreation()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A shortcut to get children by name several times.
|
||||||
|
*/
|
||||||
operator fun MfvcNodeWithSubnodes.get(names: List<Name>): MfvcNode? {
|
operator fun MfvcNodeWithSubnodes.get(names: List<Name>): MfvcNode? {
|
||||||
var cur: MfvcNode = this
|
var cur: MfvcNode = this
|
||||||
for (name in names) {
|
for (name in names) {
|
||||||
@@ -267,6 +318,9 @@ private fun validateGettingAccessorParameters(function: IrSimpleFunction) {
|
|||||||
require(function.typeParameters.isEmpty()) { "Type parameters are not expected for ${function.render()}" }
|
require(function.typeParameters.isEmpty()) { "Type parameters are not expected for ${function.render()}" }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [MfvcNode] which corresponds to non-MFVC field which is a field of some MFVC.
|
||||||
|
*/
|
||||||
class LeafMfvcNode(
|
class LeafMfvcNode(
|
||||||
override val type: IrType,
|
override val type: IrType,
|
||||||
methodFullNameMode: MethodFullNameMode,
|
methodFullNameMode: MethodFullNameMode,
|
||||||
@@ -310,6 +364,9 @@ val MfvcNode.fields
|
|||||||
is LeafMfvcNode -> field?.let(::listOf)
|
is LeafMfvcNode -> field?.let(::listOf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [MfvcNode] which corresponds to MFVC field which is a field of some class.
|
||||||
|
*/
|
||||||
class IntermediateMfvcNode(
|
class IntermediateMfvcNode(
|
||||||
override val type: IrSimpleType,
|
override val type: IrSimpleType,
|
||||||
methodFullNameMode: MethodFullNameMode,
|
methodFullNameMode: MethodFullNameMode,
|
||||||
@@ -373,7 +430,9 @@ fun IrSimpleFunction.getGetterField(): IrField? {
|
|||||||
val statement = (body?.statements?.singleOrNull() as? IrReturn)?.value as? IrGetField ?: return null
|
val statement = (body?.statements?.singleOrNull() as? IrReturn)?.value as? IrGetField ?: return null
|
||||||
return statement.symbol.owner
|
return statement.symbol.owner
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* [MfvcNode] which corresponds to MFVC itself.
|
||||||
|
*/
|
||||||
class RootMfvcNode internal constructor(
|
class RootMfvcNode internal constructor(
|
||||||
val mfvc: IrClass,
|
val mfvc: IrClass,
|
||||||
subnodes: List<NameableMfvcNode>,
|
subnodes: List<NameableMfvcNode>,
|
||||||
|
|||||||
@@ -18,29 +18,52 @@ import org.jetbrains.kotlin.ir.types.IrType
|
|||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instance-specific tree node describing structure of multi-field value class corresponding to the [MfvcNode]
|
||||||
|
*/
|
||||||
interface MfvcNodeInstance {
|
interface MfvcNodeInstance {
|
||||||
val node: MfvcNode
|
val node: MfvcNode
|
||||||
val typeArguments: TypeArguments
|
val typeArguments: TypeArguments
|
||||||
val type: IrSimpleType
|
val type: IrSimpleType
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make expressions corresponding to the flattened representation of the [MfvcNodeInstance].
|
||||||
|
*/
|
||||||
fun makeFlattenedGetterExpressions(
|
fun makeFlattenedGetterExpressions(
|
||||||
scope: IrBlockBuilder, currentClass: IrClass, registerPossibleExtraBoxCreation: () -> Unit
|
scope: IrBlockBuilder, currentClass: IrClass, registerPossibleExtraBoxCreation: () -> Unit
|
||||||
): List<IrExpression>
|
): List<IrExpression>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make expression that corresponds to read access of the instance
|
||||||
|
*/
|
||||||
fun makeGetterExpression(scope: IrBuilderWithScope, currentClass: IrClass, registerPossibleExtraBoxCreation: () -> Unit): IrExpression
|
fun makeGetterExpression(scope: IrBuilderWithScope, currentClass: IrClass, registerPossibleExtraBoxCreation: () -> Unit): IrExpression
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get child [MfvcNodeInstance] by [name]
|
||||||
|
*/
|
||||||
operator fun get(name: Name): MfvcNodeInstance?
|
operator fun get(name: Name): MfvcNodeInstance?
|
||||||
fun makeStatements(scope: IrBuilderWithScope, values: List<IrExpression>): List<IrStatement>
|
|
||||||
|
/**
|
||||||
|
* Make setter statements corresponding assignments to the [values] of the given flattened representation.
|
||||||
|
*/
|
||||||
|
fun makeSetterStatements(scope: IrBuilderWithScope, values: List<IrExpression>): List<IrStatement>
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun makeTypeFromMfvcNodeAndTypeArguments(node: MfvcNode, typeArguments: TypeArguments) =
|
private fun makeTypeFromMfvcNodeAndTypeArguments(node: MfvcNode, typeArguments: TypeArguments) =
|
||||||
node.type.substitute(typeArguments) as IrSimpleType
|
node.type.substitute(typeArguments) as IrSimpleType
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make and add setter statements corresponding assignments to the [values] of the given flattened representation.
|
||||||
|
*/
|
||||||
fun MfvcNodeInstance.addSetterStatements(scope: IrBlockBuilder, values: List<IrExpression>) = with(scope) {
|
fun MfvcNodeInstance.addSetterStatements(scope: IrBlockBuilder, values: List<IrExpression>) = with(scope) {
|
||||||
for (statement in makeStatements(this, values)) {
|
for (statement in makeSetterStatements(this, values)) {
|
||||||
+statement
|
+statement
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make a block of setter statements corresponding assignments to the [values] of the given flattened representation.
|
||||||
|
*/
|
||||||
fun MfvcNodeInstance.makeSetterExpressions(scope: IrBuilderWithScope, values: List<IrExpression>): IrExpression = scope.irBlock {
|
fun MfvcNodeInstance.makeSetterExpressions(scope: IrBuilderWithScope, values: List<IrExpression>): IrExpression = scope.irBlock {
|
||||||
addSetterStatements(this, values)
|
addSetterStatements(this, values)
|
||||||
}
|
}
|
||||||
@@ -49,6 +72,9 @@ private fun MfvcNodeInstance.checkValuesCount(values: List<IrExpression>) {
|
|||||||
require(values.size == node.leavesCount) { "Node $node requires ${node.leavesCount} values but got ${values.map { it.render() }}" }
|
require(values.size == node.leavesCount) { "Node $node requires ${node.leavesCount} values but got ${values.map { it.render() }}" }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [MfvcNodeInstance] that stores flattened instance in variables and parameters.
|
||||||
|
*/
|
||||||
class ValueDeclarationMfvcNodeInstance(
|
class ValueDeclarationMfvcNodeInstance(
|
||||||
override val node: MfvcNode,
|
override val node: MfvcNode,
|
||||||
override val typeArguments: TypeArguments,
|
override val typeArguments: TypeArguments,
|
||||||
@@ -77,7 +103,7 @@ class ValueDeclarationMfvcNodeInstance(
|
|||||||
return ValueDeclarationMfvcNodeInstance(newNode, typeArguments, valueDeclarations.slice(indices))
|
return ValueDeclarationMfvcNodeInstance(newNode, typeArguments, valueDeclarations.slice(indices))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun makeStatements(scope: IrBuilderWithScope, values: List<IrExpression>): List<IrStatement> {
|
override fun makeSetterStatements(scope: IrBuilderWithScope, values: List<IrExpression>): List<IrStatement> {
|
||||||
checkValuesCount(values)
|
checkValuesCount(values)
|
||||||
return valueDeclarations.zip(values) { declaration, value -> scope.irSet(declaration, value) }
|
return valueDeclarations.zip(values) { declaration, value -> scope.irSet(declaration, value) }
|
||||||
}
|
}
|
||||||
@@ -143,6 +169,9 @@ fun IrExpression?.isRepeatableAccessor(): Boolean = isRepeatableGetter() || isRe
|
|||||||
|
|
||||||
enum class AccessType { UseFields, ChooseEffective }
|
enum class AccessType { UseFields, ChooseEffective }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [MfvcNodeInstance] that stores boxed instance in variables and parameters.
|
||||||
|
*/
|
||||||
class ReceiverBasedMfvcNodeInstance(
|
class ReceiverBasedMfvcNodeInstance(
|
||||||
private val scope: IrBlockBuilder,
|
private val scope: IrBlockBuilder,
|
||||||
override val node: MfvcNode,
|
override val node: MfvcNode,
|
||||||
@@ -235,7 +264,7 @@ class ReceiverBasedMfvcNodeInstance(
|
|||||||
return newNode.createInstanceFromBox(scope, typeArguments, makeReceiverCopy(), accessType, saveVariable)
|
return newNode.createInstanceFromBox(scope, typeArguments, makeReceiverCopy(), accessType, saveVariable)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun makeStatements(scope: IrBuilderWithScope, values: List<IrExpression>): List<IrStatement> {
|
override fun makeSetterStatements(scope: IrBuilderWithScope, values: List<IrExpression>): List<IrStatement> {
|
||||||
checkValuesCount(values)
|
checkValuesCount(values)
|
||||||
require(fields != null) { "$node is immutable as it has custom getter and so no backing fields" }
|
require(fields != null) { "$node is immutable as it has custom getter and so no backing fields" }
|
||||||
return fields.zip(values) { field, expr -> scope.irSetField(makeReceiverCopy(), field, expr) }
|
return fields.zip(values) { field, expr -> scope.irSetField(makeReceiverCopy(), field, expr) }
|
||||||
@@ -245,8 +274,6 @@ class ReceiverBasedMfvcNodeInstance(
|
|||||||
val MfvcNodeInstance.size: Int
|
val MfvcNodeInstance.size: Int
|
||||||
get() = node.leavesCount
|
get() = node.leavesCount
|
||||||
|
|
||||||
fun IrContainerExpression.unwrapBlock(): IrExpression = statements.singleOrNull() as? IrExpression ?: this
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a variable and doesn't add it to a container. It saves the variable with given saveVariable.
|
* Creates a variable and doesn't add it to a container. It saves the variable with given saveVariable.
|
||||||
*
|
*
|
||||||
|
|||||||
+4
-2
@@ -110,7 +110,8 @@ class JsInteropFunctionsLowering(val context: WasmBackendContext) : DeclarationT
|
|||||||
val newFun = context.irFactory.createStaticFunctionWithReceivers(
|
val newFun = context.irFactory.createStaticFunctionWithReceivers(
|
||||||
function.parent,
|
function.parent,
|
||||||
name = Name.identifier(function.name.asStringStripSpecialMarkers() + "__externalAdapter"),
|
name = Name.identifier(function.name.asStringStripSpecialMarkers() + "__externalAdapter"),
|
||||||
function
|
function,
|
||||||
|
remapMultiFieldValueClassStructure = context::remapMultiFieldValueClassStructure
|
||||||
)
|
)
|
||||||
|
|
||||||
function.valueParameters.forEachIndexed { index, newParameter ->
|
function.valueParameters.forEachIndexed { index, newParameter ->
|
||||||
@@ -157,7 +158,8 @@ class JsInteropFunctionsLowering(val context: WasmBackendContext) : DeclarationT
|
|||||||
val newFun = context.irFactory.createStaticFunctionWithReceivers(
|
val newFun = context.irFactory.createStaticFunctionWithReceivers(
|
||||||
function.parent,
|
function.parent,
|
||||||
name = Name.identifier(function.name.asStringStripSpecialMarkers() + "__JsExportAdapter"),
|
name = Name.identifier(function.name.asStringStripSpecialMarkers() + "__JsExportAdapter"),
|
||||||
function
|
function,
|
||||||
|
remapMultiFieldValueClassStructure = context::remapMultiFieldValueClassStructure
|
||||||
)
|
)
|
||||||
|
|
||||||
newFun.valueParameters.forEachIndexed { index, newParameter ->
|
newFun.valueParameters.forEachIndexed { index, newParameter ->
|
||||||
|
|||||||
@@ -7,10 +7,12 @@ package org.jetbrains.kotlin.ir.util
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.ir.*
|
import org.jetbrains.kotlin.ir.*
|
||||||
|
import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope
|
||||||
import org.jetbrains.kotlin.ir.builders.declarations.addConstructor
|
import org.jetbrains.kotlin.ir.builders.declarations.addConstructor
|
||||||
import org.jetbrains.kotlin.ir.builders.declarations.buildClass
|
import org.jetbrains.kotlin.ir.builders.declarations.buildClass
|
||||||
import org.jetbrains.kotlin.ir.builders.declarations.buildReceiverParameter
|
import org.jetbrains.kotlin.ir.builders.declarations.buildReceiverParameter
|
||||||
import org.jetbrains.kotlin.ir.builders.declarations.buildTypeParameter
|
import org.jetbrains.kotlin.ir.builders.declarations.buildTypeParameter
|
||||||
|
import org.jetbrains.kotlin.ir.builders.irImplicitCast
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
@@ -1183,7 +1185,8 @@ fun IrFactory.createStaticFunctionWithReceivers(
|
|||||||
visibility: DescriptorVisibility = oldFunction.visibility,
|
visibility: DescriptorVisibility = oldFunction.visibility,
|
||||||
isFakeOverride: Boolean = oldFunction.isFakeOverride,
|
isFakeOverride: Boolean = oldFunction.isFakeOverride,
|
||||||
copyMetadata: Boolean = true,
|
copyMetadata: Boolean = true,
|
||||||
typeParametersFromContext: List<IrTypeParameter> = listOf()
|
typeParametersFromContext: List<IrTypeParameter> = listOf(),
|
||||||
|
remapMultiFieldValueClassStructure: (IrFunction, IrFunction, Map<IrValueParameter, IrValueParameter>?) -> Unit
|
||||||
): IrSimpleFunction {
|
): IrSimpleFunction {
|
||||||
return createFunction(
|
return createFunction(
|
||||||
oldFunction.startOffset, oldFunction.endOffset,
|
oldFunction.startOffset, oldFunction.endOffset,
|
||||||
@@ -1271,12 +1274,19 @@ fun IrFactory.createStaticFunctionWithReceivers(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
remapMultiFieldValueClassStructure(oldFunction, this, null)
|
||||||
|
|
||||||
if (copyMetadata) metadata = oldFunction.metadata
|
if (copyMetadata) metadata = oldFunction.metadata
|
||||||
|
|
||||||
copyAttributes(oldFunction as? IrAttributeContainer)
|
copyAttributes(oldFunction as? IrAttributeContainer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun IrBuilderWithScope.irCastIfNeeded(expression: IrExpression, to: IrType): IrExpression =
|
||||||
|
if (expression.type == to || to.isAny() || to.isNullableAny()) expression else irImplicitCast(expression, to)
|
||||||
|
|
||||||
|
fun IrContainerExpression.unwrapBlock(): IrExpression = statements.singleOrNull() as? IrExpression ?: this
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Appends the parameters in [contextParameters] to the type parameters of
|
* Appends the parameters in [contextParameters] to the type parameters of
|
||||||
* [this] function, renaming those that may clash with a provided collection of
|
* [this] function, renaming those that may clash with a provided collection of
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
// WITH_STDLIB
|
||||||
|
// WORKS_WHEN_VALUE_CLASS
|
||||||
|
// LANGUAGE: +ValueClasses
|
||||||
|
// TARGET_BACKEND: JVM_IR
|
||||||
|
|
||||||
|
interface I<T: A> {
|
||||||
|
fun f(x: T) = println(x)
|
||||||
|
fun g(x: T = error("OK")) = println(x)
|
||||||
|
fun T.f(x: T) = println(x)
|
||||||
|
fun T.g(x: T = error("OK")) = println(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmInline
|
||||||
|
value class A(val x: Int, val y: Int): I<Nothing>
|
||||||
|
|
||||||
|
@JvmInline
|
||||||
|
value class B(val x: Int, val y: Int): I<Nothing> {
|
||||||
|
override fun f(x: Nothing) = println(this)
|
||||||
|
override fun g(x: Nothing) = println(this)
|
||||||
|
fun h(x: Nothing) = println(this)
|
||||||
|
fun t(x: Nothing = error("OK")) = println(this)
|
||||||
|
override fun Nothing.f(x: Nothing) = println(this@B)
|
||||||
|
override fun Nothing.g(x: Nothing) = println(this@B)
|
||||||
|
fun Nothing.h(x: Nothing) = println(this@B)
|
||||||
|
fun Nothing.t(x: Nothing = error("OK")) = println(this@B)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
require(runCatching { A(1, 2).f(error("OK1")) }.exceptionOrNull()!!.message!! == "OK1")
|
||||||
|
require(runCatching { B(1, 2).f(error("OK2")) }.exceptionOrNull()!!.message!! == "OK2")
|
||||||
|
require(runCatching { A(1, 2).g(error("OK3")) }.exceptionOrNull()!!.message!! == "OK3")
|
||||||
|
require(runCatching { B(1, 2).g(error("OK4")) }.exceptionOrNull()!!.message!! == "OK4")
|
||||||
|
require(runCatching { A(1, 2).g() }.exceptionOrNull()!!.message!! == "OK")
|
||||||
|
require(runCatching { B(1, 2).g() }.exceptionOrNull()!!.message!! == "OK")
|
||||||
|
require(runCatching { B(1, 2).h(error("OK5")) }.exceptionOrNull()!!.message!! == "OK5")
|
||||||
|
require(runCatching { B(1, 2).t(error("OK6")) }.exceptionOrNull()!!.message!! == "OK6")
|
||||||
|
require(runCatching { B(1, 2).t() }.exceptionOrNull()!!.message!! == "OK")
|
||||||
|
|
||||||
|
require(runCatching { A(1, 2).run { error("OK1").f(error("OK")) } }.exceptionOrNull()!!.message!! == "OK1")
|
||||||
|
require(runCatching { B(1, 2).run { error("OK2").f(error("OK")) } }.exceptionOrNull()!!.message!! == "OK2")
|
||||||
|
require(runCatching { A(1, 2).run { error("OK3").g(error("OK")) } }.exceptionOrNull()!!.message!! == "OK3")
|
||||||
|
require(runCatching { B(1, 2).run { error("OK4").g(error("OK")) } }.exceptionOrNull()!!.message!! == "OK4")
|
||||||
|
require(runCatching { A(1, 2).run { error("OK5").g() } }.exceptionOrNull()!!.message!! == "OK5")
|
||||||
|
require(runCatching { B(1, 2).run { error("OK6").g() } }.exceptionOrNull()!!.message!! == "OK6")
|
||||||
|
require(runCatching { B(1, 2).run { error("OK7").h(error("OK")) } }.exceptionOrNull()!!.message!! == "OK7")
|
||||||
|
require(runCatching { B(1, 2).run { error("OK8").t(error("OK")) } }.exceptionOrNull()!!.message!! == "OK8")
|
||||||
|
require(runCatching { B(1, 2).run { error("OK9").t() } }.exceptionOrNull()!!.message!! == "OK9")
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+1
-3
@@ -2,9 +2,7 @@
|
|||||||
// WORKS_WHEN_VALUE_CLASS
|
// WORKS_WHEN_VALUE_CLASS
|
||||||
// LANGUAGE: +ValueClasses
|
// LANGUAGE: +ValueClasses
|
||||||
|
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM_IR
|
||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// Depends on KT-57973
|
|
||||||
// JVM_TARGET: 1.8
|
// JVM_TARGET: 1.8
|
||||||
|
|
||||||
interface Path {
|
interface Path {
|
||||||
|
|||||||
+1
-3
@@ -2,9 +2,7 @@
|
|||||||
// WORKS_WHEN_VALUE_CLASS
|
// WORKS_WHEN_VALUE_CLASS
|
||||||
// LANGUAGE: +ValueClasses, +GenericInlineClassParameter
|
// LANGUAGE: +ValueClasses, +GenericInlineClassParameter
|
||||||
|
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM_IR
|
||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// Depends on KT-57973
|
|
||||||
// JVM_TARGET: 1.8
|
// JVM_TARGET: 1.8
|
||||||
|
|
||||||
interface Path {
|
interface Path {
|
||||||
|
|||||||
@@ -154,11 +154,11 @@ public final class GenericFakeOverrideMFVC {
|
|||||||
public method hashCode(): int
|
public method hashCode(): int
|
||||||
public static method hashCode-impl(p0: double, p1: double): int
|
public static method hashCode-impl(p0: double, p1: double): int
|
||||||
public synthetic bridge method setP(p0: java.lang.Object): void
|
public synthetic bridge method setP(p0: java.lang.Object): void
|
||||||
public method setP-nuuzChU(@org.jetbrains.annotations.NotNull p0: DPoint): void
|
|
||||||
public static method setP-nuuzChU(p0: double, p1: double, p2: double, p3: double): void
|
public static method setP-nuuzChU(p0: double, p1: double, p2: double, p3: double): void
|
||||||
|
public method setP-nuuzChU(p0: java.lang.Object): void
|
||||||
public synthetic bridge method setP1(p0: java.lang.Object): void
|
public synthetic bridge method setP1(p0: java.lang.Object): void
|
||||||
public method setP1-nuuzChU(@org.jetbrains.annotations.NotNull p0: DPoint): void
|
|
||||||
public static method setP1-nuuzChU(p0: double, p1: double, p2: double, p3: double): void
|
public static method setP1-nuuzChU(p0: double, p1: double, p2: double, p3: double): void
|
||||||
|
public method setP1-nuuzChU(p0: java.lang.Object): void
|
||||||
public @org.jetbrains.annotations.NotNull method toString(): java.lang.String
|
public @org.jetbrains.annotations.NotNull method toString(): java.lang.String
|
||||||
public static method toString-impl(p0: double, p1: double): java.lang.String
|
public static method toString-impl(p0: double, p1: double): java.lang.String
|
||||||
public synthetic final method unbox-impl-field1(): double
|
public synthetic final method unbox-impl-field1(): double
|
||||||
|
|||||||
@@ -154,11 +154,11 @@ public final class GenericFakeOverrideMFVC {
|
|||||||
public method hashCode(): int
|
public method hashCode(): int
|
||||||
public static method hashCode-impl(p0: double, p1: double): int
|
public static method hashCode-impl(p0: double, p1: double): int
|
||||||
public synthetic bridge method setP(p0: java.lang.Object): void
|
public synthetic bridge method setP(p0: java.lang.Object): void
|
||||||
public method setP-nuuzChU(@org.jetbrains.annotations.NotNull p0: DPoint): void
|
|
||||||
public static method setP-nuuzChU(p0: double, p1: double, p2: double, p3: double): void
|
public static method setP-nuuzChU(p0: double, p1: double, p2: double, p3: double): void
|
||||||
|
public method setP-nuuzChU(p0: java.lang.Object): void
|
||||||
public synthetic bridge method setP1(p0: java.lang.Object): void
|
public synthetic bridge method setP1(p0: java.lang.Object): void
|
||||||
public method setP1-nuuzChU(@org.jetbrains.annotations.NotNull p0: DPoint): void
|
|
||||||
public static method setP1-nuuzChU(p0: double, p1: double, p2: double, p3: double): void
|
public static method setP1-nuuzChU(p0: double, p1: double, p2: double, p3: double): void
|
||||||
|
public method setP1-nuuzChU(p0: java.lang.Object): void
|
||||||
public @org.jetbrains.annotations.NotNull method toString(): java.lang.String
|
public @org.jetbrains.annotations.NotNull method toString(): java.lang.String
|
||||||
public static method toString-impl(p0: double, p1: double): java.lang.String
|
public static method toString-impl(p0: double, p1: double): java.lang.String
|
||||||
public synthetic final method unbox-impl-field1(): double
|
public synthetic final method unbox-impl-field1(): double
|
||||||
|
|||||||
@@ -64,10 +64,10 @@ public final class GenericFakeOverrideMFVC {
|
|||||||
public method hashCode(): int
|
public method hashCode(): int
|
||||||
public static method hashCode-impl(p0: java.lang.Object, p1: java.lang.Object): int
|
public static method hashCode-impl(p0: java.lang.Object, p1: java.lang.Object): int
|
||||||
public synthetic bridge method setP(p0: java.lang.Object): void
|
public synthetic bridge method setP(p0: java.lang.Object): void
|
||||||
public method setP-E-wHi0Q(@org.jetbrains.annotations.NotNull p0: XPoint): void
|
public method setP-E-wHi0Q(p0: java.lang.Object): void
|
||||||
public static method setP-E-wHi0Q(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object, p3: java.lang.Object): void
|
public static method setP-E-wHi0Q(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object, p3: java.lang.Object): void
|
||||||
public synthetic bridge method setP1(p0: java.lang.Object): void
|
public synthetic bridge method setP1(p0: java.lang.Object): void
|
||||||
public method setP1-E-wHi0Q(@org.jetbrains.annotations.NotNull p0: XPoint): void
|
public method setP1-E-wHi0Q(p0: java.lang.Object): void
|
||||||
public static method setP1-E-wHi0Q(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object, p3: java.lang.Object): void
|
public static method setP1-E-wHi0Q(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object, p3: java.lang.Object): void
|
||||||
public @org.jetbrains.annotations.NotNull method toString(): java.lang.String
|
public @org.jetbrains.annotations.NotNull method toString(): java.lang.String
|
||||||
public static method toString-impl(p0: java.lang.Object, p1: java.lang.Object): java.lang.String
|
public static method toString-impl(p0: java.lang.Object, p1: java.lang.Object): java.lang.String
|
||||||
|
|||||||
-12
@@ -49328,18 +49328,6 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
public void testAllFilesPresentInValueClasses() throws Exception {
|
public void testAllFilesPresentInValueClasses() throws Exception {
|
||||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
@TestMetadata("overrideFunctionWithDefaultParameter.kt")
|
|
||||||
public void testOverrideFunctionWithDefaultParameter() throws Exception {
|
|
||||||
runTest("compiler/testData/codegen/box/valueClasses/overrideFunctionWithDefaultParameter.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@TestMetadata("overrideFunctionWithDefaultParameterGeneric.kt")
|
|
||||||
public void testOverrideFunctionWithDefaultParameterGeneric() throws Exception {
|
|
||||||
runTest("compiler/testData/codegen/box/valueClasses/overrideFunctionWithDefaultParameterGeneric.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
|
|||||||
+6
@@ -52095,6 +52095,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
runTest("compiler/testData/codegen/box/valueClasses/mutableSharedMfvcVar.kt");
|
runTest("compiler/testData/codegen/box/valueClasses/mutableSharedMfvcVar.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("nothingAsParameterType.kt")
|
||||||
|
public void testNothingAsParameterType() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/valueClasses/nothingAsParameterType.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("overrideFunctionWithDefaultParameter.kt")
|
@TestMetadata("overrideFunctionWithDefaultParameter.kt")
|
||||||
public void testOverrideFunctionWithDefaultParameter() throws Exception {
|
public void testOverrideFunctionWithDefaultParameter() throws Exception {
|
||||||
|
|||||||
+6
@@ -52095,6 +52095,12 @@ public class IrBlackBoxCodegenWithIrInlinerTestGenerated extends AbstractIrBlack
|
|||||||
runTest("compiler/testData/codegen/box/valueClasses/mutableSharedMfvcVar.kt");
|
runTest("compiler/testData/codegen/box/valueClasses/mutableSharedMfvcVar.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("nothingAsParameterType.kt")
|
||||||
|
public void testNothingAsParameterType() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/valueClasses/nothingAsParameterType.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("overrideFunctionWithDefaultParameter.kt")
|
@TestMetadata("overrideFunctionWithDefaultParameter.kt")
|
||||||
public void testOverrideFunctionWithDefaultParameter() throws Exception {
|
public void testOverrideFunctionWithDefaultParameter() throws Exception {
|
||||||
|
|||||||
-14
@@ -40165,23 +40165,9 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
|
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void runTest(String testDataFilePath, java.util.function.Function<String, String> transformer) throws Exception {
|
|
||||||
KotlinTestUtils.runTest(path -> doTestWithTransformer(path, transformer), TargetBackend.JVM, testDataFilePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testAllFilesPresentInValueClasses() throws Exception {
|
public void testAllFilesPresentInValueClasses() throws Exception {
|
||||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("overrideFunctionWithDefaultParameter.kt")
|
|
||||||
public void testOverrideFunctionWithDefaultParameter() throws Exception {
|
|
||||||
runTest("compiler/testData/codegen/box/valueClasses/overrideFunctionWithDefaultParameter.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
|
||||||
}
|
|
||||||
|
|
||||||
@TestMetadata("overrideFunctionWithDefaultParameterGeneric.kt")
|
|
||||||
public void testOverrideFunctionWithDefaultParameterGeneric() throws Exception {
|
|
||||||
runTest("compiler/testData/codegen/box/valueClasses/overrideFunctionWithDefaultParameterGeneric.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/vararg")
|
@TestMetadata("compiler/testData/codegen/box/vararg")
|
||||||
|
|||||||
Reference in New Issue
Block a user