[KJS] Throw exception on recursive types provided to typeOf and provide proper support later within KT-40173
#KT-38140 fixed
This commit is contained in:
+2
-1
@@ -196,7 +196,8 @@ class ClassReferenceLowering(val context: JsIrBackendContext) : BodyLoweringPass
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun createKTypeParameter(typeParameter: IrTypeParameter, visitedTypeParams: MutableSet<IrTypeParameter>): IrExpression {
|
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)
|
visitedTypeParams.add(typeParameter)
|
||||||
|
|
||||||
|
|||||||
compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/recursiveBoundWithInline.kt
Vendored
+25
@@ -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"
|
||||||
|
}
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
An operation is not implemented: Non-reified type parameters with recursive bounds are not supported yet
|
||||||
+16
@@ -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"
|
||||||
|
}
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
An operation is not implemented: Non-reified type parameters with recursive bounds are not supported yet
|
||||||
@@ -1,17 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2017 JetBrains s.r.o.
|
* 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.
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@file:JvmName("MetadataProperties")
|
@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.kType: JsExpression? by MetadataProperty(default = null)
|
||||||
|
|
||||||
|
var JsExpression.kTypeWithRecursion: Boolean by MetadataProperty(default = false)
|
||||||
|
|
||||||
data class CoroutineMetadata(
|
data class CoroutineMetadata(
|
||||||
val doResumeName: JsName,
|
val doResumeName: JsName,
|
||||||
val stateName: JsName,
|
val stateName: JsName,
|
||||||
|
|||||||
@@ -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.
|
* 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
|
package org.jetbrains.kotlin.js.inline.clean
|
||||||
|
|
||||||
import org.jetbrains.kotlin.js.backend.ast.*
|
import org.jetbrains.kotlin.js.backend.ast.*
|
||||||
import org.jetbrains.kotlin.js.backend.ast.metadata.SpecialFunction
|
import org.jetbrains.kotlin.js.backend.ast.metadata.*
|
||||||
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
|
|
||||||
|
|
||||||
// Replaces getReifiedTypeParameterKType(<Class Constructor>) with its KType
|
// Replaces getReifiedTypeParameterKType(<Class Constructor>) with its KType
|
||||||
fun substituteKTypes(root: JsNode) {
|
fun substituteKTypes(root: JsNode) {
|
||||||
val visitor = object : JsVisitorWithContextImpl() {
|
val visitor = object : JsVisitorWithContextImpl() {
|
||||||
override fun endVisit(invocation: JsInvocation, ctx: JsContext<in JsNode>) {
|
override fun endVisit(invocation: JsInvocation, ctx: JsContext<in JsNode>) {
|
||||||
|
// for invocations from non-inline contexts
|
||||||
|
invocation.checkDoesNotCreateRecursiveKType()
|
||||||
|
|
||||||
val qualifier = invocation.qualifier as? JsNameRef ?: return
|
val qualifier = invocation.qualifier as? JsNameRef ?: return
|
||||||
if (qualifier.name?.specialFunction != SpecialFunction.GET_REIFIED_TYPE_PARAMETER_KTYPE) return
|
if (qualifier.name?.specialFunction != SpecialFunction.GET_REIFIED_TYPE_PARAMETER_KTYPE) return
|
||||||
|
|
||||||
val firstArg = invocation.arguments.first()
|
val firstArg = invocation.arguments.first()
|
||||||
getTransitiveKType(firstArg)?.let {
|
getTransitiveKType(firstArg)?.let {
|
||||||
|
// for invocations from inline contexts
|
||||||
|
it.checkNoInvocationsWithRecursiveKType()
|
||||||
ctx.replaceMe(it)
|
ctx.replaceMe(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -30,7 +33,7 @@ fun substituteKTypes(root: JsNode) {
|
|||||||
// kType metadata is set on jsClass expressions.
|
// kType metadata is set on jsClass expressions.
|
||||||
// There can be a chain of local variables from jsClass to its usage.
|
// 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.
|
// 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 {
|
return when {
|
||||||
e.kType != null ->
|
e.kType != null ->
|
||||||
e.kType
|
e.kType
|
||||||
@@ -43,3 +46,17 @@ fun getTransitiveKType(e: JsExpression): JsExpression? {
|
|||||||
else -> null
|
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")
|
||||||
|
}
|
||||||
|
|||||||
Generated
+10
@@ -22412,6 +22412,16 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
|
|||||||
runTest("compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/innerGeneric.kt");
|
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")
|
@TestMetadata("simpleClassParameter.kt")
|
||||||
public void testSimpleClassParameter() throws Exception {
|
public void testSimpleClassParameter() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/simpleClassParameter.kt");
|
runTest("compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/simpleClassParameter.kt");
|
||||||
|
|||||||
Generated
+10
@@ -22412,6 +22412,16 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
|||||||
runTest("compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/innerGeneric.kt");
|
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")
|
@TestMetadata("simpleClassParameter.kt")
|
||||||
public void testSimpleClassParameter() throws Exception {
|
public void testSimpleClassParameter() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/simpleClassParameter.kt");
|
runTest("compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/simpleClassParameter.kt");
|
||||||
|
|||||||
+10
@@ -22427,6 +22427,16 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
runTest("compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/innerGeneric.kt");
|
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")
|
@TestMetadata("simpleClassParameter.kt")
|
||||||
public void testSimpleClassParameter() throws Exception {
|
public void testSimpleClassParameter() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/simpleClassParameter.kt");
|
runTest("compiler/testData/codegen/box/reflection/typeOf/nonReifiedTypeParameters/simpleClassParameter.kt");
|
||||||
|
|||||||
+6
-1
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
|||||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||||
import org.jetbrains.kotlin.js.backend.ast.*
|
import org.jetbrains.kotlin.js.backend.ast.*
|
||||||
import org.jetbrains.kotlin.js.backend.ast.metadata.SpecialFunction
|
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.backend.ast.metadata.specialFunction
|
||||||
import org.jetbrains.kotlin.js.translate.callTranslator.CallInfo
|
import org.jetbrains.kotlin.js.translate.callTranslator.CallInfo
|
||||||
import org.jetbrains.kotlin.js.translate.context.Namer
|
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)
|
visitedTypeParams.add(typeParameter)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user