Don't treat values of type "Unit?" to be always equal to Unit.VALUE
Two changes here: StackValue.Constant does cast iff value is non-null (if null, no cast between classes is really needed, as null can be an instance of anything), and codegen for safe qualified expressions uses correct type for the expression #KT-4265 Fixed
This commit is contained in:
@@ -2622,13 +2622,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
public StackValue visitSafeQualifiedExpression(@NotNull JetSafeQualifiedExpression expression, StackValue unused) {
|
public StackValue visitSafeQualifiedExpression(@NotNull JetSafeQualifiedExpression expression, StackValue unused) {
|
||||||
JetExpression receiver = expression.getReceiverExpression();
|
JetExpression receiver = expression.getReceiverExpression();
|
||||||
JetExpression selector = expression.getSelectorExpression();
|
JetExpression selector = expression.getSelectorExpression();
|
||||||
|
Type type = boxType(expressionType(expression));
|
||||||
Type receiverType = expressionType(receiver);
|
Type receiverType = expressionType(receiver);
|
||||||
|
|
||||||
gen(receiver, receiverType);
|
gen(receiver, receiverType);
|
||||||
|
|
||||||
if (isPrimitive(receiverType)) {
|
if (isPrimitive(receiverType)) {
|
||||||
StackValue propValue = genQualified(StackValue.onStack(receiverType), selector);
|
StackValue propValue = genQualified(StackValue.onStack(receiverType), selector);
|
||||||
Type type = boxType(propValue.type);
|
|
||||||
propValue.put(type, v);
|
propValue.put(type, v);
|
||||||
|
|
||||||
return StackValue.onStack(type);
|
return StackValue.onStack(type);
|
||||||
@@ -2639,7 +2639,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
v.dup();
|
v.dup();
|
||||||
v.ifnull(ifnull);
|
v.ifnull(ifnull);
|
||||||
StackValue propValue = genQualified(StackValue.onStack(receiverType), selector);
|
StackValue propValue = genQualified(StackValue.onStack(receiverType), selector);
|
||||||
Type type = boxType(propValue.type);
|
|
||||||
propValue.put(type, v);
|
propValue.put(type, v);
|
||||||
v.goTo(end);
|
v.goTo(end);
|
||||||
|
|
||||||
|
|||||||
@@ -430,7 +430,10 @@ public abstract class StackValue {
|
|||||||
else {
|
else {
|
||||||
v.aconst(value);
|
v.aconst(value);
|
||||||
}
|
}
|
||||||
coerceTo(type, v);
|
|
||||||
|
if (value != null) {
|
||||||
|
coerceTo(type, v);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
fun <T : Any, R> T.let(f: (T) -> R): R = f(this)
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val o: String? = null
|
||||||
|
|
||||||
|
var state = 0
|
||||||
|
|
||||||
|
o?.let {
|
||||||
|
state = 1
|
||||||
|
} ?: ({ state = 2 })()
|
||||||
|
|
||||||
|
if (state != 2) return "Fail: $state"
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
fun isNull(x: Unit?) = x == null
|
||||||
|
|
||||||
|
fun isNullGeneric<T : Any>(x: T?) = x == null
|
||||||
|
|
||||||
|
fun deepIsNull0(x: Unit?) = isNull(x)
|
||||||
|
fun deepIsNull(x: Unit?) = deepIsNull0(x)
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
if (!isNull(null)) return "Fail 1"
|
||||||
|
|
||||||
|
val x: Unit? = null
|
||||||
|
if (!isNull(x)) return "Fail 2"
|
||||||
|
|
||||||
|
val y = x
|
||||||
|
if (!isNullGeneric(y)) return "Fail 3"
|
||||||
|
|
||||||
|
if (!deepIsNull((null : Unit?) ?: null)) return "Fail 4"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -4764,6 +4764,16 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/codegen/box/unit"), Pattern.compile("^(.+)\\.kt$"), true);
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/codegen/box/unit"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt4265.kt")
|
||||||
|
public void testKt4265() throws Exception {
|
||||||
|
doTest("compiler/testData/codegen/box/unit/kt4265.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("nullableUnit.kt")
|
||||||
|
public void testNullableUnit() throws Exception {
|
||||||
|
doTest("compiler/testData/codegen/box/unit/nullableUnit.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("unitClassObject.kt")
|
@TestMetadata("unitClassObject.kt")
|
||||||
public void testUnitClassObject() throws Exception {
|
public void testUnitClassObject() throws Exception {
|
||||||
doTest("compiler/testData/codegen/box/unit/unitClassObject.kt");
|
doTest("compiler/testData/codegen/box/unit/unitClassObject.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user