diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/Ir.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/Ir.kt index af8b8240831..fab1a62e650 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/Ir.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/Ir.kt @@ -19,8 +19,12 @@ import org.jetbrains.kotlin.ir.declarations.IrPackageFragment import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol 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.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.Name import org.jetbrains.kotlin.resolve.calls.components.isVararg @@ -34,6 +38,10 @@ abstract class Ir(val context: T, val irModule: Ir val defaultParameterDeclarationsCache = mutableMapOf() + // 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 } diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/IrUtils.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/IrUtils.kt index c9d70d55624..451c3460358 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/IrUtils.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/IrUtils.kt @@ -565,7 +565,3 @@ fun copyBodyToStatic(oldFunction: IrFunction, staticFunction: IrFunction) { ?.transform(VariableRemapper(mapping), null) ?.patchDeclarationParents(staticFunction) } - -fun IrClass.underlyingType() = if (isInline) - constructors.single { it.isPrimary }.valueParameters[0].type -else defaultType diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt index 1dac5146e23..1252c57e808 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt @@ -6,21 +6,21 @@ package org.jetbrains.kotlin.backend.common.lower 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.descriptors.Modality import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor -import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl 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.impl.* -import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol 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.transformChildrenVoid import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.utils.addToStdlib.safeAs // TODO: fix expect/actual default parameters @@ -347,11 +346,7 @@ open class DefaultParameterInjector( maskValues[maskIndex] = maskValues[maskIndex] or (1 shl (argIndex % 32)) } val valueParameterDeclaration = realFunction.valueParameters[argIndex] - val defaultValueArgument = if (valueParameterDeclaration.varargElementType != null) { - null - } else { - nullConst(expression, realFunction.valueParameters[argIndex].type) - } + val defaultValueArgument = nullConst(expression.startOffset, expression.endOffset, valueParameterDeclaration) valueParameterDeclaration to (valueArgument ?: defaultValueArgument) } @@ -387,16 +382,23 @@ open class DefaultParameterInjector( return result } - protected open fun nullConst(expression: IrElement, type: IrType): IrExpression = when { - type.isFloat() -> IrConstImpl.float(expression.startOffset, expression.endOffset, type, 0.0F) - type.isDouble() -> IrConstImpl.double(expression.startOffset, expression.endOffset, type, 0.0) - type.isBoolean() -> IrConstImpl.boolean(expression.startOffset, expression.endOffset, type, false) - type.isByte() -> IrConstImpl.byte(expression.startOffset, expression.endOffset, type, 0) - 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) - type.isLong() -> IrConstImpl.long(expression.startOffset, expression.endOffset, type, 0) - else -> IrConstImpl.constNull(expression.startOffset, expression.endOffset, context.irBuiltIns.nothingNType) + protected open fun nullConst(startOffset: Int, endOffset: Int, irParameter: IrValueParameter): IrExpression? = + if (irParameter.varargElementType != null) { + null + } else { + nullConst(startOffset, endOffset, irParameter.type) + } + + protected open fun nullConst(startOffset: Int, endOffset: Int, type: IrType): IrExpression = when { + type.isFloat() -> IrConstImpl.float(startOffset, endOffset, type, 0.0F) + 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()}" } @@ -449,7 +451,7 @@ private fun IrFunction.generateDefaultsFunctionImpl( } newFunction.copyTypeParametersFrom(this) - val newValueParameters = valueParameters.map { it.copyMaybeNullableTo(newFunction, context.irBuiltIns) } + syntheticParameters + val newValueParameters = valueParameters.map { it.copyMaybeNullableTo(newFunction, context) } + syntheticParameters newValueParameters.forEach { it.defaultValue = null } @@ -559,10 +561,10 @@ internal val kConstructorMarkerName = "marker".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) - val underlyingType = type.classOrNull?.owner?.underlyingType() ?: type - if (underlyingType in irBuiltIns.primitiveIrTypes) return copyTo(irFunction) + val underlyingType = context.ir.unfoldInlineClassType(type) ?: type + if (underlyingType in context.irBuiltIns.primitiveIrTypes) return copyTo(irFunction) val newType = type.remapTypeParameters( (parent as IrTypeParametersContainer).classIfConstructor, diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt index c3aaba0be5f..255e19e84a5 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt @@ -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.impl.IrFileImpl import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns -import org.jetbrains.kotlin.ir.symbols.* -import org.jetbrains.kotlin.ir.types.IrDynamicType -import org.jetbrains.kotlin.ir.types.IrSimpleType -import org.jetbrains.kotlin.ir.types.classifierOrFail +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol +import org.jetbrains.kotlin.ir.symbols.IrEnumEntrySymbol +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.util.SymbolTable -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.ir.util.* import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.scopes.MemberScope @@ -199,6 +197,10 @@ class JsIrBackendContext( override val returnIfSuspended = symbolTable.referenceSimpleFunction(getJsInternalFunction("returnIfSuspended")) } + override fun unfoldInlineClassType(irType: IrType): IrType? { + return irType.getInlinedClass()?.typeWith() + } + override fun shouldGenerateHandlerParameterForDefaultBodyFun() = true } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt index baef405506e..26a09f2a755 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt @@ -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.JvmSharedVariablesManager 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.state.GenerationState 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.symbols.IrClassSymbol 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.SymbolTable import org.jetbrains.kotlin.name.FqName @@ -95,6 +97,10 @@ class JvmBackendContext( ) : Ir(this, irModuleFragment) { override val symbols = JvmSymbols(this@JvmBackendContext, symbolTable, firMode) + override fun unfoldInlineClassType(irType: IrType): IrType? { + return InlineClassAbi.unboxType(irType) + } + override fun shouldGenerateHandlerParameterForDefaultBodyFun() = true } } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmDefaultParameterInjector.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmDefaultParameterInjector.kt index dc253602d7d..5c5d48466eb 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmDefaultParameterInjector.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmDefaultParameterInjector.kt @@ -5,38 +5,30 @@ 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.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.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) : DefaultParameterInjector(context, skipInline = false, skipExternalMethods = false) { override val context: JvmBackendContext get() = super.context as JvmBackendContext - override fun nullConst(expression: IrElement, type: IrType): IrExpression { - if (type !is IrSimpleType || - type.hasQuestionMark || - type.classOrNull?.owner?.isInline != true - ) { - return super.nullConst(expression, type) - } - 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 { + override fun nullConst(startOffset: Int, endOffset: Int, type: IrType): IrExpression { + if (type !is IrSimpleType || type.hasQuestionMark || type.classOrNull?.owner?.isInline != true) + return super.nullConst(startOffset, endOffset, type) + + val underlyingType = type.unboxInlineClass() + return IrCallImpl(startOffset, endOffset, type, context.ir.symbols.unsafeCoerceIntrinsicSymbol).apply { putTypeArgument(0, underlyingType) // from putTypeArgument(1, type) // to - putValueArgument(0, super.nullConst(expression, underlyingType)) + putValueArgument(0, super.nullConst(startOffset, endOffset, underlyingType)) } } - -} \ No newline at end of file +} diff --git a/compiler/testData/codegen/bytecodeText/inlineClasses/defaultParametersDontBox.kt b/compiler/testData/codegen/bytecodeText/inlineClasses/defaultParametersDontBox.kt index 625223c486f..fceef113c04 100644 --- a/compiler/testData/codegen/bytecodeText/inlineClasses/defaultParametersDontBox.kt +++ b/compiler/testData/codegen/bytecodeText/inlineClasses/defaultParametersDontBox.kt @@ -1,5 +1,4 @@ // LANGUAGE: +InlineClasses -// IGNORE_BACKEND: JVM_IR // FILE: classes.kt inline class A(val i: Int)