From b35d4134a7d7d118507ce34d275dadd13f5f4662 Mon Sep 17 00:00:00 2001 From: Georgy Bronnikov Date: Thu, 10 Dec 2020 16:13:54 +0300 Subject: [PATCH] Psi2IR: workaround for IR-based descriptors Since KotlinTypes involving IR-Based descriptors are distinct from KotlinTypes involving original descriptors of the same declarations, subtyping check breaks in InsertImplicitCasts. --- .../transformations/InsertImplicitCasts.kt | 25 ++++++++++++++++--- ...pendConversionOnArbitraryExpression.kt.txt | 4 +-- ...suspendConversionOnArbitraryExpression.txt | 6 +++-- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InsertImplicitCasts.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InsertImplicitCasts.kt index 711465e7a0c..601bbe06e6c 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InsertImplicitCasts.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InsertImplicitCasts.kt @@ -28,15 +28,15 @@ import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrField import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrVariable +import org.jetbrains.kotlin.ir.descriptors.IrBasedDeclarationDescriptor import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol -import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.impl.originalKotlinType -import org.jetbrains.kotlin.ir.types.toKotlinType import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid @@ -355,7 +355,7 @@ internal class InsertImplicitCasts( valueType.hasEnhancedNullability() && !expectedType.acceptsNullValues() -> implicitNonNull(valueType, expectedType) - KotlinTypeChecker.DEFAULT.isSubtypeOf(valueType, expectedType.makeNullable()) -> + KotlinTypeChecker.DEFAULT.isSubtypeOf(valueType.toNonIrBased(), expectedType.toNonIrBased().makeNullable()) -> this KotlinBuiltIns.isInt(valueType) && notNullableExpectedType.isBuiltInIntegerType() -> @@ -485,4 +485,23 @@ internal class InsertImplicitCasts( this ) } + + // KotlinType subtype checking fails when one of the types uses IR-based descriptors, the other one regular descriptors. + // This is a kludge to remove IR-based descriptors where possible. + private fun KotlinType.toNonIrBased(): KotlinType { + if (this !is SimpleType) return this + val newDescriptor = constructor.declarationDescriptor?.let { + if (it is IrBasedDeclarationDescriptor<*> && it.owner.symbol.hasDescriptor) + it.owner.symbol.descriptor as ClassifierDescriptor + else + it + } ?: return this + val newArguments = arguments.mapIndexed { index, it -> + if (it.isStarProjection) + StarProjectionImpl((newDescriptor as ClassDescriptor).typeConstructor.parameters[index]) + else + TypeProjectionImpl(it.projectionKind, it.type.toNonIrBased()) + } + return newDescriptor.defaultType.replace(newArguments = newArguments).makeNullableAsSpecified(isMarkedNullable) + } } diff --git a/compiler/testData/ir/irText/expressions/suspendConversionOnArbitraryExpression.kt.txt b/compiler/testData/ir/irText/expressions/suspendConversionOnArbitraryExpression.kt.txt index b56406a3173..41ae8a9e89d 100644 --- a/compiler/testData/ir/irText/expressions/suspendConversionOnArbitraryExpression.kt.txt +++ b/compiler/testData/ir/irText/expressions/suspendConversionOnArbitraryExpression.kt.txt @@ -157,7 +157,7 @@ fun testSmartCastWithSuspendConversion(a: Any) { callee.invoke() } - a::suspendConversion0 + a /*as Function0 */::suspendConversion0 }) } @@ -169,7 +169,7 @@ fun testSmartCastOnVarWithSuspendConversion(a: Any) { callee.invoke() } - b::suspendConversion0 + b /*as Function0 */::suspendConversion0 }) } diff --git a/compiler/testData/ir/irText/expressions/suspendConversionOnArbitraryExpression.txt b/compiler/testData/ir/irText/expressions/suspendConversionOnArbitraryExpression.txt index e779c2032d2..74a8f6f05c5 100644 --- a/compiler/testData/ir/irText/expressions/suspendConversionOnArbitraryExpression.txt +++ b/compiler/testData/ir/irText/expressions/suspendConversionOnArbitraryExpression.txt @@ -227,7 +227,8 @@ FILE fqName: fileName:/suspendConversionOnArbitraryExpression.kt CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=kotlin.Unit origin=null $this: GET_VAR 'callee: kotlin.Function0 declared in .testSmartCastWithSuspendConversion.suspendConversion0' type=kotlin.Function0 origin=null FUNCTION_REFERENCE 'local final fun suspendConversion0 (): kotlin.Unit [suspend] declared in .testSmartCastWithSuspendConversion' type=kotlin.coroutines.SuspendFunction0 origin=SUSPEND_CONVERSION reflectionTarget=null - $receiver: GET_VAR 'a: kotlin.Any declared in .testSmartCastWithSuspendConversion' type=kotlin.Any origin=null + $receiver: TYPE_OP type=kotlin.Function0 origin=IMPLICIT_CAST typeOperand=kotlin.Function0 + GET_VAR 'a: kotlin.Any declared in .testSmartCastWithSuspendConversion' type=kotlin.Any origin=null FUN name:testSmartCastOnVarWithSuspendConversion visibility:public modality:FINAL <> (a:kotlin.Any) returnType:kotlin.Unit VALUE_PARAMETER name:a index:0 type:kotlin.Any BLOCK_BODY @@ -244,7 +245,8 @@ FILE fqName: fileName:/suspendConversionOnArbitraryExpression.kt CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=kotlin.Unit origin=null $this: GET_VAR 'callee: kotlin.Function0 declared in .testSmartCastOnVarWithSuspendConversion.suspendConversion0' type=kotlin.Function0 origin=null FUNCTION_REFERENCE 'local final fun suspendConversion0 (): kotlin.Unit [suspend] declared in .testSmartCastOnVarWithSuspendConversion' type=kotlin.coroutines.SuspendFunction0 origin=SUSPEND_CONVERSION reflectionTarget=null - $receiver: GET_VAR 'var b: kotlin.Any [var] declared in .testSmartCastOnVarWithSuspendConversion' type=kotlin.Any origin=null + $receiver: TYPE_OP type=kotlin.Function0 origin=IMPLICIT_CAST typeOperand=kotlin.Function0 + GET_VAR 'var b: kotlin.Any [var] declared in .testSmartCastOnVarWithSuspendConversion' type=kotlin.Any origin=null FUN name:testSmartCastVsSuspendConversion visibility:public modality:FINAL <> (a:kotlin.Function0) returnType:kotlin.Unit VALUE_PARAMETER name:a index:0 type:kotlin.Function0 BLOCK_BODY