Fixes some cast optimization bugs for jsinterop.

Change-Id: Id879f24397ffd4d29d9c4eca3e46e4a0e7fea4fe
Review-Link: https://gwt-review.googlesource.com/#/c/13803/
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JTypeOracle.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JTypeOracle.java
index c83fc04..5b7a3e1 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JTypeOracle.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JTypeOracle.java
@@ -445,17 +445,21 @@
    */
   private boolean canCrossCastLikeJso(JType type) {
     if (legacyJsInterop) {
-      return canBeJavaScriptObject(type) || isNativeJsType(type)
+      return canBeJavaScriptObject(type) || isNativeJsTypeClass(type)
           || isNonNativeJsTypeInterface(type);
     }
-    return canBeJavaScriptObject(type) || type.isJsNative();
+    return canBeJavaScriptObject(type);
+  }
+
+  private boolean isJsInteropCrossCastTarget(JType type) {
+    return type.isJsNative() || type.isJsFunction();
   }
 
   public boolean isNonNativeJsTypeInterface(JType type) {
     return type.isJsType() && type instanceof JInterfaceType && !type.isJsNative();
   }
 
-  private boolean isNativeJsType(JType type) {
+  private boolean isNativeJsTypeClass(JType type) {
     return type.isJsNative() && type instanceof JClassType;
   }
 
@@ -465,6 +469,10 @@
       return true;
     }
 
+    if (isJsInteropCrossCastTarget(toType.getUnderlyingType())) {
+      return false;
+    }
+
     if (!fromType.canBeSubclass() && fromType.getUnderlyingType() instanceof JClassType &&
         fromType.getUnderlyingType() != toType.getUnderlyingType() &&
         !isSuperClass(fromType, toType) && !implementsInterface(fromType, toType)) {
diff --git a/user/test/com/google/gwt/core/client/interop/JsFunctionTest.java b/user/test/com/google/gwt/core/client/interop/JsFunctionTest.java
index 242e0eb..5e55044 100644
--- a/user/test/com/google/gwt/core/client/interop/JsFunctionTest.java
+++ b/user/test/com/google/gwt/core/client/interop/JsFunctionTest.java
@@ -20,6 +20,7 @@
 /**
  * Tests JsFunction functionality.
  */
+@SuppressWarnings("cast")
 public class JsFunctionTest extends GWTTestCase {
 
   @Override
@@ -176,7 +177,7 @@
   }
 
   public void testCast_inJava() {
-    Object object = alwaysTrue() ? new MyJsFunctionInterfaceImpl() : new Object();
+    Object object = new MyJsFunctionInterfaceImpl();
     MyJsFunctionInterface c1 = (MyJsFunctionInterface) object;
     assertNotNull(c1);
     MyJsFunctionInterfaceImpl c2 = (MyJsFunctionInterfaceImpl) c1;
@@ -197,7 +198,7 @@
   }
 
   public void testCast_crossCastJavaInstance() {
-    Object o = alwaysTrue() ? new MyJsFunctionInterfaceImpl() : new Object();
+    Object o = new MyJsFunctionInterfaceImpl();
     assertEquals(11, ((MyOtherJsFunctionInterface) o).bar(10));
     assertSame((MyJsFunctionInterface) o, (MyOtherJsFunctionInterface) o);
   }
@@ -221,7 +222,7 @@
   }
 
   public void testInstanceOf_javaInstance() {
-    Object object = alwaysTrue() ? new MyJsFunctionInterfaceImpl() : new Object();
+    Object object = new MyJsFunctionInterfaceImpl();
     assertTrue(object instanceof MyJsFunctionInterface);
     assertTrue(object instanceof MyJsFunctionInterfaceImpl);
     assertTrue(object instanceof MyJsFunctionIdentityInterface);
@@ -297,8 +298,4 @@
     var a = {};
     return a;
   }-*/;
-
-  private static native boolean alwaysTrue() /*-{
-    return !!$wnd;
-  }-*/;
 }
