IR: IrTypeOperatorCall.classifierSymbol can be computed from typeOperand

This commit is contained in:
Dmitry Petrov
2019-04-22 17:13:47 +03:00
parent 18c3778250
commit 7a44b0f951
23 changed files with 227 additions and 145 deletions
@@ -1141,7 +1141,7 @@ internal class Fir2IrVisitor(
IrTypeOperatorCallImpl( IrTypeOperatorCallImpl(
startOffset, endOffset, irType, irTypeOperator, irTypeOperand, startOffset, endOffset, irType, irTypeOperator, irTypeOperand,
irTypeOperand.classifierOrFail, typeOperatorCall.argument.toIrExpression() typeOperatorCall.argument.toIrExpression()
) )
} }
} }
@@ -121,7 +121,8 @@ fun IrBuilderWithScope.irCatch(catchParameter: IrVariable) =
fun IrBuilderWithScope.irImplicitCoercionToUnit(arg: IrExpression) = fun IrBuilderWithScope.irImplicitCoercionToUnit(arg: IrExpression) =
IrTypeOperatorCallImpl( IrTypeOperatorCallImpl(
startOffset, endOffset, context.irBuiltIns.unitType, startOffset, endOffset, context.irBuiltIns.unitType,
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT, context.irBuiltIns.unitType, context.irBuiltIns.unitClass, arg IrTypeOperator.IMPLICIT_COERCION_TO_UNIT, context.irBuiltIns.unitType,
arg
) )
open class IrBuildingTransformer(private val context: BackendContext) : IrElementTransformerVoid() { open class IrBuildingTransformer(private val context: BackendContext) : IrElementTransformerVoid() {
@@ -240,6 +240,7 @@ object JsIrBuilder {
fun buildWhen(type: IrType, branches: List<IrBranch>, origin: IrStatementOrigin = SYNTHESIZED_STATEMENT) = fun buildWhen(type: IrType, branches: List<IrBranch>, origin: IrStatementOrigin = SYNTHESIZED_STATEMENT) =
IrWhenImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, origin, branches) IrWhenImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, origin, branches)
// TODO drop type symbol here, it's really not needed
fun buildTypeOperator(type: IrType, operator: IrTypeOperator, argument: IrExpression, toType: IrType, symbol: IrClassifierSymbol) = fun buildTypeOperator(type: IrType, operator: IrTypeOperator, argument: IrExpression, toType: IrType, symbol: IrClassifierSymbol) =
IrTypeOperatorCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, operator, toType, symbol, argument) IrTypeOperatorCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, operator, toType, symbol, argument)
@@ -5,11 +5,11 @@
package org.jetbrains.kotlin.backend.jvm.descriptors package org.jetbrains.kotlin.backend.jvm.descriptors
import org.jetbrains.kotlin.backend.common.descriptors.* import org.jetbrains.kotlin.backend.common.descriptors.WrappedTypeParameterDescriptor
import org.jetbrains.kotlin.backend.common.descriptors.WrappedVariableDescriptor
import org.jetbrains.kotlin.backend.common.ir.SharedVariablesManager import org.jetbrains.kotlin.backend.common.ir.SharedVariablesManager
import org.jetbrains.kotlin.backend.common.ir.addChild import org.jetbrains.kotlin.backend.common.ir.addChild
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.impl.EmptyPackageFragmentDescriptor import org.jetbrains.kotlin.descriptors.impl.EmptyPackageFragmentDescriptor
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
@@ -19,22 +19,25 @@ import org.jetbrains.kotlin.ir.builders.declarations.buildConstructor
import org.jetbrains.kotlin.ir.builders.declarations.buildField import org.jetbrains.kotlin.ir.builders.declarations.buildField
import org.jetbrains.kotlin.ir.builders.declarations.buildValueParameter import org.jetbrains.kotlin.ir.builders.declarations.buildValueParameter
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.* import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrTypeParameterImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol
import org.jetbrains.kotlin.ir.symbols.impl.* import org.jetbrains.kotlin.ir.symbols.impl.IrExternalPackageFragmentSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.ir.types.impl.originalKotlinType
import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.parentAsClass import org.jetbrains.kotlin.ir.util.parentAsClass
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.Variance
private val SHARED_VARIABLE_ORIGIN = object : IrDeclarationOriginImpl("SHARED_VARIABLE_ORIGIN") {} private val SHARED_VARIABLE_ORIGIN = object : IrDeclarationOriginImpl("SHARED_VARIABLE_ORIGIN") {}
private val SHARED_VARIABLE_CONSTRUCTOR_CALL_ORIGIN = object : IrStatementOriginImpl("SHARED_VARIABLE_CONSTRUCTOR_CALL") {} private val SHARED_VARIABLE_CONSTRUCTOR_CALL_ORIGIN = object : IrStatementOriginImpl("SHARED_VARIABLE_CONSTRUCTOR_CALL") {}
@@ -222,7 +225,6 @@ class JvmSharedVariablesManager(
originalGet.type, originalGet.type,
IrTypeOperator.IMPLICIT_CAST, IrTypeOperator.IMPLICIT_CAST,
originalGet.type, originalGet.type,
(originalGet.type as IrSimpleType).classifier,
IrGetFieldImpl( IrGetFieldImpl(
originalGet.startOffset, originalGet.endOffset, originalGet.startOffset, originalGet.endOffset,
getElementFieldSymbol(originalGet.symbol.owner.type), getElementFieldSymbol(originalGet.symbol.owner.type),
@@ -19,14 +19,16 @@ import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrProperty
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.types.typeWith import org.jetbrains.kotlin.ir.types.typeWith
import org.jetbrains.kotlin.ir.util.filterDeclarations import org.jetbrains.kotlin.ir.util.filterDeclarations
import org.jetbrains.kotlin.ir.util.findDeclaration import org.jetbrains.kotlin.ir.util.findDeclaration
@@ -110,7 +112,6 @@ private class FunctionNVarargInvokeLowering(var context: JvmBackendContext) : Cl
backendContext.irBuiltIns.anyNType, backendContext.irBuiltIns.anyNType,
IrTypeOperator.CAST, IrTypeOperator.CAST,
target.returnType, target.returnType,
target.returnType.classifierOrFail,
irCall(target).apply { irCall(target).apply {
dispatchReceiver = irGet(dispatchReceiverParameter!!) dispatchReceiver = irGet(dispatchReceiverParameter!!)
target.valueParameters.forEachIndexed { i, irValueParameter -> target.valueParameters.forEachIndexed { i, irValueParameter ->
@@ -24,11 +24,13 @@ import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.IrBody
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
@@ -200,7 +202,7 @@ private class MakeCallsStatic(
oldReceiver.startOffset, oldReceiver.endOffset, oldReceiver.startOffset, oldReceiver.endOffset,
context.irBuiltIns.unitType, context.irBuiltIns.unitType,
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT, IrTypeOperator.IMPLICIT_COERCION_TO_UNIT,
context.irBuiltIns.unitType, context.irBuiltIns.unitType.classifierOrFail, context.irBuiltIns.unitType,
oldReceiver oldReceiver
) )
@@ -19,7 +19,6 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrFieldAccessExpression import org.jetbrains.kotlin.ir.expressions.IrFieldAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.util.hasAnnotation import org.jetbrains.kotlin.ir.util.hasAnnotation
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
@@ -113,7 +112,7 @@ class PropertiesToFieldsLowering(val context: CommonBackendContext) : IrElementT
receiver.startOffset, receiver.endOffset, receiver.startOffset, receiver.endOffset,
context.irBuiltIns.unitType, context.irBuiltIns.unitType,
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT, IrTypeOperator.IMPLICIT_COERCION_TO_UNIT,
context.irBuiltIns.unitType, context.irBuiltIns.unitType.classifierOrFail, context.irBuiltIns.unitType,
receiver receiver
) )
@@ -27,7 +27,7 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrExpressionWithCopy import org.jetbrains.kotlin.ir.expressions.IrExpressionWithCopy
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.types.classifierOrFail import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.endOffset
@@ -140,6 +140,19 @@ private fun StatementGenerator.generateThisOrSuperReceiver(receiver: ReceiverVal
return generateThisReceiver(ktReceiver.startOffsetSkippingComments, ktReceiver.endOffset, type, classDescriptor) return generateThisReceiver(ktReceiver.startOffsetSkippingComments, ktReceiver.endOffset, type, classDescriptor)
} }
fun IrExpression.implicitCastTo(expectedType: IrType?): IrExpression {
if (expectedType == null) return this
return IrTypeOperatorCallImpl(
startOffset, endOffset,
expectedType,
IrTypeOperator.IMPLICIT_CAST,
expectedType
).also {
it.argument = this
}
}
fun StatementGenerator.generateBackingFieldReceiver( fun StatementGenerator.generateBackingFieldReceiver(
startOffset: Int, startOffset: Int,
endOffset: Int, endOffset: Int,
@@ -167,8 +180,7 @@ fun StatementGenerator.generateCallReceiver(
assert(dispatchReceiver == null) { assert(dispatchReceiver == null) {
"Call for member imported from object $calleeDescriptor has non-null dispatch receiver $dispatchReceiver" "Call for member imported from object $calleeDescriptor has non-null dispatch receiver $dispatchReceiver"
} }
dispatchReceiverValue = dispatchReceiverValue = generateReceiverForCalleeImportedFromObject(startOffset, endOffset, calleeDescriptor)
generateReceiverForCalleeImportedFromObject(startOffset, endOffset, calleeDescriptor)
extensionReceiverValue = generateReceiverOrNull(ktDefaultElement, extensionReceiver) extensionReceiverValue = generateReceiverOrNull(ktDefaultElement, extensionReceiver)
} }
is TypeAliasConstructorDescriptor -> { is TypeAliasConstructorDescriptor -> {
@@ -291,15 +303,7 @@ fun StatementGenerator.castArgumentToFunctionalInterfaceForSamType(
val kotlinFunctionType = samConversion.getFunctionTypeForSAMClass(samClassDescriptor) val kotlinFunctionType = samConversion.getFunctionTypeForSAMClass(samClassDescriptor)
val irFunctionType = context.typeTranslator.translateType(kotlinFunctionType) val irFunctionType = context.typeTranslator.translateType(kotlinFunctionType)
return IrTypeOperatorCallImpl( return irExpression.implicitCastTo(irFunctionType)
irExpression.startOffset, irExpression.endOffset,
irFunctionType,
IrTypeOperator.IMPLICIT_CAST,
irFunctionType
).apply {
argument = irExpression
typeOperandClassifier = irFunctionType.classifierOrFail
}
} }
fun Generator.getSuperQualifier(resolvedCall: ResolvedCall<*>): ClassDescriptor? { fun Generator.getSuperQualifier(resolvedCall: ResolvedCall<*>): ClassDescriptor? {
@@ -429,7 +433,6 @@ fun StatementGenerator.generateSamConversionForValueArgumentsIfRequired(call: Ca
val originalArgument = call.irValueArgumentsByIndex[i] ?: continue val originalArgument = call.irValueArgumentsByIndex[i] ?: continue
val targetType = underlyingParameterType.toIrType() val targetType = underlyingParameterType.toIrType()
val targetClassifier = targetType.classifierOrFail
call.irValueArgumentsByIndex[i] = call.irValueArgumentsByIndex[i] =
IrTypeOperatorCallImpl( IrTypeOperatorCallImpl(
@@ -437,7 +440,6 @@ fun StatementGenerator.generateSamConversionForValueArgumentsIfRequired(call: Ca
targetType, targetType,
IrTypeOperator.SAM_CONVERSION, IrTypeOperator.SAM_CONVERSION,
targetType, targetType,
targetClassifier,
castArgumentToFunctionalInterfaceForSamType(originalArgument, underlyingParameterType) castArgumentToFunctionalInterfaceForSamType(originalArgument, underlyingParameterType)
) )
} }
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.psi2ir.intermediate.*
import org.jetbrains.kotlin.psi2ir.unwrappedGetMethod import org.jetbrains.kotlin.psi2ir.unwrappedGetMethod
import org.jetbrains.kotlin.psi2ir.unwrappedSetMethod import org.jetbrains.kotlin.psi2ir.unwrappedSetMethod
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.PropertyImportedFromObject
import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.tasks.isDynamic import org.jetbrains.kotlin.resolve.calls.tasks.isDynamic
@@ -301,6 +302,12 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen
} }
} }
private fun PropertyDescriptor.unwrapPropertyDescriptor() =
when (this) {
is PropertyImportedFromObject -> callableFromObject
else -> this
}
private fun createPropertyLValue( private fun createPropertyLValue(
ktExpression: KtExpression, ktExpression: KtExpression,
descriptor: PropertyDescriptor, descriptor: PropertyDescriptor,
@@ -311,8 +318,9 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen
): PropertyLValueBase { ): PropertyLValueBase {
val superQualifierSymbol = superQualifier?.let { context.symbolTable.referenceClass(it) } val superQualifierSymbol = superQualifier?.let { context.symbolTable.referenceClass(it) }
val getterDescriptor = descriptor.unwrappedGetMethod val unwrappedPropertyDescriptor = descriptor.unwrapPropertyDescriptor()
val setterDescriptor = descriptor.unwrappedSetMethod val getterDescriptor = unwrappedPropertyDescriptor.unwrappedGetMethod
val setterDescriptor = unwrappedPropertyDescriptor.unwrappedSetMethod
val getterSymbol = getterDescriptor?.let { context.symbolTable.referenceFunction(it.original) } val getterSymbol = getterDescriptor?.let { context.symbolTable.referenceFunction(it.original) }
val setterSymbol = setterDescriptor?.let { context.symbolTable.referenceFunction(it.original) } val setterSymbol = setterDescriptor?.let { context.symbolTable.referenceFunction(it.original) }
@@ -341,7 +349,7 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen
context, context,
scope, scope,
ktExpression.startOffsetSkippingComments, ktExpression.endOffset, origin, ktExpression.startOffsetSkippingComments, ktExpression.endOffset, origin,
context.symbolTable.referenceField(descriptor), context.symbolTable.referenceField(unwrappedPropertyDescriptor.original),
propertyIrType, propertyIrType,
propertyReceiver, propertyReceiver,
superQualifierSymbol superQualifierSymbol
@@ -207,12 +207,11 @@ class BranchingExpressionGenerator(statementGenerator: StatementGenerator) : Sta
private fun generateIsPatternCondition(irSubject: IrVariable, ktCondition: KtWhenConditionIsPattern): IrExpression { private fun generateIsPatternCondition(irSubject: IrVariable, ktCondition: KtWhenConditionIsPattern): IrExpression {
val typeOperand = getOrFail(BindingContext.TYPE, ktCondition.typeReference) val typeOperand = getOrFail(BindingContext.TYPE, ktCondition.typeReference)
val irTypeOperand = typeOperand.toIrType() val irTypeOperand = typeOperand.toIrType()
val typeSymbol = irTypeOperand.classifierOrNull ?: throw AssertionError("Not a classifier type: $typeOperand")
val irInstanceOf = IrTypeOperatorCallImpl( val irInstanceOf = IrTypeOperatorCallImpl(
ktCondition.startOffsetSkippingComments, ktCondition.endOffset, ktCondition.startOffsetSkippingComments, ktCondition.endOffset,
context.irBuiltIns.booleanType, context.irBuiltIns.booleanType,
IrTypeOperator.INSTANCEOF, IrTypeOperator.INSTANCEOF,
irTypeOperand, typeSymbol, irTypeOperand,
irSubject.defaultLoad() irSubject.defaultLoad()
) )
return if (ktCondition.isNegated) return if (ktCondition.isNegated)
@@ -75,7 +75,6 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
targetType, targetType,
IrTypeOperator.SAM_CONVERSION, IrTypeOperator.SAM_CONVERSION,
targetType, targetType,
targetType.classifierOrFail,
statementGenerator.castArgumentToFunctionalInterfaceForSamType( statementGenerator.castArgumentToFunctionalInterfaceForSamType(
call.irValueArgumentsByIndex[0]!!, call.irValueArgumentsByIndex[0]!!,
targetKotlinType targetKotlinType
@@ -25,7 +25,6 @@ import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.types.impl.originalKotlinType import org.jetbrains.kotlin.ir.types.impl.originalKotlinType
import org.jetbrains.kotlin.ir.types.makeNotNull import org.jetbrains.kotlin.ir.types.makeNotNull
import org.jetbrains.kotlin.ir.util.referenceClassifier
import org.jetbrains.kotlin.ir.util.referenceFunction import org.jetbrains.kotlin.ir.util.referenceFunction
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
@@ -104,7 +103,6 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
return IrTypeOperatorCallImpl( return IrTypeOperatorCallImpl(
expression.startOffsetSkippingComments, expression.endOffset, resultType.toIrType(), irOperator, rhsType.toIrType(), expression.startOffsetSkippingComments, expression.endOffset, resultType.toIrType(), irOperator, rhsType.toIrType(),
context.symbolTable.referenceClassifier(rhsType.constructor.declarationDescriptor!!),
expression.left.genExpr() expression.left.genExpr()
) )
} }
@@ -117,7 +115,6 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
return IrTypeOperatorCallImpl( return IrTypeOperatorCallImpl(
expression.startOffsetSkippingComments, expression.endOffset, context.irBuiltIns.booleanType, irOperator, expression.startOffsetSkippingComments, expression.endOffset, context.irBuiltIns.booleanType, irOperator,
againstType.toIrType(), againstType.toIrType(),
context.symbolTable.referenceClassifier(againstType.constructor.declarationDescriptor!!),
expression.leftHandSide.genExpr() expression.leftHandSide.genExpr()
) )
} }
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.psi2ir.transformations package org.jetbrains.kotlin.psi2ir.transformations
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
@@ -32,119 +31,151 @@ import org.jetbrains.kotlin.ir.types.impl.originalKotlinType
import org.jetbrains.kotlin.ir.util.TypeTranslator import org.jetbrains.kotlin.ir.util.TypeTranslator
import org.jetbrains.kotlin.ir.util.coerceToUnitIfNeeded import org.jetbrains.kotlin.ir.util.coerceToUnitIfNeeded
import org.jetbrains.kotlin.ir.util.parentAsClass import org.jetbrains.kotlin.ir.util.parentAsClass
import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext
import org.jetbrains.kotlin.psi2ir.generators.GeneratorExtensions
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.isDynamic
import org.jetbrains.kotlin.types.isNullabilityFlexible import org.jetbrains.kotlin.types.isNullabilityFlexible
import org.jetbrains.kotlin.types.typeUtil.isUnit import org.jetbrains.kotlin.types.typeUtil.isUnit
fun insertImplicitCasts(element: IrElement, context: GeneratorContext) { fun insertImplicitCasts(element: IrElement, context: GeneratorContext) {
element.transformChildren( element.transformChildren(
InsertImplicitCasts(context.builtIns, context.irBuiltIns, context.typeTranslator, context.extensions.samConversion), InsertImplicitCasts(context.irBuiltIns, context.typeTranslator),
null null
) )
} }
open class InsertImplicitCasts( open class InsertImplicitCasts(
private val builtIns: KotlinBuiltIns,
private val irBuiltIns: IrBuiltIns, private val irBuiltIns: IrBuiltIns,
private val typeTranslator: TypeTranslator, private val typeTranslator: TypeTranslator
private val samConversion: GeneratorExtensions.SamConversion
) : IrElementTransformerVoid() { ) : IrElementTransformerVoid() {
// override fun visitCallableReference(expression: IrCallableReference): IrExpression = private fun getDeclarationTypeParameters(declaration: IrFunction): List<IrTypeParameterSymbol> {
// expression.transformPostfix { return (declaration.typeParameters + if (declaration is IrConstructor) declaration.parentAsClass.typeParameters else emptyList())
// transformReceiverArguments() .map { it.symbol }
// }
private fun getDeclarationSideTypeParameters(declaration: IrFunction): List<IrTypeParameterSymbol> {
return run {
declaration.typeParameters + if (declaration is IrConstructor) declaration.parentAsClass.typeParameters else emptyList()
}.map { it.symbol }
} }
private fun getTypeSideTypeParameters(declaration: IrFunction): List<IrTypeParameterSymbol> { private fun getDispatchReceiverTypeParameters(declaration: IrDeclaration): List<IrTypeParameterSymbol> {
return declaration.dispatchReceiverParameter?.run { val classWithTypeParameters =
extractTypeParameters(declaration.parentAsClass).map { it.symbol } if (declaration.isNonStaticMemberDeclaration())
} ?: emptyList() declaration.parentAsClass
else
return emptyList()
return extractTypeParameters(classWithTypeParameters).map { it.symbol }
} }
private fun getTypeArguments(expression: IrMemberAccessExpression, declarationTypeParameters: List<IrTypeParameterSymbol>): List<IrTypeArgument> { private fun IrDeclaration.isNonStaticMemberDeclaration() =
this is IrFunction && dispatchReceiverParameter != null ||
this is IrField && !isStatic
val expressionTypeArguments = private fun getTypeArguments(
declarationTypeParameters.map { p -> makeTypeProjection(expression.getTypeArgument(p.owner.index)!!, p.owner.variance) } expression: IrExpression,
declarationTypeParameters: List<IrTypeParameterSymbol>
val receiverTypeArguments = expression.dispatchReceiver?.type?.let { (it as? IrSimpleType)?.arguments } ?: emptyList() ): List<IrTypeArgument> =
when (expression) {
return expressionTypeArguments + receiverTypeArguments is IrMemberAccessExpression -> {
} val expressionTypeArguments = declarationTypeParameters.map { p ->
makeTypeProjection(expression.getTypeArgument(p.owner.index)!!, p.owner.variance)
private fun IrType.substitute(typeParameters: List<IrTypeParameterSymbol>, typeArguments: List<IrTypeArgument>): IrType { }
return IrTypeSubstitutor(typeParameters.distinct(), typeArguments, irBuiltIns).substitute(this) val receiverTypeArguments = expression.dispatchReceiver.getTypeArgumentsForReceiver()
} expressionTypeArguments + receiverTypeArguments
}
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression { is IrFieldAccessExpression -> {
return expression.transformPostfix { expression.receiver.getTypeArgumentsForReceiver()
val declaration = symbol.owner }
val dTypeParameters = getDeclarationSideTypeParameters(declaration) else -> {
val cTypeParameters = getTypeSideTypeParameters(declaration) throw AssertionError("Unexpected expression: ${expression.render()}")
val typeArguments = getTypeArguments(expression, dTypeParameters) }
dispatchReceiver = dispatchReceiver?.cast(declaration.dispatchReceiverParameter?.type?.substitute(dTypeParameters + cTypeParameters, typeArguments))
extensionReceiver = extensionReceiver?.cast(declaration.extensionReceiverParameter?.type?.substitute(dTypeParameters + cTypeParameters, typeArguments))
} }
private fun IrExpression?.getTypeArgumentsForReceiver(): List<IrTypeArgument> {
if (this == null) return emptyList()
val expressionType = type as? IrSimpleType ?: return emptyList()
return expressionType.arguments
} }
override fun visitPropertyReference(expression: IrPropertyReference): IrExpression { private fun IrType.substitute(typeParameters: List<IrTypeParameterSymbol>, typeArguments: List<IrTypeArgument>): IrType =
return expression.transformPostfix { IrTypeSubstitutor(typeParameters.distinct(), typeArguments, irBuiltIns).substitute(this)
val dispatchReceiver = expression.run { getter?.owner?.dispatchReceiverParameter ?: setter?.owner?.dispatchReceiverParameter }
val extensionReceiver = expression.run { getter?.owner?.extensionReceiverParameter ?: setter?.owner?.extensionReceiverParameter } override fun visitFunctionReference(expression: IrFunctionReference): IrExpression =
expression.transformPostfix {
val declaration = symbol.owner
val declarationTypeParameters = getDeclarationTypeParameters(declaration)
val dispatchReceiverTypeParameters = getDispatchReceiverTypeParameters(declaration)
val typeParameters = declarationTypeParameters + dispatchReceiverTypeParameters
val typeArguments = getTypeArguments(expression, declarationTypeParameters)
dispatchReceiver = dispatchReceiver?.cast(
declaration.dispatchReceiverParameter?.type?.substitute(typeParameters, typeArguments)
)
extensionReceiver = extensionReceiver?.cast(
declaration.extensionReceiverParameter?.type?.substitute(typeParameters, typeArguments)
)
}
override fun visitPropertyReference(expression: IrPropertyReference): IrExpression =
expression.transformPostfix {
val dispatchReceiver = expression.run {
getter?.owner?.dispatchReceiverParameter
?: setter?.owner?.dispatchReceiverParameter
}
val extensionReceiver = expression.run {
getter?.owner?.extensionReceiverParameter
?: setter?.owner?.extensionReceiverParameter
}
this.dispatchReceiver = this.dispatchReceiver?.cast(dispatchReceiver?.type) this.dispatchReceiver = this.dispatchReceiver?.cast(dispatchReceiver?.type)
this.extensionReceiver = this.extensionReceiver?.cast(extensionReceiver?.type) this.extensionReceiver = this.extensionReceiver?.cast(extensionReceiver?.type)
} }
}
override fun visitLocalDelegatedPropertyReference(expression: IrLocalDelegatedPropertyReference): IrExpression { override fun visitLocalDelegatedPropertyReference(expression: IrLocalDelegatedPropertyReference): IrExpression =
return expression.transformPostfix { expression.transformPostfix {
val declaration = expression.getter.owner val declaration = expression.getter.owner
val dTypeParameters = getDeclarationSideTypeParameters(declaration) val declarationTypeParameters = getDeclarationTypeParameters(declaration)
val cTypeParameters = getTypeSideTypeParameters(declaration) val receiverTypeParameters = getDispatchReceiverTypeParameters(declaration)
val typeArguments = getTypeArguments(expression, dTypeParameters) val typeParameters = declarationTypeParameters + receiverTypeParameters
val typeArguments = getTypeArguments(expression, declarationTypeParameters)
dispatchReceiver = dispatchReceiver?.cast( dispatchReceiver = dispatchReceiver?.cast(
declaration.dispatchReceiverParameter?.type?.substitute(dTypeParameters + cTypeParameters, typeArguments) declaration.dispatchReceiverParameter?.run {
type.substitute(typeParameters, typeArguments)
}
) )
extensionReceiver = extensionReceiver?.cast( extensionReceiver = extensionReceiver?.cast(
declaration.extensionReceiverParameter?.type?.substitute(dTypeParameters + cTypeParameters, typeArguments) declaration.extensionReceiverParameter?.run {
type.substitute(typeParameters, typeArguments)
}
) )
} }
}
private fun IrMemberAccessExpression.transformReceiverArguments() { private fun IrMemberAccessExpression.transformReceiverArguments() {
val declaration = (this as IrFunctionAccessExpression).symbol.owner val declaration = (this as IrFunctionAccessExpression).symbol.owner
val dTypeParameters = getDeclarationSideTypeParameters(declaration) val declarationTypeParameters = getDeclarationTypeParameters(declaration)
val cTypeParameters = getTypeSideTypeParameters(declaration) val receiverTypeParameters = getDispatchReceiverTypeParameters(declaration)
val typeArguments = getTypeArguments(this, dTypeParameters) val typeParameters = declarationTypeParameters + receiverTypeParameters
val typeArguments = getTypeArguments(this, declarationTypeParameters)
dispatchReceiver = dispatchReceiver?.cast( dispatchReceiver = dispatchReceiver?.cast(
declaration.dispatchReceiverParameter?.type?.substitute(dTypeParameters + cTypeParameters, typeArguments) declaration.dispatchReceiverParameter?.run {
type.substitute(typeParameters, typeArguments)
}
) )
extensionReceiver = extensionReceiver?.cast( extensionReceiver = extensionReceiver?.cast(
declaration.extensionReceiverParameter?.type?.substitute(dTypeParameters + cTypeParameters, typeArguments) declaration.extensionReceiverParameter?.run {
type.substitute(typeParameters, typeArguments)
}
) )
} }
override fun visitMemberAccess(expression: IrMemberAccessExpression): IrExpression = override fun visitMemberAccess(expression: IrMemberAccessExpression): IrExpression =
with (expression as IrFunctionAccessExpression) { with(expression as IrFunctionAccessExpression) {
val declaration = symbol.owner val declaration = symbol.owner
val dTypeParameters = getDeclarationSideTypeParameters(declaration) val declarationTypeParameters = getDeclarationTypeParameters(declaration)
val cTypeParameters = getTypeSideTypeParameters(declaration) val receiverTypeParameters = getDispatchReceiverTypeParameters(declaration)
val typeArguments = getTypeArguments(expression, dTypeParameters) val typeArguments = getTypeArguments(expression, declarationTypeParameters)
val typeParameters = declarationTypeParameters + receiverTypeParameters
transformPostfix { transformPostfix {
transformReceiverArguments() transformReceiverArguments()
for (index in declaration.valueParameters.indices) { for (index in declaration.valueParameters.indices) {
val argument = getValueArgument(index) ?: continue val argument = getValueArgument(index) ?: continue
val parameterType = declaration.valueParameters[index].type.substitute(dTypeParameters + cTypeParameters, typeArguments) val parameterType = declaration.valueParameters[index].type.substitute(typeParameters, typeArguments)
putValueArgument(index, argument.cast(parameterType)) putValueArgument(index, argument.cast(parameterType))
} }
} }
@@ -189,9 +220,29 @@ open class InsertImplicitCasts(
value = value.cast(expression.symbol.owner.type) value = value.cast(expression.symbol.owner.type)
} }
override fun visitGetField(expression: IrGetField): IrExpression =
expression.transformPostfix {
val declaration = expression.symbol.owner
val receiverTypeParameters = getDispatchReceiverTypeParameters(declaration)
val typeArguments = getTypeArguments(expression, receiverTypeParameters)
receiver = receiver?.cast(
declaration.parentAsClass.thisReceiver?.run {
type.substitute(receiverTypeParameters, typeArguments)
}
)
}
override fun visitSetField(expression: IrSetField): IrExpression = override fun visitSetField(expression: IrSetField): IrExpression =
expression.transformPostfix { expression.transformPostfix {
value = value.cast(expression.symbol.owner.type) val declaration = expression.symbol.owner
val receiverTypeParameters = getDispatchReceiverTypeParameters(declaration)
val typeArguments = getTypeArguments(expression, receiverTypeParameters)
receiver = receiver?.cast(
declaration.parentAsClass.thisReceiver?.run {
type.substitute(receiverTypeParameters, typeArguments)
}
)
value = value.cast(expression.symbol.owner.type.substitute(receiverTypeParameters, typeArguments))
} }
override fun visitVariable(declaration: IrVariable): IrVariable = override fun visitVariable(declaration: IrVariable): IrVariable =
@@ -248,13 +299,15 @@ open class InsertImplicitCasts(
finallyExpression = finallyExpression?.coerceToUnit() finallyExpression = finallyExpression?.coerceToUnit()
} }
override fun visitTypeOperator(expression: IrTypeOperatorCall): IrExpression = override fun visitTypeOperator(expression: IrTypeOperatorCall): IrExpression {
when (expression.operator) { expression.transformChildren()
return when (expression.operator) {
IrTypeOperator.IMPLICIT_CAST -> IrTypeOperator.IMPLICIT_CAST ->
expression.argument.cast(expression.typeOperand) expression.argument.cast(expression.typeOperand)
else -> else ->
super.visitTypeOperator(expression) super.visitTypeOperator(expression)
} }
}
override fun visitVararg(expression: IrVararg): IrExpression = override fun visitVararg(expression: IrVararg): IrExpression =
expression.transformPostfix { expression.transformPostfix {
@@ -333,7 +386,7 @@ open class InsertImplicitCasts(
endOffset, endOffset,
targetType, targetType,
typeOperator, typeOperator,
targetType, targetType.classifierOrFail, targetType,
this this
) )
} }
@@ -342,19 +395,6 @@ open class InsertImplicitCasts(
return coerceToUnitIfNeeded(type, irBuiltIns) return coerceToUnitIfNeeded(type, irBuiltIns)
} }
protected fun getKotlinType(irExpression: IrExpression) =
irExpression.type.originalKotlinType!!
private fun KotlinType.isBuiltInIntegerType(): Boolean =
KotlinBuiltIns.isByte(this) ||
KotlinBuiltIns.isShort(this) ||
KotlinBuiltIns.isInt(this) ||
KotlinBuiltIns.isLong(this) ||
KotlinBuiltIns.isUByte(this) ||
KotlinBuiltIns.isUShort(this) ||
KotlinBuiltIns.isUInt(this) ||
KotlinBuiltIns.isULong(this)
private fun IrType.isBuiltInIntegerType(): Boolean = private fun IrType.isBuiltInIntegerType(): Boolean =
isByte() || isShort() || isInt() || isLong() || isByte() || isShort() || isInt() || isLong() ||
isUByte() || isUShort() || isUInt() || isULong() isUByte() || isUShort() || isUInt() || isULong()
@@ -316,7 +316,7 @@ fun IrBuilderWithScope.typeOperator(
typeOperator: IrTypeOperator, typeOperator: IrTypeOperator,
typeOperand: IrType typeOperand: IrType
) = ) =
IrTypeOperatorCallImpl(startOffset, endOffset, resultType, typeOperator, typeOperand, typeOperand.classifierOrFail, argument) IrTypeOperatorCallImpl(startOffset, endOffset, resultType, typeOperator, typeOperand, argument)
fun IrBuilderWithScope.irIs(argument: IrExpression, type: IrType) = fun IrBuilderWithScope.irIs(argument: IrExpression, type: IrType) =
typeOperator(context.irBuiltIns.booleanType, argument, IrTypeOperator.INSTANCEOF, type) typeOperator(context.irBuiltIns.booleanType, argument, IrTypeOperator.INSTANCEOF, type)
@@ -325,10 +325,10 @@ fun IrBuilderWithScope.irNotIs(argument: IrExpression, type: IrType) =
typeOperator(context.irBuiltIns.booleanType, argument, IrTypeOperator.NOT_INSTANCEOF, type) typeOperator(context.irBuiltIns.booleanType, argument, IrTypeOperator.NOT_INSTANCEOF, type)
fun IrBuilderWithScope.irAs(argument: IrExpression, type: IrType) = fun IrBuilderWithScope.irAs(argument: IrExpression, type: IrType) =
IrTypeOperatorCallImpl(startOffset, endOffset, type, IrTypeOperator.CAST, type, type.classifierOrFail, argument) IrTypeOperatorCallImpl(startOffset, endOffset, type, IrTypeOperator.CAST, type, argument)
fun IrBuilderWithScope.irImplicitCast(argument: IrExpression, type: IrType) = fun IrBuilderWithScope.irImplicitCast(argument: IrExpression, type: IrType) =
IrTypeOperatorCallImpl(startOffset, endOffset, type, IrTypeOperator.IMPLICIT_CAST, type, type.classifierOrFail, argument) IrTypeOperatorCallImpl(startOffset, endOffset, type, IrTypeOperator.IMPLICIT_CAST, type, argument)
fun IrBuilderWithScope.irInt(value: Int) = fun IrBuilderWithScope.irInt(value: Int) =
IrConstImpl.int(startOffset, endOffset, context.irBuiltIns.intType, value) IrConstImpl.int(startOffset, endOffset, context.irBuiltIns.intType, value)
@@ -11,8 +11,10 @@ import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
interface IrField : IrSymbolDeclaration<IrFieldSymbol>, IrOverridableDeclaration<IrFieldSymbol>, interface IrField :
IrSymbolDeclaration<IrFieldSymbol>, IrOverridableDeclaration<IrFieldSymbol>,
IrDeclarationWithName, IrDeclarationWithVisibility, IrDeclarationParent { IrDeclarationWithName, IrDeclarationWithVisibility, IrDeclarationParent {
override val descriptor: PropertyDescriptor override val descriptor: PropertyDescriptor
val type: IrType val type: IrType
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
@@ -35,8 +36,22 @@ class IrTypeOperatorCallImpl(
IrTypeOperatorCall { IrTypeOperatorCall {
override lateinit var argument: IrExpression override lateinit var argument: IrExpression
override lateinit var typeOperandClassifier: IrClassifierSymbol
override val typeOperandClassifier: IrClassifierSymbol
get() = typeOperand.classifierOrFail
constructor(
startOffset: Int,
endOffset: Int,
type: IrType,
operator: IrTypeOperator,
typeOperand: IrType,
argument: IrExpression
) : this(startOffset, endOffset, type, operator, typeOperand) {
this.argument = argument
}
@Deprecated("Doesn't require typeOperandClassifier")
constructor( constructor(
startOffset: Int, startOffset: Int,
endOffset: Int, endOffset: Int,
@@ -47,7 +62,6 @@ class IrTypeOperatorCallImpl(
argument: IrExpression argument: IrExpression
) : this(startOffset, endOffset, type, operator, typeOperand) { ) : this(startOffset, endOffset, type, operator, typeOperand) {
this.argument = argument this.argument = argument
this.typeOperandClassifier = typeOperandClassifier
} }
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R = override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
@@ -7,8 +7,10 @@ package org.jetbrains.kotlin.ir.types
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.types.impl.* import org.jetbrains.kotlin.ir.types.impl.buildSimpleType
import org.jetbrains.kotlin.types.TypeSubstitutor import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.ir.types.impl.toBuilder
import org.jetbrains.kotlin.ir.util.render
class IrTypeSubstitutor( class IrTypeSubstitutor(
@@ -16,6 +18,16 @@ class IrTypeSubstitutor(
typeArguments: List<IrTypeArgument>, typeArguments: List<IrTypeArgument>,
private val irBuiltIns: IrBuiltIns private val irBuiltIns: IrBuiltIns
) { ) {
init {
assert(typeParameters.size == typeArguments.size) {
"Unexpected number of type arguments: ${typeArguments.size}\n" +
"Type parameters are:\n" +
typeParameters.joinToString(separator = "\n") { it.owner.render() } +
"Type arguments are:\n" +
typeArguments.joinToString(separator = "\n") { it.render() }
}
}
private val substitution = typeParameters.zip(typeArguments).toMap() private val substitution = typeParameters.zip(typeArguments).toMap()
private fun IrType.typeParameterConstructor(): IrTypeParameterSymbol? { private fun IrType.typeParameterConstructor(): IrTypeParameterSymbol? {
@@ -23,16 +35,17 @@ class IrTypeSubstitutor(
else null else null
} }
private fun getSubstitutionArgument(typeParameter: IrTypeParameterSymbol): IrTypeArgument =
substitution[typeParameter]
?: throw AssertionError("Unsubstituted type parameter: ${typeParameter.owner.render()}")
fun substitute(type: IrType): IrType { fun substitute(type: IrType): IrType {
if (substitution.isEmpty()) return type if (substitution.isEmpty()) return type
return type.typeParameterConstructor()?.let { return type.typeParameterConstructor()?.let {
// check whether it's T or T? when (val typeArgument = getSubstitutionArgument(it)) {
val isNullable = type.isMarkedNullable() is IrStarProjection -> irBuiltIns.anyNType // TODO upper bound for T
val typeArgument = substitution.getValue(it) is IrTypeProjection -> typeArgument.type.run { if (type.isMarkedNullable()) makeNullable() else this }
when (typeArgument) {
is IrStarProjection -> if (isNullable) irBuiltIns.anyNType else irBuiltIns.anyType
is IrTypeProjection -> with(typeArgument.type) { if (isNullable) makeNullable() else makeNotNull() }
else -> error("unknown type argument") else -> error("unknown type argument")
} }
} ?: substituteType(type) } ?: substituteType(type)
@@ -61,7 +74,7 @@ class IrTypeSubstitutor(
if (type is IrSimpleType) { if (type is IrSimpleType) {
val classifier = type.classifier val classifier = type.classifier
if (classifier is IrTypeParameterSymbol) { if (classifier is IrTypeParameterSymbol) {
val newArgument = substitution.getValue(classifier) val newArgument = getSubstitutionArgument(classifier)
return if (newArgument is IrTypeProjection) { return if (newArgument is IrTypeProjection) {
makeTypeProjection(newArgument.type, typeArgument.variance) makeTypeProjection(newArgument.type, typeArgument.variance)
} else newArgument } else newArgument
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
import org.jetbrains.kotlin.ir.declarations.lazy.* import org.jetbrains.kotlin.ir.declarations.lazy.*
import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl
@@ -618,7 +618,6 @@ open class DeepCopyIrTreeWithSymbols(
expression.type.remapType(), expression.type.remapType(),
expression.operator, expression.operator,
expression.typeOperand.remapType(), expression.typeOperand.remapType(),
symbolRemapper.getReferencedClassifier(expression.typeOperandClassifier),
expression.argument.transform() expression.argument.transform()
) )
@@ -17,8 +17,6 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
@@ -154,7 +152,7 @@ fun IrExpression.coerceToUnitIfNeeded(valueType: KotlinType, irBuiltIns: IrBuilt
startOffset, endOffset, startOffset, endOffset,
irBuiltIns.unitType, irBuiltIns.unitType,
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT, IrTypeOperator.IMPLICIT_COERCION_TO_UNIT,
irBuiltIns.unitType, irBuiltIns.unitType.classifierOrFail, irBuiltIns.unitType,
this this
) )
} }
@@ -167,7 +165,7 @@ fun IrExpression.coerceToUnitIfNeeded(valueType: IrType, irBuiltIns: IrBuiltIns)
startOffset, endOffset, startOffset, endOffset,
irBuiltIns.unitType, irBuiltIns.unitType,
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT, IrTypeOperator.IMPLICIT_COERCION_TO_UNIT,
irBuiltIns.unitType, irBuiltIns.unitType.classifierOrFail, irBuiltIns.unitType,
this this
) )
} }
@@ -688,6 +688,13 @@ private fun IrDeclaration.renderDeclarationParentFqn(sb: StringBuilder) {
fun IrType.render() = RenderIrElementVisitor().renderType(this) fun IrType.render() = RenderIrElementVisitor().renderType(this)
fun IrTypeArgument.render() =
when (this) {
is IrStarProjection -> "*"
is IrTypeProjection -> "$variance ${type.render()}"
else -> throw AssertionError("Unexpected IrTypeArgument: $this")
}
internal inline fun <T> StringBuilder.appendListWith( internal inline fun <T> StringBuilder.appendListWith(
list: List<T>, list: List<T>,
prefix: String, prefix: String,
@@ -558,7 +558,6 @@ abstract class IrModuleDeserializer(
val argument = deserializeExpression(proto.argument) val argument = deserializeExpression(proto.argument)
return IrTypeOperatorCallImpl(start, end, type, operator, operand).apply { return IrTypeOperatorCallImpl(start, end, type, operator, operand).apply {
this.argument = argument this.argument = argument
this.typeOperandClassifier = operand.classifierOrFail
} }
} }