diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/CallableMethod.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/CallableMethod.kt index bad19c172b0..751dd1be912 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/CallableMethod.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/CallableMethod.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.codegen +import org.jetbrains.kotlin.codegen.state.StaticTypeMapperForOldBackend import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature @@ -51,7 +52,7 @@ class CallableMethod( override fun genInvokeInstruction(v: InstructionAdapter) { if (boxInlineClassBeforeInvoke) { - StackValue.boxInlineClass(dispatchReceiverKotlinType!!, v) + StackValue.boxInlineClass(dispatchReceiverKotlinType!!, v, StaticTypeMapperForOldBackend) } v.visitMethodInsn( invokeOpcode, diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionsFromAnyGeneratorImpl.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionsFromAnyGeneratorImpl.java index 0d7dc837228..dd86b2fb30e 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionsFromAnyGeneratorImpl.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionsFromAnyGeneratorImpl.java @@ -34,7 +34,8 @@ import org.jetbrains.org.objectweb.asm.commons.Method; import java.util.List; -import static org.jetbrains.kotlin.codegen.AsmUtil.*; +import static org.jetbrains.kotlin.codegen.AsmUtil.correctElementType; +import static org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive; import static org.jetbrains.kotlin.codegen.DescriptorAsmUtil.*; import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.JAVA_STRING_TYPE; import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE; @@ -306,7 +307,7 @@ public class FunctionsFromAnyGeneratorImpl extends FunctionsFromAnyGenerator { iv.load(secondParameterIndex, OBJECT_TYPE); iv.checkcast(wrapperType); - StackValue.unboxInlineClass(wrapperType, wrapperKotlinType, iv); + StackValue.unboxInlineClass(wrapperType, wrapperKotlinType, iv, typeMapper); iv.store(unboxedValueIndex, underlyingType.getType()); return unboxedValueIndex; diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java index 4a76cc9bce7..aa7b669fbcc 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java @@ -20,11 +20,14 @@ import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt; import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods; import org.jetbrains.kotlin.codegen.pseudoInsns.PseudoInsnsKt; import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper; +import org.jetbrains.kotlin.codegen.state.KotlinTypeMapperBase; +import org.jetbrains.kotlin.codegen.state.StaticTypeMapperForOldBackend; import org.jetbrains.kotlin.config.LanguageFeature; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor; import org.jetbrains.kotlin.load.java.DescriptorsJvmAbiUtil; import org.jetbrains.kotlin.load.java.JvmAbi; +import org.jetbrains.kotlin.load.kotlin.TypeMappingMode; import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.psi.KtExpression; import org.jetbrains.kotlin.psi.ValueArgument; @@ -43,6 +46,7 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue; import org.jetbrains.kotlin.types.KotlinType; import org.jetbrains.kotlin.types.SimpleType; import org.jetbrains.kotlin.types.TypeUtils; +import org.jetbrains.kotlin.types.model.KotlinTypeMarker; import org.jetbrains.org.objectweb.asm.Label; import org.jetbrains.org.objectweb.asm.Opcodes; import org.jetbrains.org.objectweb.asm.Type; @@ -452,11 +456,13 @@ public abstract class StackValue { v.invokevirtual(methodOwner.getInternalName(), type.getClassName() + "Value", "()" + type.getDescriptor(), false); } - public static void boxInlineClass(@NotNull KotlinType kotlinType, @NotNull InstructionAdapter v) { - Type boxedType = KotlinTypeMapper.mapInlineClassTypeAsDeclaration(kotlinType); - Type underlyingType = KotlinTypeMapper.mapUnderlyingTypeOfInlineClassType(kotlinType); + public static void boxInlineClass( + @NotNull KotlinTypeMarker kotlinType, @NotNull InstructionAdapter v, @NotNull KotlinTypeMapperBase typeMapper + ) { + Type boxedType = typeMapper.mapTypeCommon(kotlinType, TypeMappingMode.CLASS_DECLARATION); + Type underlyingType = KotlinTypeMapper.mapUnderlyingTypeOfInlineClassType(kotlinType, typeMapper); - if (TypeUtils.isNullableType(kotlinType) && !isPrimitive(underlyingType)) { + if (typeMapper.getTypeSystem().isNullableType(kotlinType) && !isPrimitive(underlyingType)) { boxOrUnboxWithNullCheck(v, vv -> invokeBoxMethod(vv, boxedType, underlyingType)); } else { @@ -477,14 +483,19 @@ public abstract class StackValue { ); } - public static void unboxInlineClass(@NotNull Type type, @NotNull KotlinType targetInlineClassType, @NotNull InstructionAdapter v) { - Type owner = KotlinTypeMapper.mapInlineClassTypeAsDeclaration(targetInlineClassType); + public static void unboxInlineClass( + @NotNull Type type, + @NotNull KotlinTypeMarker targetInlineClassType, + @NotNull InstructionAdapter v, + @NotNull KotlinTypeMapperBase typeMapper + ) { + Type owner = typeMapper.mapTypeCommon(targetInlineClassType, TypeMappingMode.CLASS_DECLARATION); coerce(type, owner, v); - Type resultType = KotlinTypeMapper.mapUnderlyingTypeOfInlineClassType(targetInlineClassType); + Type resultType = KotlinTypeMapper.mapUnderlyingTypeOfInlineClassType(targetInlineClassType, typeMapper); - if (TypeUtils.isNullableType(targetInlineClassType) && !isPrimitive(resultType)) { + if (typeMapper.getTypeSystem().isNullableType(targetInlineClassType) && !isPrimitive(resultType)) { boxOrUnboxWithNullCheck(v, vv -> invokeUnboxMethod(vv, owner, resultType)); } else { @@ -537,7 +548,7 @@ public abstract class StackValue { @Nullable KotlinType toKotlinType, @NotNull InstructionAdapter v ) { - if (coerceInlineClasses(fromType, fromKotlinType, toType, toKotlinType, v)) return; + if (coerceInlineClasses(fromType, fromKotlinType, toType, toKotlinType, v, StaticTypeMapperForOldBackend.INSTANCE)) return; coerce(fromType, toType, v); } @@ -573,7 +584,8 @@ public abstract class StackValue { @Nullable KotlinType fromKotlinType, @NotNull Type toType, @Nullable KotlinType toKotlinType, - @NotNull InstructionAdapter v + @NotNull InstructionAdapter v, + @NotNull KotlinTypeMapperBase typeMapper ) { // NB see also requiresInlineClassBoxingOrUnboxing above @@ -600,23 +612,23 @@ public abstract class StackValue { boolean isFromTypeUnboxed = isUnboxedInlineClass(fromKotlinType, fromType); boolean isToTypeUnboxed = isUnboxedInlineClass(toKotlinType, toType); if (isFromTypeUnboxed && !isToTypeUnboxed) { - boxInlineClass(fromKotlinType, v); + boxInlineClass(fromKotlinType, v, typeMapper); return true; } else if (!isFromTypeUnboxed && isToTypeUnboxed) { - unboxInlineClass(fromType, toKotlinType, v); + unboxInlineClass(fromType, toKotlinType, v, typeMapper); return true; } } else if (isFromTypeInlineClass) { if (isUnboxedInlineClass(fromKotlinType, fromType)) { - boxInlineClass(fromKotlinType, v); + boxInlineClass(fromKotlinType, v, typeMapper); return true; } } else { // isToTypeInlineClass is `true` if (isUnboxedInlineClass(toKotlinType, toType)) { - unboxInlineClass(fromType, toKotlinType, v); + unboxInlineClass(fromType, toKotlinType, v, typeMapper); return true; } } @@ -625,7 +637,7 @@ public abstract class StackValue { } public static boolean isUnboxedInlineClass(@NotNull KotlinType kotlinType, @NotNull Type actualType) { - return KotlinTypeMapper.mapUnderlyingTypeOfInlineClassType(kotlinType).equals(actualType); + return KotlinTypeMapper.mapUnderlyingTypeOfInlineClassType(kotlinType, StaticTypeMapperForOldBackend.INSTANCE).equals(actualType); } public static void coerce(@NotNull Type fromType, @NotNull Type toType, @NotNull InstructionAdapter v) { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineCodegen.kt index f2439415d67..d7d0f1fe0bb 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineCodegen.kt @@ -44,7 +44,6 @@ import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature import org.jetbrains.kotlin.serialization.DescriptorSerializer import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.typeUtil.makeNullable -import org.jetbrains.kotlin.backend.common.SamType import org.jetbrains.kotlin.utils.sure import org.jetbrains.org.objectweb.asm.Label import org.jetbrains.org.objectweb.asm.MethodVisitor @@ -451,7 +450,7 @@ class CoroutineCodegenForLambda private constructor( if (parameter.type.isInlineClassType()) { load(cloneIndex, fieldInfoForCoroutineLambdaParameter.ownerType) load(index, AsmTypes.OBJECT_TYPE) - StackValue.unboxInlineClass(AsmTypes.OBJECT_TYPE, parameter.type, this) + StackValue.unboxInlineClass(AsmTypes.OBJECT_TYPE, parameter.type, this, typeMapper) putfield( fieldInfoForCoroutineLambdaParameter.ownerInternalName, fieldInfoForCoroutineLambdaParameter.fieldName, @@ -757,7 +756,7 @@ class CoroutineCodegenForNamedFunction private constructor( generateCoroutineSuspendedCheck(languageVersionSettings) // Now we box the inline class StackValue.coerce(AsmTypes.OBJECT_TYPE, typeMapper.mapType(inlineClassToBoxInInvokeSuspend), this) - StackValue.boxInlineClass(inlineClassToBoxInInvokeSuspend, this) + StackValue.boxInlineClass(inlineClassToBoxInInvokeSuspend, this, typeMapper) } } @@ -861,4 +860,4 @@ fun reportSuspensionPointInsideMonitor(element: KtElement, state: GenerationStat } private fun FunctionDescriptor.allValueParameterTypes(): List = - (listOfNotNull(extensionReceiverParameter?.type)) + valueParameters.map { it.type } \ No newline at end of file + (listOfNotNull(extensionReceiverParameter?.type)) + valueParameters.map { it.type } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/inlineCodegenUtils.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/inlineCodegenUtils.kt index 1e9eca5483e..18d9eecdba0 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/inlineCodegenUtils.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/inlineCodegenUtils.kt @@ -7,8 +7,11 @@ package org.jetbrains.kotlin.codegen.inline import com.intellij.openapi.vfs.VirtualFile import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.codegen.* +import org.jetbrains.kotlin.codegen.ASSERTIONS_DISABLED_FIELD_NAME +import org.jetbrains.kotlin.codegen.AsmUtil +import org.jetbrains.kotlin.codegen.BaseExpressionCodegen import org.jetbrains.kotlin.codegen.SamWrapperCodegen.SAM_WRAPPER_SUFFIX +import org.jetbrains.kotlin.codegen.StackValue import org.jetbrains.kotlin.codegen.`when`.WhenByEnumsMapping import org.jetbrains.kotlin.codegen.binding.CodegenBinding import org.jetbrains.kotlin.codegen.context.CodegenContext @@ -22,6 +25,7 @@ import org.jetbrains.kotlin.codegen.optimization.common.asSequence import org.jetbrains.kotlin.codegen.optimization.common.intConstant import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper +import org.jetbrains.kotlin.codegen.state.KotlinTypeMapperBase import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil import org.jetbrains.kotlin.load.java.JvmAbi @@ -32,9 +36,9 @@ import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.jvm.AsmTypes import org.jetbrains.kotlin.resolve.jvm.JvmClassName -import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeProjectionImpl import org.jetbrains.kotlin.types.TypeSubstitutor +import org.jetbrains.kotlin.types.model.KotlinTypeMarker import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.org.objectweb.asm.* @@ -415,13 +419,13 @@ fun addInlineMarker(v: InstructionAdapter, isStartNotEnd: Boolean) { internal fun addUnboxInlineClassMarkersIfNeeded(v: InstructionAdapter, descriptor: CallableDescriptor, typeMapper: KotlinTypeMapper) { val inlineClass = (descriptor as? FunctionDescriptor)?.originalReturnTypeOfSuspendFunctionReturningUnboxedInlineClass(typeMapper) if (inlineClass != null) { - generateResumePathUnboxing(v, inlineClass) + generateResumePathUnboxing(v, inlineClass, typeMapper) } } -fun generateResumePathUnboxing(v: InstructionAdapter, inlineClass: KotlinType) { +fun generateResumePathUnboxing(v: InstructionAdapter, inlineClass: KotlinTypeMarker, typeMapper: KotlinTypeMapperBase) { addBeforeUnboxInlineClassMarker(v) - StackValue.unboxInlineClass(AsmTypes.OBJECT_TYPE, inlineClass, v) + StackValue.unboxInlineClass(AsmTypes.OBJECT_TYPE, inlineClass, v, typeMapper) // Suspend functions always returns Any?, but the unboxing disrupts type analysis of the bytecode. // For example, if the underlying type is String, CHECKCAST String is removed. // However, the unboxing is moved to the resume path, the direct path still has Any?, but now, without the CHECKCAST. 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 3d94bc36658..67118204301 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.kt @@ -75,7 +75,6 @@ import org.jetbrains.kotlin.types.checker.SimpleClassicTypeSystemContext import org.jetbrains.kotlin.types.checker.convertVariance import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.* import org.jetbrains.kotlin.types.model.* -import org.jetbrains.kotlin.backend.common.SamType import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.org.objectweb.asm.Opcodes.* import org.jetbrains.org.objectweb.asm.Type @@ -101,6 +100,9 @@ class KotlinTypeMapper @JvmOverloads constructor( field = value } + override val typeSystem: TypeSystemCommonBackendContext + get() = SimpleClassicTypeSystemContext + private val typeMappingConfiguration = object : TypeMappingConfiguration { override fun commonSupertype(types: Collection): KotlinType { return CommonSupertypes.commonSupertype(types) @@ -233,6 +235,10 @@ class KotlinTypeMapper @JvmOverloads constructor( return mapType(classifier.defaultType, null, TypeMappingMode.CLASS_DECLARATION) } + override fun mapTypeCommon(type: KotlinTypeMarker, mode: TypeMappingMode): Type { + return mapType(type as KotlinType, null, mode) + } + fun mapTypeAsDeclaration(kotlinType: KotlinType): Type { return mapType(kotlinType, null, TypeMappingMode.CLASS_DECLARATION) } @@ -1272,29 +1278,6 @@ class KotlinTypeMapper @JvmOverloads constructor( } companion object { - - private val staticTypeMappingConfiguration = object : TypeMappingConfiguration { - override fun commonSupertype(types: Collection): KotlinType { - return CommonSupertypes.commonSupertype(types) - } - - override fun getPredefinedTypeForClass(classDescriptor: ClassDescriptor): Type? { - return null - } - - override fun getPredefinedInternalNameForClass(classDescriptor: ClassDescriptor): String? { - return null - } - - override fun processErrorType(kotlinType: KotlinType, descriptor: ClassDescriptor) { - throw IllegalStateException(generateErrorMessageForErrorType(kotlinType, descriptor)) - } - - override fun preprocessType(kotlinType: KotlinType): KotlinType? { - return null - } - } - /** * Use proper LanguageVersionSettings where possible. */ @@ -1412,30 +1395,15 @@ class KotlinTypeMapper @JvmOverloads constructor( return ContainingClassesInfo.forPackageMember(facadeName, implClassName) } - // Make sure this method is called only from back-end - // It uses staticTypeMappingConfiguration that throws exception on error types @JvmStatic - fun mapInlineClassTypeAsDeclaration(kotlinType: KotlinType): Type { - return mapInlineClassType(kotlinType, TypeMappingMode.CLASS_DECLARATION, staticTypeMappingConfiguration) + fun mapUnderlyingTypeOfInlineClassType(kotlinType: KotlinTypeMarker, typeMapper: KotlinTypeMapperBase): Type { + val underlyingType = with(typeMapper.typeSystem) { + kotlinType.getUnsubstitutedUnderlyingType() + } ?: throw IllegalStateException("There should be underlying type for inline class type: $kotlinType") + return typeMapper.mapTypeCommon(underlyingType, TypeMappingMode.DEFAULT) } - // Make sure this method is called only from back-end - // It uses staticTypeMappingConfiguration that throws exception on error types - @JvmStatic - fun mapUnderlyingTypeOfInlineClassType(kotlinType: KotlinType): Type { - val underlyingType = kotlinType.unsubstitutedUnderlyingType() - ?: throw IllegalStateException("There should be underlying type for inline class type: $kotlinType") - return mapInlineClassType(underlyingType, TypeMappingMode.DEFAULT, staticTypeMappingConfiguration) - } - - private fun mapInlineClassType( - kotlinType: KotlinType, - mode: TypeMappingMode, - configuration: TypeMappingConfiguration - ): Type = - mapType(kotlinType, AsmTypeFactory, mode, configuration, null) - - private fun generateErrorMessageForErrorType(type: KotlinType, descriptor: DeclarationDescriptor): String { + internal fun generateErrorMessageForErrorType(type: KotlinType, descriptor: DeclarationDescriptor): String { val declarationElement = DescriptorToSourceUtils.descriptorToDeclaration(descriptor) ?: return "Error type encountered: $type (${type.javaClass.simpleName})." diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapperBase.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapperBase.kt index 63e778f2957..7f252efcfe5 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapperBase.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapperBase.kt @@ -8,11 +8,18 @@ package org.jetbrains.kotlin.codegen.state import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassifierDescriptor import org.jetbrains.kotlin.load.java.JvmAbi +import org.jetbrains.kotlin.load.kotlin.TypeMappingMode +import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext +import org.jetbrains.kotlin.types.model.KotlinTypeMarker import org.jetbrains.org.objectweb.asm.Type abstract class KotlinTypeMapperBase { + abstract val typeSystem: TypeSystemCommonBackendContext + abstract fun mapClass(classifier: ClassifierDescriptor): Type + abstract fun mapTypeCommon(type: KotlinTypeMarker, mode: TypeMappingMode): Type + fun mapDefaultImpls(descriptor: ClassDescriptor): Type = Type.getObjectType(mapClass(descriptor).internalName + JvmAbi.DEFAULT_IMPLS_SUFFIX) } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/StaticTypeMapperForOldBackend.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/StaticTypeMapperForOldBackend.kt new file mode 100644 index 00000000000..d134a760186 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/StaticTypeMapperForOldBackend.kt @@ -0,0 +1,54 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.codegen.state + +import org.jetbrains.kotlin.codegen.signature.AsmTypeFactory +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.ClassifierDescriptor +import org.jetbrains.kotlin.load.kotlin.TypeMappingConfiguration +import org.jetbrains.kotlin.load.kotlin.TypeMappingMode +import org.jetbrains.kotlin.load.kotlin.mapType +import org.jetbrains.kotlin.types.CommonSupertypes +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext +import org.jetbrains.kotlin.types.checker.SimpleClassicTypeSystemContext +import org.jetbrains.kotlin.types.model.KotlinTypeMarker +import org.jetbrains.org.objectweb.asm.Type + +// This class exists only because it's used to box/unbox inline classes in the static method StackValue.coerce in the old backend, which +// has no access to the correct type mapper instance, yet has a lot of call sites across the old backend, refactoring which would be costly. +object StaticTypeMapperForOldBackend : KotlinTypeMapperBase() { + override val typeSystem: TypeSystemCommonBackendContext + get() = SimpleClassicTypeSystemContext + + private val staticTypeMappingConfiguration = object : TypeMappingConfiguration { + override fun commonSupertype(types: Collection): KotlinType { + return CommonSupertypes.commonSupertype(types) + } + + override fun getPredefinedTypeForClass(classDescriptor: ClassDescriptor): Type? { + return null + } + + override fun getPredefinedInternalNameForClass(classDescriptor: ClassDescriptor): String? { + return null + } + + override fun processErrorType(kotlinType: KotlinType, descriptor: ClassDescriptor) { + throw IllegalStateException(KotlinTypeMapper.generateErrorMessageForErrorType(kotlinType, descriptor)) + } + + override fun preprocessType(kotlinType: KotlinType): KotlinType? { + return null + } + } + + override fun mapClass(classifier: ClassifierDescriptor): Type = TODO("Should not be called") + + override fun mapTypeCommon(type: KotlinTypeMarker, mode: TypeMappingMode): Type { + return mapType(type as KotlinType, AsmTypeFactory, mode, staticTypeMappingConfiguration, null) + } +} diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/declarations/InlineClassesUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/declarations/InlineClassesUtils.kt index a461821e11a..e39b8d6ca9a 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/declarations/InlineClassesUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/declarations/InlineClassesUtils.kt @@ -11,10 +11,19 @@ import org.jetbrains.kotlin.fir.resolve.substitution.createTypeSubstitutorByType import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolved import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol -import org.jetbrains.kotlin.fir.types.* +import org.jetbrains.kotlin.fir.types.ConeKotlinType +import org.jetbrains.kotlin.fir.types.ConeLookupTagBasedType +import org.jetbrains.kotlin.fir.types.ConeTypeContext +import org.jetbrains.kotlin.fir.types.coneType import org.jetbrains.kotlin.types.model.typeConstructor -fun ConeKotlinType.substitutedUnderlyingTypeForInlineClass(session: FirSession, context: ConeTypeContext): ConeKotlinType? { +internal fun ConeKotlinType.substitutedUnderlyingTypeForInlineClass(session: FirSession, context: ConeTypeContext): ConeKotlinType? { + val unsubstitutedType = unsubstitutedUnderlyingTypeForInlineClass(session) ?: return null + val substitutor = createTypeSubstitutorByTypeConstructor(mapOf(this.typeConstructor(context) to this), context) + return substitutor.substituteOrNull(unsubstitutedType) +} + +internal fun ConeKotlinType.unsubstitutedUnderlyingTypeForInlineClass(session: FirSession): ConeKotlinType? { val symbol = (this.fullyExpandedType(session) as? ConeLookupTagBasedType) ?.lookupTag ?.toSymbol(session) as? FirRegularClassSymbol @@ -24,8 +33,5 @@ fun ConeKotlinType.substitutedUnderlyingTypeForInlineClass(session: FirSession, if (!firClass.status.isInline) return null val constructor = firClass.declarations.singleOrNull { it is FirConstructor && it.isPrimary } as FirConstructor? ?: return null val valueParameter = constructor.valueParameters.singleOrNull() ?: return null - val unsubstitutedType = valueParameter.returnTypeRef.coneType - - val substitutor = createTypeSubstitutorByTypeConstructor(mapOf(this.typeConstructor(context) to this), context) - return substitutor.substituteOrNull(unsubstitutedType) + return valueParameter.returnTypeRef.coneType } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt index 470c36c966a..45f9bc4cf66 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt @@ -497,6 +497,11 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty ?: session.builtinTypes.nullableAnyType.type } + override fun KotlinTypeMarker.getUnsubstitutedUnderlyingType(): KotlinTypeMarker? { + require(this is ConeKotlinType) + return unsubstitutedUnderlyingTypeForInlineClass(session) + } + override fun KotlinTypeMarker.getSubstitutedUnderlyingType(): KotlinTypeMarker? { require(this is ConeKotlinType) return substitutedUnderlyingTypeForInlineClass(session, this@ConeTypeContext) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt index 6bc7059c98f..0ced5396255 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt @@ -468,7 +468,7 @@ class ExpressionCodegen( if (isSuspensionPoint != SuspensionPointKind.NEVER) { addSuspendMarker(mv, isStartNotEnd = false, isSuspensionPoint == SuspensionPointKind.NOT_INLINE) if (unboxedInlineClassIrType != null) { - generateResumePathUnboxing(mv, unboxedInlineClassIrType.toIrBasedKotlinType()) + generateResumePathUnboxing(mv, unboxedInlineClassIrType, typeMapper) } addInlineMarker(mv, isStartNotEnd = false) } @@ -484,7 +484,7 @@ class ExpressionCodegen( mv.checkcast(unboxedInlineClassIrType.asmType) } if (irFunction.isInvokeSuspendOfContinuation()) { - StackValue.boxInlineClass(unboxedInlineClassIrType.toIrBasedKotlinType(), mv) + StackValue.boxInlineClass(unboxedInlineClassIrType, mv, typeMapper) } } @@ -637,7 +637,7 @@ class ExpressionCodegen( if (!irFunction.isInlineCallableReference) return if (irFunction.extensionReceiverParameter?.symbol == arg.symbol) return if (arg.type.isNullable() && arg.type.makeNotNull().unboxInlineClass().isNullable()) return - StackValue.unboxInlineClass(OBJECT_TYPE, arg.type.erasedUpperBound.defaultType.toIrBasedKotlinType(), mv) + StackValue.unboxInlineClass(OBJECT_TYPE, arg.type.erasedUpperBound.defaultType, mv, typeMapper) } // We do not mangle functions if Result is the only parameter of the function, @@ -664,7 +664,7 @@ class ExpressionCodegen( // Result parameter of SAM-wrapper to Java SAM is already unboxed in visitGetValue, do not unbox it anymore if (irFunction.parentAsClass.superTypes.any { it.getClass()?.isFromJava() == true }) return - StackValue.unboxInlineClass(OBJECT_TYPE, arg.type.erasedUpperBound.defaultType.toIrBasedKotlinType(), mv) + StackValue.unboxInlineClass(OBJECT_TYPE, arg.type.erasedUpperBound.defaultType, mv, typeMapper) } private fun IrClass.isSamAdapter(): Boolean = this.superTypes.any { it.getClass()?.isFun == true } @@ -920,7 +920,7 @@ class ExpressionCodegen( expression.value.accept(this, data).materializeAt(returnType, returnIrType) // In case of non-local return from suspend lambda 'materializeAt' does not box return value, box it manually. if (isNonLocalReturn && owner.isInvokeSuspendOfLambda() && expression.value.type.isKotlinResult()) { - StackValue.boxInlineClass(expression.value.type.toIrBasedKotlinType(), mv) + StackValue.boxInlineClass(expression.value.type, mv, typeMapper) } generateFinallyBlocksIfNeeded(returnType, afterReturnLabel, data, null) expression.markLineNumber(startOffset = true) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrTypeMapper.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrTypeMapper.kt index 034ca808618..3b88f871b24 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrTypeMapper.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrTypeMapper.kt @@ -40,7 +40,7 @@ import org.jetbrains.kotlin.ir.types.isKClass as isKClassImpl import org.jetbrains.kotlin.ir.util.isSuspendFunction as isSuspendFunctionImpl class IrTypeMapper(private val context: JvmBackendContext) : KotlinTypeMapperBase(), TypeMappingContext { - internal val typeSystem = IrTypeSystemContextImpl(context.irBuiltIns) + override val typeSystem: IrTypeSystemContext = IrTypeSystemContextImpl(context.irBuiltIns) override val typeContext: TypeSystemCommonBackendContextForTypeMapping = IrTypeCheckerContextForTypeMapping(typeSystem, context) override fun mapClass(classifier: ClassifierDescriptor): Type = @@ -53,6 +53,9 @@ class IrTypeMapper(private val context: JvmBackendContext) : KotlinTypeMapperBas error("Unknown descriptor: $classifier") } + override fun mapTypeCommon(type: KotlinTypeMarker, mode: TypeMappingMode): Type = + mapType(type as IrType, mode) + private fun computeClassInternalName(irClass: IrClass): StringBuilder { context.getLocalClassType(irClass)?.internalName?.let { return StringBuilder(it) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/PromisedValue.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/PromisedValue.kt index a04c91af2ce..24735061dde 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/PromisedValue.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/PromisedValue.kt @@ -12,15 +12,11 @@ import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.InlineClassAbi import org.jetbrains.kotlin.codegen.AsmUtil import org.jetbrains.kotlin.codegen.StackValue import org.jetbrains.kotlin.ir.declarations.IrTypeParameter -import org.jetbrains.kotlin.ir.descriptors.toIrBasedKotlinType import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.util.isTypeParameter import org.jetbrains.kotlin.ir.util.parentAsClass -import org.jetbrains.kotlin.ir.util.substitute import org.jetbrains.kotlin.resolve.jvm.AsmTypes -import org.jetbrains.kotlin.types.model.SimpleTypeMarker -import org.jetbrains.kotlin.types.model.typeConstructor import org.jetbrains.org.objectweb.asm.Label import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter @@ -50,12 +46,12 @@ abstract class PromisedValue(val codegen: ExpressionCodegen, val type: Type, val when { isFromTypeUnboxed && !isToTypeUnboxed -> { - StackValue.boxInlineClass(erasedSourceType.toIrBasedKotlinType(), mv) + StackValue.boxInlineClass(erasedSourceType, mv, typeMapper) return } !isFromTypeUnboxed && isToTypeUnboxed -> { - StackValue.unboxInlineClass(type, erasedTargetType.toIrBasedKotlinType(), mv) + StackValue.unboxInlineClass(type, erasedTargetType, mv, typeMapper) return } } @@ -64,7 +60,6 @@ abstract class PromisedValue(val codegen: ExpressionCodegen, val type: Type, val if (type != target || (castForReified && irType.anyTypeArgument { it.isReified })) { StackValue.coerce(type, target, mv, type == target) } - } abstract fun discard() diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt index 948adec804a..7e378bbfba6 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt @@ -431,20 +431,22 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon irClass.kind != ClassKind.INTERFACE && irClass.kind != ClassKind.ANNOTATION_CLASS } ?: owner.superTypes.first() - override fun KotlinTypeMarker.getSubstitutedUnderlyingType(): KotlinTypeMarker? { + override fun KotlinTypeMarker.getUnsubstitutedUnderlyingType(): KotlinTypeMarker? { // Code in inlineClassesUtils.kt loads the property with the same name from the scope of the substituted type and takes its type. // This code below should have the same effect. - val irClass = (this as? IrType)?.classOrNull?.owner?.takeIf { it.isInline } ?: return null - val inlineClassParameter = irClass.primaryConstructor?.valueParameters?.singleOrNull() - return inlineClassParameter?.let { parameter -> + val irClass = (this as? IrType)?.classOrNull?.owner?.takeIf { it.isInline } + return irClass?.primaryConstructor?.valueParameters?.singleOrNull()?.type + } + + override fun KotlinTypeMarker.getSubstitutedUnderlyingType(): KotlinTypeMarker? = + getUnsubstitutedUnderlyingType()?.let { type -> // Taking only the type parameters of the class (and not its outer classes) is OK since inner classes are always top level IrTypeSubstitutor( - irClass.typeParameters.map { it.symbol }, + (this as IrType).getClass()!!.typeParameters.map { it.symbol }, (this as? IrSimpleType)?.arguments.orEmpty(), irBuiltIns - ).substitute(parameter.type) + ).substitute(type as IrType) } - } override fun TypeConstructorMarker.getPrimitiveType(): PrimitiveType? { if (this !is IrClassSymbol) return null diff --git a/core/compiler.common/src/org/jetbrains/kotlin/types/TypeSystemCommonBackendContext.kt b/core/compiler.common/src/org/jetbrains/kotlin/types/TypeSystemCommonBackendContext.kt index 1fd2917e485..75715abd8b3 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/types/TypeSystemCommonBackendContext.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/types/TypeSystemCommonBackendContext.kt @@ -34,6 +34,7 @@ interface TypeSystemCommonBackendContext : TypeSystemContext { fun TypeConstructorMarker.isInlineClass(): Boolean fun TypeConstructorMarker.isInnerClass(): Boolean fun TypeParameterMarker.getRepresentativeUpperBound(): KotlinTypeMarker + fun KotlinTypeMarker.getUnsubstitutedUnderlyingType(): KotlinTypeMarker? fun KotlinTypeMarker.getSubstitutedUnderlyingType(): KotlinTypeMarker? fun KotlinTypeMarker.makeNullable(): KotlinTypeMarker = diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt b/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt index e815d9babbe..4575fee58ee 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor import org.jetbrains.kotlin.resolve.descriptorUtil.* import org.jetbrains.kotlin.resolve.isInlineClass import org.jetbrains.kotlin.resolve.substitutedUnderlyingType +import org.jetbrains.kotlin.resolve.unsubstitutedUnderlyingType import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.model.* import org.jetbrains.kotlin.types.typeUtil.asTypeProjection @@ -645,6 +646,11 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy return representativeUpperBound } + override fun KotlinTypeMarker.getUnsubstitutedUnderlyingType(): KotlinTypeMarker? { + require(this is KotlinType, this::errorMessage) + return unsubstitutedUnderlyingType() + } + override fun KotlinTypeMarker.getSubstitutedUnderlyingType(): KotlinTypeMarker? { require(this is KotlinType, this::errorMessage) return substitutedUnderlyingType()