rra/ilgonmic/revert-signatures-changes
[JS IR] Fix line number test [JS IR] Ignore isInstance repl test [JS IR] Ignore isInstance repl test [JS IR] Add test with unsafe variance Revert "[JS IR] Optimize away upcasts" This reverts commit8149189585. Get rid of duplicated signatures Revert "[JS IR] Consider erasing type parameters in return type in js signatures" This reverts commit6adcbe081e. Revert "rra/ilgonmic/exported-bridges-2 [JS IR] Use js name for signature" This reverts commit00289d35[JS IR] Leave as is [JS IR] Add test with overloading by generic [JS IR] Add test from master [JS IR] Add tests from master Merge-request: KT-MR-5987 Merged-by: Ilya Goncharov <Ilya.Goncharov@jetbrains.com> ^KT-51700 fixed ^KT-51523 fixed ^KT-51685 fixed
This commit is contained in:
+7
-43
@@ -9,18 +9,16 @@ import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrArithBuilder
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.varargParameterIndex
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.eraseGenerics
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.getJsNameOrKotlinName
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.hasStableJsName
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.jsFunctionSignature
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrValueDeclaration
|
||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrNull
|
||||
import org.jetbrains.kotlin.ir.types.isUnit
|
||||
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
|
||||
import org.jetbrains.kotlin.ir.util.render
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
class JsBridgesConstruction(context: JsIrBackendContext) : BridgesConstruction<JsIrBackendContext>(context) {
|
||||
|
||||
@@ -35,21 +33,8 @@ class JsBridgesConstruction(context: JsIrBackendContext) : BridgesConstruction<J
|
||||
private val primitiveArrays = context.intrinsics.primitiveArrays
|
||||
private val primitiveToLiteralConstructor = context.intrinsics.primitiveToLiteralConstructor
|
||||
|
||||
private fun IrType.getJsInlinedClass() = context.inlineClassesUtils.getInlinedClass(this)
|
||||
|
||||
override fun getFunctionSignature(function: IrSimpleFunction): JsSignature =
|
||||
if (function.hasStableJsName(context)) {
|
||||
JsStableNameSignature(function.getJsNameOrKotlinName())
|
||||
} else {
|
||||
JsNonStableSignature(
|
||||
function.name,
|
||||
function.extensionReceiverParameter?.type?.eraseGenerics(context.irBuiltIns),
|
||||
function.valueParameters.map { it.type.eraseGenerics(context.irBuiltIns) },
|
||||
function.returnType.takeIf {
|
||||
it.getJsInlinedClass() != null || it.isUnit()
|
||||
}?.eraseGenerics(context.irBuiltIns)
|
||||
)
|
||||
}
|
||||
override fun getFunctionSignature(function: IrSimpleFunction) =
|
||||
jsFunctionSignature(function, context)
|
||||
|
||||
override fun getBridgeOrigin(bridge: IrSimpleFunction): IrDeclarationOrigin =
|
||||
when {
|
||||
@@ -167,24 +152,3 @@ class JsBridgesConstruction(context: JsIrBackendContext) : BridgesConstruction<J
|
||||
return createTmpVariable(varargCopiedAsArray, nameHint = varargElement.name.asString())
|
||||
}
|
||||
}
|
||||
|
||||
interface JsSignature {
|
||||
val name: Name
|
||||
}
|
||||
|
||||
data class JsNonStableSignature(
|
||||
override val name: Name,
|
||||
val extensionReceiverType: IrType?,
|
||||
val valueParametersType: List<IrType>,
|
||||
val returnType: IrType?,
|
||||
) : JsSignature {
|
||||
override fun toString(): String {
|
||||
val er = extensionReceiverType?.let { "(er: ${it.render()}) " } ?: ""
|
||||
val parameters = valueParametersType.joinToString(", ") { it.render() }
|
||||
return "[$er$name($parameters) -> ${returnType?.let { " -> ${it.render()}" } ?: ""}]"
|
||||
}
|
||||
}
|
||||
|
||||
data class JsStableNameSignature(
|
||||
override val name: Name,
|
||||
) : JsSignature
|
||||
|
||||
+2
-28
@@ -9,7 +9,6 @@ import org.jetbrains.kotlin.backend.common.BodyLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.compilationException
|
||||
import org.jetbrains.kotlin.backend.common.ir.isPure
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrArithBuilder
|
||||
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
|
||||
@@ -19,7 +18,6 @@ import org.jetbrains.kotlin.ir.declarations.IrDeclarationBase
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
@@ -229,37 +227,13 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : BodyLoweringPass {
|
||||
* └─────────────┻─────────────────────────────┴───────────────────────────────┘
|
||||
* ```
|
||||
* Note: advanced check is performed when casting to primitive types, array types, function types, or interfaces.
|
||||
*
|
||||
* If we statically know that this is an upcast, we try to generate no checks.
|
||||
* In this case, the following logic is applied:
|
||||
* ```
|
||||
* ┌─────────────┬─────────────┐
|
||||
* │ to non-null │ to nullable │
|
||||
* ┌─────────────╋━━━━━━━━━━━━━┻━━━━━━━━━━━━━┫
|
||||
* │from non-null┃ true │
|
||||
* ├─────────────╋─────────────┬─────────────┤
|
||||
* │from nullable┃ null check │ true │
|
||||
* └─────────────┻─────────────┴─────────────┘
|
||||
* ```
|
||||
*/
|
||||
private fun generateTypeCheck(argument: () -> IrExpression, toType: IrType): IrExpression {
|
||||
val toNotNullable = toType.makeNotNull()
|
||||
val argumentInstance = argument()
|
||||
val fromType = argumentInstance.type
|
||||
val fromNotNullable = fromType.makeNotNull()
|
||||
|
||||
val isFromNullable = fromType.isNullable()
|
||||
val isToNullable = toType.isNullable()
|
||||
|
||||
if (fromNotNullable !is IrDynamicType && fromNotNullable.isSubtypeOf(toNotNullable, context.typeSystem)) {
|
||||
// This is an upcast
|
||||
return when {
|
||||
isFromNullable && !isToNullable -> calculator.run { not(nullCheck(argument())) }
|
||||
else -> IrConstImpl.constTrue(UNDEFINED_OFFSET, UNDEFINED_OFFSET, context.irBuiltIns.booleanType)
|
||||
}
|
||||
}
|
||||
|
||||
val instanceCheck = generateTypeCheckNonNull(argumentInstance, toNotNullable)
|
||||
val isFromNullable = argumentInstance.type.isNullable()
|
||||
val isToNullable = toType.isNullable()
|
||||
val isNativeCheck = !advancedCheckRequired(toNotNullable)
|
||||
|
||||
return when {
|
||||
|
||||
@@ -14,7 +14,11 @@ import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol
|
||||
import org.jetbrains.kotlin.ir.types.isUnit
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.util.file
|
||||
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
|
||||
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
|
||||
import org.jetbrains.kotlin.ir.util.isInterface
|
||||
import org.jetbrains.kotlin.ir.util.render
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.js.common.isES5IdentifierPart
|
||||
@@ -137,17 +141,22 @@ fun jsFunctionSignature(declaration: IrFunction, context: JsIrBackendContext): S
|
||||
val nameBuilder = StringBuilder()
|
||||
nameBuilder.append(declarationName)
|
||||
|
||||
// TODO should we skip type parameters and use upper bound of type parameter when print type of value parameters?
|
||||
declaration.typeParameters.ifNotEmpty {
|
||||
nameBuilder.append("_\$t")
|
||||
joinTo(nameBuilder, "") { "_${it.name.asString()}" }
|
||||
}
|
||||
declaration.extensionReceiverParameter?.let {
|
||||
nameBuilder.append("_r$${it.type.eraseGenerics(context.irBuiltIns).asString()}")
|
||||
nameBuilder.append("_r$${it.type.asString()}")
|
||||
}
|
||||
declaration.valueParameters.ifNotEmpty {
|
||||
joinTo(nameBuilder, "") { "_${it.type.eraseGenerics(context.irBuiltIns).asString()}" }
|
||||
joinTo(nameBuilder, "") { "_${it.type.asString()}" }
|
||||
}
|
||||
declaration.returnType.let {
|
||||
// Return type is only used in signature for inline class and Unit types because
|
||||
// they are binary incompatible with supertypes.
|
||||
if (context.inlineClassesUtils.isTypeInlined(it) || it.isUnit()) {
|
||||
nameBuilder.append("_ret$${it.eraseGenerics(context.irBuiltIns).asString()}")
|
||||
nameBuilder.append("_ret$${it.asString()}")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
// MODULE: lib
|
||||
// FILE: t.kt
|
||||
|
||||
fun bar(a: String, b: String): Any
|
||||
fun bar(a: String, b: String): String
|
||||
|
||||
fun foo(): Any {
|
||||
fun foo(): String {
|
||||
return bar("O", "K")
|
||||
}
|
||||
|
||||
@@ -17,4 +17,4 @@ fun box(): String {
|
||||
val r = foo()
|
||||
if (r is String) return r
|
||||
return "OK"
|
||||
}
|
||||
}
|
||||
+12
-6
@@ -2287,12 +2287,6 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
||||
runTest("js/js.translator/testData/box/expression/cast/primitiveToClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("redundantCast.kt")
|
||||
public void testRedundantCast() throws Exception {
|
||||
runTest("js/js.translator/testData/box/expression/cast/redundantCast.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("reifiedToNotNull.kt")
|
||||
public void testReifiedToNotNull() throws Exception {
|
||||
@@ -2352,6 +2346,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
||||
public void testSmartCastInFunction() throws Exception {
|
||||
runTest("js/js.translator/testData/box/expression/cast/smartCastInFunction.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("unsafeVarianceCast.kt")
|
||||
public void testUnsafeVarianceCast() throws Exception {
|
||||
runTest("js/js.translator/testData/box/expression/cast/unsafeVarianceCast.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@@ -3013,6 +3013,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
||||
runTest("js/js.translator/testData/box/expression/function/overloadClassConstructorByFactoryMethod.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("overloadGeneric.kt")
|
||||
public void testOverloadGeneric() throws Exception {
|
||||
runTest("js/js.translator/testData/box/expression/function/overloadGeneric.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("overloadOverridenFun.kt")
|
||||
public void testOverloadOverridenFun() throws Exception {
|
||||
|
||||
+12
-6
@@ -2683,12 +2683,6 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
|
||||
runTest("js/js.translator/testData/box/expression/cast/primitiveToClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("redundantCast.kt")
|
||||
public void testRedundantCast() throws Exception {
|
||||
runTest("js/js.translator/testData/box/expression/cast/redundantCast.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("reifiedToNotNull.kt")
|
||||
public void testReifiedToNotNull() throws Exception {
|
||||
@@ -2748,6 +2742,12 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
|
||||
public void testSmartCastInFunction() throws Exception {
|
||||
runTest("js/js.translator/testData/box/expression/cast/smartCastInFunction.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("unsafeVarianceCast.kt")
|
||||
public void testUnsafeVarianceCast() throws Exception {
|
||||
runTest("js/js.translator/testData/box/expression/cast/unsafeVarianceCast.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@@ -3397,6 +3397,12 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
|
||||
runTest("js/js.translator/testData/box/expression/function/overloadClassConstructorByFactoryMethod.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("overloadGeneric.kt")
|
||||
public void testOverloadGeneric() throws Exception {
|
||||
runTest("js/js.translator/testData/box/expression/function/overloadGeneric.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("overloadOverridenFun.kt")
|
||||
public void testOverloadOverridenFun() throws Exception {
|
||||
|
||||
@@ -1,150 +0,0 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1306
|
||||
|
||||
// Test that upcasts are optimized away
|
||||
|
||||
open class Base
|
||||
|
||||
class Derived: Base()
|
||||
|
||||
var counter = 0
|
||||
var _derived = Derived()
|
||||
|
||||
@JsExport
|
||||
fun getDerived(): Derived {
|
||||
counter += 1
|
||||
return _derived
|
||||
}
|
||||
|
||||
@JsExport
|
||||
fun getDerivedNullable(): Derived? {
|
||||
counter += 1
|
||||
return _derived
|
||||
}
|
||||
|
||||
@JsExport
|
||||
fun getDerivedNull(): Derived? {
|
||||
counter += 1
|
||||
return null
|
||||
}
|
||||
|
||||
// CHECK_CONTAINS_NO_CALLS: upcast1 except=getDerived IGNORED_BACKENDS=JS
|
||||
// CHECK_TERNARY_OPERATOR_COUNT: function=upcast1 count=0 IGNORED_BACKENDS=JS
|
||||
// CHECK_IF_COUNT: function=upcast1 count=0 IGNORED_BACKENDS=JS
|
||||
// CHECK_BINOP_COUNT: function=upcast1 count=0 symbol=instanceof IGNORED_BACKENDS=JS
|
||||
fun upcast1() = getDerived() as Base
|
||||
|
||||
// CHECK_CONTAINS_NO_CALLS: upcast2 except=getDerived IGNORED_BACKENDS=JS
|
||||
// CHECK_TERNARY_OPERATOR_COUNT: function=upcast2 count=0 IGNORED_BACKENDS=JS
|
||||
// CHECK_IF_COUNT: function=upcast2 count=0 IGNORED_BACKENDS=JS
|
||||
// CHECK_BINOP_COUNT: function=upcast2 count=0 symbol=instanceof IGNORED_BACKENDS=JS
|
||||
fun upcast2() = getDerived() as Base?
|
||||
|
||||
// CHECK_BINOP_COUNT: function=upcast3 count=0 symbol=instanceof IGNORED_BACKENDS=JS
|
||||
fun upcast3() = getDerivedNullable() as Base
|
||||
|
||||
// CHECK_CONTAINS_NO_CALLS: upcast4 except=getDerivedNullable IGNORED_BACKENDS=JS
|
||||
// CHECK_TERNARY_OPERATOR_COUNT: function=upcast4 count=0 IGNORED_BACKENDS=JS
|
||||
// CHECK_IF_COUNT: function=upcast4 count=0 IGNORED_BACKENDS=JS
|
||||
// CHECK_BINOP_COUNT: function=upcast1 count=0 symbol=instanceof IGNORED_BACKENDS=JS
|
||||
fun upcast4() = getDerivedNullable() as Base?
|
||||
|
||||
// CHECK_BINOP_COUNT: function=upcast5 count=0 symbol=instanceof IGNORED_BACKENDS=JS
|
||||
fun upcast5() = getDerivedNull() as Base
|
||||
|
||||
// CHECK_CONTAINS_NO_CALLS: upcast6 except=getDerivedNull IGNORED_BACKENDS=JS
|
||||
// CHECK_TERNARY_OPERATOR_COUNT: function=upcast6 count=0 IGNORED_BACKENDS=JS
|
||||
// CHECK_IF_COUNT: function=upcast6 count=0 IGNORED_BACKENDS=JS
|
||||
// CHECK_BINOP_COUNT: function=upcast6 count=0 symbol=instanceof IGNORED_BACKENDS=JS
|
||||
fun upcast6() = getDerivedNull() as Base?
|
||||
|
||||
// CHECK_CONTAINS_NO_CALLS: safeCast1 except=getDerived IGNORED_BACKENDS=JS
|
||||
// CHECK_TERNARY_OPERATOR_COUNT: function=safeCast1 count=0 IGNORED_BACKENDS=JS
|
||||
// CHECK_IF_COUNT: function=safeCast1 count=0 IGNORED_BACKENDS=JS
|
||||
// CHECK_BINOP_COUNT: function=safeCast1 count=0 symbol=instanceof IGNORED_BACKENDS=JS
|
||||
fun safeCast1() = getDerived() as? Base
|
||||
|
||||
// CHECK_CONTAINS_NO_CALLS: safeCast2 except=getDerived IGNORED_BACKENDS=JS
|
||||
// CHECK_TERNARY_OPERATOR_COUNT: function=safeCast1 count=0 IGNORED_BACKENDS=JS
|
||||
// CHECK_IF_COUNT: function=safeCast1 count=0 IGNORED_BACKENDS=JS
|
||||
// CHECK_BINOP_COUNT: function=safeCast2 count=0 symbol=instanceof IGNORED_BACKENDS=JS
|
||||
fun safeCast2() = getDerived() as? Base?
|
||||
|
||||
// CHECK_BINOP_COUNT: function=safeCast3 count=0 symbol=instanceof IGNORED_BACKENDS=JS
|
||||
fun safeCast3() = getDerivedNullable() as? Base
|
||||
|
||||
// CHECK_CONTAINS_NO_CALLS: safeCast4 except=getDerivedNullable IGNORED_BACKENDS=JS
|
||||
// CHECK_TERNARY_OPERATOR_COUNT: function=safeCast4 count=0 IGNORED_BACKENDS=JS
|
||||
// CHECK_IF_COUNT: function=safeCast4 count=0 IGNORED_BACKENDS=JS
|
||||
// CHECK_BINOP_COUNT: function=safeCast4 count=0 symbol=instanceof IGNORED_BACKENDS=JS
|
||||
fun safeCast4() = getDerivedNullable() as? Base?
|
||||
|
||||
// CHECK_BINOP_COUNT: function=safeCast5 count=0 symbol=instanceof IGNORED_BACKENDS=JS
|
||||
fun safeCast5() = getDerivedNull() as? Base
|
||||
|
||||
// CHECK_CONTAINS_NO_CALLS: safeCast6 except=getDerivedNull IGNORED_BACKENDS=JS
|
||||
// CHECK_TERNARY_OPERATOR_COUNT: function=safeCast6 count=0 IGNORED_BACKENDS=JS
|
||||
// CHECK_IF_COUNT: function=safeCast6 count=0 IGNORED_BACKENDS=JS
|
||||
// CHECK_BINOP_COUNT: function=safeCast6 count=0 symbol=instanceof IGNORED_BACKENDS=JS
|
||||
fun safeCast6() = getDerivedNull() as? Base?
|
||||
|
||||
// CHECK_CONTAINS_NO_CALLS: upcast1 except=getDerived IGNORED_BACKENDS=JS
|
||||
// CHECK_TERNARY_OPERATOR_COUNT: function=upcast1 count=0 IGNORED_BACKENDS=JS
|
||||
// CHECK_IF_COUNT: function=upcast1 count=0 IGNORED_BACKENDS=JS
|
||||
// CHECK_BINOP_COUNT: function=instanceCheck1 count=0 symbol=instanceof IGNORED_BACKENDS=JS
|
||||
fun instanceCheck1() = getDerived() is Base
|
||||
|
||||
// CHECK_CONTAINS_NO_CALLS: upcast2 except=getDerived IGNORED_BACKENDS=JS
|
||||
// CHECK_TERNARY_OPERATOR_COUNT: function=upcast2 count=0 IGNORED_BACKENDS=JS
|
||||
// CHECK_IF_COUNT: function=upcast2 count=0 IGNORED_BACKENDS=JS
|
||||
// CHECK_BINOP_COUNT: function=instanceCheck2 count=0 symbol=instanceof IGNORED_BACKENDS=JS
|
||||
fun instanceCheck2() = getDerived() is Base?
|
||||
|
||||
// CHECK_BINOP_COUNT: function=instanceCheck3 count=0 symbol=instanceof IGNORED_BACKENDS=JS
|
||||
fun instanceCheck3() = getDerivedNullable() is Base
|
||||
|
||||
// CHECK_CONTAINS_NO_CALLS: upcast4 except=getDerivedNullable IGNORED_BACKENDS=JS
|
||||
// CHECK_TERNARY_OPERATOR_COUNT: function=upcast4 count=0 IGNORED_BACKENDS=JS
|
||||
// CHECK_IF_COUNT: function=upcast4 count=0 IGNORED_BACKENDS=JS
|
||||
// CHECK_BINOP_COUNT: function=instanceCheck4 count=0 symbol=instanceof IGNORED_BACKENDS=JS
|
||||
fun instanceCheck4() = getDerivedNullable() is Base?
|
||||
|
||||
// CHECK_BINOP_COUNT: function=instanceCheck5 count=0 symbol=instanceof IGNORED_BACKENDS=JS
|
||||
fun instanceCheck5() = getDerivedNull() is Base
|
||||
|
||||
// CHECK_CONTAINS_NO_CALLS: upcast6 except=getDerivedNull IGNORED_BACKENDS=JS
|
||||
// CHECK_TERNARY_OPERATOR_COUNT: function=upcast6 count=0 IGNORED_BACKENDS=JS
|
||||
// CHECK_IF_COUNT: function=upcast6 count=0 IGNORED_BACKENDS=JS
|
||||
// CHECK_BINOP_COUNT: function=instanceCheck6 count=0 symbol=instanceof IGNORED_BACKENDS=JS
|
||||
fun instanceCheck6() = getDerivedNull() is Base?
|
||||
|
||||
fun box(): String {
|
||||
assertSame(_derived, upcast1(), "upcast1()")
|
||||
assertSame(_derived, upcast2(), "upcast2()")
|
||||
assertSame(_derived, upcast3(), "upcast3()")
|
||||
assertSame(_derived, upcast4(), "upcast4()")
|
||||
failsClassCast("upcast5()") { upcast5() }
|
||||
assertSame(null, upcast6(), "upcast6()")
|
||||
assertEquals(6, counter)
|
||||
|
||||
counter = 0
|
||||
|
||||
assertSame(_derived, safeCast1(), "safeCast1()")
|
||||
assertSame(_derived, safeCast2(), "safeCast2()")
|
||||
assertSame(_derived, safeCast3(), "safeCast3()")
|
||||
assertSame(_derived, safeCast4(), "safeCast4()")
|
||||
assertSame(null, safeCast5(), "safeCast5()")
|
||||
assertSame(null, safeCast6(), "safeCast6()")
|
||||
assertEquals(6, counter)
|
||||
|
||||
counter = 0
|
||||
|
||||
assertTrue(instanceCheck1(), "instanceCheck1()")
|
||||
assertTrue(instanceCheck2(), "instanceCheck2()")
|
||||
assertTrue(instanceCheck3(), "instanceCheck3()")
|
||||
assertTrue(instanceCheck4(), "instanceCheck4()")
|
||||
assertFalse(instanceCheck5(), "instanceCheck5()")
|
||||
assertTrue(instanceCheck6(), "instanceCheck6()")
|
||||
assertEquals(6, counter)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
abstract class Foo<out E> {
|
||||
abstract fun foo(element: @UnsafeVariance E): Boolean
|
||||
}
|
||||
|
||||
class Bar<E : C> : Foo<E>() {
|
||||
override fun foo(element: E): Boolean {
|
||||
if (element !is C?) return false
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
open class C
|
||||
|
||||
open class D : C()
|
||||
|
||||
fun box(): String {
|
||||
val a = (object{})
|
||||
val foo: Foo<Any?> = Bar<D>()
|
||||
if (foo.foo(a as Any?)) return "fail"
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
|
||||
class L<T>
|
||||
|
||||
class A {
|
||||
fun foo(a: L<Int>) = "Int"
|
||||
fun foo(a: L<String>) = "String"
|
||||
fun L<Int>.bar() = "Int2"
|
||||
fun L<String>.bar() = "String2"
|
||||
}
|
||||
|
||||
fun foo(a: L<Int>) = "Int"
|
||||
fun foo(a: L<String>) = "String"
|
||||
|
||||
private class TestClass {
|
||||
private val data = mutableListOf<List<Any>>()
|
||||
fun withData(data: List<List<Any>>) = apply { this.data.addAll(data) }
|
||||
fun withData(row: List<Any>) = apply {
|
||||
data.add(row)
|
||||
}
|
||||
|
||||
fun getCols(): Int {
|
||||
return data.firstOrNull()?.size ?: return 0
|
||||
}
|
||||
}
|
||||
|
||||
object B {
|
||||
fun baz(vararg v: B) = "[A]"
|
||||
|
||||
fun baz(vararg v: String) = "[S]"
|
||||
|
||||
fun baz(v: Array<String>) = "Array<String>"
|
||||
}
|
||||
|
||||
class C<in T> {
|
||||
fun bac(c: T): String {
|
||||
return "T4"
|
||||
}
|
||||
|
||||
fun bac(c: Int): String {
|
||||
return "Int5"
|
||||
}
|
||||
|
||||
fun bac(c: List<T>): String {
|
||||
return "ListT4"
|
||||
}
|
||||
|
||||
fun bac(c: List<Int>): String {
|
||||
return "ListInt4"
|
||||
}
|
||||
|
||||
fun bac(c: List<*>): String {
|
||||
return "ListStar4"
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
if (A().foo(L<Int>()) != "Int") return "fail1"
|
||||
A().apply {
|
||||
if (L<Int>().bar() != "Int2") return "fail2"
|
||||
}
|
||||
if (foo(L<Int>()) != "Int") return "fail3"
|
||||
|
||||
val b = TestClass()
|
||||
val data = mutableListOf<List<Any>>()
|
||||
data.add(listOf("a", "b", "c"))
|
||||
data.add(listOf("d", "e", "f"))
|
||||
b.withData(data)
|
||||
if (b.getCols() != 3) return "fail4"
|
||||
|
||||
if (B.baz(B) != "[A]") return "fail5"
|
||||
if (B.baz("a") != "[S]") return "fail6"
|
||||
if (B.baz(arrayOf("b")) != "Array<String>") return "fail7"
|
||||
|
||||
if(C<String>().bac("a") != "T4") return "fail8"
|
||||
if(C<String>().bac(5) != "Int5") return "fail9"
|
||||
if(C<String>().bac(listOf("a", "b")) != "ListT4") return "fail10"
|
||||
if(C<String>().bac(listOf(5, 6)) != "ListInt4") return "fail11"
|
||||
if(C<String>().bac(listOf(Any(), Any())) != "ListStar4") return "fail12"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+1
-2
@@ -3,8 +3,7 @@ package foo
|
||||
|
||||
// CHECK_NOT_CALLED: isTypeOfOrNull
|
||||
// CHECK_NULLS_COUNT: function=box count=10 TARGET_BACKENDS=JS
|
||||
// CHECK_NULLS_COUNT: function=box count=0 IGNORED_BACKENDS=JS
|
||||
// CHECK_CONTAINS_NO_CALLS: box except=assertEquals;A IGNORED_BACKENDS=JS
|
||||
// CHECK_NULLS_COUNT: function=box count=6 IGNORED_BACKENDS=JS
|
||||
|
||||
inline
|
||||
fun <reified T> Any?.isTypeOfOrNull() = this is T?
|
||||
|
||||
+4
-5
@@ -1,5 +1,6 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1285
|
||||
// CHECK_CALLED_IN_SCOPE: function=isType scope=box TARGET_BACKENDS=JS
|
||||
// CHECK_CALLED_IN_SCOPE: function=isObject scope=box IGNORED_BACKENDS=JS
|
||||
package foo
|
||||
|
||||
class A : Any()
|
||||
@@ -15,11 +16,9 @@ fun box(): String {
|
||||
|
||||
if (arrayOf(1, 2, 3).asAny() !is Any) return "fail3"
|
||||
|
||||
if (testUtils.isLegacyBackend()) {
|
||||
if (createNakedObject() is Any) return "fail4"
|
||||
}
|
||||
if (createNakedObject() is Any) return "fail4"
|
||||
|
||||
if (({ }).asAny() !is Any) return "fail5"
|
||||
if (({ }).asAny() !is Any) return "fail5"
|
||||
|
||||
if ((23).asAny() !is Any) return "fail6"
|
||||
|
||||
@@ -32,4 +31,4 @@ fun box(): String {
|
||||
return "OK"
|
||||
}
|
||||
|
||||
fun createNakedObject(): Any? = js("Object.create(null)")
|
||||
fun createNakedObject(): Any? = js("Object.create(null)")
|
||||
+1
-1
@@ -14,4 +14,4 @@ open class A
|
||||
open class B : A()
|
||||
|
||||
// LINES(JS): 1 10 2 2 2 2 3 3 4 4 5 5 6 6 8 8 12 * 14 14
|
||||
// LINES(JS_IR): 2 2 4 4 * 14
|
||||
// LINES(JS_IR): 2 2 3 4 4 5 6 6 8 8 * 14
|
||||
|
||||
+3
@@ -122,6 +122,8 @@ abstract class AbstractReplTestRunner : TestCase() {
|
||||
Assert.assertEquals("OK", compileAndEval(lines))
|
||||
}
|
||||
|
||||
/* Ignore annotation doesn't work, so comment it
|
||||
@Ignore("we use Object.assign inside type checks and nashorn does not support it")
|
||||
@Test
|
||||
fun testInstanceOf() {
|
||||
val lines = listOf(
|
||||
@@ -134,6 +136,7 @@ abstract class AbstractReplTestRunner : TestCase() {
|
||||
)
|
||||
Assert.assertEquals("truetrue", compileAndEval(lines))
|
||||
}
|
||||
*/
|
||||
|
||||
@Test
|
||||
fun testScopes() {
|
||||
|
||||
Reference in New Issue
Block a user