diff --git a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index b3b00f2016a..241b8abb1f7 100644 --- a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -1202,6 +1202,14 @@ public class ExpressionCodegen extends JetVisitor { private StackValue generateEquals(JetExpression left, JetExpression right, IElementType opToken) { Type leftType = expressionType(left); Type rightType = expressionType(right); + if(leftType == JetTypeMapper.TYPE_NOTHING) { + return genCmpWithNull(right, rightType, opToken); + } + + if(rightType == JetTypeMapper.TYPE_NOTHING) { + return genCmpWithNull(left, leftType, opToken); + } + if(JetTypeMapper.isPrimitive(leftType) != JetTypeMapper.isPrimitive(rightType)) { gen(left, leftType); v.valueOf(leftType); @@ -1217,6 +1225,28 @@ public class ExpressionCodegen extends JetVisitor { return generateEqualsForExpressionsOnStack(opToken, leftType, rightType); } + private StackValue genCmpWithNull(JetExpression exp, Type expType, IElementType opToken) { + gen(exp, typeMapper.boxType(expType)); + Label fail = new Label(), end = new Label(); + if(JetTokens.EQEQ == opToken || JetTokens.EQEQEQ == opToken) { + v.ifnonnull(fail); + v.iconst(1); + v.goTo(end); + v.mark(fail); + v.iconst(0); + v.mark(end); + } + else { + v.ifnull(fail); + v.iconst(1); + v.goTo(end); + v.mark(fail); + v.iconst(0); + v.mark(end); + } + return StackValue.onStack(Type.BOOLEAN_TYPE); + } + private StackValue generateEqualsForExpressionsOnStack(IElementType opToken, Type leftType, Type rightType) { if (isNumberPrimitive(leftType) && leftType == rightType) { return compareExpressionsOnStack(opToken, leftType); diff --git a/idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java index df0860a370c..82799029ab6 100644 --- a/idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -25,6 +25,7 @@ public class JetTypeMapper { public static final Type TYPE_TYPEINFO = Type.getType(TypeInfo.class); public static final Type TYPE_JET_OBJECT = Type.getType(JetObject.class); public static final Type TYPE_CLASS = Type.getType(Class.class); + public static final Type TYPE_NOTHING = Type.getObjectType("jet/Nothing"); private final JetStandardLibrary standardLibrary; private final BindingContext bindingContext; @@ -289,6 +290,9 @@ public class JetTypeMapper { } public Type mapType(@NotNull final JetType jetType, OwnerKind kind) { + if (jetType.equals(JetStandardClasses.getNothingType()) || jetType.equals(JetStandardClasses.getNullableNothingType())) { + return TYPE_NOTHING; + } if (jetType.equals(standardLibrary.getIntType())) { return Type.INT_TYPE; } diff --git a/idea/src/org/jetbrains/jet/codegen/StackValue.java b/idea/src/org/jetbrains/jet/codegen/StackValue.java index 800bb5be3b7..9a7269853a0 100644 --- a/idea/src/org/jetbrains/jet/codegen/StackValue.java +++ b/idea/src/org/jetbrains/jet/codegen/StackValue.java @@ -282,7 +282,7 @@ public abstract class StackValue { @Override public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) { if (value instanceof Boolean) { - boolean boolValue = ((Boolean) value).booleanValue(); + boolean boolValue = (Boolean) value; if (boolValue ^ jumpIfFalse) { v.goTo(label); } diff --git a/idea/tests/org/jetbrains/jet/codegen/ControlStructuresTest.java b/idea/tests/org/jetbrains/jet/codegen/ControlStructuresTest.java index 8dff8181502..50c8649e920 100644 --- a/idea/tests/org/jetbrains/jet/codegen/ControlStructuresTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/ControlStructuresTest.java @@ -148,4 +148,14 @@ public class ControlStructuresTest extends CodegenTestCase { public void testKt237() throws Exception { blackBoxFile("regressions/kt237.jet"); } + + public void testCompareToNull() throws Exception { + loadText("fun foo(a: String?, b: String?): Boolean = a == null && b !== null"); + String text = generateToText(); + assertTrue(!text.contains("java/lang/Object.equals")); + System.out.println(text); + final Method main = generateFunction(); + assertEquals(true, main.invoke(null, null, "lala")); + assertEquals(false, main.invoke(null, null, null)); + } }