Skip to content

Commit

Permalink
Value classes: treat @JvmInline value classes as inline classes
Browse files Browse the repository at this point in the history
Report error on value classes without @JvmInline annotation.
Do not check for @JvmInline annotation in value classes since
it breaks reflection.
  • Loading branch information
ilmirus committed Nov 27, 2020
1 parent 6c68660 commit 92f1681
Show file tree
Hide file tree
Showing 100 changed files with 2,668 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ public static int getMethodAsmFlags(
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) {
Expand Down Expand Up @@ -559,7 +559,7 @@ private static CallableMethod getSpecializedToStringCallableMethodOrNull(
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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1190,7 +1190,7 @@ public void pushClosureOnStack(
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++);
}
Expand Down Expand Up @@ -4830,7 +4830,7 @@ public StackValue generateConstructorCall(@NotNull ResolvedCall<?> resolvedCall,
ReceiverParameterDescriptor dispatchReceiver = constructor.getDispatchReceiverParameter();
ClassDescriptor containingDeclaration = constructor.getContainingDeclaration();

if (!containingDeclaration.isInline()) {
if (!InlineClassesUtilsKt.isInlineClass(containingDeclaration)) {
v.anew(objectType);
v.dup();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1589,7 +1589,7 @@ public void generateBody(

// 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) {
Expand All @@ -1609,7 +1609,7 @@ public void generateBody(
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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ protected void generateToStringMethod(
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;
}
Expand Down Expand Up @@ -161,7 +161,7 @@ protected void generateHashCodeMethod(
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;
}
Expand Down Expand Up @@ -233,7 +233,7 @@ protected void generateEqualsMethod(
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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ protected void generateDefaultImplsIfNeeded() {
@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();
Expand All @@ -269,7 +269,7 @@ protected void generateErasedInlineClassIfNeeded() {
@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);
Expand Down Expand Up @@ -450,7 +450,7 @@ protected void generateConstructors() {
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);
Expand Down Expand Up @@ -552,7 +552,7 @@ private void generateFunctionsForDataClasses() {
}

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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -775,7 +775,8 @@ public static StackValue thisOrOuter(
) {
// 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);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
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;
Expand All @@ -48,7 +49,7 @@ public StackValue getOuterExpression(StackValue prefix, boolean ignoreNoOuter) {
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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,7 @@ class KotlinTypeMapper @JvmOverloads constructor(
}
}
} else {
val toInlinedErasedClass = functionParent.isInline &&
val toInlinedErasedClass = functionParent.isInlineClass() &&
(!isAccessor(functionDescriptor) || isInlineClassConstructorAccessor(functionDescriptor))

if (toInlinedErasedClass) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -93,4 +94,4 @@ fun KotlinType.removeExternalProjections(): KotlinType {

fun isInlineClassConstructorAccessor(descriptor: FunctionDescriptor): Boolean =
descriptor is AccessorForConstructorDescriptor &&
descriptor.calleeDescriptor.constructedClass.isInline
descriptor.calleeDescriptor.constructedClass.isInlineClass()

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 92f1681

Please sign in to comment.