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!!) }
}
@@ -12534,6 +12534,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/inlineClasses/kt34268.kt");
}
@TestMetadata("kt37998.kt")
public void testKt37998() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/kt37998.kt");
}
@TestMetadata("mangledDefaultParameterFunction.kt")
public void testMangledDefaultParameterFunction() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/mangledDefaultParameterFunction.kt");
@@ -12898,6 +12903,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
public void testInlineClassTypeTopLevelVar() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/inlineClassTypeTopLevelVar.kt");
}
@TestMetadata("kt37986.kt")
public void testKt37986() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/kt37986.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors")
@@ -0,0 +1,25 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND_FIR: JVM_IR
inline class R(val x: Any)
fun useR(r: R) {
if (r.x as String != "OK") throw AssertionError("$r")
}
fun useR0(fn: () -> R) {
useR(fn())
}
fun useR1(r: R, fn: (R) -> R) {
useR(fn(r))
}
fun fnWithDefaultR(r: R = R("OK")) = r
fun box(): String {
useR0(::fnWithDefaultR)
useR1(R("OK"), ::fnWithDefaultR)
return "OK"
}
+13
View File
@@ -0,0 +1,13 @@
inline class Z(val x: Int)
class A {
fun foo() = Z(42)
}
fun test(a: A?) = a?.foo()!!
fun box(): String {
val t = test(A())
if (t.x != 42) throw AssertionError("$t")
return "OK"
}
@@ -13724,6 +13724,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/inlineClasses/kt34268.kt");
}
@TestMetadata("kt37998.kt")
public void testKt37998() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/kt37998.kt");
}
@TestMetadata("mangledDefaultParameterFunction.kt")
public void testMangledDefaultParameterFunction() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/mangledDefaultParameterFunction.kt");
@@ -14088,6 +14093,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
public void testInlineClassTypeTopLevelVar() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/inlineClassTypeTopLevelVar.kt");
}
@TestMetadata("kt37986.kt")
public void testKt37986() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/kt37986.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors")
@@ -13729,6 +13729,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/inlineClasses/kt34268.kt");
}
@TestMetadata("kt37998.kt")
public void testKt37998() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/kt37998.kt");
}
@TestMetadata("mangledDefaultParameterFunction.kt")
public void testMangledDefaultParameterFunction() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/mangledDefaultParameterFunction.kt");
@@ -14088,6 +14093,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
public void testInlineClassTypeTopLevelVar() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/inlineClassTypeTopLevelVar.kt");
}
@TestMetadata("kt37986.kt")
public void testKt37986() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/kt37986.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors")
@@ -12534,6 +12534,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/inlineClasses/kt34268.kt");
}
@TestMetadata("kt37998.kt")
public void testKt37998() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/kt37998.kt");
}
@TestMetadata("mangledDefaultParameterFunction.kt")
public void testMangledDefaultParameterFunction() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/mangledDefaultParameterFunction.kt");
@@ -12898,6 +12903,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
public void testInlineClassTypeTopLevelVar() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/inlineClassTypeTopLevelVar.kt");
}
@TestMetadata("kt37986.kt")
public void testKt37986() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/kt37986.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors")
@@ -10764,6 +10764,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/inlineClasses/kt34268.kt");
}
@TestMetadata("kt37998.kt")
public void testKt37998() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/kt37998.kt");
}
@TestMetadata("mangledDefaultParameterFunction.kt")
public void testMangledDefaultParameterFunction() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/mangledDefaultParameterFunction.kt");
@@ -11113,6 +11118,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
public void testInlineClassTypeTopLevelVar() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/inlineClassTypeTopLevelVar.kt");
}
@TestMetadata("kt37986.kt")
public void testKt37986() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/kt37986.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors")
@@ -10829,6 +10829,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/inlineClasses/kt34268.kt");
}
@TestMetadata("kt37998.kt")
public void testKt37998() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/kt37998.kt");
}
@TestMetadata("mangledDefaultParameterFunction.kt")
public void testMangledDefaultParameterFunction() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/mangledDefaultParameterFunction.kt");
@@ -11178,6 +11183,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
public void testInlineClassTypeTopLevelVar() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/inlineClassTypeTopLevelVar.kt");
}
@TestMetadata("kt37986.kt")
public void testKt37986() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/kt37986.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors")