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;
|
return Unit.INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Type returnType = isNonLocalReturn ? nonLocalReturn.returnType : this.returnType;
|
Type returnType;
|
||||||
KotlinType returnKotlinType = isNonLocalReturn ? null : this.context.getFunctionDescriptor().getReturnType();
|
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();
|
StackValue valueToReturn = returnedExpression != null ? gen(returnedExpression) : StackValue.none();
|
||||||
|
|
||||||
putStackValue(returnedExpression, returnType, returnKotlinType, valueToReturn);
|
putStackValue(returnedExpression, returnType, returnKotlinType, valueToReturn);
|
||||||
@@ -1558,7 +1566,10 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
FunctionDescriptor containingFunction =
|
FunctionDescriptor containingFunction =
|
||||||
BindingContextUtils.getContainingFunctionSkipFunctionLiterals(descriptor, true).getFirst();
|
BindingContextUtils.getContainingFunctionSkipFunctionLiterals(descriptor, true).getFirst();
|
||||||
//FIRST_FUN_LABEL to prevent clashing with existing labels
|
//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 {
|
} else {
|
||||||
//local
|
//local
|
||||||
return null;
|
return null;
|
||||||
@@ -1570,7 +1581,11 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
DeclarationDescriptor elementDescriptor = typeMapper.getBindingContext().get(DECLARATION_TO_DESCRIPTOR, element);
|
DeclarationDescriptor elementDescriptor = typeMapper.getBindingContext().get(DECLARATION_TO_DESCRIPTOR, element);
|
||||||
assert element != null : "Expression should be not null " + expression.getText();
|
assert element != null : "Expression should be not null " + expression.getText();
|
||||||
assert elementDescriptor != null : "Descriptor should be not null: " + element.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;
|
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 static class NonLocalReturnInfo {
|
||||||
|
|
||||||
private final Type returnType;
|
private final JvmKotlinType returnType;
|
||||||
|
|
||||||
private final String labelName;
|
private final String labelName;
|
||||||
|
|
||||||
private NonLocalReturnInfo(@NotNull Type type, @NotNull String name) {
|
private NonLocalReturnInfo(@NotNull JvmKotlinType type, @NotNull String name) {
|
||||||
returnType = type;
|
returnType = type;
|
||||||
labelName = name;
|
labelName = name;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -450,7 +450,7 @@ public abstract class StackValue {
|
|||||||
if (isFromTypeUnboxed && !isToTypeUnboxed) {
|
if (isFromTypeUnboxed && !isToTypeUnboxed) {
|
||||||
boxInlineClass(fromKotlinType, v);
|
boxInlineClass(fromKotlinType, v);
|
||||||
}
|
}
|
||||||
else if (!isFromTypeUnboxed) {
|
else if (!isFromTypeUnboxed && isToTypeUnboxed) {
|
||||||
unboxInlineClass(fromType, fromKotlinType, v);
|
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);
|
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")
|
@TestMetadata("checkBoxingFromReturnTypeForInlineClasses.kt")
|
||||||
public void testCheckBoxingFromReturnTypeForInlineClasses() throws Exception {
|
public void testCheckBoxingFromReturnTypeForInlineClasses() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/checkBoxingFromReturnTypeForInlineClasses.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/checkBoxingFromReturnTypeForInlineClasses.kt");
|
||||||
|
|||||||
+6
@@ -10419,6 +10419,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("checkBoxingFromReturnTypeForInlineClasses.kt")
|
||||||
public void testCheckBoxingFromReturnTypeForInlineClasses() throws Exception {
|
public void testCheckBoxingFromReturnTypeForInlineClasses() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/checkBoxingFromReturnTypeForInlineClasses.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/checkBoxingFromReturnTypeForInlineClasses.kt");
|
||||||
|
|||||||
@@ -1944,6 +1944,12 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("callMemberMethodsInsideInlineClass.kt")
|
||||||
public void testCallMemberMethodsInsideInlineClass() throws Exception {
|
public void testCallMemberMethodsInsideInlineClass() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/inlineClasses/callMemberMethodsInsideInlineClass.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/inlineClasses/callMemberMethodsInsideInlineClass.kt");
|
||||||
|
|||||||
+6
@@ -10419,6 +10419,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("checkBoxingFromReturnTypeForInlineClasses.kt")
|
||||||
public void testCheckBoxingFromReturnTypeForInlineClasses() throws Exception {
|
public void testCheckBoxingFromReturnTypeForInlineClasses() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/checkBoxingFromReturnTypeForInlineClasses.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/checkBoxingFromReturnTypeForInlineClasses.kt");
|
||||||
|
|||||||
+6
@@ -11403,6 +11403,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("checkBoxingFromReturnTypeForInlineClasses.kt")
|
||||||
public void testCheckBoxingFromReturnTypeForInlineClasses() throws Exception {
|
public void testCheckBoxingFromReturnTypeForInlineClasses() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/checkBoxingFromReturnTypeForInlineClasses.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/checkBoxingFromReturnTypeForInlineClasses.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user