Use new getInlineClassRepresentation in some utilities

This commit is contained in:
Alexander Udalov
2021-03-23 14:51:31 +01:00
parent 7fb3f48c67
commit 4c7f207309
10 changed files with 74 additions and 97 deletions
@@ -12,6 +12,7 @@ import kotlin.Unit;
import kotlin.collections.CollectionsKt; import kotlin.collections.CollectionsKt;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.backend.common.SamType;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.codegen.binding.CalculatedClosure; import org.jetbrains.kotlin.codegen.binding.CalculatedClosure;
import org.jetbrains.kotlin.codegen.context.ClosureContext; import org.jetbrains.kotlin.codegen.context.ClosureContext;
@@ -31,7 +32,6 @@ import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader;
import org.jetbrains.kotlin.metadata.ProtoBuf; import org.jetbrains.kotlin.metadata.ProtoBuf;
import org.jetbrains.kotlin.psi.KtElement; import org.jetbrains.kotlin.psi.KtElement;
import org.jetbrains.kotlin.resolve.DescriptorUtils; import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.InlineClassesUtilsKt;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt; import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt; import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
@@ -40,7 +40,7 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver;
import org.jetbrains.kotlin.serialization.DescriptorSerializer; import org.jetbrains.kotlin.serialization.DescriptorSerializer;
import org.jetbrains.kotlin.types.KotlinType; import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.SimpleType; import org.jetbrains.kotlin.types.SimpleType;
import org.jetbrains.kotlin.backend.common.SamType; import org.jetbrains.kotlin.types.TypeUtils;
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils; import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils;
import org.jetbrains.kotlin.util.OperatorNameConventions; import org.jetbrains.kotlin.util.OperatorNameConventions;
import org.jetbrains.org.objectweb.asm.MethodVisitor; import org.jetbrains.org.objectweb.asm.MethodVisitor;
@@ -376,10 +376,12 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
value = StackValue.local(slot, type, bridgeParameterKotlinTypes.get(i)); value = StackValue.local(slot, type, bridgeParameterKotlinTypes.get(i));
slot += type.getSize(); slot += type.getSize();
} }
if (InlineClassesCodegenUtilKt.isInlineClassWithUnderlyingTypeAnyOrAnyN(parameterType) && if (InlineClassesCodegenUtilKt.isInlineClassWithUnderlyingTypeAnyOrAnyN(parameterType) && functionReferenceCall == null) {
functionReferenceCall == null ClassDescriptor descriptor = TypeUtils.getClassDescriptor(parameterType);
) { InlineClassRepresentation<SimpleType> representation =
parameterType = InlineClassesUtilsKt.unsubstitutedUnderlyingParameter(parameterType).getType(); descriptor != null ? descriptor.getInlineClassRepresentation() : null;
assert representation != null : "Not an inline class type: " + parameterType;
parameterType = representation.getUnderlyingType();
} }
value.put(typeMapper.mapType(calleeParameter), parameterType, iv); value.put(typeMapper.mapType(calleeParameter), parameterType, iv);
} }
@@ -72,7 +72,7 @@ class ErasedInlineClassBodyCodegen(
} }
private fun generateUnboxMethod() { private fun generateUnboxMethod() {
val boxMethodDescriptor = InlineClassDescriptorResolver.createBoxFunctionDescriptor(descriptor) ?: return val boxMethodDescriptor = InlineClassDescriptorResolver.createBoxFunctionDescriptor(descriptor)
functionCodegen.generateMethod( functionCodegen.generateMethod(
Synthetic(null, boxMethodDescriptor), boxMethodDescriptor, object : FunctionGenerationStrategy.CodegenBased(state) { Synthetic(null, boxMethodDescriptor), boxMethodDescriptor, object : FunctionGenerationStrategy.CodegenBased(state) {
@@ -103,7 +103,7 @@ class ErasedInlineClassBodyCodegen(
} }
private fun generateSpecializedEqualsStub() { private fun generateSpecializedEqualsStub() {
val specializedEqualsDescriptor = InlineClassDescriptorResolver.createSpecializedEqualsDescriptor(descriptor) ?: return val specializedEqualsDescriptor = InlineClassDescriptorResolver.createSpecializedEqualsDescriptor(descriptor)
functionCodegen.generateMethod( functionCodegen.generateMethod(
Synthetic(null, specializedEqualsDescriptor), specializedEqualsDescriptor, object : FunctionGenerationStrategy.CodegenBased(state) { Synthetic(null, specializedEqualsDescriptor), specializedEqualsDescriptor, object : FunctionGenerationStrategy.CodegenBased(state) {
@@ -20,6 +20,7 @@ import kotlin.text.StringsKt;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.backend.common.CodegenUtil; import org.jetbrains.kotlin.backend.common.CodegenUtil;
import org.jetbrains.kotlin.backend.common.SamType;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.codegen.binding.CalculatedClosure; import org.jetbrains.kotlin.codegen.binding.CalculatedClosure;
import org.jetbrains.kotlin.codegen.binding.CodegenBinding; import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
@@ -92,7 +93,6 @@ import org.jetbrains.kotlin.types.model.KotlinTypeMarker;
import org.jetbrains.kotlin.types.model.TypeParameterMarker; import org.jetbrains.kotlin.types.model.TypeParameterMarker;
import org.jetbrains.kotlin.types.typesApproximation.CapturedTypeApproximationKt; import org.jetbrains.kotlin.types.typesApproximation.CapturedTypeApproximationKt;
import org.jetbrains.kotlin.util.OperatorNameConventions; import org.jetbrains.kotlin.util.OperatorNameConventions;
import org.jetbrains.kotlin.backend.common.SamType;
import org.jetbrains.org.objectweb.asm.Label; import org.jetbrains.org.objectweb.asm.Label;
import org.jetbrains.org.objectweb.asm.MethodVisitor; import org.jetbrains.org.objectweb.asm.MethodVisitor;
import org.jetbrains.org.objectweb.asm.Opcodes; import org.jetbrains.org.objectweb.asm.Opcodes;
@@ -2024,10 +2024,12 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
// Do not unbox parameters of suspend lambda, they are unboxed in `invoke` method // Do not unbox parameters of suspend lambda, they are unboxed in `invoke` method
!CoroutineCodegenUtilKt.isInvokeSuspendOfLambda(context.getFunctionDescriptor()) !CoroutineCodegenUtilKt.isInvokeSuspendOfLambda(context.getFunctionDescriptor())
) { ) {
KotlinType underlyingType = InlineClassesUtilsKt.underlyingRepresentation( ClassDescriptor inlineClass = (ClassDescriptor) inlineClassType.getConstructor().getDeclarationDescriptor();
(ClassDescriptor) inlineClassType.getConstructor().getDeclarationDescriptor()).getType(); InlineClassRepresentation<SimpleType> representation =
return StackValue.underlyingValueOfInlineClass( inlineClass != null ? inlineClass.getInlineClassRepresentation() : null;
typeMapper.mapType(underlyingType), underlyingType, localOrCaptured); assert representation != null : "Not an inline class: " + inlineClassType;
KotlinType underlyingType = representation.getUnderlyingType();
return StackValue.underlyingValueOfInlineClass(typeMapper.mapType(underlyingType), underlyingType, localOrCaptured);
} }
} }
return localOrCaptured; return localOrCaptured;
@@ -53,6 +53,7 @@ import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature; import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature;
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature; import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
import org.jetbrains.kotlin.types.KotlinType; import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.SimpleType;
import org.jetbrains.kotlin.types.TypeUtils; import org.jetbrains.kotlin.types.TypeUtils;
import org.jetbrains.org.objectweb.asm.Label; import org.jetbrains.org.objectweb.asm.Label;
import org.jetbrains.org.objectweb.asm.MethodVisitor; import org.jetbrains.org.objectweb.asm.MethodVisitor;
@@ -369,23 +370,22 @@ public class FunctionCodegen {
public static void generateMethodInsideInlineClassWrapper( public static void generateMethodInsideInlineClassWrapper(
@NotNull JvmDeclarationOrigin origin, @NotNull JvmDeclarationOrigin origin,
@NotNull FunctionDescriptor functionDescriptor, @NotNull FunctionDescriptor functionDescriptor,
@NotNull ClassDescriptor containingDeclaration, @NotNull ClassDescriptor inlineClass,
@NotNull MethodVisitor mv, @NotNull MethodVisitor mv,
@NotNull KotlinTypeMapper typeMapper @NotNull KotlinTypeMapper typeMapper
) { ) {
mv.visitCode(); mv.visitCode();
Type fieldOwnerType = typeMapper.mapClass(containingDeclaration); Type fieldOwnerType = typeMapper.mapClass(inlineClass);
Method erasedMethodImpl = typeMapper.mapAsmMethod(functionDescriptor.getOriginal(), OwnerKind.ERASED_INLINE_CLASS); Method erasedMethodImpl = typeMapper.mapAsmMethod(functionDescriptor.getOriginal(), OwnerKind.ERASED_INLINE_CLASS);
ValueParameterDescriptor valueRepresentation = InlineClassesUtilsKt.underlyingRepresentation(containingDeclaration); InlineClassRepresentation<SimpleType> representation = inlineClass.getInlineClassRepresentation();
if (valueRepresentation == null) return; assert representation != null : "Not an inline class: " + inlineClass;
Type fieldType = typeMapper.mapType(valueRepresentation);
generateDelegateToStaticErasedVersion( generateDelegateToStaticErasedVersion(
mv, erasedMethodImpl, mv, erasedMethodImpl, fieldOwnerType,
fieldOwnerType, valueRepresentation.getName().asString(), fieldType representation.getUnderlyingPropertyName().asString(),
typeMapper.mapType(representation.getUnderlyingType())
); );
endVisit(mv, null, origin.getElement()); endVisit(mv, null, origin.getElement());
@@ -55,6 +55,7 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver;
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue; import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
import org.jetbrains.kotlin.serialization.DescriptorSerializer; import org.jetbrains.kotlin.serialization.DescriptorSerializer;
import org.jetbrains.kotlin.types.KotlinType; import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.SimpleType;
import org.jetbrains.org.objectweb.asm.FieldVisitor; import org.jetbrains.org.objectweb.asm.FieldVisitor;
import org.jetbrains.org.objectweb.asm.MethodVisitor; import org.jetbrains.org.objectweb.asm.MethodVisitor;
import org.jetbrains.org.objectweb.asm.Type; import org.jetbrains.org.objectweb.asm.Type;
@@ -274,26 +275,25 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
@Override @Override
protected void generateUnboxMethodForInlineClass() { protected void generateUnboxMethodForInlineClass() {
if (!(myClass instanceof KtClass)) return; if (!(myClass instanceof KtClass)) return;
if (!InlineClassesUtilsKt.isInlineClass(descriptor)) return; InlineClassRepresentation<SimpleType> inlineClassRepresentation = descriptor.getInlineClassRepresentation();
if (inlineClassRepresentation == null) return;
Type ownerType = typeMapper.mapClass(descriptor); Type ownerType = typeMapper.mapClass(descriptor);
ValueParameterDescriptor inlinedValue = InlineClassesUtilsKt.underlyingRepresentation(this.descriptor); Type valueType = typeMapper.mapType(inlineClassRepresentation.getUnderlyingType());
if (inlinedValue == null) return;
Type valueType = typeMapper.mapType(inlinedValue.getType());
SimpleFunctionDescriptor functionDescriptor = InlineClassDescriptorResolver.createUnboxFunctionDescriptor(this.descriptor); SimpleFunctionDescriptor functionDescriptor = InlineClassDescriptorResolver.createUnboxFunctionDescriptor(this.descriptor);
assert functionDescriptor != null : "FunctionDescriptor for unbox method should be not null during codegen";
functionCodegen.generateMethod( functionCodegen.generateMethod(
JvmDeclarationOriginKt.UnboxMethodOfInlineClass(functionDescriptor), functionDescriptor, JvmDeclarationOriginKt.UnboxMethodOfInlineClass(functionDescriptor), functionDescriptor,
new FunctionGenerationStrategy.CodegenBased(state) { new FunctionGenerationStrategy.CodegenBased(state) {
@Override @Override
public void doGenerateBody( public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature
) {
InstructionAdapter iv = codegen.v; InstructionAdapter iv = codegen.v;
iv.load(0, OBJECT_TYPE); iv.load(0, OBJECT_TYPE);
iv.getfield(ownerType.getInternalName(), inlinedValue.getName().asString(), valueType.getDescriptor()); iv.getfield(
ownerType.getInternalName(),
inlineClassRepresentation.getUnderlyingPropertyName().asString(),
valueType.getDescriptor()
);
iv.areturn(valueType); iv.areturn(valueType);
} }
} }
@@ -12,8 +12,6 @@ import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
import org.jetbrains.kotlin.load.kotlin.VirtualFileFinder import org.jetbrains.kotlin.load.kotlin.VirtualFileFinder
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.resolve.descriptorUtil.classId import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.resolve.isInlineClassType
import org.jetbrains.kotlin.resolve.underlyingRepresentation
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
@@ -26,9 +24,8 @@ import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.commons.Method import org.jetbrains.org.objectweb.asm.commons.Method
fun KotlinType.isInlineClassWithUnderlyingTypeAnyOrAnyN(): Boolean { fun KotlinType.isInlineClassWithUnderlyingTypeAnyOrAnyN(): Boolean {
if (!isInlineClassType()) return false val classDescriptor = constructor.declarationDescriptor
val classDescriptor = constructor.declarationDescriptor as? ClassDescriptor ?: return false return classDescriptor is ClassDescriptor && classDescriptor.inlineClassRepresentation?.underlyingType?.isAnyOrNullableAny() == true
return classDescriptor.underlyingRepresentation()?.type?.isAnyOrNullableAny() == true
} }
fun CallableDescriptor.isGenericParameter(): Boolean { fun CallableDescriptor.isGenericParameter(): Boolean {
@@ -79,4 +76,4 @@ fun classFileContainsMethod(classId: ClassId, state: GenerationState, method: Me
} }
}, ClassReader.SKIP_FRAMES) }, ClassReader.SKIP_FRAMES)
return found return found
} }
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.types.KotlinType
object InlineClassDescriptorResolver { object InlineClassDescriptorResolver {
@JvmField @JvmField
@@ -28,11 +29,11 @@ object InlineClassDescriptorResolver {
val SPECIALIZED_EQUALS_SECOND_PARAMETER_NAME = Name.identifier("p2") val SPECIALIZED_EQUALS_SECOND_PARAMETER_NAME = Name.identifier("p2")
@JvmStatic @JvmStatic
fun createBoxFunctionDescriptor(owner: ClassDescriptor): SimpleFunctionDescriptor? = fun createBoxFunctionDescriptor(owner: ClassDescriptor): SimpleFunctionDescriptor =
createConversionFunctionDescriptor(true, owner) createConversionFunctionDescriptor(true, owner)
@JvmStatic @JvmStatic
fun createUnboxFunctionDescriptor(owner: ClassDescriptor): SimpleFunctionDescriptor? = fun createUnboxFunctionDescriptor(owner: ClassDescriptor): SimpleFunctionDescriptor =
createConversionFunctionDescriptor(false, owner) createConversionFunctionDescriptor(false, owner)
@JvmStatic @JvmStatic
@@ -57,9 +58,7 @@ object InlineClassDescriptorResolver {
private fun isSynthesizedInlineClassMember(descriptor: CallableMemberDescriptor) = private fun isSynthesizedInlineClassMember(descriptor: CallableMemberDescriptor) =
descriptor.kind == CallableMemberDescriptor.Kind.SYNTHESIZED && descriptor.containingDeclaration.isInlineClass() descriptor.kind == CallableMemberDescriptor.Kind.SYNTHESIZED && descriptor.containingDeclaration.isInlineClass()
fun createSpecializedEqualsDescriptor(owner: ClassDescriptor): SimpleFunctionDescriptor? { fun createSpecializedEqualsDescriptor(owner: ClassDescriptor): SimpleFunctionDescriptor {
val inlinedValue = owner.underlyingRepresentation() ?: return null
val functionDescriptor = SimpleFunctionDescriptorImpl.create( val functionDescriptor = SimpleFunctionDescriptorImpl.create(
owner, owner,
Annotations.EMPTY, Annotations.EMPTY,
@@ -72,7 +71,7 @@ object InlineClassDescriptorResolver {
null, null,
null, null,
emptyList<TypeParameterDescriptor>(), emptyList<TypeParameterDescriptor>(),
createValueParametersForSpecializedEquals(functionDescriptor, inlinedValue), createValueParametersForSpecializedEquals(functionDescriptor, owner.inlineClassRepresentation!!.underlyingType),
owner.builtIns.booleanType, owner.builtIns.booleanType,
Modality.FINAL, Modality.FINAL,
DescriptorVisibilities.PUBLIC DescriptorVisibilities.PUBLIC
@@ -81,12 +80,7 @@ object InlineClassDescriptorResolver {
return functionDescriptor return functionDescriptor
} }
private fun createConversionFunctionDescriptor( private fun createConversionFunctionDescriptor(isBoxMethod: Boolean, owner: ClassDescriptor): SimpleFunctionDescriptor {
isBoxMethod: Boolean,
owner: ClassDescriptor
): SimpleFunctionDescriptor? {
val inlinedValue = owner.underlyingRepresentation() ?: return null
val functionDescriptor = SimpleFunctionDescriptorImpl.create( val functionDescriptor = SimpleFunctionDescriptorImpl.create(
owner, owner,
Annotations.EMPTY, Annotations.EMPTY,
@@ -95,12 +89,13 @@ object InlineClassDescriptorResolver {
SourceElement.NO_SOURCE SourceElement.NO_SOURCE
) )
val underlyingType = owner.inlineClassRepresentation!!.underlyingType
functionDescriptor.initialize( functionDescriptor.initialize(
null, null,
if (isBoxMethod) null else owner.thisAsReceiverParameter, if (isBoxMethod) null else owner.thisAsReceiverParameter,
emptyList<TypeParameterDescriptor>(), emptyList<TypeParameterDescriptor>(),
if (isBoxMethod) listOf(createValueParameterForBoxing(functionDescriptor, inlinedValue)) else emptyList(), if (isBoxMethod) listOf(createValueParameterForBoxing(functionDescriptor, underlyingType)) else emptyList(),
if (isBoxMethod) owner.defaultType else inlinedValue.returnType, if (isBoxMethod) owner.defaultType else underlyingType,
Modality.FINAL, Modality.FINAL,
DescriptorVisibilities.PUBLIC DescriptorVisibilities.PUBLIC
) )
@@ -109,36 +104,22 @@ object InlineClassDescriptorResolver {
} }
private fun createValueParameterForBoxing( private fun createValueParameterForBoxing(
functionDescriptor: FunctionDescriptor, functionDescriptor: FunctionDescriptor, underlyingType: KotlinType
inlinedValue: ValueParameterDescriptor ): ValueParameterDescriptorImpl =
): ValueParameterDescriptorImpl { createValueParameter(functionDescriptor, underlyingType, BOXING_VALUE_PARAMETER_NAME, 0)
return createValueParameter(functionDescriptor, inlinedValue, BOXING_VALUE_PARAMETER_NAME, 0)
}
private fun createValueParametersForSpecializedEquals( private fun createValueParametersForSpecializedEquals(
functionDescriptor: FunctionDescriptor, functionDescriptor: FunctionDescriptor, underlyingType: KotlinType
inlinedValue: ValueParameterDescriptor ): List<ValueParameterDescriptor> =
): List<ValueParameterDescriptor> { listOf(
return listOf( createValueParameter(functionDescriptor, underlyingType, SPECIALIZED_EQUALS_FIRST_PARAMETER_NAME, 0),
createValueParameter(functionDescriptor, inlinedValue, SPECIALIZED_EQUALS_FIRST_PARAMETER_NAME, 0), createValueParameter(functionDescriptor, underlyingType, SPECIALIZED_EQUALS_SECOND_PARAMETER_NAME, 1)
createValueParameter(functionDescriptor, inlinedValue, SPECIALIZED_EQUALS_SECOND_PARAMETER_NAME, 1)
) )
}
private fun createValueParameter( private fun createValueParameter(
functionDescriptor: FunctionDescriptor, functionDescriptor: FunctionDescriptor, type: KotlinType, name: Name, index: Int
inlinedValue: ValueParameterDescriptor, ): ValueParameterDescriptorImpl =
name: Name, ValueParameterDescriptorImpl(
index: Int functionDescriptor, null, index, Annotations.EMPTY, name, type, false, false, false, null, SourceElement.NO_SOURCE
): ValueParameterDescriptorImpl {
return ValueParameterDescriptorImpl(
functionDescriptor,
null,
index,
Annotations.EMPTY,
name,
inlinedValue.type,
false, false, false, null, SourceElement.NO_SOURCE
) )
}
} }
@@ -39,6 +39,7 @@ import org.jetbrains.kotlin.resolve.constants.*
import org.jetbrains.kotlin.resolve.constants.evaluate.CompileTimeType.* import org.jetbrains.kotlin.resolve.constants.evaluate.CompileTimeType.*
import org.jetbrains.kotlin.resolve.descriptorUtil.classId import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.SimpleType
import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
import org.jetbrains.kotlin.types.expressions.DoubleColonLHS import org.jetbrains.kotlin.types.expressions.DoubleColonLHS
@@ -857,7 +858,7 @@ private class ConstantExpressionEvaluatorVisitor(
} }
classDescriptor.isInlineClass() && UnsignedTypes.isUnsignedClass(classDescriptor) -> classDescriptor.isInlineClass() && UnsignedTypes.isUnsignedClass(classDescriptor) ->
createConstantValueForUnsignedTypeConstructor(call, resultingDescriptor, classDescriptor) createConstantValueForUnsignedTypeConstructor(call, resultingDescriptor, classDescriptor.inlineClassRepresentation!!)
else -> null else -> null
} }
@@ -869,20 +870,17 @@ private class ConstantExpressionEvaluatorVisitor(
private fun createConstantValueForUnsignedTypeConstructor( private fun createConstantValueForUnsignedTypeConstructor(
call: ResolvedCall<*>, call: ResolvedCall<*>,
constructorDescriptor: ConstructorDescriptor, constructorDescriptor: ConstructorDescriptor,
classDescriptor: ClassDescriptor representation: InlineClassRepresentation<SimpleType>,
): TypedCompileTimeConstant<*>? { ): TypedCompileTimeConstant<*>? {
assert(classDescriptor.isInlineClass()) { "Unsigned type should be an inline class type, but it is: $classDescriptor" }
if (!constructorDescriptor.isPrimary) return null if (!constructorDescriptor.isPrimary) return null
val valueArguments = call.valueArguments val valueArguments = call.valueArguments
if (valueArguments.size > 1) return null if (valueArguments.size > 1) return null
val underlyingType = classDescriptor.underlyingRepresentation()?.type ?: return null
val argument = valueArguments.values.singleOrNull()?.arguments?.singleOrNull() ?: return null val argument = valueArguments.values.singleOrNull()?.arguments?.singleOrNull() ?: return null
val argumentExpression = argument.getArgumentExpression() ?: return null val argumentExpression = argument.getArgumentExpression() ?: return null
val underlyingType = representation.underlyingType
val compileTimeConstant = evaluate(argumentExpression, underlyingType) val compileTimeConstant = evaluate(argumentExpression, underlyingType)
val evaluatedArgument = compileTimeConstant?.toConstantValue(underlyingType) ?: return null val evaluatedArgument = compileTimeConstant?.toConstantValue(underlyingType) ?: return null
@@ -165,17 +165,18 @@ class DescriptorSerializer private constructor(
builder.typeTable = typeTableProto builder.typeTable = typeTableProto
} }
classDescriptor.underlyingRepresentation()?.let { parameter -> val representation = classDescriptor.inlineClassRepresentation
builder.inlineClassUnderlyingPropertyName = getSimpleNameIndex(parameter.name) if (representation != null) {
builder.inlineClassUnderlyingPropertyName = getSimpleNameIndex(representation.underlyingPropertyName)
val property = callableMembers.single { val property = callableMembers.single {
it is PropertyDescriptor && it.extensionReceiverParameter == null && it.name == parameter.name it is PropertyDescriptor && it.extensionReceiverParameter == null && it.name == representation.underlyingPropertyName
} }
if (!property.visibility.isPublicAPI) { if (!property.visibility.isPublicAPI) {
if (useTypeTable()) { if (useTypeTable()) {
builder.inlineClassUnderlyingTypeId = typeId(parameter.type) builder.inlineClassUnderlyingTypeId = typeId(representation.underlyingType)
} else { } else {
builder.setInlineClassUnderlyingType(type(parameter.type)) builder.setInlineClassUnderlyingType(type(representation.underlyingType))
} }
} }
} }
@@ -15,7 +15,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs
val JVM_INLINE_ANNOTATION_FQ_NAME = FqName("kotlin.jvm.JvmInline") val JVM_INLINE_ANNOTATION_FQ_NAME = FqName("kotlin.jvm.JvmInline")
fun ClassDescriptor.underlyingRepresentation(): ValueParameterDescriptor? { private fun ClassDescriptor.underlyingRepresentation(): ValueParameterDescriptor? {
if (!isInlineClass()) return null if (!isInlineClass()) return null
return unsubstitutedPrimaryConstructor?.valueParameters?.singleOrNull() return unsubstitutedPrimaryConstructor?.valueParameters?.singleOrNull()
} }
@@ -24,7 +24,7 @@ fun ClassDescriptor.underlyingRepresentation(): ValueParameterDescriptor? {
// FIXME: would like to check as well. // FIXME: would like to check as well.
fun DeclarationDescriptor.isInlineClass() = this is ClassDescriptor && (isInline || isValue) fun DeclarationDescriptor.isInlineClass() = this is ClassDescriptor && (isInline || isValue)
fun KotlinType.unsubstitutedUnderlyingParameter(): ValueParameterDescriptor? { private fun KotlinType.unsubstitutedUnderlyingParameter(): ValueParameterDescriptor? {
return constructor.declarationDescriptor.safeAs<ClassDescriptor>()?.underlyingRepresentation() return constructor.declarationDescriptor.safeAs<ClassDescriptor>()?.underlyingRepresentation()
} }
@@ -67,10 +67,6 @@ fun KotlinType.isNullableUnderlyingType(): Boolean {
fun CallableDescriptor.isGetterOfUnderlyingPropertyOfInlineClass() = fun CallableDescriptor.isGetterOfUnderlyingPropertyOfInlineClass() =
this is PropertyGetterDescriptor && correspondingProperty.isUnderlyingPropertyOfInlineClass() this is PropertyGetterDescriptor && correspondingProperty.isUnderlyingPropertyOfInlineClass()
fun VariableDescriptor.isUnderlyingPropertyOfInlineClass(): Boolean { fun VariableDescriptor.isUnderlyingPropertyOfInlineClass(): Boolean =
if (extensionReceiverParameter != null) return false extensionReceiverParameter == null &&
val containingDeclaration = this.containingDeclaration (containingDeclaration as? ClassDescriptor)?.inlineClassRepresentation?.underlyingPropertyName == this.name
if (!containingDeclaration.isInlineClass()) return false
return (containingDeclaration as ClassDescriptor).underlyingRepresentation()?.name == this.name
}