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:
+22
-3
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -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
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
+4
-2
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user