Value classes: treat @JvmInline value classes as inline classes
Report error on value classes without @JvmInline annotation. Do not check for @JvmInline annotation in value classes since it breaks reflection.
This commit is contained in:
+1
-1
@@ -267,7 +267,7 @@ class DefaultParameterValueSubstitutor(val state: GenerationState) {
|
||||
if (classDescriptor.kind != ClassKind.CLASS) return false
|
||||
|
||||
if (classOrObject.isLocal) return false
|
||||
if (classDescriptor.isInline) return false
|
||||
if (classDescriptor.isInlineClass()) return false
|
||||
if (shouldHideConstructorDueToInlineClassTypeValueParameters(constructorDescriptor)) return false
|
||||
|
||||
if (CodegenBinding.canHaveOuter(state.bindingContext, classDescriptor)) return false
|
||||
|
||||
@@ -216,7 +216,7 @@ public class DescriptorAsmUtil {
|
||||
private static boolean isInlineClassWrapperConstructor(@NotNull FunctionDescriptor functionDescriptor, @Nullable OwnerKind kind) {
|
||||
if (!(functionDescriptor instanceof ConstructorDescriptor)) return false;
|
||||
ClassDescriptor classDescriptor = ((ConstructorDescriptor) functionDescriptor).getConstructedClass();
|
||||
return classDescriptor.isInline() && kind == OwnerKind.IMPLEMENTATION;
|
||||
return InlineClassesUtilsKt.isInlineClass(classDescriptor) && kind == OwnerKind.IMPLEMENTATION;
|
||||
}
|
||||
|
||||
public static int getCommonCallableFlags(FunctionDescriptor functionDescriptor, @NotNull GenerationState state) {
|
||||
@@ -559,7 +559,7 @@ public class DescriptorAsmUtil {
|
||||
if (receiverKotlinType.isMarkedNullable()) return null;
|
||||
|
||||
DeclarationDescriptor receiverTypeDescriptor = receiverKotlinType.getConstructor().getDeclarationDescriptor();
|
||||
assert receiverTypeDescriptor instanceof ClassDescriptor && ((ClassDescriptor) receiverTypeDescriptor).isInline() :
|
||||
assert receiverTypeDescriptor != null && InlineClassesUtilsKt.isInlineClass(receiverTypeDescriptor) :
|
||||
"Inline class type expected: " + receiverKotlinType;
|
||||
ClassDescriptor receiverClassDescriptor = (ClassDescriptor) receiverTypeDescriptor;
|
||||
FunctionDescriptor toStringDescriptor = receiverClassDescriptor.getUnsubstitutedMemberScope()
|
||||
|
||||
@@ -1190,7 +1190,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
ClassDescriptor captureThis = closure.getCapturedOuterClassDescriptor();
|
||||
if (captureThis != null) {
|
||||
StackValue thisOrOuter = generateThisOrOuter(captureThis, false);
|
||||
assert !isPrimitive(thisOrOuter.type) || captureThis.isInline() :
|
||||
assert !isPrimitive(thisOrOuter.type) || InlineClassesUtilsKt.isInlineClass(captureThis) :
|
||||
"This or outer for " + captureThis + " should be non-primitive: " + thisOrOuter.type;
|
||||
callGenerator.putCapturedValueOnStack(thisOrOuter, thisOrOuter.type, paramIndex++);
|
||||
}
|
||||
@@ -4830,7 +4830,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
ReceiverParameterDescriptor dispatchReceiver = constructor.getDispatchReceiverParameter();
|
||||
ClassDescriptor containingDeclaration = constructor.getContainingDeclaration();
|
||||
|
||||
if (!containingDeclaration.isInline()) {
|
||||
if (!InlineClassesUtilsKt.isInlineClass(containingDeclaration)) {
|
||||
v.anew(objectType);
|
||||
v.dup();
|
||||
}
|
||||
|
||||
@@ -1589,7 +1589,7 @@ public class FunctionCodegen {
|
||||
|
||||
// When delegating to inline class, we invoke static implementation method
|
||||
// that takes inline class underlying value as 1st argument.
|
||||
int toArgsShift = toClass.isInline() ? 1 : 0;
|
||||
int toArgsShift = InlineClassesUtilsKt.isInlineClass(toClass) ? 1 : 0;
|
||||
|
||||
int reg = 1;
|
||||
for (int i = 0; i < argTypes.length; ++i) {
|
||||
@@ -1609,7 +1609,7 @@ public class FunctionCodegen {
|
||||
if (toClass.getKind() == ClassKind.INTERFACE) {
|
||||
iv.invokeinterface(internalName, delegateToMethod.getName(), delegateToMethod.getDescriptor());
|
||||
}
|
||||
else if (toClass.isInline()) {
|
||||
else if (InlineClassesUtilsKt.isInlineClass(toClass)) {
|
||||
iv.invokestatic(internalName, delegateToMethod.getName(), delegateToMethod.getDescriptor(), false);
|
||||
}
|
||||
else {
|
||||
|
||||
+3
-3
@@ -84,7 +84,7 @@ public class FunctionsFromAnyGeneratorImpl extends FunctionsFromAnyGenerator {
|
||||
String toStringMethodDesc = getToStringDesc();
|
||||
MethodVisitor mv = v.newMethod(methodOrigin, getAccess(), toStringMethodName, toStringMethodDesc, null, null);
|
||||
|
||||
if (!isInErasedInlineClass && classDescriptor.isInline()) {
|
||||
if (!isInErasedInlineClass && InlineClassesUtilsKt.isInlineClass(classDescriptor)) {
|
||||
FunctionCodegen.generateMethodInsideInlineClassWrapper(methodOrigin, function, classDescriptor, mv, typeMapper);
|
||||
return;
|
||||
}
|
||||
@@ -161,7 +161,7 @@ public class FunctionsFromAnyGeneratorImpl extends FunctionsFromAnyGenerator {
|
||||
String hashCodeMethodDesc = getHashCodeDesc();
|
||||
MethodVisitor mv = v.newMethod(methodOrigin, getAccess(), hashCodeMethodName, hashCodeMethodDesc, null, null);
|
||||
|
||||
if (!isInErasedInlineClass && classDescriptor.isInline()) {
|
||||
if (!isInErasedInlineClass && InlineClassesUtilsKt.isInlineClass(classDescriptor)) {
|
||||
FunctionCodegen.generateMethodInsideInlineClassWrapper(methodOrigin, function, classDescriptor, mv, typeMapper);
|
||||
return;
|
||||
}
|
||||
@@ -233,7 +233,7 @@ public class FunctionsFromAnyGeneratorImpl extends FunctionsFromAnyGenerator {
|
||||
String equalsMethodDesc = getEqualsDesc();
|
||||
MethodVisitor mv = v.newMethod(methodOrigin, getAccess(), equalsMethodName, equalsMethodDesc, null, null);
|
||||
|
||||
if (!isInErasedInlineClass && classDescriptor.isInline()) {
|
||||
if (!isInErasedInlineClass && InlineClassesUtilsKt.isInlineClass(classDescriptor)) {
|
||||
FunctionCodegen.generateMethodInsideInlineClassWrapper(methodOrigin, function, classDescriptor, mv, typeMapper);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -260,7 +260,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
@Override
|
||||
protected void generateErasedInlineClassIfNeeded() {
|
||||
if (!(myClass instanceof KtClass)) return;
|
||||
if (!descriptor.isInline()) return;
|
||||
if (!InlineClassesUtilsKt.isInlineClass(descriptor)) return;
|
||||
|
||||
ClassContext erasedInlineClassContext = context.intoWrapperForErasedInlineClass(descriptor, state);
|
||||
new ErasedInlineClassBodyCodegen((KtClass) myClass, erasedInlineClassContext, v, state, this).generate();
|
||||
@@ -269,7 +269,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
@Override
|
||||
protected void generateUnboxMethodForInlineClass() {
|
||||
if (!(myClass instanceof KtClass)) return;
|
||||
if (!descriptor.isInline()) return;
|
||||
if (!InlineClassesUtilsKt.isInlineClass(descriptor)) return;
|
||||
|
||||
Type ownerType = typeMapper.mapClass(descriptor);
|
||||
ValueParameterDescriptor inlinedValue = InlineClassesUtilsKt.underlyingRepresentation(this.descriptor);
|
||||
@@ -450,7 +450,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
try {
|
||||
lookupConstructorExpressionsInClosureIfPresent();
|
||||
constructorCodegen.generatePrimaryConstructor(delegationFieldsInfo, superClassAsmType);
|
||||
if (!descriptor.isInline() && !(descriptor instanceof SyntheticClassOrObjectDescriptor)) {
|
||||
if (!InlineClassesUtilsKt.isInlineClass(descriptor) && !(descriptor instanceof SyntheticClassOrObjectDescriptor)) {
|
||||
// Synthetic classes does not have declarations for secondary constructors
|
||||
for (ClassConstructorDescriptor secondaryConstructor : DescriptorUtilsKt.getSecondaryConstructors(descriptor)) {
|
||||
constructorCodegen.generateSecondaryConstructor(secondaryConstructor, superClassAsmType);
|
||||
@@ -552,7 +552,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
private void generateFunctionsFromAnyForInlineClasses() {
|
||||
if (!descriptor.isInline()) return;
|
||||
if (!InlineClassesUtilsKt.isInlineClass(descriptor)) return;
|
||||
if (!(myClass instanceof KtClassOrObject)) return;
|
||||
new FunctionsFromAnyGeneratorImpl(
|
||||
(KtClassOrObject) myClass, bindingContext, descriptor, classAsmType, context, v, state
|
||||
|
||||
@@ -775,7 +775,8 @@ public abstract class StackValue {
|
||||
) {
|
||||
// Coerce 'this' for the case when it is smart cast.
|
||||
// Do not coerce for other cases due to the 'protected' access issues (JVMS 7, 4.9.2 Structural Constraints).
|
||||
boolean coerceType = descriptor.getKind() == ClassKind.INTERFACE || descriptor.isInline() || (castReceiver && !isSuper);
|
||||
boolean coerceType = descriptor.getKind() == ClassKind.INTERFACE || InlineClassesUtilsKt.isInlineClass(descriptor) ||
|
||||
(castReceiver && !isSuper);
|
||||
return new ThisOuter(codegen, descriptor, isSuper, coerceType);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.codegen.binding.MutableClosure;
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor;
|
||||
import org.jetbrains.kotlin.resolve.InlineClassesUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
|
||||
import org.jetbrains.kotlin.types.SimpleType;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
@@ -48,7 +49,7 @@ public class ConstructorContext extends MethodContext {
|
||||
ClassDescriptor capturedOuterClassDescriptor = closure != null ? closure.getCapturedOuterClassDescriptor() : null;
|
||||
StackValue stackValue;
|
||||
if (capturedOuterClassDescriptor != null) {
|
||||
if (capturedOuterClassDescriptor.isInline()) {
|
||||
if (InlineClassesUtilsKt.isInlineClass(capturedOuterClassDescriptor)) {
|
||||
SimpleType outerClassKotlinType = capturedOuterClassDescriptor.getDefaultType();
|
||||
Type outerClassType = kotlinTypeMapper.mapType(capturedOuterClassDescriptor);
|
||||
stackValue = StackValue.local(1, outerClassType, outerClassKotlinType);
|
||||
|
||||
+2
-1
@@ -20,6 +20,7 @@ import com.intellij.openapi.util.Pair
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.resolve.isInlineClass
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
|
||||
@@ -119,7 +120,7 @@ fun getUnboxedType(boxedType: Type, state: GenerationState): Type {
|
||||
|
||||
fun unboxedTypeOfInlineClass(boxedType: Type, state: GenerationState): Type? {
|
||||
val descriptor =
|
||||
state.jvmBackendClassResolver.resolveToClassDescriptors(boxedType).singleOrNull()?.takeIf { it.isInline } ?: return null
|
||||
state.jvmBackendClassResolver.resolveToClassDescriptors(boxedType).singleOrNull()?.takeIf { it.isInlineClass() } ?: return null
|
||||
return state.mapInlineClass(descriptor)
|
||||
}
|
||||
|
||||
|
||||
@@ -445,7 +445,7 @@ class KotlinTypeMapper @JvmOverloads constructor(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val toInlinedErasedClass = functionParent.isInline &&
|
||||
val toInlinedErasedClass = functionParent.isInlineClass() &&
|
||||
(!isAccessor(functionDescriptor) || isInlineClassConstructorAccessor(functionDescriptor))
|
||||
|
||||
if (toInlinedErasedClass) {
|
||||
|
||||
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.InlineClassDescriptorResolver
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||
import org.jetbrains.kotlin.resolve.isInlineClass
|
||||
import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForParameterTypes
|
||||
import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForReturnType
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
@@ -111,7 +112,7 @@ fun getManglingSuffixBasedOnKotlinSignature(
|
||||
private fun getInfoForMangling(type: KotlinType): InfoForMangling? {
|
||||
val descriptor = type.constructor.declarationDescriptor ?: return null
|
||||
return when (descriptor) {
|
||||
is ClassDescriptor -> InfoForMangling(descriptor.fqNameUnsafe, descriptor.isInline, type.isMarkedNullable)
|
||||
is ClassDescriptor -> InfoForMangling(descriptor.fqNameUnsafe, descriptor.isInlineClass(), type.isMarkedNullable)
|
||||
|
||||
is TypeParameterDescriptor -> {
|
||||
getInfoForMangling(descriptor.representativeUpperBound)
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.isInlineClass
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
|
||||
|
||||
@@ -93,4 +94,4 @@ fun KotlinType.removeExternalProjections(): KotlinType {
|
||||
|
||||
fun isInlineClassConstructorAccessor(descriptor: FunctionDescriptor): Boolean =
|
||||
descriptor is AccessorForConstructorDescriptor &&
|
||||
descriptor.calleeDescriptor.constructedClass.isInline
|
||||
descriptor.calleeDescriptor.constructedClass.isInlineClass()
|
||||
|
||||
Reference in New Issue
Block a user