diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/CastTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/CastTest.java index 74cab0ed722..84a795ec856 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/semantics/CastTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/CastTest.java @@ -32,6 +32,10 @@ public final class CastTest extends AbstractExpressionTest { checkFooBoxIsOk(); } + public void testCastToGenericType() throws Exception { + checkFooBoxIsOk(); + } + public void testSmartCastInExtensionFunction() throws Exception { checkFooBoxIsOk(); } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java b/js/js.translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java index ad27cb000e9..bff86d88814 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java @@ -17,7 +17,6 @@ package org.jetbrains.k2js.translate.expression; import com.google.dart.compiler.backend.js.ast.*; -import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; @@ -29,6 +28,7 @@ import org.jetbrains.jet.lang.resolve.BindingContextUtils; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.constants.NullValue; import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.TypeUtils; import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.k2js.translate.context.TemporaryVariable; import org.jetbrains.k2js.translate.context.TranslationContext; @@ -347,9 +347,12 @@ public final class ExpressionVisitor extends TranslatorVisitor { if (expression.getOperationReference().getReferencedNameElementType() != JetTokens.AS_KEYWORD) return jsExpression.source(expression); - JetType rightType = BindingContextUtils.getNotNull(context.bindingContext(), BindingContext.TYPE, expression.getRight()); + JetTypeReference right = expression.getRight(); + assert right != null; + + JetType rightType = BindingContextUtils.getNotNull(context.bindingContext(), BindingContext.TYPE, right); JetType leftType = BindingContextUtils.getNotNull(context.bindingContext(), BindingContext.EXPRESSION_TYPE, expression.getLeft()); - if (rightType.isNullable() || !leftType.isNullable()) { + if (TypeUtils.isNullableType(rightType) || !TypeUtils.isNullableType(leftType)) { return jsExpression.source(expression); } diff --git a/js/js.translator/testData/expression/cast/cases/castToGenericType.kt b/js/js.translator/testData/expression/cast/cases/castToGenericType.kt new file mode 100644 index 00000000000..09687e93127 --- /dev/null +++ b/js/js.translator/testData/expression/cast/cases/castToGenericType.kt @@ -0,0 +1,74 @@ +package foo + +class A(val s: String) + +fun castsNotNullToNullableT(a: Any) { + a as T + a as T? + a as? T + a as? T? +} + +fun castsNullableToNullableT(a: Any?) { + a as T + a as T? + a as? T + a as? T? +} + + +fun castsNotNullToNotNullT(a: Any) { + a as T + a as T? + a as? T + a as? T? +} + +fun castNullableToNotNullT(a: Any?) { + a as T +} + +fun castsNullableToNotNullT(a: Any?) { + a as T? + a as? T + a as? T? +} + +fun test(f: () -> Unit) { + try { + f() + } + catch(e: Exception) { + throw Exception("Failed in $f with unexpected exception $e") + } +} + +fun fails(f: () -> Unit) { + try { + f() + } + catch(e: Exception) { + return + } + + throw Exception("Expected an exception to be thrown from $f") +} + +fun box(): String { + val a = A("OK") + + test { castsNotNullToNullableT(a) } + + test { castsNullableToNullableT(a) } + test { castsNullableToNullableT(null) } + + test { castsNotNullToNotNullT(a) } + + test { castsNullableToNotNullT(a) } + test { castsNullableToNotNullT(null) } + + test { castNullableToNotNullT(a) } + fails { castNullableToNotNullT(null) } + + return "OK" +}