summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZalim Bashorov <zalim.bashorov@jetbrains.com>2020-07-10 02:45:30 +0300
committerZalim Bashorov <zalim.bashorov@jetbrains.com>2020-07-14 18:49:34 +0300
commitc6749451c2359d7415aa0783f895bedb18ed2409 (patch)
tree1e055693128780c200648a44142bc77a6ab29954
parentaf80a0a8cdbef1e7566c9335a8a73e65ad1e650c (diff)
downloadkotlin-c6749451c2359d7415aa0783f895bedb18ed2409.tar.gz
[KJS] Throw exception on recursive types provided to typeOf and provide proper support later within KT-40173
#KT-38140 fixed (cherry picked from commit 340512e27ae06b7331c970d3d9f64c8ebe84402a)
-rw-r--r--compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ClassReferenceLowering.kt3
-rw-r--r--compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithInline.kt25
-rw-r--r--compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithInline.kt.fail1
-rw-r--r--compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithoutInline.kt16
-rw-r--r--compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithoutInline.kt.fail1
-rw-r--r--js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/metadata/metadataProperties.kt17
-rw-r--r--js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/substituteKTypes.kt29
-rw-r--r--js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java10
-rw-r--r--js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java10
-rw-r--r--js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java10
-rw-r--r--js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/factories/TypeOfFIF.kt7
11 files changed, 108 insertions, 21 deletions
diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ClassReferenceLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ClassReferenceLowering.kt
index 8385567a2e5..2500c038043 100644
--- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ClassReferenceLowering.kt
+++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ClassReferenceLowering.kt
@@ -196,7 +196,8 @@ class ClassReferenceLowering(val context: JsIrBackendContext) : BodyLoweringPass
}
private fun createKTypeParameter(typeParameter: IrTypeParameter, visitedTypeParams: MutableSet<IrTypeParameter>): IrExpression {
- if (typeParameter in visitedTypeParams) return buildCall(context.intrinsics.getStarKTypeProjection!!)
+ // See KT-40173
+ if (typeParameter in visitedTypeParams) TODO("Non-reified type parameters with recursive bounds are not supported yet")
visitedTypeParams.add(typeParameter)
diff --git a/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithInline.kt b/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithInline.kt
new file mode 100644
index 00000000000..05dc2a70845
--- /dev/null
+++ b/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithInline.kt
@@ -0,0 +1,25 @@
+// !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi
+// TODO: it should target all backends, but now it's possible to have only one .fial file per test file,
+// so we can't define different messages for different test suites/runners.
+// TARGET_BACKEND: JS
+// KJS_WITH_FULL_RUNTIME
+
+import kotlin.reflect.typeOf
+
+fun <T : Comparable<T>> foo() {
+ bar<List<T>>()
+ baz<List<T>>()
+}
+
+inline fun <reified T> bar() {
+ baz<T>()
+}
+
+inline fun <reified T> baz() {
+ typeOf<Set<T>>()
+}
+
+fun box(): String {
+ foo<Int>()
+ return "OK"
+}
diff --git a/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithInline.kt.fail b/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithInline.kt.fail
new file mode 100644
index 00000000000..9803cffba2d
--- /dev/null
+++ b/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithInline.kt.fail
@@ -0,0 +1 @@
+An operation is not implemented: Non-reified type parameters with recursive bounds are not supported yet \ No newline at end of file
diff --git a/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithoutInline.kt b/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithoutInline.kt
new file mode 100644
index 00000000000..ea49c1e1127
--- /dev/null
+++ b/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithoutInline.kt
@@ -0,0 +1,16 @@
+// !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi
+// TODO: it should target all backends, but now it's possible to have only one .fial file per test file,
+// so we can't define different messages for different test suites/runners.
+// TARGET_BACKEND: JS
+// KJS_WITH_FULL_RUNTIME
+
+import kotlin.reflect.typeOf
+
+fun <T : Comparable<T>> foo() {
+ typeOf<List<T>>()
+}
+
+fun box(): String {
+ foo<Int>()
+ return "OK"
+}
diff --git a/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithoutInline.kt.fail b/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithoutInline.kt.fail
new file mode 100644
index 00000000000..9803cffba2d
--- /dev/null
+++ b/compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithoutInline.kt.fail
@@ -0,0 +1 @@
+An operation is not implemented: Non-reified type parameters with recursive bounds are not supported yet \ No newline at end of file
diff --git a/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/metadata/metadataProperties.kt b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/metadata/metadataProperties.kt
index b1be72cb9d3..0aec0c1693c 100644
--- a/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/metadata/metadataProperties.kt
+++ b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/metadata/metadataProperties.kt
@@ -1,17 +1,6 @@
/*
- * Copyright 2010-2017 JetBrains s.r.o.
- *
- * 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.
+ * Copyright 2010-2020 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.
*/
@file:JvmName("MetadataProperties")
@@ -129,6 +118,8 @@ var JsExpression.primitiveKClass: JsExpression? by MetadataProperty(default = nu
var JsExpression.kType: JsExpression? by MetadataProperty(default = null)
+var JsExpression.kTypeWithRecursion: Boolean by MetadataProperty(default = false)
+
data class CoroutineMetadata(
val doResumeName: JsName,
val stateName: JsName,
diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/substituteKTypes.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/substituteKTypes.kt
index f8a28b05362..d7dfc75ae3d 100644
--- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/substituteKTypes.kt
+++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/substituteKTypes.kt
@@ -1,24 +1,27 @@
/*
- * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Copyright 2010-2020 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.
*/
package org.jetbrains.kotlin.js.inline.clean
import org.jetbrains.kotlin.js.backend.ast.*
-import org.jetbrains.kotlin.js.backend.ast.metadata.SpecialFunction
-import org.jetbrains.kotlin.js.backend.ast.metadata.kType
-import org.jetbrains.kotlin.js.backend.ast.metadata.specialFunction
-import org.jetbrains.kotlin.js.backend.ast.metadata.staticRef
+import org.jetbrains.kotlin.js.backend.ast.metadata.*
// Replaces getReifiedTypeParameterKType(<Class Constructor>) with its KType
fun substituteKTypes(root: JsNode) {
val visitor = object : JsVisitorWithContextImpl() {
override fun endVisit(invocation: JsInvocation, ctx: JsContext<in JsNode>) {
+ // for invocations from non-inline contexts
+ invocation.checkDoesNotCreateRecursiveKType()
+
val qualifier = invocation.qualifier as? JsNameRef ?: return
if (qualifier.name?.specialFunction != SpecialFunction.GET_REIFIED_TYPE_PARAMETER_KTYPE) return
+
val firstArg = invocation.arguments.first()
getTransitiveKType(firstArg)?.let {
+ // for invocations from inline contexts
+ it.checkNoInvocationsWithRecursiveKType()
ctx.replaceMe(it)
}
}
@@ -30,7 +33,7 @@ fun substituteKTypes(root: JsNode) {
// kType metadata is set on jsClass expressions.
// There can be a chain of local variables from jsClass to its usage.
// This methods uses staticRef to find the original expression with kType metadata.
-fun getTransitiveKType(e: JsExpression): JsExpression? {
+private fun getTransitiveKType(e: JsExpression): JsExpression? {
return when {
e.kType != null ->
e.kType
@@ -43,3 +46,17 @@ fun getTransitiveKType(e: JsExpression): JsExpression? {
else -> null
}
}
+
+private fun JsExpression.checkNoInvocationsWithRecursiveKType() {
+ val visitor = object : JsVisitorWithContextImpl() {
+ override fun endVisit(invocation: JsInvocation, ctx: JsContext<in JsNode>) {
+ invocation.checkDoesNotCreateRecursiveKType()
+ }
+ }
+ visitor.accept(this)
+}
+
+private fun JsInvocation.checkDoesNotCreateRecursiveKType() {
+ // See KT-40173
+ if (kTypeWithRecursion) TODO("Non-reified type parameters with recursive bounds are not supported yet")
+}
diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java
index 711a144ef9d..5dc406443fc 100644
--- a/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java
+++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java
@@ -22368,6 +22368,16 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
runTest("compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/innerGeneric.kt");
}
+ @TestMetadata("recursiveBoundWithInline.kt")
+ public void testRecursiveBoundWithInline() throws Exception {
+ runTest("compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithInline.kt");
+ }
+
+ @TestMetadata("recursiveBoundWithoutInline.kt")
+ public void testRecursiveBoundWithoutInline() throws Exception {
+ runTest("compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithoutInline.kt");
+ }
+
@TestMetadata("simpleClassParameter.kt")
public void testSimpleClassParameter() throws Exception {
runTest("compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/simpleClassParameter.kt");
diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java
index cea4a3dc20b..1076cde05ce 100644
--- a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java
+++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java
@@ -22368,6 +22368,16 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/innerGeneric.kt");
}
+ @TestMetadata("recursiveBoundWithInline.kt")
+ public void testRecursiveBoundWithInline() throws Exception {
+ runTest("compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithInline.kt");
+ }
+
+ @TestMetadata("recursiveBoundWithoutInline.kt")
+ public void testRecursiveBoundWithoutInline() throws Exception {
+ runTest("compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithoutInline.kt");
+ }
+
@TestMetadata("simpleClassParameter.kt")
public void testSimpleClassParameter() throws Exception {
runTest("compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/simpleClassParameter.kt");
diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java
index 3b769e9b9bc..5c95e5b4649 100644
--- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java
+++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java
@@ -22383,6 +22383,16 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/innerGeneric.kt");
}
+ @TestMetadata("recursiveBoundWithInline.kt")
+ public void testRecursiveBoundWithInline() throws Exception {
+ runTest("compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithInline.kt");
+ }
+
+ @TestMetadata("recursiveBoundWithoutInline.kt")
+ public void testRecursiveBoundWithoutInline() throws Exception {
+ runTest("compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithoutInline.kt");
+ }
+
@TestMetadata("simpleClassParameter.kt")
public void testSimpleClassParameter() throws Exception {
runTest("compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/simpleClassParameter.kt");
diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/factories/TypeOfFIF.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/factories/TypeOfFIF.kt
index 578ab341033..803a5597fd2 100644
--- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/factories/TypeOfFIF.kt
+++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/factories/TypeOfFIF.kt
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.js.backend.ast.*
import org.jetbrains.kotlin.js.backend.ast.metadata.SpecialFunction
+import org.jetbrains.kotlin.js.backend.ast.metadata.kTypeWithRecursion
import org.jetbrains.kotlin.js.backend.ast.metadata.specialFunction
import org.jetbrains.kotlin.js.translate.callTranslator.CallInfo
import org.jetbrains.kotlin.js.translate.context.Namer
@@ -146,7 +147,11 @@ private class KTypeConstructor(private val context: TranslationContext) {
)
}
- if (typeParameter in visitedTypeParams) return callHelperFunction(Namer.GET_START_KTYPE_PROJECTION)
+ if (typeParameter in visitedTypeParams) {
+ return callHelperFunction(Namer.GET_START_KTYPE_PROJECTION).also {
+ it.kTypeWithRecursion = true
+ }
+ }
visitedTypeParams.add(typeParameter)