[JS BEs] use star projection when type parameter used recursively
#KT-37128 Fixed
This commit is contained in:
Generated
+5
@@ -25201,6 +25201,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/reified/reifiedTypeArgumentWithIntersectionTypeAsTypeArgument.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("reifiedTypeArgumentWithRecursion.kt")
|
||||
public void testReifiedTypeArgumentWithRecursion() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reified/reifiedTypeArgumentWithRecursion.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("safecast.kt")
|
||||
public void testSafecast() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reified/safecast.kt");
|
||||
|
||||
+21
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
@@ -136,9 +136,10 @@ class ClassReferenceLowering(val context: JsIrBackendContext) : BodyLoweringPass
|
||||
}
|
||||
}
|
||||
|
||||
fun createKType(type: IrType): IrExpression {
|
||||
private fun createKType(type: IrType, visitedTypeParams: MutableSet<IrTypeParameter>): IrExpression {
|
||||
|
||||
if (type is IrSimpleType)
|
||||
return createSimpleKType(type)
|
||||
return createSimpleKType(type, visitedTypeParams)
|
||||
if (type is IrDynamicType)
|
||||
return createDynamicType()
|
||||
error("Unexpected type $type")
|
||||
@@ -148,7 +149,7 @@ class ClassReferenceLowering(val context: JsIrBackendContext) : BodyLoweringPass
|
||||
return buildCall(context.intrinsics.createDynamicKType!!)
|
||||
}
|
||||
|
||||
private fun createSimpleKType(type: IrSimpleType): IrExpression {
|
||||
private fun createSimpleKType(type: IrSimpleType, visitedTypeParams: MutableSet<IrTypeParameter>): IrExpression {
|
||||
val classifier: IrClassifierSymbol = type.classifier
|
||||
|
||||
// TODO: Check why do we have un-substituted reified parameters
|
||||
@@ -156,9 +157,9 @@ class ClassReferenceLowering(val context: JsIrBackendContext) : BodyLoweringPass
|
||||
// error("Fail")
|
||||
// }
|
||||
|
||||
val kClassifier = createKClassifier(classifier)
|
||||
val kClassifier = createKClassifier(classifier, visitedTypeParams)
|
||||
// TODO: Use static array types
|
||||
val arguments = type.arguments.map { createKTypeProjection(it) }.toJsArrayLiteral(
|
||||
val arguments = type.arguments.map { createKTypeProjection(it, visitedTypeParams) }.toJsArrayLiteral(
|
||||
context,
|
||||
context.dynamicType,
|
||||
context.dynamicType
|
||||
@@ -172,7 +173,7 @@ class ClassReferenceLowering(val context: JsIrBackendContext) : BodyLoweringPass
|
||||
)
|
||||
}
|
||||
|
||||
private fun createKTypeProjection(tp: IrTypeArgument): IrExpression {
|
||||
private fun createKTypeProjection(tp: IrTypeArgument, visitedTypeParams: MutableSet<IrTypeParameter>): IrExpression {
|
||||
if (tp !is IrTypeProjection) {
|
||||
return buildCall(context.intrinsics.getStarKTypeProjection!!)
|
||||
}
|
||||
@@ -183,20 +184,24 @@ class ClassReferenceLowering(val context: JsIrBackendContext) : BodyLoweringPass
|
||||
Variance.OUT_VARIANCE -> context.intrinsics.createCovariantKTypeProjection!!
|
||||
}
|
||||
|
||||
val kType = createKType(tp.type)
|
||||
val kType = createKType(tp.type, visitedTypeParams)
|
||||
return buildCall(factoryName, kType)
|
||||
|
||||
}
|
||||
|
||||
private fun createKClassifier(classifier: IrClassifierSymbol): IrExpression =
|
||||
private fun createKClassifier(classifier: IrClassifierSymbol, visitedTypeParams: MutableSet<IrTypeParameter>): IrExpression =
|
||||
when (classifier) {
|
||||
is IrTypeParameterSymbol -> createKTypeParameter(classifier.owner)
|
||||
is IrTypeParameterSymbol -> createKTypeParameter(classifier.owner, visitedTypeParams)
|
||||
else -> callGetKClass(typeArgument = classifier.defaultType)
|
||||
}
|
||||
|
||||
private fun createKTypeParameter(typeParameter: IrTypeParameter): IrExpression {
|
||||
private fun createKTypeParameter(typeParameter: IrTypeParameter, visitedTypeParams: MutableSet<IrTypeParameter>): IrExpression {
|
||||
if (typeParameter in visitedTypeParams) return buildCall(context.intrinsics.getStarKTypeProjection!!)
|
||||
|
||||
visitedTypeParams.add(typeParameter)
|
||||
|
||||
val name = JsIrBuilder.buildString(context.irBuiltIns.stringType, typeParameter.name.asString())
|
||||
val upperBounds = typeParameter.superTypes.map { createKType(it) }.toJsArrayLiteral(
|
||||
val upperBounds = typeParameter.superTypes.map { createKType(it, visitedTypeParams) }.toJsArrayLiteral(
|
||||
context,
|
||||
context.dynamicType,
|
||||
context.dynamicType
|
||||
@@ -218,7 +223,9 @@ class ClassReferenceLowering(val context: JsIrBackendContext) : BodyLoweringPass
|
||||
name,
|
||||
upperBounds,
|
||||
variance
|
||||
)
|
||||
).also {
|
||||
visitedTypeParams.remove(typeParameter)
|
||||
}
|
||||
}
|
||||
|
||||
override fun lower(irBody: IrBody, container: IrDeclaration) {
|
||||
@@ -238,7 +245,7 @@ class ClassReferenceLowering(val context: JsIrBackendContext) : BodyLoweringPass
|
||||
|
||||
override fun visitCall(expression: IrCall): IrExpression =
|
||||
if (Symbols.isTypeOfIntrinsic(expression.symbol)) {
|
||||
createKType(expression.getTypeArgument(0)!!)
|
||||
createKType(expression.getTypeArgument(0)!!, hashSetOf())
|
||||
} else {
|
||||
super.visitCall(expression)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
|
||||
// See KT-37128
|
||||
|
||||
import kotlin.reflect.typeOf
|
||||
|
||||
// TODO check real effects to fix the behavior when we reach consensus
|
||||
// and to be sure that something is not dropped by optimizations.
|
||||
|
||||
@OptIn(kotlin.ExperimentalStdlibApi::class)
|
||||
inline fun <reified T> T.causeBug() {
|
||||
val x = this
|
||||
x is T
|
||||
x as T
|
||||
T::class
|
||||
typeOf<T>()
|
||||
Array<T>(1) { x }
|
||||
}
|
||||
|
||||
interface SomeToImplement<SELF_TVAR>
|
||||
|
||||
class Y : SomeToImplement<Y>
|
||||
|
||||
class Something<T> where T: SomeToImplement<T> {
|
||||
fun op() = causeBug()
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
Something<Y>().op()
|
||||
return "OK"
|
||||
}
|
||||
+5
@@ -26717,6 +26717,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/reified/reifiedTypeArgumentWithIntersectionTypeAsTypeArgument.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("reifiedTypeArgumentWithRecursion.kt")
|
||||
public void testReifiedTypeArgumentWithRecursion() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reified/reifiedTypeArgumentWithRecursion.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("safecast.kt")
|
||||
public void testSafecast() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reified/safecast.kt");
|
||||
|
||||
+5
@@ -25534,6 +25534,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/reified/reifiedTypeArgumentWithIntersectionTypeAsTypeArgument.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("reifiedTypeArgumentWithRecursion.kt")
|
||||
public void testReifiedTypeArgumentWithRecursion() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reified/reifiedTypeArgumentWithRecursion.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("safecast.kt")
|
||||
public void testSafecast() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reified/safecast.kt");
|
||||
|
||||
+5
@@ -25201,6 +25201,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/reified/reifiedTypeArgumentWithIntersectionTypeAsTypeArgument.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("reifiedTypeArgumentWithRecursion.kt")
|
||||
public void testReifiedTypeArgumentWithRecursion() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reified/reifiedTypeArgumentWithRecursion.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("safecast.kt")
|
||||
public void testSafecast() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reified/safecast.kt");
|
||||
|
||||
Reference in New Issue
Block a user