[JS Legacy] Fix Unit materialization in overridden methods
^KT-51878 Fixed
This commit is contained in:
@@ -895,6 +895,24 @@ public abstract class KotlinBuiltIns {
|
||||
return isNotNullConstructedFromGivenClass(type, FqNames.unit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if the <code>descriptor</code>'s return type is not <code>Unit</code>,
|
||||
* or it overrides a function with a non-<code>Unit</code> return type.
|
||||
*/
|
||||
public static boolean mayReturnNonUnitValue(@NotNull FunctionDescriptor descriptor) {
|
||||
KotlinType functionReturnType = descriptor.getReturnType();
|
||||
assert functionReturnType != null : "Function return typed type must be resolved.";
|
||||
boolean mayReturnNonUnitValue = !isUnit(functionReturnType);
|
||||
for (FunctionDescriptor overriddenDescriptor : descriptor.getOriginal().getOverriddenDescriptors()) {
|
||||
if (mayReturnNonUnitValue)
|
||||
break;
|
||||
KotlinType overriddenFunctionReturnType = overriddenDescriptor.getReturnType();
|
||||
assert overriddenFunctionReturnType != null : "Function return typed type must be resolved.";
|
||||
mayReturnNonUnitValue = !isUnit(overriddenFunctionReturnType);
|
||||
}
|
||||
return mayReturnNonUnitValue;
|
||||
}
|
||||
|
||||
public static boolean isUnitOrNullableUnit(@NotNull KotlinType type) {
|
||||
return isConstructedFromGivenClass(type, FqNames.unit);
|
||||
}
|
||||
|
||||
@@ -750,6 +750,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
||||
runTest("js/js.translator/testData/box/coercion/unitIsAs.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("unitMaterializationInOverriddenMethod.kt")
|
||||
public void testUnitMaterializationInOverriddenMethod() throws Exception {
|
||||
runTest("js/js.translator/testData/box/coercion/unitMaterializationInOverriddenMethod.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("unitNullCheck.kt")
|
||||
public void testUnitNullCheck() throws Exception {
|
||||
|
||||
+6
@@ -750,6 +750,12 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
|
||||
runTest("js/js.translator/testData/box/coercion/unitIsAs.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("unitMaterializationInOverriddenMethod.kt")
|
||||
public void testUnitMaterializationInOverriddenMethod() throws Exception {
|
||||
runTest("js/js.translator/testData/box/coercion/unitMaterializationInOverriddenMethod.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("unitNullCheck.kt")
|
||||
public void testUnitNullCheck() throws Exception {
|
||||
|
||||
+6
-1
@@ -160,7 +160,12 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
|
||||
|
||||
JsReturn jsReturn;
|
||||
if (returned == null) {
|
||||
jsReturn = new JsReturn(null);
|
||||
JsExpression returnExpression = null;
|
||||
if (returnTarget != null && KotlinBuiltIns.mayReturnNonUnitValue(returnTarget)) {
|
||||
ClassDescriptor unit = context.getCurrentModule().getBuiltIns().getUnit();
|
||||
returnExpression = ReferenceTranslator.translateAsValueReference(unit, context);
|
||||
}
|
||||
jsReturn = new JsReturn(returnExpression);
|
||||
}
|
||||
else {
|
||||
JsExpression jsReturnExpression = translateAsExpression(returned, context);
|
||||
|
||||
+1
-3
@@ -161,9 +161,7 @@ public final class FunctionBodyTranslator extends AbstractTranslator {
|
||||
}
|
||||
|
||||
private boolean mustAddReturnToGeneratedFunctionBody() {
|
||||
KotlinType functionReturnType = descriptor.getReturnType();
|
||||
assert functionReturnType != null : "Function return typed type must be resolved.";
|
||||
return (!declaration.hasBlockBody()) && !(KotlinBuiltIns.isUnit(functionReturnType) && !descriptor.isSuspend());
|
||||
return !declaration.hasBlockBody() && (KotlinBuiltIns.mayReturnNonUnitValue(descriptor) || descriptor.isSuspend());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1279
|
||||
// KT-51878
|
||||
|
||||
open class A {
|
||||
open fun foo(): Any = "string"
|
||||
}
|
||||
|
||||
var condition = true
|
||||
|
||||
class B: A() {
|
||||
override fun foo(): Unit {
|
||||
if (condition) {
|
||||
return
|
||||
}
|
||||
condition = !condition
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val b: A = B()
|
||||
if (b.foo() !is Unit) return "fail1"
|
||||
if (b.foo() !is Unit) return "fail2"
|
||||
return "OK"
|
||||
}
|
||||
Reference in New Issue
Block a user