JVM: Mangle functions returning inline class values

Mangling suffix is base64-encoded MD5 of ":<returnTypeFQN>"
This commit is contained in:
Dmitry Petrov
2020-04-29 16:15:03 +03:00
parent 9beb36ca2b
commit b5bd3604b1
21 changed files with 175 additions and 93 deletions
@@ -35,10 +35,10 @@ abstract class ArgumentGenerator {
* @see kotlin.reflect.jvm.internal.KCallableImpl.callBy
*/
open fun generate(
valueArgumentsByIndex: List<ResolvedValueArgument>,
actualArgs: List<ResolvedValueArgument>,
// may be null for a constructor of an object literal
calleeDescriptor: CallableDescriptor?
valueArgumentsByIndex: List<ResolvedValueArgument>,
actualArgs: List<ResolvedValueArgument>,
// 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()
}
)
@@ -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<JvmMethodParameterSignature> =
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
)
}
}
@@ -219,6 +219,11 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
return parentCodegen;
}
@NotNull
public KotlinTypeMapper getTypeMapper() {
return typeMapper;
}
@NotNull
public ObjectLiteralResult generateObjectLiteral(@NotNull KtObjectLiteralExpression literal) {
KtObjectDeclaration objectDeclaration = literal.getObjectDeclaration();
@@ -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());
}
@@ -467,7 +467,7 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
Name.special("<clinit>"), 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;
}
@@ -53,7 +53,8 @@ internal class ObjectSuperCallArgumentGenerator(
valueArgumentsByIndex: List<ResolvedValueArgument>,
actualArgs: List<ResolvedValueArgument>,
calleeDescriptor: CallableDescriptor?
): DefaultCallArgs = super.generate(valueArgumentsByIndex, valueArgumentsByIndex, calleeDescriptor)
): DefaultCallArgs =
super.generate(valueArgumentsByIndex, valueArgumentsByIndex, calleeDescriptor)
public override fun generateExpression(i: Int, argument: ExpressionValueArgument) {
generateSuperCallArgument(i)
@@ -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<String, ProgressionIteratorBasicValue> =
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? =
@@ -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
@@ -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)
}
}
@@ -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)
}
}
@@ -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)
}
}
}
@@ -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
@@ -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<KotlinType>) =
if (requiresFunctionNameMangling(valueParameterTypes))
"-" + md5base64(collectSignatureForMangling(valueParameterTypes))
else
null
private fun collectSignatureForMangling(types: List<KotlinType>) =
types.joinToString { getSignatureElementForMangling(it) }
@@ -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");
@@ -8,7 +8,7 @@ enum class RequestFields {
ENUM_ONE
}
data class RequestInputParameters(
class RequestInputParameters(
private val backingMap: Map<RequestFields, FieldValue>
) : Map<RequestFields, FieldValue> by backingMap
+13
View File
@@ -0,0 +1,13 @@
// !LANGUAGE: +InlineClasses
inline class IC(val s: String)
interface IFoo<T> {
fun foo(x: T, s: String = "K"): String
}
class FooImpl : IFoo<IC> {
override fun foo(x: IC, s: String): String = x.s + s
}
fun box(): String = FooImpl().foo(IC("O"))
@@ -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");
@@ -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");
@@ -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");
@@ -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");
@@ -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");