Fix inline class handling in DefaultParameterInjector
This commit is contained in:
committed by
Georgy Bronnikov
parent
79f71f61d5
commit
9182fe887e
@@ -19,8 +19,12 @@ import org.jetbrains.kotlin.ir.declarations.IrPackageFragment
|
|||||||
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.symbols.IrFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
import org.jetbrains.kotlin.ir.types.classOrNull
|
import org.jetbrains.kotlin.ir.types.classOrNull
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.ReferenceSymbolTable
|
||||||
|
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
|
||||||
|
import org.jetbrains.kotlin.ir.util.getPackageFragment
|
||||||
|
import org.jetbrains.kotlin.ir.util.referenceFunction
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.calls.components.isVararg
|
import org.jetbrains.kotlin.resolve.calls.components.isVararg
|
||||||
@@ -34,6 +38,10 @@ abstract class Ir<out T : CommonBackendContext>(val context: T, val irModule: Ir
|
|||||||
|
|
||||||
val defaultParameterDeclarationsCache = mutableMapOf<IrFunction, IrFunction>()
|
val defaultParameterDeclarationsCache = mutableMapOf<IrFunction, IrFunction>()
|
||||||
|
|
||||||
|
// If irType is an inline class type, return the underlying type according to the
|
||||||
|
// unfolding rules of the current backend. Otherwise, returns null.
|
||||||
|
open fun unfoldInlineClassType(irType: IrType): IrType? = null
|
||||||
|
|
||||||
open fun shouldGenerateHandlerParameterForDefaultBodyFun() = false
|
open fun shouldGenerateHandlerParameterForDefaultBodyFun() = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -565,7 +565,3 @@ fun copyBodyToStatic(oldFunction: IrFunction, staticFunction: IrFunction) {
|
|||||||
?.transform(VariableRemapper(mapping), null)
|
?.transform(VariableRemapper(mapping), null)
|
||||||
?.patchDeclarationParents(staticFunction)
|
?.patchDeclarationParents(staticFunction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun IrClass.underlyingType() = if (isInline)
|
|
||||||
constructors.single { it.isPrimary }.valueParameters[0].type
|
|
||||||
else defaultType
|
|
||||||
|
|||||||
+26
-24
@@ -6,21 +6,21 @@
|
|||||||
package org.jetbrains.kotlin.backend.common.lower
|
package org.jetbrains.kotlin.backend.common.lower
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.*
|
import org.jetbrains.kotlin.backend.common.*
|
||||||
import org.jetbrains.kotlin.backend.common.descriptors.*
|
import org.jetbrains.kotlin.backend.common.descriptors.WrappedClassConstructorDescriptor
|
||||||
|
import org.jetbrains.kotlin.backend.common.descriptors.WrappedValueParameterDescriptor
|
||||||
|
import org.jetbrains.kotlin.backend.common.descriptors.synthesizedName
|
||||||
|
import org.jetbrains.kotlin.backend.common.descriptors.wrappedSimpleFunctionDescriptorBasedOn
|
||||||
import org.jetbrains.kotlin.backend.common.ir.*
|
import org.jetbrains.kotlin.backend.common.ir.*
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
|
||||||
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.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
|
||||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
|
||||||
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.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
|
||||||
@@ -31,7 +31,6 @@ import org.jetbrains.kotlin.ir.util.*
|
|||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
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.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
|
||||||
|
|
||||||
// TODO: fix expect/actual default parameters
|
// TODO: fix expect/actual default parameters
|
||||||
|
|
||||||
@@ -347,11 +346,7 @@ open class DefaultParameterInjector(
|
|||||||
maskValues[maskIndex] = maskValues[maskIndex] or (1 shl (argIndex % 32))
|
maskValues[maskIndex] = maskValues[maskIndex] or (1 shl (argIndex % 32))
|
||||||
}
|
}
|
||||||
val valueParameterDeclaration = realFunction.valueParameters[argIndex]
|
val valueParameterDeclaration = realFunction.valueParameters[argIndex]
|
||||||
val defaultValueArgument = if (valueParameterDeclaration.varargElementType != null) {
|
val defaultValueArgument = nullConst(expression.startOffset, expression.endOffset, valueParameterDeclaration)
|
||||||
null
|
|
||||||
} else {
|
|
||||||
nullConst(expression, realFunction.valueParameters[argIndex].type)
|
|
||||||
}
|
|
||||||
valueParameterDeclaration to (valueArgument ?: defaultValueArgument)
|
valueParameterDeclaration to (valueArgument ?: defaultValueArgument)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -387,16 +382,23 @@ open class DefaultParameterInjector(
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun nullConst(expression: IrElement, type: IrType): IrExpression = when {
|
protected open fun nullConst(startOffset: Int, endOffset: Int, irParameter: IrValueParameter): IrExpression? =
|
||||||
type.isFloat() -> IrConstImpl.float(expression.startOffset, expression.endOffset, type, 0.0F)
|
if (irParameter.varargElementType != null) {
|
||||||
type.isDouble() -> IrConstImpl.double(expression.startOffset, expression.endOffset, type, 0.0)
|
null
|
||||||
type.isBoolean() -> IrConstImpl.boolean(expression.startOffset, expression.endOffset, type, false)
|
} else {
|
||||||
type.isByte() -> IrConstImpl.byte(expression.startOffset, expression.endOffset, type, 0)
|
nullConst(startOffset, endOffset, irParameter.type)
|
||||||
type.isChar() -> IrConstImpl.char(expression.startOffset, expression.endOffset, type, 0.toChar())
|
}
|
||||||
type.isShort() -> IrConstImpl.short(expression.startOffset, expression.endOffset, type, 0)
|
|
||||||
type.isInt() -> IrConstImpl.int(expression.startOffset, expression.endOffset, type, 0)
|
protected open fun nullConst(startOffset: Int, endOffset: Int, type: IrType): IrExpression = when {
|
||||||
type.isLong() -> IrConstImpl.long(expression.startOffset, expression.endOffset, type, 0)
|
type.isFloat() -> IrConstImpl.float(startOffset, endOffset, type, 0.0F)
|
||||||
else -> IrConstImpl.constNull(expression.startOffset, expression.endOffset, context.irBuiltIns.nothingNType)
|
type.isDouble() -> IrConstImpl.double(startOffset, endOffset, type, 0.0)
|
||||||
|
type.isBoolean() -> IrConstImpl.boolean(startOffset, endOffset, type, false)
|
||||||
|
type.isByte() -> IrConstImpl.byte(startOffset, endOffset, type, 0)
|
||||||
|
type.isChar() -> IrConstImpl.char(startOffset, endOffset, type, 0.toChar())
|
||||||
|
type.isShort() -> IrConstImpl.short(startOffset, endOffset, type, 0)
|
||||||
|
type.isInt() -> IrConstImpl.int(startOffset, endOffset, type, 0)
|
||||||
|
type.isLong() -> IrConstImpl.long(startOffset, endOffset, type, 0)
|
||||||
|
else -> IrConstImpl.constNull(startOffset, endOffset, context.irBuiltIns.nothingNType)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun log(msg: () -> String) = context.log { "DEFAULT-INJECTOR: ${msg()}" }
|
private fun log(msg: () -> String) = context.log { "DEFAULT-INJECTOR: ${msg()}" }
|
||||||
@@ -449,7 +451,7 @@ private fun IrFunction.generateDefaultsFunctionImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
newFunction.copyTypeParametersFrom(this)
|
newFunction.copyTypeParametersFrom(this)
|
||||||
val newValueParameters = valueParameters.map { it.copyMaybeNullableTo(newFunction, context.irBuiltIns) } + syntheticParameters
|
val newValueParameters = valueParameters.map { it.copyMaybeNullableTo(newFunction, context) } + syntheticParameters
|
||||||
newValueParameters.forEach {
|
newValueParameters.forEach {
|
||||||
it.defaultValue = null
|
it.defaultValue = null
|
||||||
}
|
}
|
||||||
@@ -559,10 +561,10 @@ internal val kConstructorMarkerName = "marker".synthesizedName
|
|||||||
|
|
||||||
private fun parameterMaskName(number: Int) = "mask$number".synthesizedName
|
private fun parameterMaskName(number: Int) = "mask$number".synthesizedName
|
||||||
|
|
||||||
private fun IrValueParameter.copyMaybeNullableTo(irFunction: IrFunction, irBuiltIns: IrBuiltIns): IrValueParameter {
|
private fun IrValueParameter.copyMaybeNullableTo(irFunction: IrFunction, context: CommonBackendContext): IrValueParameter {
|
||||||
if (defaultValue == null) return copyTo(irFunction)
|
if (defaultValue == null) return copyTo(irFunction)
|
||||||
val underlyingType = type.classOrNull?.owner?.underlyingType() ?: type
|
val underlyingType = context.ir.unfoldInlineClassType(type) ?: type
|
||||||
if (underlyingType in irBuiltIns.primitiveIrTypes) return copyTo(irFunction)
|
if (underlyingType in context.irBuiltIns.primitiveIrTypes) return copyTo(irFunction)
|
||||||
|
|
||||||
val newType = type.remapTypeParameters(
|
val newType = type.remapTypeParameters(
|
||||||
(parent as IrTypeParametersContainer).classIfConstructor,
|
(parent as IrTypeParametersContainer).classIfConstructor,
|
||||||
|
|||||||
+10
-8
@@ -29,15 +29,13 @@ import org.jetbrains.kotlin.ir.backend.js.utils.OperatorNames
|
|||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
|
||||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||||
import org.jetbrains.kotlin.ir.symbols.*
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.IrDynamicType
|
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
import org.jetbrains.kotlin.ir.symbols.IrEnumEntrySymbol
|
||||||
import org.jetbrains.kotlin.ir.types.classifierOrFail
|
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
import org.jetbrains.kotlin.ir.types.impl.IrDynamicTypeImpl
|
import org.jetbrains.kotlin.ir.types.impl.IrDynamicTypeImpl
|
||||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.util.getPropertyGetter
|
|
||||||
import org.jetbrains.kotlin.ir.util.getPropertySetter
|
|
||||||
import org.jetbrains.kotlin.ir.util.kotlinPackageFqn
|
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||||
@@ -199,6 +197,10 @@ class JsIrBackendContext(
|
|||||||
override val returnIfSuspended = symbolTable.referenceSimpleFunction(getJsInternalFunction("returnIfSuspended"))
|
override val returnIfSuspended = symbolTable.referenceSimpleFunction(getJsInternalFunction("returnIfSuspended"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun unfoldInlineClassType(irType: IrType): IrType? {
|
||||||
|
return irType.getInlinedClass()?.typeWith()
|
||||||
|
}
|
||||||
|
|
||||||
override fun shouldGenerateHandlerParameterForDefaultBodyFun() = true
|
override fun shouldGenerateHandlerParameterForDefaultBodyFun() = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.backend.jvm.codegen.IrTypeMapper
|
|||||||
import org.jetbrains.kotlin.backend.jvm.descriptors.JvmDeclarationFactory
|
import org.jetbrains.kotlin.backend.jvm.descriptors.JvmDeclarationFactory
|
||||||
import org.jetbrains.kotlin.backend.jvm.descriptors.JvmSharedVariablesManager
|
import org.jetbrains.kotlin.backend.jvm.descriptors.JvmSharedVariablesManager
|
||||||
import org.jetbrains.kotlin.backend.jvm.intrinsics.IrIntrinsicMethods
|
import org.jetbrains.kotlin.backend.jvm.intrinsics.IrIntrinsicMethods
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.InlineClassAbi
|
||||||
import org.jetbrains.kotlin.codegen.ClassBuilder
|
import org.jetbrains.kotlin.codegen.ClassBuilder
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
@@ -21,6 +22,7 @@ import org.jetbrains.kotlin.ir.declarations.*
|
|||||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||||
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.symbols.IrFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
import org.jetbrains.kotlin.ir.util.ReferenceSymbolTable
|
import org.jetbrains.kotlin.ir.util.ReferenceSymbolTable
|
||||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
@@ -95,6 +97,10 @@ class JvmBackendContext(
|
|||||||
) : Ir<JvmBackendContext>(this, irModuleFragment) {
|
) : Ir<JvmBackendContext>(this, irModuleFragment) {
|
||||||
override val symbols = JvmSymbols(this@JvmBackendContext, symbolTable, firMode)
|
override val symbols = JvmSymbols(this@JvmBackendContext, symbolTable, firMode)
|
||||||
|
|
||||||
|
override fun unfoldInlineClassType(irType: IrType): IrType? {
|
||||||
|
return InlineClassAbi.unboxType(irType)
|
||||||
|
}
|
||||||
|
|
||||||
override fun shouldGenerateHandlerParameterForDefaultBodyFun() = true
|
override fun shouldGenerateHandlerParameterForDefaultBodyFun() = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-21
@@ -5,38 +5,30 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.jvm.lower
|
package org.jetbrains.kotlin.backend.jvm.lower
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.ir.underlyingType
|
|
||||||
import org.jetbrains.kotlin.backend.common.lower.DefaultParameterInjector
|
import org.jetbrains.kotlin.backend.common.lower.DefaultParameterInjector
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.unboxInlineClass
|
||||||
|
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.impl.IrCallImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||||
import org.jetbrains.kotlin.ir.types.*
|
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||||
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
|
import org.jetbrains.kotlin.ir.types.classOrNull
|
||||||
|
|
||||||
class JvmDefaultParameterInjector(context: JvmBackendContext) :
|
class JvmDefaultParameterInjector(context: JvmBackendContext) :
|
||||||
DefaultParameterInjector(context, skipInline = false, skipExternalMethods = false) {
|
DefaultParameterInjector(context, skipInline = false, skipExternalMethods = false) {
|
||||||
|
|
||||||
override val context: JvmBackendContext get() = super.context as JvmBackendContext
|
override val context: JvmBackendContext get() = super.context as JvmBackendContext
|
||||||
|
|
||||||
override fun nullConst(expression: IrElement, type: IrType): IrExpression {
|
override fun nullConst(startOffset: Int, endOffset: Int, type: IrType): IrExpression {
|
||||||
if (type !is IrSimpleType ||
|
if (type !is IrSimpleType || type.hasQuestionMark || type.classOrNull?.owner?.isInline != true)
|
||||||
type.hasQuestionMark ||
|
return super.nullConst(startOffset, endOffset, type)
|
||||||
type.classOrNull?.owner?.isInline != true
|
|
||||||
) {
|
val underlyingType = type.unboxInlineClass()
|
||||||
return super.nullConst(expression, type)
|
return IrCallImpl(startOffset, endOffset, type, context.ir.symbols.unsafeCoerceIntrinsicSymbol).apply {
|
||||||
}
|
|
||||||
val underlyingType = type.classOrNull!!.owner.underlyingType()
|
|
||||||
return IrCallImpl(
|
|
||||||
expression.startOffset, expression.endOffset,
|
|
||||||
type,
|
|
||||||
context.ir.symbols.unsafeCoerceIntrinsicSymbol, context.ir.symbols.unsafeCoerceIntrinsicSymbol.descriptor,
|
|
||||||
typeArgumentsCount = 2,
|
|
||||||
valueArgumentsCount = 1
|
|
||||||
).apply {
|
|
||||||
putTypeArgument(0, underlyingType) // from
|
putTypeArgument(0, underlyingType) // from
|
||||||
putTypeArgument(1, type) // to
|
putTypeArgument(1, type) // to
|
||||||
putValueArgument(0, super.nullConst(expression, underlyingType))
|
putValueArgument(0, super.nullConst(startOffset, endOffset, underlyingType))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
-1
@@ -1,5 +1,4 @@
|
|||||||
// LANGUAGE: +InlineClasses
|
// LANGUAGE: +InlineClasses
|
||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// FILE: classes.kt
|
// FILE: classes.kt
|
||||||
|
|
||||||
inline class A(val i: Int)
|
inline class A(val i: Int)
|
||||||
|
|||||||
Reference in New Issue
Block a user