Fix boxing for non-local and labeled returns with inline classes
This commit is contained in:
@@ -1510,8 +1510,16 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
return Unit.INSTANCE;
|
||||
}
|
||||
|
||||
Type returnType = isNonLocalReturn ? nonLocalReturn.returnType : this.returnType;
|
||||
KotlinType returnKotlinType = isNonLocalReturn ? null : this.context.getFunctionDescriptor().getReturnType();
|
||||
Type returnType;
|
||||
KotlinType returnKotlinType;
|
||||
if (isNonLocalReturn) {
|
||||
returnType = nonLocalReturn.returnType.getType();
|
||||
returnKotlinType = nonLocalReturn.returnType.getKotlinType();
|
||||
}
|
||||
else {
|
||||
returnType = this.returnType;
|
||||
returnKotlinType = this.context.getFunctionDescriptor().getReturnType();
|
||||
}
|
||||
StackValue valueToReturn = returnedExpression != null ? gen(returnedExpression) : StackValue.none();
|
||||
|
||||
putStackValue(returnedExpression, returnType, returnKotlinType, valueToReturn);
|
||||
@@ -1558,7 +1566,10 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
FunctionDescriptor containingFunction =
|
||||
BindingContextUtils.getContainingFunctionSkipFunctionLiterals(descriptor, true).getFirst();
|
||||
//FIRST_FUN_LABEL to prevent clashing with existing labels
|
||||
return new NonLocalReturnInfo(typeMapper.mapReturnType(containingFunction), FIRST_FUN_LABEL);
|
||||
return new NonLocalReturnInfo(
|
||||
new JvmKotlinType(typeMapper.mapReturnType(containingFunction), containingFunction.getReturnType()),
|
||||
FIRST_FUN_LABEL
|
||||
);
|
||||
} else {
|
||||
//local
|
||||
return null;
|
||||
@@ -1570,7 +1581,11 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
DeclarationDescriptor elementDescriptor = typeMapper.getBindingContext().get(DECLARATION_TO_DESCRIPTOR, element);
|
||||
assert element != null : "Expression should be not null " + expression.getText();
|
||||
assert elementDescriptor != null : "Descriptor should be not null: " + element.getText();
|
||||
return new NonLocalReturnInfo(typeMapper.mapReturnType((CallableDescriptor) elementDescriptor), expression.getLabelName());
|
||||
CallableDescriptor function = (CallableDescriptor) elementDescriptor;
|
||||
return new NonLocalReturnInfo(
|
||||
new JvmKotlinType(typeMapper.mapReturnType(function), function.getReturnType()),
|
||||
expression.getLabelName()
|
||||
);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -4574,11 +4589,11 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
|
||||
private static class NonLocalReturnInfo {
|
||||
|
||||
private final Type returnType;
|
||||
private final JvmKotlinType returnType;
|
||||
|
||||
private final String labelName;
|
||||
|
||||
private NonLocalReturnInfo(@NotNull Type type, @NotNull String name) {
|
||||
private NonLocalReturnInfo(@NotNull JvmKotlinType type, @NotNull String name) {
|
||||
returnType = type;
|
||||
labelName = name;
|
||||
}
|
||||
|
||||
@@ -450,7 +450,7 @@ public abstract class StackValue {
|
||||
if (isFromTypeUnboxed && !isToTypeUnboxed) {
|
||||
boxInlineClass(fromKotlinType, v);
|
||||
}
|
||||
else if (!isFromTypeUnboxed) {
|
||||
else if (!isFromTypeUnboxed && isToTypeUnboxed) {
|
||||
unboxInlineClass(fromType, fromKotlinType, v);
|
||||
}
|
||||
}
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
// !LANGUAGE: +InlineClasses
|
||||
|
||||
inline class ULong(val l: Long)
|
||||
|
||||
fun nonLocal(): ULong? {
|
||||
val u1 = ULong(1)
|
||||
|
||||
run {
|
||||
return u1 // box
|
||||
}
|
||||
|
||||
ULong(-1)
|
||||
}
|
||||
|
||||
fun foo(): Boolean = true
|
||||
|
||||
fun labeled(): ULong? {
|
||||
val u = ULong(2)
|
||||
return run {
|
||||
if (foo()) return@run u
|
||||
ULong(-1) // box
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
if (nonLocal()!!.l != 1L) return "fail"
|
||||
if (labeled()!!.l != 2L) return "fail"
|
||||
return "OK"
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
// !LANGUAGE: +InlineClasses
|
||||
|
||||
inline class ULong(val l: Long)
|
||||
|
||||
fun nonLocal(): ULong? {
|
||||
val u = ULong(0)
|
||||
|
||||
run {
|
||||
return u // box
|
||||
}
|
||||
|
||||
TODO()
|
||||
}
|
||||
|
||||
fun foo(): Boolean = true
|
||||
|
||||
fun labeled(): ULong? {
|
||||
val u = ULong(0)
|
||||
return run {
|
||||
if (foo()) return@run u
|
||||
u // box
|
||||
}
|
||||
}
|
||||
|
||||
// 2 INVOKESTATIC ULong\$Erased.box
|
||||
// 0 INVOKEVIRTUAL ULong.unbox
|
||||
|
||||
// 0 valueOf
|
||||
// 0 intValue
|
||||
Generated
+6
@@ -10419,6 +10419,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("checkBoxingForNonLocalAndLabeledReturns.kt")
|
||||
public void testCheckBoxingForNonLocalAndLabeledReturns() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/checkBoxingForNonLocalAndLabeledReturns.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("checkBoxingFromReturnTypeForInlineClasses.kt")
|
||||
public void testCheckBoxingFromReturnTypeForInlineClasses() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/checkBoxingFromReturnTypeForInlineClasses.kt");
|
||||
|
||||
+6
@@ -10419,6 +10419,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("checkBoxingForNonLocalAndLabeledReturns.kt")
|
||||
public void testCheckBoxingForNonLocalAndLabeledReturns() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/checkBoxingForNonLocalAndLabeledReturns.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("checkBoxingFromReturnTypeForInlineClasses.kt")
|
||||
public void testCheckBoxingFromReturnTypeForInlineClasses() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/checkBoxingFromReturnTypeForInlineClasses.kt");
|
||||
|
||||
@@ -1944,6 +1944,12 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("boxingForNonLocalAndLabeledReturnsOfInlineClasses.kt")
|
||||
public void testBoxingForNonLocalAndLabeledReturnsOfInlineClasses() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/inlineClasses/boxingForNonLocalAndLabeledReturnsOfInlineClasses.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("callMemberMethodsInsideInlineClass.kt")
|
||||
public void testCallMemberMethodsInsideInlineClass() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/inlineClasses/callMemberMethodsInsideInlineClass.kt");
|
||||
|
||||
+6
@@ -10419,6 +10419,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("checkBoxingForNonLocalAndLabeledReturns.kt")
|
||||
public void testCheckBoxingForNonLocalAndLabeledReturns() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/checkBoxingForNonLocalAndLabeledReturns.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("checkBoxingFromReturnTypeForInlineClasses.kt")
|
||||
public void testCheckBoxingFromReturnTypeForInlineClasses() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/checkBoxingFromReturnTypeForInlineClasses.kt");
|
||||
|
||||
+6
@@ -11403,6 +11403,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("checkBoxingForNonLocalAndLabeledReturns.kt")
|
||||
public void testCheckBoxingForNonLocalAndLabeledReturns() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/checkBoxingForNonLocalAndLabeledReturns.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("checkBoxingFromReturnTypeForInlineClasses.kt")
|
||||
public void testCheckBoxingFromReturnTypeForInlineClasses() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/checkBoxingFromReturnTypeForInlineClasses.kt");
|
||||
|
||||
Reference in New Issue
Block a user