diff --git a/user/test/com/google/gwt/core/client/interop/JsTypeTest.java b/user/test/com/google/gwt/core/client/interop/JsTypeTest.java
index 2173649..e680184 100644
--- a/user/test/com/google/gwt/core/client/interop/JsTypeTest.java
+++ b/user/test/com/google/gwt/core/client/interop/JsTypeTest.java
@@ -33,6 +33,7 @@
 /**
  * Tests JsType functionality.
  */
+@SuppressWarnings("cast")
 public class JsTypeTest extends GWTTestCase {
 
   @Override
@@ -53,12 +54,12 @@
     FooImpl listNoExport = new FooImpl(); // Does not export .add().
 
     // Use a loose type reference to force polymorphic dispatch.
-    Collection collectionWithExport = alwaysTrue() ? listWithExport : listNoExport;
+    Collection collectionWithExport = listWithExport;
     collectionWithExport.add("Loose");
     assertEquals("LooseListImpl", listWithExport.x);
 
     // Use a loose type reference to force polymorphic dispatch.
-    Collection collectionNoExport = alwaysTrue() ? listNoExport : listWithExport;
+    Collection collectionNoExport = listNoExport;
     collectionNoExport.add("Loose");
     assertEquals("LooseCollectionBaseFooImpl", listNoExport.x);
 
@@ -135,12 +136,7 @@
 
     ConcreteJsTypeJsSubclass subclass = new ConcreteJsTypeJsSubclass();
     assertEquals(100, subclass.publicMethodAlsoExposedAsNonJsMethod());
-    SubclassInterface subclassInterface = alwaysTrue() ? subclass : new SubclassInterface() {
-      @Override
-      public int publicMethodAlsoExposedAsNonJsMethod() {
-        return 0;
-      }
-    };
+    SubclassInterface subclassInterface = subclass;
     assertEquals(100, subclassInterface.publicMethodAlsoExposedAsNonJsMethod());
   }
 
@@ -247,7 +243,7 @@
 
   public void testInstanceOf_implementsJsType() {
     // Foils type tightening.
-    Object object = alwaysTrue() ? new ElementLikeNativeInterfaceImpl() : new Object();
+    Object object = new ElementLikeNativeInterfaceImpl();
 
     assertTrue(object instanceof Object);
     assertFalse(object instanceof HTMLElementAnotherConcreteNativeJsType);
@@ -266,7 +262,7 @@
 
   public void testInstanceOf_implementsJsTypeWithPrototype() {
     // Foils type tightening.
-    Object object = alwaysTrue() ? new MyNativeJsTypeInterfaceImpl() : new Object();
+    Object object = new MyNativeJsTypeInterfaceImpl();
 
     assertTrue(object instanceof Object);
     assertFalse(object instanceof HTMLElementAnotherConcreteNativeJsType);
@@ -285,7 +281,7 @@
 
   public void testInstanceOf_concreteJsType() {
     // Foils type tightening.
-    Object object = alwaysTrue() ? new ConcreteJsType() : new Object();
+    Object object = new ConcreteJsType();
 
     assertTrue(object instanceof Object);
     assertFalse(object instanceof HTMLElementAnotherConcreteNativeJsType);
@@ -304,7 +300,7 @@
 
   public void testInstanceOf_extendsJsTypeWithProto() {
     // Foils type tightening.
-    Object object = alwaysTrue() ? new MyCustomHtmlButtonWithIterator() : new Object();
+    Object object = new MyCustomHtmlButtonWithIterator();
 
     assertTrue(object instanceof Object);
     assertTrue(object instanceof HTMLElementAnotherConcreteNativeJsType);
@@ -376,10 +372,6 @@
     assertEquals(1, callPublicMethodFromEnumerationSubclass(MyEnumWithSubclassGen.C));
   }
 
-  private static native boolean alwaysTrue() /*-{
-    return !!$wnd;
-  }-*/;
-
   private static native int callIntFunction(Object object, String functionName) /*-{
     return object[functionName]();
   }-*/;