diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ArgumentGenerator.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/ArgumentGenerator.kt index cff0fd13b00..fcabd113986 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ArgumentGenerator.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ArgumentGenerator.kt @@ -35,10 +35,10 @@ abstract class ArgumentGenerator { * @see kotlin.reflect.jvm.internal.KCallableImpl.callBy */ open fun generate( - valueArgumentsByIndex: List, - actualArgs: List, - // may be null for a constructor of an object literal - calleeDescriptor: CallableDescriptor? + valueArgumentsByIndex: List, + actualArgs: List, + // may be null for a constructor of an object literal + calleeDescriptor: CallableDescriptor? ): DefaultCallArgs { assert(valueArgumentsByIndex.size == actualArgs.size) { "Value arguments collection should have same size, but ${valueArgumentsByIndex.size} != ${actualArgs.size}" @@ -50,9 +50,9 @@ abstract class ArgumentGenerator { ArgumentAndDeclIndex(it, arg2Index[it]!!) }.toMutableList() - valueArgumentsByIndex.withIndex().forEach { - if (it.value is DefaultValueArgument) { - actualArgsWithDeclIndex.add(it.index, ArgumentAndDeclIndex(it.value, it.index)) + for ((index, value) in valueArgumentsByIndex.withIndex()) { + if (value is DefaultValueArgument) { + actualArgsWithDeclIndex.add(index, ArgumentAndDeclIndex(value, index)) } } @@ -70,8 +70,7 @@ abstract class ArgumentGenerator { is DefaultValueArgument -> { if (calleeDescriptor?.defaultValueFromJava(declIndex) == true) { generateDefaultJava(declIndex, argument) - } - else { + } else { defaultArgs.mark(declIndex) generateDefault(declIndex, argument) } @@ -116,11 +115,11 @@ abstract class ArgumentGenerator { } private fun CallableDescriptor.defaultValueFromJava(index: Int): Boolean = DFS.ifAny( - listOf(this), - { current -> current.original.overriddenDescriptors.map { it.original } }, - { descriptor -> - descriptor.original.overriddenDescriptors.isEmpty() && - descriptor is JavaCallableMemberDescriptor && - descriptor.valueParameters[index].declaresDefaultValue() - } + listOf(this), + { current -> current.original.overriddenDescriptors.map { it.original } }, + { descriptor -> + descriptor.original.overriddenDescriptors.isEmpty() && + descriptor is JavaCallableMemberDescriptor && + descriptor.valueParameters[index].declaresDefaultValue() + } ) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/CallableMethod.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/CallableMethod.kt index ec2ba11137a..2eecf6f147c 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/CallableMethod.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/CallableMethod.kt @@ -5,7 +5,7 @@ package org.jetbrains.kotlin.codegen -import org.jetbrains.kotlin.load.java.JvmAbi +import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature @@ -20,7 +20,7 @@ import org.jetbrains.org.objectweb.asm.util.Printer class CallableMethod( override val owner: Type, private val defaultImplOwner: Type?, - computeDefaultMethodDesc: () -> String, + computeDefaultMethod: () -> Method, private val signature: JvmMethodSignature, val invokeOpcode: Int, override val dispatchReceiverType: Type?, @@ -32,7 +32,10 @@ class CallableMethod( val isInterfaceMethod: Boolean, private val isDefaultMethodInInterface: Boolean ) : Callable { - private val defaultMethodDesc: String by lazy(LazyThreadSafetyMode.PUBLICATION, computeDefaultMethodDesc) + private val defaultImplMethod: Method by lazy(LazyThreadSafetyMode.PUBLICATION, computeDefaultMethod) + + private val defaultImplMethodName: String get() = defaultImplMethod.name + private val defaultMethodDesc: String get() = defaultImplMethod.descriptor fun getValueParameters(): List = signature.valueParameters @@ -68,10 +71,14 @@ class CallableMethod( } else { v.visitMethodInsn( INVOKESTATIC, defaultImplOwner.internalName, - method.name + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, defaultMethodDesc, isDefaultMethodInInterface + defaultImplMethodName, defaultMethodDesc, isDefaultMethodInInterface ) - StackValue.coerce(Type.getReturnType(defaultMethodDesc), Type.getReturnType(signature.asmMethod.descriptor), v) + StackValue.coerce( + Type.getReturnType(defaultMethodDesc), + Type.getReturnType(signature.asmMethod.descriptor), + v + ) } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index beb4f5c4ce8..a20b1ce1018 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -219,6 +219,11 @@ public class ExpressionCodegen extends KtVisitor impleme return parentCodegen; } + @NotNull + public KotlinTypeMapper getTypeMapper() { + return typeMapper; + } + @NotNull public ObjectLiteralResult generateObjectLiteral(@NotNull KtObjectLiteralExpression literal) { KtObjectDeclaration objectDeclaration = literal.getObjectDeclaration(); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java index aca1e37cb43..4c03ea700e2 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java @@ -1038,10 +1038,7 @@ public class FunctionCodegen { // or all return types are supertypes of inline class (and can't be inline classes). for (DescriptorBasedFunctionHandleForJvm handle : bridge.getOriginalFunctions()) { - KotlinType returnType = handle.getDescriptor().getReturnType(); - if (returnType != null) { - return returnType; - } + return state.getTypeMapper().getReturnValueType(handle.getDescriptor()); } if (state.getClassBuilderMode().mightBeIncorrectCode) { @@ -1450,8 +1447,8 @@ public class FunctionCodegen { } } - KotlinType returnType = descriptor.getReturnType(); - StackValue.coerce(delegateTo.getReturnType(), returnType, bridge.getReturnType(), bridgeReturnType, iv); + KotlinType returnValueType = state.getTypeMapper().getReturnValueType(descriptor); + StackValue.coerce(delegateTo.getReturnType(), returnValueType, bridge.getReturnType(), bridgeReturnType, iv); iv.areturn(bridge.getReturnType()); endVisit(mv, "bridge method", origin); @@ -1619,7 +1616,7 @@ public class FunctionCodegen { ) ); - stackValue.put(delegateMethod.getReturnType(), delegatedTo.getReturnType(), iv); + stackValue.put(delegateMethod.getReturnType(), delegateFunction.getReturnType(), iv); iv.areturn(delegateMethod.getReturnType()); } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java index 2a26313094d..7f14f56a6ff 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java @@ -467,7 +467,7 @@ public abstract class MemberCodegen"), SYNTHESIZED, KotlinSourceElementKt.toSourceElement(element)); clInit.initialize(null, null, Collections.emptyList(), Collections.emptyList(), DescriptorUtilsKt.getModule(descriptor).getBuiltIns().getUnitType(), - null, Visibilities.PRIVATE); + Modality.FINAL, Visibilities.PRIVATE); return clInit; } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ObjectSuperCallArgumentGenerator.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/ObjectSuperCallArgumentGenerator.kt index 7e9cb4bc317..0b0f274db8a 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ObjectSuperCallArgumentGenerator.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ObjectSuperCallArgumentGenerator.kt @@ -53,7 +53,8 @@ internal class ObjectSuperCallArgumentGenerator( valueArgumentsByIndex: List, actualArgs: List, calleeDescriptor: CallableDescriptor? - ): DefaultCallArgs = super.generate(valueArgumentsByIndex, valueArgumentsByIndex, calleeDescriptor) + ): DefaultCallArgs = + super.generate(valueArgumentsByIndex, valueArgumentsByIndex, calleeDescriptor) public override fun generateExpression(i: Int, argument: ExpressionValueArgument) { generateSuperCallArgument(i) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/boxing/ProgressionIteratorBasicValue.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/boxing/ProgressionIteratorBasicValue.kt index dce74568094..0fcfb4d8ec2 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/boxing/ProgressionIteratorBasicValue.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/boxing/ProgressionIteratorBasicValue.kt @@ -51,10 +51,11 @@ private constructor( private val INT_PROGRESSION_ITERATOR_VALUE = ProgressionIteratorBasicValue("Int", Type.INT_TYPE) private val LONG_PROGRESSION_ITERATOR_VALUE = ProgressionIteratorBasicValue("Long", Type.LONG_TYPE) - private val UINT_PROGRESSION_ITERATOR_VALUE = - ProgressionIteratorBasicValue("UInt", Type.INT_TYPE, Type.getObjectType("kotlin/UInt")) - private val ULONG_PROGRESSION_ITERATOR_VALUE = - ProgressionIteratorBasicValue("ULong", Type.LONG_TYPE, Type.getObjectType("kotlin/ULong")) + // TODO functions returning inline classes are mangled now, should figure out how to work with UInt/ULong iterators here + // private val UINT_PROGRESSION_ITERATOR_VALUE = + // ProgressionIteratorBasicValue("UInt", Type.INT_TYPE, Type.getObjectType("kotlin/UInt")) + // private val ULONG_PROGRESSION_ITERATOR_VALUE = + // ProgressionIteratorBasicValue("ULong", Type.LONG_TYPE, Type.getObjectType("kotlin/ULong")) private val PROGRESSION_CLASS_NAME_TO_ITERATOR_VALUE: Map = hashMapOf( @@ -64,10 +65,10 @@ private constructor( INT_PROGRESSION_FQN to INT_PROGRESSION_ITERATOR_VALUE, LONG_RANGE_FQN to LONG_PROGRESSION_ITERATOR_VALUE, LONG_PROGRESSION_FQN to LONG_PROGRESSION_ITERATOR_VALUE, - UINT_RANGE_FQN to UINT_PROGRESSION_ITERATOR_VALUE, - UINT_PROGRESSION_FQN to UINT_PROGRESSION_ITERATOR_VALUE, - ULONG_RANGE_FQN to ULONG_PROGRESSION_ITERATOR_VALUE, - ULONG_PROGRESSION_FQN to ULONG_PROGRESSION_ITERATOR_VALUE + // UINT_RANGE_FQN to UINT_PROGRESSION_ITERATOR_VALUE, + // UINT_PROGRESSION_FQN to UINT_PROGRESSION_ITERATOR_VALUE, + // ULONG_RANGE_FQN to ULONG_PROGRESSION_ITERATOR_VALUE, + // ULONG_PROGRESSION_FQN to ULONG_PROGRESSION_ITERATOR_VALUE ) fun byProgressionClassType(progressionClassType: Type): ProgressionIteratorBasicValue? = diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/forLoop/AbstractForInProgressionLoopGenerator.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/forLoop/AbstractForInProgressionLoopGenerator.kt index 2672413c291..86fdd69b1b7 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/forLoop/AbstractForInProgressionLoopGenerator.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/forLoop/AbstractForInProgressionLoopGenerator.kt @@ -34,16 +34,13 @@ abstract class AbstractForInProgressionLoopGenerator( ) : AbstractForInProgressionOrRangeLoopGenerator(codegen, forExpression) { protected var incrementVar: Int = -1 - protected val asmLoopRangeType: Type - protected val rangeKotlinType = bindingContext.getType(forExpression.loopRange!!)!! + protected val asmLoopRangeType: Type = codegen.asmType(rangeKotlinType) private val rangeElementKotlinType = getRangeOrProgressionElementType(rangeKotlinType) ?: throw AssertionError("Unexpected loop range type: $rangeKotlinType") private val incrementKotlinType: KotlinType protected val incrementType: Type init { - asmLoopRangeType = codegen.asmType(rangeKotlinType) - val incrementProp = rangeKotlinType.memberScope.getContributedVariables(Name.identifier("step"), NoLookupLocation.FROM_BACKEND) assert(incrementProp.size == 1) { rangeKotlinType.toString() + " " + incrementProp.size } incrementKotlinType = incrementProp.single().type diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/forLoop/AbstractForInProgressionOrRangeLoopGenerator.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/forLoop/AbstractForInProgressionOrRangeLoopGenerator.kt index 96c362043e9..a35c1adc366 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/forLoop/AbstractForInProgressionOrRangeLoopGenerator.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/forLoop/AbstractForInProgressionOrRangeLoopGenerator.kt @@ -17,8 +17,12 @@ package org.jetbrains.kotlin.codegen.range.forLoop import org.jetbrains.kotlin.codegen.ExpressionCodegen +import org.jetbrains.kotlin.codegen.OwnerKind import org.jetbrains.kotlin.codegen.StackValue +import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtForExpression +import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.org.objectweb.asm.Label import org.jetbrains.org.objectweb.asm.Type @@ -28,6 +32,8 @@ abstract class AbstractForInProgressionOrRangeLoopGenerator(codegen: ExpressionC private var loopParameter: StackValue? = null + protected val rangeKotlinType = bindingContext.getType(forExpression.loopRange!!)!! + init { assert( asmElementType.sort == Type.INT || @@ -36,7 +42,7 @@ abstract class AbstractForInProgressionOrRangeLoopGenerator(codegen: ExpressionC asmElementType.sort == Type.CHAR || asmElementType.sort == Type.LONG ) { - "Unexpected range element type: " + asmElementType + "Unexpected range element type: $asmElementType" } } @@ -48,7 +54,7 @@ abstract class AbstractForInProgressionOrRangeLoopGenerator(codegen: ExpressionC protected fun checkPostCondition(loopExit: Label) { assert(endVar != -1) { - "endVar must be allocated, endVar = " + endVar + "endVar must be allocated, endVar = $endVar" } loopParameter().put(asmElementType, elementType, v) v.load(endVar, asmElementType) @@ -64,4 +70,14 @@ abstract class AbstractForInProgressionOrRangeLoopGenerator(codegen: ExpressionC protected fun loopParameter(): StackValue = loopParameter ?: StackValue.local(loopParameterVar, loopParameterType).also { loopParameter = it } + + protected fun KotlinType.getPropertyGetterName(propertyName: String): String { + // In case of unsigned ranges, getter methods for corresponding range/progression properties would be mangled. + val propertyDescriptor = memberScope.getContributedVariables(Name.identifier(propertyName), NoLookupLocation.FROM_BACKEND) + .singleOrNull() + ?: throw AssertionError("No '$propertyName' in member scope of type $this") + val getter = propertyDescriptor.getter + ?: throw AssertionError("Property has no getter: $propertyDescriptor") + return codegen.typeMapper.mapFunctionName(getter, OwnerKind.IMPLEMENTATION) + } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/forLoop/ForInProgressionExpressionLoopGenerator.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/forLoop/ForInProgressionExpressionLoopGenerator.kt index 65e4300357b..b44eab0432b 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/forLoop/ForInProgressionExpressionLoopGenerator.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/forLoop/ForInProgressionExpressionLoopGenerator.kt @@ -31,8 +31,12 @@ class ForInProgressionExpressionLoopGenerator( v.dup() v.dup() - generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, loopParameterType, loopParameterVar) - generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, asmElementType, endVar) - generateRangeOrProgressionProperty(asmLoopRangeType, "getStep", incrementType, incrementType, incrementVar) + val firstName = rangeKotlinType.getPropertyGetterName("first") + val lastName = rangeKotlinType.getPropertyGetterName("last") + val stepName = rangeKotlinType.getPropertyGetterName("step") + + generateRangeOrProgressionProperty(asmLoopRangeType, firstName, asmElementType, loopParameterType, loopParameterVar) + generateRangeOrProgressionProperty(asmLoopRangeType, lastName, asmElementType, asmElementType, endVar) + generateRangeOrProgressionProperty(asmLoopRangeType, stepName, incrementType, incrementType, incrementVar) } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/forLoop/ForInRangeInstanceLoopGenerator.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/forLoop/ForInRangeInstanceLoopGenerator.kt index 42740c3144f..23d247e19b5 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/forLoop/ForInRangeInstanceLoopGenerator.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/forLoop/ForInRangeInstanceLoopGenerator.kt @@ -17,9 +17,13 @@ package org.jetbrains.kotlin.codegen.range.forLoop import org.jetbrains.kotlin.codegen.ExpressionCodegen +import org.jetbrains.kotlin.codegen.OwnerKind import org.jetbrains.kotlin.codegen.range.comparison.ComparisonGenerator +import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtForExpression +import org.jetbrains.kotlin.types.KotlinType class ForInRangeInstanceLoopGenerator( codegen: ExpressionCodegen, @@ -30,18 +34,21 @@ class ForInRangeInstanceLoopGenerator( ) : AbstractForInRangeLoopGenerator(codegen, forExpression, if (reversed) -1 else 1, comparisonGenerator) { override fun storeRangeStartAndEnd() { - val loopRangeType = codegen.bindingContext.getType(rangeExpression)!! - val asmLoopRangeType = codegen.asmType(loopRangeType) - codegen.gen(rangeExpression, asmLoopRangeType, loopRangeType) + val asmLoopRangeType = codegen.asmType(rangeKotlinType) + codegen.gen(rangeExpression, asmLoopRangeType, rangeKotlinType) v.dup() + val firstName = rangeKotlinType.getPropertyGetterName("first") + val lastName = rangeKotlinType.getPropertyGetterName("last") + // ranges inherit first and last from corresponding progressions if (reversed) { - generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, loopParameterType, loopParameterVar) - generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, asmElementType, endVar) + generateRangeOrProgressionProperty(asmLoopRangeType, lastName, asmElementType, loopParameterType, loopParameterVar) + generateRangeOrProgressionProperty(asmLoopRangeType, firstName, asmElementType, asmElementType, endVar) } else { - generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, loopParameterType, loopParameterVar) - generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, asmElementType, endVar) + generateRangeOrProgressionProperty(asmLoopRangeType, firstName, asmElementType, loopParameterType, loopParameterVar) + generateRangeOrProgressionProperty(asmLoopRangeType, lastName, asmElementType, asmElementType, endVar) } } + } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.kt index 0ddd594c566..d56de7a53e8 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.kt @@ -364,39 +364,29 @@ class KotlinTypeMapper @JvmOverloads constructor( // and, more importantly, returns 'kotlin.Any' (so that it can return as a reference value or a special COROUTINE_SUSPENDED object). // This also causes boxing of primitives and inline class values. // If we have a function returning an inline class value that is mapped to a reference type, we want to avoid boxing. - // However, we have to do that consistently both on declaration site and on call site in case of covariant overrides. + // However, we have to do that consistently both on declaration site and on call site. if (!functionDescriptor.isSuspend) return null val originalSuspendFunction = functionDescriptor.unwrapInitialDescriptorForSuspendFunction() val originalReturnType = originalSuspendFunction.returnType!! + if (!originalReturnType.isInlineClassType()) return null - if (!originalReturnType.isInlineClassTypeSafeToKeepUnboxedOnSuspendFunReturn()) { - return originalSuspendFunction.module.builtIns.nullableAnyType + // Force boxing for primitives + if (AsmUtil.isPrimitive(mapType(originalReturnType))) { + return functionDescriptor.builtIns.nullableAnyType } - // Lambdas, callable references, and function literals implicitly override corresponding generic method from a base class. - // NB we don't have suspend function literals so far, but we support it in back-end, just in case. - if (isFunctionLiteral(originalSuspendFunction) || isFunctionExpression(originalSuspendFunction)) { - return originalSuspendFunction.module.builtIns.nullableAnyType - } - - // NB JVM view of a Kotlin function overrides JVM views of corresponding overridden functions - val originalOverridden = getAllOverriddenDeclarations(functionDescriptor).map { - it.unwrapInitialDescriptorForSuspendFunction().original - } - if (originalOverridden.any { !it.returnType!!.isInlineClassTypeSafeToKeepUnboxedOnSuspendFunReturn() }) { - return originalSuspendFunction.module.builtIns.nullableAnyType + // Force boxing for nullable inline class types with nullable underlying type + if (originalReturnType.isMarkedNullable && originalReturnType.isNullableUnderlyingType()) { + return functionDescriptor.builtIns.nullableAnyType } + // Don't box other inline classes return originalReturnType } - private fun KotlinType.isInlineClassTypeSafeToKeepUnboxedOnSuspendFunReturn(): Boolean = - isInlineClassType() && !AsmUtil.isPrimitive(mapType(this)) && (!isMarkedNullable || !isNullableUnderlyingType()) - - @JvmOverloads fun mapToCallableMethod( descriptor: FunctionDescriptor, @@ -410,7 +400,7 @@ class KotlinTypeMapper @JvmOverloads constructor( val owner = mapOwner(descriptor) val originalDescriptor = descriptor.original return CallableMethod( - owner, owner, { mapDefaultMethod(originalDescriptor, OwnerKind.IMPLEMENTATION).descriptor }, method, INVOKESPECIAL, + owner, owner, { mapDefaultMethod(originalDescriptor, OwnerKind.IMPLEMENTATION) }, method, INVOKESPECIAL, null, null, null, null, null, originalDescriptor.returnType, isInterfaceMethod = false, isDefaultMethodInInterface = false ) } @@ -571,7 +561,7 @@ class KotlinTypeMapper @JvmOverloads constructor( return CallableMethod( owner, ownerForDefaultImpl, - { mapDefaultMethod(baseMethodDescriptor, getKindForDefaultImplCall(baseMethodDescriptor)).descriptor }, + { mapDefaultMethod(baseMethodDescriptor, getKindForDefaultImplCall(baseMethodDescriptor)) }, signature, invokeOpcode, thisClass, dispatchReceiverKotlinType, receiverParameterType, extensionReceiverKotlinType, calleeType, returnKotlinType, if (jvmTarget >= JvmTarget.JVM_1_8) isInterfaceMember else invokeOpcode == INVOKEINTERFACE, @@ -663,11 +653,16 @@ class KotlinTypeMapper @JvmOverloads constructor( } } - val suffix = getInlineClassSignatureManglingSuffix(descriptor) - if (suffix != null) { - newName += suffix - } else if (kind === OwnerKind.ERASED_INLINE_CLASS) { - newName += JvmAbi.IMPL_SUFFIX_FOR_INLINE_CLASS_MEMBERS + // Skip inline class mangling for property reference signatures, + // so that we don't have to repeat the same logic in reflection + // in case of properties without getter methods. + if (kind !== OwnerKind.PROPERTY_REFERENCE_SIGNATURE || descriptor.isPropertyWithGetterSignaturePresent()) { + val suffix = getManglingSuffixBasedOnKotlinSignature(descriptor) + if (suffix != null) { + newName += suffix + } else if (kind === OwnerKind.ERASED_INLINE_CLASS) { + newName += JvmAbi.IMPL_SUFFIX_FOR_INLINE_CLASS_MEMBERS + } } newName = sanitizeNameIfNeeded(newName, languageVersionSettings) @@ -966,12 +961,12 @@ class KotlinTypeMapper @JvmOverloads constructor( // implicitly override generic 'invoke' from a corresponding base class. if ((isFunctionExpression(descriptor) || isFunctionLiteral(descriptor)) && returnType.isInlineClassType()) return true - return isJvmPrimitiveOrInlineClass(returnType) && - getAllOverriddenDescriptors(descriptor).any { !isJvmPrimitiveOrInlineClass(it.returnType!!) } + return isJvmPrimitive(returnType) && + getAllOverriddenDescriptors(descriptor).any { !isJvmPrimitive(it.returnType!!) } } - private fun isJvmPrimitiveOrInlineClass(kotlinType: KotlinType) = - KotlinBuiltIns.isPrimitiveType(kotlinType) || kotlinType.isInlineClassType() + private fun isJvmPrimitive(kotlinType: KotlinType) = + KotlinBuiltIns.isPrimitiveType(kotlinType) private fun isBoxMethodForInlineClass(descriptor: FunctionDescriptor): Boolean { val containingDeclaration = descriptor.containingDeclaration diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/inlineClassManglingUtils.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/inlineClassManglingUtils.kt index 79a96b9f14b..12f6d403229 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/inlineClassManglingUtils.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/inlineClassManglingUtils.kt @@ -5,31 +5,41 @@ package org.jetbrains.kotlin.codegen.state +import org.jetbrains.kotlin.codegen.coroutines.unwrapInitialDescriptorForSuspendFunction import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.resolve.InlineClassDescriptorResolver import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe +import org.jetbrains.kotlin.resolve.isInlineClassType import org.jetbrains.kotlin.resolve.jvm.* import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound import java.security.MessageDigest import java.util.* -fun getInlineClassSignatureManglingSuffix(descriptor: CallableMemberDescriptor): String? { +fun getManglingSuffixBasedOnKotlinSignature(descriptor: CallableMemberDescriptor): String? { if (descriptor !is FunctionDescriptor) return null if (descriptor is ConstructorDescriptor) return null if (InlineClassDescriptorResolver.isSynthesizedBoxOrUnboxMethod(descriptor)) return null + // If a function accepts inline class parameters, mangle its name. val actualValueParameterTypes = listOfNotNull(descriptor.extensionReceiverParameter?.type) + descriptor.valueParameters.map { it.type } + if (requiresFunctionNameMangling(actualValueParameterTypes)) { + return "-" + md5base64(collectSignatureForMangling(actualValueParameterTypes)) + } - return getInlineClassSignatureManglingSuffix(actualValueParameterTypes) + // If a class member function returns inline class value, mangle its name. + // NB here function can be a suspend function JVM view with return type replaced with 'Any', + // should unwrap it and take original return type instead. + if (descriptor.containingDeclaration is ClassDescriptor) { + val returnType = descriptor.unwrapInitialDescriptorForSuspendFunction().returnType!! + // NB functions returning all inline classes (including our special 'kotlin.Result') should be mangled. + if (returnType.isInlineClassType()) { + return "-" + md5base64(":" + getSignatureElementForMangling(returnType)) + } + } + return null } -private fun getInlineClassSignatureManglingSuffix(valueParameterTypes: List) = - if (requiresFunctionNameMangling(valueParameterTypes)) - "-" + md5base64(collectSignatureForMangling(valueParameterTypes)) - else - null - private fun collectSignatureForMangling(types: List) = types.joinToString { getSignatureElementForMangling(it) } diff --git a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java index 14992dc6352..296ddd02ed6 100644 --- a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java @@ -12908,6 +12908,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/inlineClasses/kt37998.kt"); } + @TestMetadata("kt38680.kt") + public void testKt38680() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/kt38680.kt"); + } + @TestMetadata("mangledDefaultParameterFunction.kt") public void testMangledDefaultParameterFunction() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/mangledDefaultParameterFunction.kt"); diff --git a/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/kt31585.kt b/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/kt31585.kt index 69bfcee4dd0..44b0a32ffef 100644 --- a/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/kt31585.kt +++ b/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/kt31585.kt @@ -8,7 +8,7 @@ enum class RequestFields { ENUM_ONE } -data class RequestInputParameters( +class RequestInputParameters( private val backingMap: Map ) : Map by backingMap diff --git a/compiler/testData/codegen/box/inlineClasses/kt38680.kt b/compiler/testData/codegen/box/inlineClasses/kt38680.kt new file mode 100644 index 00000000000..025234af0b4 --- /dev/null +++ b/compiler/testData/codegen/box/inlineClasses/kt38680.kt @@ -0,0 +1,13 @@ +// !LANGUAGE: +InlineClasses + +inline class IC(val s: String) + +interface IFoo { + fun foo(x: T, s: String = "K"): String +} + +class FooImpl : IFoo { + override fun foo(x: IC, s: String): String = x.s + s +} + +fun box(): String = FooImpl().foo(IC("O")) \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index b98c7025216..40ecd5f8327 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -14123,6 +14123,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/inlineClasses/kt37998.kt"); } + @TestMetadata("kt38680.kt") + public void testKt38680() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/kt38680.kt"); + } + @TestMetadata("mangledDefaultParameterFunction.kt") public void testMangledDefaultParameterFunction() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/mangledDefaultParameterFunction.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 79217b1a1d3..9d1bc75a81c 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -14128,6 +14128,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/inlineClasses/kt37998.kt"); } + @TestMetadata("kt38680.kt") + public void testKt38680() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/kt38680.kt"); + } + @TestMetadata("mangledDefaultParameterFunction.kt") public void testMangledDefaultParameterFunction() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/mangledDefaultParameterFunction.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 4c34208f3d5..447f9ecc4f5 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -12908,6 +12908,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/inlineClasses/kt37998.kt"); } + @TestMetadata("kt38680.kt") + public void testKt38680() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/kt38680.kt"); + } + @TestMetadata("mangledDefaultParameterFunction.kt") public void testMangledDefaultParameterFunction() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/mangledDefaultParameterFunction.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index 7248ea1a565..23a96db1f5d 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -11118,6 +11118,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/inlineClasses/kt37998.kt"); } + @TestMetadata("kt38680.kt") + public void testKt38680() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/kt38680.kt"); + } + @TestMetadata("mangledDefaultParameterFunction.kt") public void testMangledDefaultParameterFunction() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/mangledDefaultParameterFunction.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 601a7252109..49968332ddb 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -11183,6 +11183,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/inlineClasses/kt37998.kt"); } + @TestMetadata("kt38680.kt") + public void testKt38680() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/kt38680.kt"); + } + @TestMetadata("mangledDefaultParameterFunction.kt") public void testMangledDefaultParameterFunction() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/mangledDefaultParameterFunction.kt");