diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/TypeOperatorLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/TypeOperatorLowering.kt index 9d33262bbbf..a7afe4846c6 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/TypeOperatorLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/TypeOperatorLowering.kt @@ -254,7 +254,7 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : BodyLoweringPass { toType is IrDynamicType -> argument toType.isAny() -> generateIsObjectCheck(argument) toType.isNothing() -> JsIrBuilder.buildComposite(context.irBuiltIns.booleanType, listOf(argument, litFalse)) - toType.isSuspendFunctionTypeOrSubtype() -> generateSuspendFunctionCheck(argument, toType) + toType.isSuspendFunction() -> generateSuspendFunctionCheck(argument, toType) isTypeOfCheckingType(toType) -> generateTypeOfCheck(argument, toType) // toType.isChar() -> generateCheckForChar(argument) toType.isNumber() -> generateNumberCheck(argument) diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/BoxJsTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/BoxJsTestGenerated.java index 817361bbccc..1910a34d5db 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/BoxJsTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/BoxJsTestGenerated.java @@ -796,6 +796,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest { runTest("js/js.translator/testData/box/coroutines/debugStatement.kt"); } + @Test + @TestMetadata("kt54382.kt") + public void testKt54382() throws Exception { + runTest("js/js.translator/testData/box/coroutines/kt54382.kt"); + } + @Test @TestMetadata("lambdaWithValueClass.kt") public void testLambdaWithValueClass() throws Exception { @@ -819,6 +825,18 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest { public void testOnlyInlineSuspendFunction() throws Exception { runTest("js/js.translator/testData/box/coroutines/onlyInlineSuspendFunction.kt"); } + + @Test + @TestMetadata("suspendFunctionAsSupertypeIsCheck.kt") + public void testSuspendFunctionAsSupertypeIsCheck() throws Exception { + runTest("js/js.translator/testData/box/coroutines/suspendFunctionAsSupertypeIsCheck.kt"); + } + + @Test + @TestMetadata("suspendFunctionIsAs.kt") + public void testSuspendFunctionIsAs() throws Exception { + runTest("js/js.translator/testData/box/coroutines/suspendFunctionIsAs.kt"); + } } @Nested diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/FirJsTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/FirJsTestGenerated.java index f93ccb92046..988b5cba2ad 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/FirJsTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/FirJsTestGenerated.java @@ -860,6 +860,12 @@ public class FirJsTestGenerated extends AbstractFirJsTest { runTest("js/js.translator/testData/box/coroutines/debugStatement.kt"); } + @Test + @TestMetadata("kt54382.kt") + public void testKt54382() throws Exception { + runTest("js/js.translator/testData/box/coroutines/kt54382.kt"); + } + @Test @TestMetadata("lambdaWithValueClass.kt") public void testLambdaWithValueClass() throws Exception { @@ -883,6 +889,18 @@ public class FirJsTestGenerated extends AbstractFirJsTest { public void testOnlyInlineSuspendFunction() throws Exception { runTest("js/js.translator/testData/box/coroutines/onlyInlineSuspendFunction.kt"); } + + @Test + @TestMetadata("suspendFunctionAsSupertypeIsCheck.kt") + public void testSuspendFunctionAsSupertypeIsCheck() throws Exception { + runTest("js/js.translator/testData/box/coroutines/suspendFunctionAsSupertypeIsCheck.kt"); + } + + @Test + @TestMetadata("suspendFunctionIsAs.kt") + public void testSuspendFunctionIsAs() throws Exception { + runTest("js/js.translator/testData/box/coroutines/suspendFunctionIsAs.kt"); + } } @Nested diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsTestGenerated.java index 7383f4a290e..1a719b10bf9 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsTestGenerated.java @@ -860,6 +860,12 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest { runTest("js/js.translator/testData/box/coroutines/debugStatement.kt"); } + @Test + @TestMetadata("kt54382.kt") + public void testKt54382() throws Exception { + runTest("js/js.translator/testData/box/coroutines/kt54382.kt"); + } + @Test @TestMetadata("lambdaWithValueClass.kt") public void testLambdaWithValueClass() throws Exception { @@ -883,6 +889,18 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest { public void testOnlyInlineSuspendFunction() throws Exception { runTest("js/js.translator/testData/box/coroutines/onlyInlineSuspendFunction.kt"); } + + @Test + @TestMetadata("suspendFunctionAsSupertypeIsCheck.kt") + public void testSuspendFunctionAsSupertypeIsCheck() throws Exception { + runTest("js/js.translator/testData/box/coroutines/suspendFunctionAsSupertypeIsCheck.kt"); + } + + @Test + @TestMetadata("suspendFunctionIsAs.kt") + public void testSuspendFunctionIsAs() throws Exception { + runTest("js/js.translator/testData/box/coroutines/suspendFunctionIsAs.kt"); + } } @Nested diff --git a/js/js.translator/testData/box/coroutines/kt54382.kt b/js/js.translator/testData/box/coroutines/kt54382.kt new file mode 100644 index 00000000000..f0eff72a095 --- /dev/null +++ b/js/js.translator/testData/box/coroutines/kt54382.kt @@ -0,0 +1,29 @@ +// WITH_STDLIB +// WITH_COROUTINES + +typealias AsyncFun = suspend () -> Unit +val actions = arrayListOf() + +private class SyncFunAdapter(private val target: () -> Unit) : AsyncFun { + override fun equals(other: Any?): Boolean { + return if (other is SyncFunAdapter) { + target == other.target + } else { + target == other + } + } + + override fun hashCode() = target.hashCode() + + override suspend fun invoke() { + target() + } +} + +fun box(): String { + val x = SyncFunAdapter { } + actions.add(x) + if (!actions.remove(x)) return "FAIL 1" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/coroutines/suspendFunctionAsSupertypeIsCheck.kt b/js/js.translator/testData/box/coroutines/suspendFunctionAsSupertypeIsCheck.kt new file mode 100644 index 00000000000..bc92d561689 --- /dev/null +++ b/js/js.translator/testData/box/coroutines/suspendFunctionAsSupertypeIsCheck.kt @@ -0,0 +1,54 @@ +// WITH_STDLIB +// !LANGUAGE: +SuspendFunctionAsSupertype +// IGNORE_BACKEND: JS + +import kotlin.coroutines.* + +class C: suspend () -> Unit { + override suspend fun invoke() { + } +} + +interface I: suspend () -> Unit {} + +fun interface FI: suspend () -> Unit {} + +@Suppress("INCOMPATIBLE_TYPES") +fun box(): String { + val c = C() + if (c !is SuspendFunction0<*>) return "FAIL 1" + if (c is SuspendFunction1<*, *>) return "FAIL 3" + + val i = object : I { + override suspend fun invoke() { + } + } + if (i !is SuspendFunction0) return "FAIL 4" + if (i is SuspendFunction1<*, *>) return "FAIL 6" + + val fi = object : FI { + override suspend fun invoke() { + } + } + if (fi !is SuspendFunction0) return "FAIL 7" + if (fi is SuspendFunction1<*, *>) return "FAIL 9" + + val o = object : suspend () -> Unit { + override suspend fun invoke() { + } + } + if (o !is SuspendFunction0) return "FAIL 10" + if (o is SuspendFunction1<*, *>) return "FAIL 12" + + if (c !is C) return "FAIL 13" + if (i !is I) return "FAIL 14" + if (fi !is FI) return "FAIL 15" + + if (c !is C) return "FAIL 16" + val a: Any = c + if (a !is C) return "FAIL 17" + if (i !is I) return "FAIL 18" + if (fi !is FI) return "FAIL 19" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/coroutines/suspendFunctionIsAs.kt b/js/js.translator/testData/box/coroutines/suspendFunctionIsAs.kt new file mode 100644 index 00000000000..a0d34e0b6d8 --- /dev/null +++ b/js/js.translator/testData/box/coroutines/suspendFunctionIsAs.kt @@ -0,0 +1,66 @@ +// WITH_STDLIB +// WITH_COROUTINES +// IGNORE_BACKEND: JS + +import helpers.* +import kotlin.coroutines.* + +fun check(condition: Boolean, msg: () -> Unit) { + if (!condition) { + throw AssertionError(msg()) + } +} + +fun fn1(x: Any) {} +suspend fun suspendFn0() {} + +val lambda1 = { x: Any -> } as (Any) -> Unit +val suspendLambda0: suspend () -> Unit = {} + +fun Any.extFun(a: Any) {} +suspend fun Any.suspendExtFun() {} + +class A { + fun foo(a: Any) {} + suspend fun suspendFoo() {} +} + +inline fun Unit> checkReified(noinline x: (Any?) -> Unit) { + if(x is T) throw IllegalStateException("x is T") +} + +fun box(): String { + val f1 = ::fn1 as Any + val sf0 = ::suspendFn0 as Any + + val ef = Any::extFun as Any + val sef = Any::suspendExtFun as Any + + val afoo = A::foo + val safoo = A::suspendFoo + + fun local1(x: Any) {} + suspend fun suspendLocal0() {} + + val localFun1 = ::local1 as Any + val suspendLocalFun0 = ::suspendLocal0 as Any + + check(f1 !is SuspendFunction0<*>) { "Failed: f1 !is SuspendFunction0<*>" } + check(sf0 is SuspendFunction0<*>) { "Failed: f1 is SuspendFunction0<*>" } + + check(lambda1 !is SuspendFunction0<*>) { "Failed: lambda1 !is SuspendFunction0<*>" } + check(suspendLambda0 is SuspendFunction0<*>) { "Failed: suspendLambda0 is SuspendFunction0<*>" } + + check(localFun1 !is SuspendFunction0<*>) { "Failed: localFun1 !is SuspendFunction0<*, *>" } + check(suspendLocalFun0 is SuspendFunction0<*>) { "Failed: suspendLocalFun0 is SuspendFunction0<*>" } + + check(ef !is SuspendFunction1<*, *>) { "Failed: ef !is SuspendFunction1<*, *>" } + check(sef is SuspendFunction1<*, *>) { "Failed: sef is SuspendFunction1<*, *>" } + + check(afoo !is SuspendFunction1<*, *>) { "afoo !is SuspendFunction1<*, *>" } + check(safoo is SuspendFunction1<*, *>) { "asfoo is SuspendFunction1<*, *>" } + + checkReified Unit> {} + + return "OK" +} \ No newline at end of file