KT-37986 Force boxing of inline class returned from function reference

KT-37998 Provide KotlinType for safe call
This commit is contained in:
Dmitry Petrov
2020-04-03 16:31:00 +03:00
parent 5ed845d0b4
commit d5ace43614
11 changed files with 131 additions and 16 deletions
@@ -1033,13 +1033,19 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
);
ClosureCodegen coroutineCodegen = CoroutineCodegenForLambda.create(this, descriptor, declaration, cv);
ClosureContext closureContext = descriptor.isSuspend() ? this.context.intoCoroutineClosure(
CoroutineCodegenUtilKt.getOrCreateJvmSuspendFunctionView(descriptor, state),
descriptor, this, state.getTypeMapper()
) : this.context.intoClosure(descriptor, this, typeMapper);
ClosureCodegen closureCodegen = coroutineCodegen != null ? coroutineCodegen : new ClosureCodegen(
state, declaration, samType, closureContext, functionReferenceCall, strategy, parentCodegen, cv
);
ClosureContext closureContext =
descriptor.isSuspend()
? this.context.intoCoroutineClosure(
CoroutineCodegenUtilKt.getOrCreateJvmSuspendFunctionView(descriptor, state),
descriptor, this, state.getTypeMapper()
)
: this.context.intoClosure(descriptor, this, typeMapper);
ClosureCodegen closureCodegen =
coroutineCodegen != null
? coroutineCodegen
: new ClosureCodegen(
state, declaration, samType, closureContext, functionReferenceCall, strategy, parentCodegen, cv
);
closureCodegen.generate();
@@ -3399,7 +3405,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
StackValue result;
if (!isPrimitive(expressionType(expression.getReceiverExpression()))) {
result = new StackValue.SafeFallback(type, ifnull, newReceiver);
result = new StackValue.SafeFallback(type, kotlinType, ifnull, newReceiver);
} else {
result = newReceiver;
}
@@ -4363,7 +4369,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
return StackValue.none();
}
@Override
public StackValue visitDestructuringDeclaration(@NotNull KtDestructuringDeclaration multiDeclaration, StackValue receiver) {
return initializeDestructuringDeclaration(multiDeclaration, false);
@@ -2308,8 +2308,8 @@ public abstract class StackValue {
@Nullable private final Label ifNull;
public SafeFallback(@NotNull Type type, @Nullable Label ifNull, StackValue receiver) {
super(type, null, false, false, receiver, true);
public SafeFallback(@NotNull Type type, @Nullable KotlinType kotlinType, @Nullable Label ifNull, StackValue receiver) {
super(type, kotlinType, false, false, receiver, true);
this.ifNull = ifNull;
}
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
import org.jetbrains.kotlin.descriptors.impl.LocalVariableAccessorDescriptor
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
@@ -41,10 +42,7 @@ import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaPackageFragment
import org.jetbrains.kotlin.load.kotlin.*
import org.jetbrains.kotlin.load.kotlin.incremental.IncrementalPackageFragmentProvider.IncrementalMultifileClassPackageFragment
import org.jetbrains.kotlin.name.*
import org.jetbrains.kotlin.psi.KtBinaryExpressionWithTypeRHS
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtFunctionLiteral
import org.jetbrains.kotlin.psi.KtLambdaExpression
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getOutermostParenthesizerOrThis
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelector
import org.jetbrains.kotlin.resolve.*
@@ -66,6 +64,7 @@ import org.jetbrains.kotlin.resolve.jvm.annotations.hasJvmDefaultAnnotation
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DescriptorWithContainerSource
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor
import org.jetbrains.kotlin.types.*
@@ -936,7 +935,20 @@ class KotlinTypeMapper @JvmOverloads constructor(
private fun forceBoxedReturnType(descriptor: FunctionDescriptor): Boolean {
if (isBoxMethodForInlineClass(descriptor)) return true
return isJvmPrimitiveOrInlineClass(descriptor.returnType!!) &&
val returnType = descriptor.returnType!!
// Crude hack to determine whether it is an AnonymousFunctionDescriptor created for callable reference.
// Ideally, we should force return type boxing for all anonymous functions returning an inline class value
// (so that the result is boxed properly, since technically it is a covariant override of a corresponding generic 'invoke').
// But, unfortunately, we can't do so right now, because it'd break binary compatibility for lambdas returning 'Result'.
if (descriptor is AnonymousFunctionDescriptor) {
val source = descriptor.source
if (source is KotlinSourceElement && source.psi is KtCallableReferenceExpression && returnType.isInlineClassType()) {
return true
}
}
return isJvmPrimitiveOrInlineClass(returnType) &&
getAllOverriddenDescriptors(descriptor).any { !isJvmPrimitiveOrInlineClass(it.returnType!!) }
}