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.
This commit is contained in:
Georgy Bronnikov
2020-12-10 16:13:54 +03:00
parent 99c874ba8a
commit b35d4134a7
3 changed files with 28 additions and 7 deletions
@@ -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)
}
}
@@ -157,7 +157,7 @@ fun testSmartCastWithSuspendConversion(a: Any) {
callee.invoke()
}
a::suspendConversion0
a /*as Function0<Unit> */::suspendConversion0
})
}
@@ -169,7 +169,7 @@ fun testSmartCastOnVarWithSuspendConversion(a: Any) {
callee.invoke()
}
b::suspendConversion0
b /*as Function0<Unit> */::suspendConversion0
})
}
@@ -227,7 +227,8 @@ FILE fqName:<root> 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<kotlin.Unit> declared in <root>.testSmartCastWithSuspendConversion.suspendConversion0' type=kotlin.Function0<kotlin.Unit> origin=null
FUNCTION_REFERENCE 'local final fun suspendConversion0 (): kotlin.Unit [suspend] declared in <root>.testSmartCastWithSuspendConversion' type=kotlin.coroutines.SuspendFunction0<kotlin.Unit> origin=SUSPEND_CONVERSION reflectionTarget=null
$receiver: GET_VAR 'a: kotlin.Any declared in <root>.testSmartCastWithSuspendConversion' type=kotlin.Any origin=null
$receiver: TYPE_OP type=kotlin.Function0<kotlin.Unit> origin=IMPLICIT_CAST typeOperand=kotlin.Function0<kotlin.Unit>
GET_VAR 'a: kotlin.Any declared in <root>.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:<root> 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<kotlin.Unit> declared in <root>.testSmartCastOnVarWithSuspendConversion.suspendConversion0' type=kotlin.Function0<kotlin.Unit> origin=null
FUNCTION_REFERENCE 'local final fun suspendConversion0 (): kotlin.Unit [suspend] declared in <root>.testSmartCastOnVarWithSuspendConversion' type=kotlin.coroutines.SuspendFunction0<kotlin.Unit> origin=SUSPEND_CONVERSION reflectionTarget=null
$receiver: GET_VAR 'var b: kotlin.Any [var] declared in <root>.testSmartCastOnVarWithSuspendConversion' type=kotlin.Any origin=null
$receiver: TYPE_OP type=kotlin.Function0<kotlin.Unit> origin=IMPLICIT_CAST typeOperand=kotlin.Function0<kotlin.Unit>
GET_VAR 'var b: kotlin.Any [var] declared in <root>.testSmartCastOnVarWithSuspendConversion' type=kotlin.Any origin=null
FUN name:testSmartCastVsSuspendConversion visibility:public modality:FINAL <> (a:kotlin.Function0<kotlin.Unit>) returnType:kotlin.Unit
VALUE_PARAMETER name:a index:0 type:kotlin.Function0<kotlin.Unit>
BLOCK_BODY