Implement UncheckedCast annotation.
Change-Id: I7d3ac459a924082480d687353c4def33267977a4
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JTransformer.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JTransformer.java
index 6478f28..0614d99 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JTransformer.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JTransformer.java
@@ -220,7 +220,8 @@
}
public T missing(JNode x) {
- throw new InternalCompilerException("Missing transform for " + x);
+ throw new InternalCompilerException(
+ "Missing transform for " + x + " (" + x.getClass().getSimpleName() + ")");
}
public T transformNullLiteral(JNullLiteral x) {
@@ -339,6 +340,10 @@
return transformExpression(x);
}
+ public T transformUnsafeTypeCoercion(JUnsafeTypeCoercion x) {
+ return transformExpression(x);
+ }
+
public T transformWhileStatement(JWhileStatement x) {
return transformStatement(x);
}
@@ -1023,6 +1028,12 @@
return false;
}
+ public final boolean visit(JUnsafeTypeCoercion x, Context ctx) {
+ assert result == null;
+ result = transformUnsafeTypeCoercion(x);
+ return false;
+ }
+
public final boolean visit(JValueLiteral x, Context ctx) {
assert result == null;
result = transformValueLiteral(x);
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JUnsafeTypeCoercion.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JUnsafeTypeCoercion.java
new file mode 100644
index 0000000..6832647
--- /dev/null
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JUnsafeTypeCoercion.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.dev.jjs.ast;
+
+import com.google.gwt.dev.jjs.SourceInfo;
+
+/**
+ * An unsafe type coercion (mostly resulting form the UncheckedCast annotation).
+ */
+public class JUnsafeTypeCoercion extends JExpression {
+
+ private JType coercionType;
+ private JExpression expression;
+
+ public JUnsafeTypeCoercion(SourceInfo info, JType coercionType, JExpression expression) {
+ super(info);
+ this.coercionType = coercionType;
+ this.expression = expression;
+ }
+
+ public JType getCoercionType() {
+ return coercionType;
+ }
+
+ public JExpression getExpression() {
+ return expression;
+ }
+
+ @Override
+ public JType getType() {
+ if (!expression.getType().canBeNull() && !coercionType.isNullType()) {
+ // Strengthen type to non null unless it has been determined that the type is not instantiable
+ // (and that is reflected by replacing the coercion type by the null type).
+ return coercionType.strengthenToNonNull();
+ }
+ return coercionType;
+ }
+
+ @Override
+ public boolean hasSideEffects() {
+ return expression.hasSideEffects();
+ }
+
+ /**
+ * Resolve an external reference during AST stitching.
+ */
+ public void resolve(JType coercionType) {
+ assert coercionType.replaces(this.coercionType);
+ this.coercionType = coercionType;
+ }
+
+ @Override
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
+ expression = visitor.accept(expression);
+ }
+ visitor.endVisit(this, ctx);
+ }
+
+}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JVisitor.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JVisitor.java
index c83d046..a74785c 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JVisitor.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JVisitor.java
@@ -477,6 +477,10 @@
endVisit((JExpression) x, ctx);
}
+ public void endVisit(JUnsafeTypeCoercion x, Context ctx) {
+ endVisit((JExpression) x, ctx);
+ }
+
public void endVisit(JValueLiteral x, Context ctx) {
endVisit((JLiteral) x, ctx);
}
@@ -793,6 +797,10 @@
return visit((JExpression) x, ctx);
}
+ public boolean visit(JUnsafeTypeCoercion x, Context ctx) {
+ return visit((JExpression) x, ctx);
+ }
+
public boolean visit(JValueLiteral x, Context ctx) {
return visit((JLiteral) x, ctx);
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/CloneExpressionVisitor.java b/dev/core/src/com/google/gwt/dev/jjs/impl/CloneExpressionVisitor.java
index a453256..9dfd509 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/CloneExpressionVisitor.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/CloneExpressionVisitor.java
@@ -47,6 +47,7 @@
import com.google.gwt.dev.jjs.ast.JRunAsync;
import com.google.gwt.dev.jjs.ast.JStringLiteral;
import com.google.gwt.dev.jjs.ast.JThisRef;
+import com.google.gwt.dev.jjs.ast.JUnsafeTypeCoercion;
import com.google.gwt.dev.jjs.ast.JVisitor;
import com.google.gwt.dev.jjs.ast.js.JMultiExpression;
import com.google.gwt.dev.jjs.ast.js.JsniFieldRef;
@@ -299,4 +300,11 @@
expression = new JThisRef(x.getSourceInfo(), x.getClassType());
return false;
}
+
+ @Override
+ public boolean visit(JUnsafeTypeCoercion x, Context ctx) {
+ expression = new JUnsafeTypeCoercion(
+ x.getSourceInfo(), x.getCoercionType(), cloneExpression(x.getExpression()));
+ return false;
+ }
}
\ No newline at end of file
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/ControlFlowAnalyzer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/ControlFlowAnalyzer.java
index 1299734..cbc44f4 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/ControlFlowAnalyzer.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/ControlFlowAnalyzer.java
@@ -46,6 +46,7 @@
import com.google.gwt.dev.jjs.ast.JRunAsync;
import com.google.gwt.dev.jjs.ast.JStringLiteral;
import com.google.gwt.dev.jjs.ast.JType;
+import com.google.gwt.dev.jjs.ast.JUnsafeTypeCoercion;
import com.google.gwt.dev.jjs.ast.JVariable;
import com.google.gwt.dev.jjs.ast.JVariableRef;
import com.google.gwt.dev.jjs.ast.JVisitor;
@@ -198,30 +199,7 @@
@Override
public boolean visit(JCastOperation x, Context ctx) {
- // Rescue any JavaScriptObject type that is the target of a cast.
- JType targetType = x.getCastType();
-
- if (!canBeInstantiatedInJavaScript(targetType)) {
- return true;
- }
- rescue((JReferenceType) targetType, true);
- JType exprType = x.getExpr().getType();
- if (program.typeOracle.isSingleJsoImpl(targetType)) {
- /*
- * It's a JSO interface, check if the source expr can be a live JSO:
- * 1) source is java.lang.Object (JSO could have been assigned to it)
- * 2) source is JSO
- * 3) source is SingleJSO interface whose implementor is live
- */
- if (program.getTypeJavaLangObject() == exprType
- || program.typeOracle.canBeJavaScriptObject(exprType)) {
- // source is JSO or SingleJso interface whose implementor is live
- JClassType jsoImplementor =
- program.typeOracle.getSingleJsoImpl((JReferenceType) targetType);
- rescue(jsoImplementor, true);
- }
- }
-
+ rescueByTypeCoercion(x.getCastType(), x.getExpr().getType());
return true;
}
@@ -509,6 +487,35 @@
return true;
}
+ @Override
+ public boolean visit(JUnsafeTypeCoercion x, Context ctx) {
+ rescueByTypeCoercion(x.getCoercionType(), x.getExpression().getType());
+ return true;
+ }
+
+ private void rescueByTypeCoercion(JType targetType, JType expressionType) {
+ // Rescue any JavaScriptObject type that is the target of a cast.
+ if (!canBeInstantiatedInJavaScript(targetType)) {
+ return;
+ }
+ rescue((JReferenceType) targetType, true);
+ if (program.typeOracle.isSingleJsoImpl(targetType)) {
+ /*
+ * It's a JSO interface, check if the source expr can be a live JSO:
+ * 1) source is java.lang.Object (JSO could have been assigned to it)
+ * 2) source is JSO
+ * 3) source is SingleJSO interface whose implementor is live
+ */
+ if (program.getTypeJavaLangObject() == expressionType
+ || program.typeOracle.canBeJavaScriptObject(expressionType)) {
+ // source is JSO or SingleJso interface whose implementor is live
+ JClassType jsoImplementor =
+ program.typeOracle.getSingleJsoImpl((JReferenceType) targetType);
+ rescue(jsoImplementor, true);
+ }
+ }
+ }
+
private boolean canBeInstantiatedInJavaScript(JType type) {
// Technically, JsType/JsFunction are also instantiatable in JavaScript but we don't track
// them using similar to JSO as if we do that then after cast normalization, they got pruned.
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
index f78edbb..f96c3d8 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
@@ -92,6 +92,7 @@
import com.google.gwt.dev.jjs.ast.JTryStatement;
import com.google.gwt.dev.jjs.ast.JType;
import com.google.gwt.dev.jjs.ast.JUnaryOperator;
+import com.google.gwt.dev.jjs.ast.JUnsafeTypeCoercion;
import com.google.gwt.dev.jjs.ast.JVariable;
import com.google.gwt.dev.jjs.ast.JVisitor;
import com.google.gwt.dev.jjs.ast.JWhileStatement;
@@ -1153,6 +1154,11 @@
}
@Override
+ public JsNode transformUnsafeTypeCoercion(JUnsafeTypeCoercion unsafeTypeCoercion) {
+ return transform(unsafeTypeCoercion.getExpression());
+ }
+
+ @Override
public JsNode transformWhileStatement(JWhileStatement whileStatement) {
SourceInfo info = whileStatement.getSourceInfo();
JsWhile stmt = new JsWhile(info);
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java
index 15d44e7..5930ad1 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java
@@ -91,6 +91,7 @@
import com.google.gwt.dev.jjs.ast.JTryStatement;
import com.google.gwt.dev.jjs.ast.JType;
import com.google.gwt.dev.jjs.ast.JUnaryOperator;
+import com.google.gwt.dev.jjs.ast.JUnsafeTypeCoercion;
import com.google.gwt.dev.jjs.ast.JVariable;
import com.google.gwt.dev.jjs.ast.JWhileStatement;
import com.google.gwt.dev.jjs.ast.js.JMultiExpression;
@@ -1541,24 +1542,26 @@
}
}
- JMethodCall call = new JMethodCall(info, receiver, method);
+ JMethodCall methodCall = new JMethodCall(info, receiver, method);
// On a super ref, don't allow polymorphic dispatch. Oddly enough,
// QualifiedSuperReference not derived from SuperReference!
boolean isSuperRef =
x.receiver instanceof SuperReference || x.receiver instanceof QualifiedSuperReference;
if (isSuperRef) {
- call.setStaticDispatchOnly();
+ methodCall.setStaticDispatchOnly();
}
- // The arguments come first...
- call.addArgs(arguments);
+ // The arguments come first.
+ methodCall.addArgs(arguments);
if (x.valueCast != null) {
- JType castType = typeMap.get(x.valueCast);
- push(maybeCast(castType, call));
+ JType targetType = typeMap.get(x.valueCast);
+ push(isUncheckedGenericMethodCall(x)
+ ? maybeInsertUnsafeTypeCoersion(targetType, methodCall)
+ : maybeCast(targetType, methodCall));
} else {
- push(call);
+ push(methodCall);
}
} catch (Throwable e) {
throw translateException(x, e);
@@ -1568,7 +1571,6 @@
@Override
public void endVisit(MethodDeclaration x, ClassScope scope) {
try {
-
if (x.isNative()) {
processNativeMethod(x);
} else {
@@ -3068,12 +3070,20 @@
private JExpression maybeCast(JType expected, JExpression expression) {
if (expected != expression.getType()) {
- // Must be a generic; insert a cast operation.
- JReferenceType toType = (JReferenceType) expected;
- return new JCastOperation(expression.getSourceInfo(), toType, expression);
- } else {
- return expression;
+ // Must be a generic cast; insert a cast operation.
+ return new JCastOperation(expression.getSourceInfo(), expected, expression);
}
+
+ return expression;
+ }
+
+ private JExpression maybeInsertUnsafeTypeCoersion(JType expected, JExpression expression) {
+ if (expected != expression.getType()) {
+ // A generic call marked as @UncheckedCast.
+ return new JUnsafeTypeCoercion(expression.getSourceInfo(), expected, expression);
+ }
+
+ return expression;
}
private JNode pop() {
@@ -4152,7 +4162,15 @@
x.setSuppressedWarnings(JdtUtil.getSuppressedWarnings(annotations));
}
- private void maybeSetInliningMode(AbstractMethodDeclaration x, JMethod method) {
+ private static boolean isUncheckedGenericMethodCall(MessageSend messageSend) {
+ if (messageSend.binding.genericMethod() != null) {
+ return JdtUtil.getAnnotation(messageSend.binding.genericMethod(),
+ "javaemul.internal.annotations.UncheckedCast") != null;
+ }
+ return false;
+ }
+
+ private static void maybeSetInliningMode(AbstractMethodDeclaration x, JMethod method) {
MethodBinding bind = x.binding;
if (JdtUtil.getAnnotation(bind, "javaemul.internal.annotations.DoNotInline") != null) {
method.setInliningMode(InliningMode.DO_NOT_INLINE);
@@ -4161,8 +4179,7 @@
}
}
- private void maybeSetHasNoSideEffects(AbstractMethodDeclaration x,
- JMethod method) {
+ private static void maybeSetHasNoSideEffects(AbstractMethodDeclaration x, JMethod method) {
if (JdtUtil.getAnnotation(x.binding,
"javaemul.internal.annotations.HasNoSideEffects") != null) {
method.setHasSideEffects(false);
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/UnifyAst.java b/dev/core/src/com/google/gwt/dev/jjs/impl/UnifyAst.java
index ae9af27..feaf680 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/UnifyAst.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/UnifyAst.java
@@ -67,6 +67,7 @@
import com.google.gwt.dev.jjs.ast.JThisRef;
import com.google.gwt.dev.jjs.ast.JTryStatement;
import com.google.gwt.dev.jjs.ast.JType;
+import com.google.gwt.dev.jjs.ast.JUnsafeTypeCoercion;
import com.google.gwt.dev.jjs.ast.JVariable;
import com.google.gwt.dev.jjs.ast.RuntimeConstants;
import com.google.gwt.dev.jjs.ast.js.JDebuggerStatement;
@@ -361,6 +362,11 @@
}
@Override
+ public void endVisit(JUnsafeTypeCoercion x, Context ctx) {
+ x.resolve(translate(x.getCoercionType()));
+ }
+
+ @Override
public void endVisit(JVariable x, Context ctx) {
x.setType(translate(x.getType()));
}
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/annotations/UncheckedCast.java b/user/super/com/google/gwt/emul/javaemul/internal/annotations/UncheckedCast.java
new file mode 100644
index 0000000..82c5597
--- /dev/null
+++ b/user/super/com/google/gwt/emul/javaemul/internal/annotations/UncheckedCast.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package javaemul.internal.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/**
+ * An annotation to mark a method as unchecked to prevent the compiler from inserting casts on
+ * returns call sites due to erasure.
+ */
+@Target(ElementType.METHOD)
+@CompilerHint
+public @interface UncheckedCast {
+}
diff --git a/user/test/com/google/gwt/dev/jjs/CompilerSuite.java b/user/test/com/google/gwt/dev/jjs/CompilerSuite.java
index 3c5fc29..55f0681 100644
--- a/user/test/com/google/gwt/dev/jjs/CompilerSuite.java
+++ b/user/test/com/google/gwt/dev/jjs/CompilerSuite.java
@@ -39,6 +39,7 @@
import com.google.gwt.dev.jjs.test.NativeLongTest;
import com.google.gwt.dev.jjs.test.ObjectIdentityTest;
import com.google.gwt.dev.jjs.test.SingleJsoImplTest;
+import com.google.gwt.dev.jjs.test.UncheckedCastTest;
import com.google.gwt.dev.jjs.test.VarargsTest;
import com.google.gwt.dev.jjs.test.singlejso.TypeHierarchyTest;
import com.google.gwt.junit.tools.GWTTestSuite;
@@ -81,6 +82,7 @@
suite.addTestSuite(ObjectIdentityTest.class);
suite.addTestSuite(SingleJsoImplTest.class);
suite.addTestSuite(TypeHierarchyTest.class);
+ suite.addTestSuite(UncheckedCastTest.class);
suite.addTestSuite(VarargsTest.class);
// $JUnit-END$
diff --git a/user/test/com/google/gwt/dev/jjs/OptimizedOnlyCompilerSuite.java b/user/test/com/google/gwt/dev/jjs/OptimizedOnlyCompilerSuite.java
index b95797c..bb5c85a 100644
--- a/user/test/com/google/gwt/dev/jjs/OptimizedOnlyCompilerSuite.java
+++ b/user/test/com/google/gwt/dev/jjs/OptimizedOnlyCompilerSuite.java
@@ -21,6 +21,7 @@
import com.google.gwt.dev.jjs.optimized.JsOverlayMethodOptimizationTest;
import com.google.gwt.dev.jjs.optimized.SpecializationTest;
import com.google.gwt.dev.jjs.optimized.StringOptimizationTest;
+import com.google.gwt.dev.jjs.optimized.UncheckedCastOptimizationTest;
import com.google.gwt.dev.jjs.test.HasNoSideEffectsTest;
import com.google.gwt.dev.jjs.test.RunAsyncContentTest;
import com.google.gwt.junit.tools.GWTTestSuite;
@@ -43,6 +44,7 @@
suite.addTestSuite(JsOverlayMethodOptimizationTest.class);
suite.addTestSuite(SpecializationTest.class);
suite.addTestSuite(HasNoSideEffectsTest.class);
+ suite.addTestSuite(UncheckedCastOptimizationTest.class);
// RunAsyncContentTest relies in string interning for its assertions which is now always off
// in non optimzied compiles.
suite.addTestSuite(RunAsyncContentTest.class);
diff --git a/user/test/com/google/gwt/dev/jjs/optimized/UncheckedCastOptimizationTest.java b/user/test/com/google/gwt/dev/jjs/optimized/UncheckedCastOptimizationTest.java
new file mode 100644
index 0000000..021beed
--- /dev/null
+++ b/user/test/com/google/gwt/dev/jjs/optimized/UncheckedCastOptimizationTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.dev.jjs.optimized;
+
+import com.google.gwt.junit.DoNotRunWith;
+import com.google.gwt.junit.Platform;
+
+import javaemul.internal.annotations.UncheckedCast;
+
+import jsinterop.annotations.JsPackage;
+import jsinterop.annotations.JsType;
+
+/**
+ * Tests that unchecked casts allow other optimizations to happen.
+ */
+@DoNotRunWith(Platform.Devel)
+public class UncheckedCastOptimizationTest extends OptimizationTestBase {
+
+ @JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "Array")
+ private static class JsArray {
+ public int length;
+ }
+
+ @JsType(isNative = true)
+ private interface NativeObject {
+ }
+
+ @UncheckedCast
+ public static <T> T uncheckedCast(Object o) {
+ return (T) o;
+ }
+ public static int unckeckedCastOperation() {
+ JsArray array = uncheckedCast(new NativeObject[] {null, null});
+ return array.length;
+ }
+
+ private static native String getGeneratedUncheckedCastFunctionDefinition() /*-{
+ return function() {
+ @com.google.gwt.dev.jjs.optimized.UncheckedCastOptimizationTest::unckeckedCastOperation()();
+ }.toString();
+ }-*/;
+
+ public void testUncheckedCastAllowsOptimizaionsC() throws Exception {
+ String functionDef = getGeneratedUncheckedCastFunctionDefinition();
+ assertFunctionMatches(functionDef, "var<obf>;<obf>=[null,null]");
+ }
+}
diff --git a/user/test/com/google/gwt/dev/jjs/test/UncheckedCastTest.java b/user/test/com/google/gwt/dev/jjs/test/UncheckedCastTest.java
new file mode 100644
index 0000000..bfe873b
--- /dev/null
+++ b/user/test/com/google/gwt/dev/jjs/test/UncheckedCastTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.dev.jjs.test;
+
+import com.google.gwt.junit.DoNotRunWith;
+import com.google.gwt.junit.Platform;
+import com.google.gwt.junit.client.GWTTestCase;
+
+import javaemul.internal.annotations.UncheckedCast;
+
+/**
+ * Tests for {@link UncheckedCast}.
+ */
+@DoNotRunWith(Platform.Devel)
+public class UncheckedCastTest extends GWTTestCase {
+
+ @Override
+ public String getModuleName() {
+ return "com.google.gwt.dev.jjs.CompilerSuite";
+ }
+
+ @UncheckedCast
+ private static <T> T uncheckedCast(Object object) {
+ return (T) object;
+ }
+
+ public void testUnsafeCast() {
+ Integer boxedInt = uncheckedCast(new Object());
+ assertNotNull(boxedInt);
+ Double d = uncheckedCast(new Object());
+ assertNotNull(d);
+ boolean unboxedBoolean = uncheckedCast(new Double(12));
+ assertTrue(unboxedBoolean);
+ }
+}