Fix inline class handling in DefaultParameterInjector

This commit is contained in:
Steven Schäfer
2019-08-05 13:16:20 +02:00
committed by Georgy Bronnikov
parent 79f71f61d5
commit 9182fe887e
7 changed files with 64 additions and 59 deletions
@@ -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
@@ -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,
@@ -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
} }
} }
@@ -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,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)