JS: add tests to prove that compiler does not optimize RTTI and safe calls based on type information. Remove corresponding optimization for !! operation. See KT-14033

This commit is contained in:
Alexey Andreev
2016-12-13 17:13:53 +03:00
parent e6501591fa
commit b21f906856
8 changed files with 86 additions and 14 deletions
-3
View File
@@ -1,6 +1,3 @@
// TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: JS
fun <T> foo(t: T) {
t!!
}
@@ -1753,6 +1753,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
doTest(fileName);
}
@TestMetadata("explicitUpcast.kt")
public void testExplicitUpcast() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/expression/cast/explicitUpcast.kt");
doTest(fileName);
}
@TestMetadata("implicitCastToLong.kt")
public void testImplicitCastToLong() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/expression/cast/implicitCastToLong.kt");
@@ -6887,6 +6893,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/box/safeCall"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.JS, true);
}
@TestMetadata("redundantSafeAccess.kt")
public void testRedundantSafeAccess() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/safeCall/redundantSafeAccess.kt");
doTest(fileName);
}
@TestMetadata("safeAccess.kt")
public void testSafeAccess() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/safeCall/safeAccess.kt");
@@ -7851,13 +7851,7 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
@TestMetadata("genericNull.kt")
public void testGenericNull() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/exclExcl/genericNull.kt");
try {
doTest(fileName);
}
catch (Throwable ignore) {
return;
}
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
doTest(fileName);
}
@TestMetadata("primitive.kt")
@@ -29,12 +29,10 @@ import org.jetbrains.kotlin.lexer.KtTokens;
import org.jetbrains.kotlin.psi.KtConstantExpression;
import org.jetbrains.kotlin.psi.KtExpression;
import org.jetbrains.kotlin.psi.KtUnaryExpression;
import org.jetbrains.kotlin.resolve.BindingContextUtils;
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant;
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
import org.jetbrains.kotlin.types.KotlinType;
import static org.jetbrains.kotlin.js.translate.general.Translation.translateAsExpression;
import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.getCompileTimeValue;
@@ -55,9 +53,8 @@ public final class UnaryOperationTranslator {
IElementType operationToken = expression.getOperationReference().getReferencedNameElementType();
if (operationToken == KtTokens.EXCLEXCL) {
KtExpression baseExpression = getBaseExpression(expression);
KotlinType type = BindingContextUtils.getTypeNotNull(context.bindingContext(), baseExpression);
JsExpression translatedExpression = translateAsExpression(baseExpression, context);
return type.isMarkedNullable() ? sure(translatedExpression, context) : translatedExpression;
return sure(translatedExpression, context);
}
if (operationToken == KtTokens.MINUS) {
@@ -0,0 +1,3 @@
function createWrongObject() {
return new (JS_TESTS.foo.C);
}
@@ -0,0 +1,34 @@
package foo
open class A
class B : A()
class C
fun box(): String {
var b: B = createWrongObject()
if (b is A) return "fail1: is"
if (b as? A != null) return "fail1: as?"
try {
println(b as A)
return "fail1: as"
}
catch (e: ClassCastException) {
// It's expected
}
b = B()
if (b !is A) return "fail2: is"
if (b as? A == null) return "fail2: as?"
try {
if ((b as A) != b) return "fail2: as"
}
catch (e: ClassCastException) {
return "fail2a: as"
}
return "OK"
}
external fun createWrongObject(): B
@@ -0,0 +1,3 @@
function createWrongObject() {
return null
}
@@ -0,0 +1,32 @@
package foo
class A(val x: String) {
fun foo() = x
}
fun box(): String {
var b: A = createWrongObject()
if (b?.x != null) return "fail1: ?."
if (b?.foo() != null) return "fail1a: ?."
try {
println(b!!.x)
return "fail1: !!"
}
catch (e: NullPointerException) {
// It's expected
}
b = A("OK")
if (b?.x != "OK") return "fail2: ?."
if (b?.foo() != "OK") return "fail2a: ?."
try {
if (b!!.x != "OK") return "fail2: !!"
}
catch (e: NullPointerException) {
return "fail2a: !!"
}
return "OK"
}
external fun createWrongObject(): A