[FIR2IR] Get rid of most of usages IrSymbol.owner from CallAndReferenceGenerator
^KT-60924
This commit is contained in:
committed by
Space Team
parent
ff1c38872e
commit
d847d00d6f
@@ -814,3 +814,38 @@ fun FirExpression.asCompileTimeIrInitializer(components: Fir2IrComponents): IrEx
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: for componentN call, we have to change the type here (to the original component type) to keep compatibility with PSI2IR
|
||||
* Some backend optimizations related to withIndex() probably depend on this type: index should always be Int
|
||||
* See e.g. forInStringWithIndexWithExplicitlyTypedIndexVariable.kt from codegen box tests
|
||||
*
|
||||
* [predefinedType] is needed for case, when this function is used to convert some variable access, and
|
||||
* default IR type, for it is already known
|
||||
* It's not correct to always use converted [this.returnTypeRef] in one particular case:
|
||||
*
|
||||
* val <T> T.some: T
|
||||
* get() = ...
|
||||
* set(value) {
|
||||
* field = value <----
|
||||
* }
|
||||
*
|
||||
* Here `value` has type `T`. In FIR there is one type parameter `T` for the whole property
|
||||
* But in IR we have different type parameters for getter and setter. And by default `toIrType()` transforms
|
||||
* `T` as type parameter of getter, but here we are in context of the setter. And in CallAndReferenceGenerator.convertToIrCall
|
||||
* we already know that `value` should have type `T[set-some]`, so this type is provided as [predefinedType]
|
||||
*
|
||||
* The alternative could be to determine outside that we are in scope of setter and pass type origin, but it's
|
||||
* much more complicated and messy
|
||||
*/
|
||||
context(Fir2IrComponents)
|
||||
internal fun FirVariable.irTypeForPotentiallyComponentCall(predefinedType: IrType? = null): IrType {
|
||||
val typeRef = when (val initializer = initializer) {
|
||||
is FirComponentCall -> initializer.resolvedType
|
||||
else -> {
|
||||
if (predefinedType != null) return predefinedType
|
||||
this.returnTypeRef.coneType
|
||||
}
|
||||
}
|
||||
return typeRef.toIrType(typeConverter)
|
||||
}
|
||||
|
||||
+1
-4
@@ -1526,10 +1526,7 @@ class Fir2IrDeclarationStorage(
|
||||
irParent: IrDeclarationParent,
|
||||
givenOrigin: IrDeclarationOrigin? = null
|
||||
): IrVariable = convertCatching(variable) {
|
||||
// Note: for components call, we have to change type here (to original component type) to keep compatibility with PSI2IR
|
||||
// Some backend optimizations related to withIndex() probably depend on this type: index should always be Int
|
||||
// See e.g. forInStringWithIndexWithExplicitlyTypedIndexVariable.kt from codegen box tests
|
||||
val type = ((variable.initializer as? FirComponentCall)?.resolvedType ?: variable.returnTypeRef.coneType).toIrType()
|
||||
val type = variable.irTypeForPotentiallyComponentCall()
|
||||
// Some temporary variables are produced in RawFirBuilder, but we consistently use special names for them.
|
||||
val origin = when {
|
||||
givenOrigin != null -> givenOrigin
|
||||
|
||||
@@ -472,6 +472,20 @@ class IrBuiltInsOverFir(
|
||||
)
|
||||
}
|
||||
|
||||
fun getNonBuiltInFunctionsWithFirCounterpartByExtensionReceiver(
|
||||
name: Name,
|
||||
vararg packageNameSegments: String,
|
||||
): Map<IrClassifierSymbol, Pair<FirNamedFunctionSymbol, IrSimpleFunctionSymbol>> {
|
||||
return getFunctionsByKey(
|
||||
name,
|
||||
*packageNameSegments,
|
||||
mapKey = { symbol ->
|
||||
with(components) { symbol.fir.receiverParameter?.typeRef?.toIrType(typeConverter)?.classifierOrNull }
|
||||
},
|
||||
mapValue = { firSymbol, irSymbol -> firSymbol to irSymbol }
|
||||
)
|
||||
}
|
||||
|
||||
private val functionNMap = mutableMapOf<Int, IrClass>()
|
||||
private val kFunctionNMap = mutableMapOf<Int, IrClass>()
|
||||
private val suspendFunctionNMap = mutableMapOf<Int, IrClass>()
|
||||
|
||||
+11
-8
@@ -87,10 +87,12 @@ internal class AdapterGenerator(
|
||||
internal fun needToGenerateAdaptedCallableReference(
|
||||
callableReferenceAccess: FirCallableReferenceAccess,
|
||||
type: IrSimpleType,
|
||||
function: IrFunction
|
||||
): Boolean =
|
||||
needSuspendConversion(type, function) || needCoercionToUnit(type, function) ||
|
||||
function: FirFunction
|
||||
): Boolean {
|
||||
return needSuspendConversion(type, function) ||
|
||||
needCoercionToUnit(type, function) ||
|
||||
hasVarargOrDefaultArguments(callableReferenceAccess)
|
||||
}
|
||||
|
||||
/**
|
||||
* For example,
|
||||
@@ -100,8 +102,9 @@ internal class AdapterGenerator(
|
||||
*
|
||||
* At the use site, instead of referenced, we can put the suspend lambda as an adapter.
|
||||
*/
|
||||
private fun needSuspendConversion(type: IrSimpleType, function: IrFunction): Boolean =
|
||||
type.isSuspendFunction() && !function.isSuspend
|
||||
private fun needSuspendConversion(type: IrSimpleType, function: FirFunction): Boolean {
|
||||
return type.isSuspendFunction() && !function.isSuspend
|
||||
}
|
||||
|
||||
/**
|
||||
* For example,
|
||||
@@ -111,12 +114,12 @@ internal class AdapterGenerator(
|
||||
*
|
||||
* At the use site, instead of referenced, we can put the adapter: { ... -> referenced(...) }
|
||||
*/
|
||||
private fun needCoercionToUnit(type: IrSimpleType, function: IrFunction): Boolean {
|
||||
private fun needCoercionToUnit(type: IrSimpleType, function: FirFunction): Boolean {
|
||||
val expectedReturnType = type.arguments.last().typeOrNull
|
||||
val actualReturnType = function.returnType
|
||||
val actualReturnType = function.returnTypeRef.coneType
|
||||
return expectedReturnType?.isUnit() == true &&
|
||||
// In case of an external function whose return type is a type parameter, e.g., operator fun <T, R> invoke(T): R
|
||||
!actualReturnType.isUnit() && !actualReturnType.isTypeParameter()
|
||||
!actualReturnType.isUnit && actualReturnType.toSymbol(components.session) !is FirTypeParameterSymbol
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+133
-119
@@ -9,18 +9,18 @@ import com.intellij.openapi.progress.ProcessCanceledException
|
||||
import org.jetbrains.kotlin.KtFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.backend.*
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isInterface
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isMethodOfAny
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isStatic
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.buildAnnotationCall
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
|
||||
import org.jetbrains.kotlin.fir.languageVersionSettings
|
||||
import org.jetbrains.kotlin.fir.references.*
|
||||
import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.FirSyntheticFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.getExpectedType
|
||||
@@ -44,12 +44,11 @@ import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.dump
|
||||
import org.jetbrains.kotlin.ir.util.isFunctionTypeOrSubtype
|
||||
import org.jetbrains.kotlin.ir.util.isInterface
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.calls.NewCommonSuperTypeCalculator.commonSuperType
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.runIf
|
||||
|
||||
class CallAndReferenceGenerator(
|
||||
private val components: Fir2IrComponents,
|
||||
@@ -65,7 +64,6 @@ class CallAndReferenceGenerator(
|
||||
private fun ConeKotlinType.toIrType(): IrType =
|
||||
with(typeConverter) { toIrType(conversionScope.defaultConversionTypeOrigin()) }
|
||||
|
||||
@OptIn(IrSymbolInternals::class)
|
||||
fun convertToIrCallableReference(
|
||||
callableReferenceAccess: FirCallableReferenceAccess,
|
||||
explicitReceiverExpression: IrExpression?,
|
||||
@@ -101,20 +99,19 @@ class CallAndReferenceGenerator(
|
||||
return callableReferenceAccess.convertWithOffsets { startOffset, endOffset ->
|
||||
when (symbol) {
|
||||
is IrPropertySymbol -> {
|
||||
val referencedProperty = symbol.owner
|
||||
val referencedPropertyGetter = referencedProperty.getter
|
||||
val referencedPropertySetterSymbol =
|
||||
if (callableReferenceAccess.resolvedType.isKMutableProperty(session)) referencedProperty.setter?.symbol
|
||||
else null
|
||||
val referencedPropertyGetterSymbol = declarationStorage.findGetterOfProperty(symbol)
|
||||
val referencedPropertySetterSymbol = runIf(callableReferenceAccess.resolvedType.isKMutableProperty(session)) {
|
||||
declarationStorage.findSetterOfProperty(symbol)
|
||||
}
|
||||
val backingFieldSymbol = when {
|
||||
referencedPropertyGetter != null -> null
|
||||
else -> referencedProperty.backingField?.symbol
|
||||
referencedPropertyGetterSymbol != null -> null
|
||||
else -> declarationStorage.findBackingFieldOfProperty(symbol)
|
||||
}
|
||||
IrPropertyReferenceImpl(
|
||||
startOffset, endOffset, type, symbol,
|
||||
typeArgumentsCount = referencedPropertyGetter?.typeParameters?.size ?: 0,
|
||||
typeArgumentsCount = callableReferenceAccess.toResolvedCallableSymbol()?.fir?.typeParameters?.size ?: 0,
|
||||
field = backingFieldSymbol,
|
||||
getter = referencedPropertyGetter?.symbol,
|
||||
getter = referencedPropertyGetterSymbol,
|
||||
setter = referencedPropertySetterSymbol,
|
||||
origin = origin
|
||||
).applyTypeArguments(callableReferenceAccess).applyReceivers(callableReferenceAccess, explicitReceiverExpression)
|
||||
@@ -123,40 +120,43 @@ class CallAndReferenceGenerator(
|
||||
is IrLocalDelegatedPropertySymbol -> {
|
||||
IrLocalDelegatedPropertyReferenceImpl(
|
||||
startOffset, endOffset, type, symbol,
|
||||
delegate = symbol.owner.delegate.symbol,
|
||||
getter = symbol.owner.getter.symbol,
|
||||
setter = symbol.owner.setter?.symbol,
|
||||
delegate = declarationStorage.findDelegateVariableOfProperty(symbol),
|
||||
getter = declarationStorage.findGetterOfProperty(symbol),
|
||||
setter = declarationStorage.findSetterOfProperty(symbol),
|
||||
origin = origin
|
||||
)
|
||||
}
|
||||
|
||||
is IrFieldSymbol -> {
|
||||
val referencedField = symbol.owner
|
||||
val propertySymbol = referencedField.correspondingPropertySymbol
|
||||
val field = (callableSymbol as FirFieldSymbol).fir
|
||||
val propertySymbol = declarationStorage.findPropertyForBackingField(symbol)
|
||||
?: run {
|
||||
// In case of [IrField] without the corresponding property, we've created it directly from [FirField].
|
||||
// Since it's used as a field reference, we need a bogus property as a placeholder.
|
||||
val firSymbol =
|
||||
(callableReferenceAccess.calleeReference as FirResolvedNamedReference).resolvedSymbol as FirFieldSymbol
|
||||
declarationStorage.getOrCreateIrPropertyByPureField(firSymbol.fir, referencedField.parent).symbol
|
||||
@OptIn(IrSymbolInternals::class)
|
||||
declarationStorage.getOrCreateIrPropertyByPureField(firSymbol.fir, symbol.owner.parent).symbol
|
||||
}
|
||||
IrPropertyReferenceImpl(
|
||||
startOffset, endOffset, type,
|
||||
propertySymbol,
|
||||
typeArgumentsCount = 0,
|
||||
field = symbol,
|
||||
getter = if (referencedField.isStatic) null else propertySymbol.owner.getter?.symbol,
|
||||
setter = if (referencedField.isStatic) null else propertySymbol.owner.setter?.symbol,
|
||||
getter = runIf(!field.isStatic) { declarationStorage.findGetterOfProperty(propertySymbol) },
|
||||
setter = runIf(!field.isStatic) { declarationStorage.findSetterOfProperty(propertySymbol) },
|
||||
origin
|
||||
).applyReceivers(callableReferenceAccess, explicitReceiverExpression)
|
||||
}
|
||||
|
||||
is IrFunctionSymbol -> {
|
||||
assert(type.isFunctionTypeOrSubtype()) {
|
||||
"Callable reference whose symbol refers to a function should be of functional type."
|
||||
require(type is IrSimpleType)
|
||||
var function = callableReferenceAccess.calleeReference.toResolvedFunctionSymbol()!!.fir
|
||||
if (function is FirConstructor) {
|
||||
// The number of type parameters of typealias constructor may mismatch with that number in the original constructor.
|
||||
// And for IR, we need to use the original constructor as a source of truth
|
||||
function = function.originalConstructorIfTypeAlias ?: function
|
||||
}
|
||||
type as IrSimpleType
|
||||
val function = symbol.owner
|
||||
if (adapterGenerator.needToGenerateAdaptedCallableReference(callableReferenceAccess, type, function)) {
|
||||
// Receivers are being applied inside
|
||||
with(adapterGenerator) {
|
||||
@@ -165,13 +165,10 @@ class CallAndReferenceGenerator(
|
||||
generateAdaptedCallableReference(callableReferenceAccess, explicitReceiverExpression, symbol, adaptedType)
|
||||
}
|
||||
} else {
|
||||
val klass = function.parent as? IrClass
|
||||
val typeArgumentCount = function.typeParameters.size +
|
||||
if (function is IrConstructor) klass?.typeParameters?.size ?: 0 else 0
|
||||
IrFunctionReferenceImpl(
|
||||
startOffset, endOffset, type, symbol,
|
||||
typeArgumentsCount = typeArgumentCount,
|
||||
valueArgumentsCount = function.valueParameters.size,
|
||||
typeArgumentsCount = function.typeParameters.size,
|
||||
valueArgumentsCount = function.valueParameters.size + function.contextReceivers.size,
|
||||
reflectionTarget = symbol
|
||||
).applyTypeArguments(callableReferenceAccess)
|
||||
.applyReceivers(callableReferenceAccess, explicitReceiverExpression)
|
||||
@@ -363,7 +360,6 @@ class CallAndReferenceGenerator(
|
||||
return IrGetValueImpl(startOffset, endOffset, type, injectedValue.irParameterSymbol, origin)
|
||||
}
|
||||
|
||||
@OptIn(IrSymbolInternals::class)
|
||||
fun convertToIrCall(
|
||||
qualifiedAccess: FirQualifiedAccessExpression,
|
||||
type: ConeKotlinType,
|
||||
@@ -449,8 +445,9 @@ class CallAndReferenceGenerator(
|
||||
|
||||
is IrLocalDelegatedPropertySymbol -> {
|
||||
IrCallImpl(
|
||||
startOffset, endOffset, irType, symbol.owner.getter.symbol,
|
||||
typeArgumentsCount = symbol.owner.getter.typeParameters.size,
|
||||
startOffset, endOffset, irType,
|
||||
declarationStorage.findGetterOfProperty(symbol),
|
||||
typeArgumentsCount = calleeReference.toResolvedCallableSymbol()!!.fir.typeParameters.size,
|
||||
valueArgumentsCount = 0,
|
||||
origin = IrStatementOrigin.GET_LOCAL_PROPERTY,
|
||||
superQualifierSymbol = dispatchReceiver.superQualifierSymbol()
|
||||
@@ -458,19 +455,23 @@ class CallAndReferenceGenerator(
|
||||
}
|
||||
|
||||
is IrPropertySymbol -> {
|
||||
val getter = symbol.owner.getter
|
||||
val backingField = symbol.owner.backingField
|
||||
val property = calleeReference.toResolvedPropertySymbol()!!.fir
|
||||
val getterSymbol = declarationStorage.findGetterOfProperty(symbol)
|
||||
val backingFieldSymbol = declarationStorage.findBackingFieldOfProperty(symbol)
|
||||
when {
|
||||
getter != null -> IrCallImpl(
|
||||
startOffset, endOffset, irType, getter.symbol,
|
||||
typeArgumentsCount = getter.typeParameters.size,
|
||||
valueArgumentsCount = getter.valueParameters.size,
|
||||
origin = IrStatementOrigin.GET_PROPERTY,
|
||||
superQualifierSymbol = dispatchReceiver.superQualifierSymbol()
|
||||
)
|
||||
getterSymbol != null -> {
|
||||
IrCallImpl(
|
||||
startOffset, endOffset, irType,
|
||||
getterSymbol,
|
||||
typeArgumentsCount = property.typeParameters.size,
|
||||
valueArgumentsCount = property.contextReceivers.size,
|
||||
origin = IrStatementOrigin.GET_PROPERTY,
|
||||
superQualifierSymbol = dispatchReceiver.superQualifierSymbol()
|
||||
)
|
||||
}
|
||||
|
||||
backingField != null -> IrGetFieldImpl(
|
||||
startOffset, endOffset, backingField.symbol, irType,
|
||||
backingFieldSymbol != null -> IrGetFieldImpl(
|
||||
startOffset, endOffset, backingFieldSymbol, irType,
|
||||
superQualifierSymbol = dispatchReceiver.superQualifierSymbol()
|
||||
)
|
||||
|
||||
@@ -496,11 +497,12 @@ class CallAndReferenceGenerator(
|
||||
}
|
||||
|
||||
is IrValueSymbol -> {
|
||||
val variable = calleeReference.toResolvedVariableSymbol()!!.fir
|
||||
IrGetValueImpl(
|
||||
// Note: sometimes we change an IR type of local variable
|
||||
// (see component call case: Fir2IrDeclarationStorage.createIrVariable -> val type = ...)
|
||||
// That's why we should use here v the IR variable type and not FIR converted type (to prevent IR inconsistency)
|
||||
startOffset, endOffset, symbol.owner.type, symbol,
|
||||
startOffset, endOffset,
|
||||
// Note: there is a case with componentN function when IR type of variable differs from FIR type
|
||||
variable.irTypeForPotentiallyComponentCall(predefinedType = irType),
|
||||
symbol,
|
||||
origin = if (variableAsFunctionMode) IrStatementOrigin.VARIABLE_AS_FUNCTION
|
||||
else calleeReference.statementOrigin()
|
||||
)
|
||||
@@ -575,7 +577,6 @@ class CallAndReferenceGenerator(
|
||||
|
||||
internal fun findInjectedValue(calleeReference: FirReference) = extensions.findInjectedValue(calleeReference, conversionScope)
|
||||
|
||||
@OptIn(IrSymbolInternals::class)
|
||||
fun convertToIrSetCall(variableAssignment: FirVariableAssignment, explicitReceiverExpression: IrExpression?): IrExpression {
|
||||
try {
|
||||
val type = irBuiltIns.unitType
|
||||
@@ -614,12 +615,13 @@ class CallAndReferenceGenerator(
|
||||
}
|
||||
|
||||
is IrLocalDelegatedPropertySymbol -> {
|
||||
val setter = symbol.owner.setter
|
||||
val firProperty = calleeReference.toResolvedPropertySymbol()!!.fir
|
||||
val setterSymbol = declarationStorage.findSetterOfProperty(symbol)
|
||||
when {
|
||||
setter != null -> IrCallImpl(
|
||||
startOffset, endOffset, type, setter.symbol,
|
||||
typeArgumentsCount = setter.typeParameters.size,
|
||||
valueArgumentsCount = setter.valueParameters.size,
|
||||
setterSymbol != null -> IrCallImpl(
|
||||
startOffset, endOffset, type, setterSymbol,
|
||||
typeArgumentsCount = firProperty.typeParameters.size,
|
||||
valueArgumentsCount = 1 + firProperty.contextReceivers.size,
|
||||
origin = origin,
|
||||
superQualifierSymbol = variableAssignment.dispatchReceiver.superQualifierSymbol()
|
||||
).apply {
|
||||
@@ -632,29 +634,29 @@ class CallAndReferenceGenerator(
|
||||
}
|
||||
|
||||
is IrPropertySymbol -> {
|
||||
val irProperty = symbol.owner
|
||||
val setter = irProperty.setter
|
||||
var backingField = irProperty.backingField
|
||||
val setterSymbol = declarationStorage.findSetterOfProperty(symbol)
|
||||
var backingFieldSymbol = declarationStorage.findBackingFieldOfProperty(symbol)
|
||||
val firProperty = calleeReference.toResolvedPropertySymbol()!!.fir
|
||||
|
||||
// If we found neither a setter nor a backing field, check if we have an override (possibly fake) of a val with
|
||||
// backing field. This can happen in a class initializer where `this` was smart-casted. See KT-57105.
|
||||
if (setter == null && backingField == null) {
|
||||
backingField = irProperty.overriddenBackingFieldOrNull()
|
||||
if (setterSymbol == null && backingFieldSymbol == null) {
|
||||
backingFieldSymbol = symbol.overriddenBackingFieldOrNull()
|
||||
}
|
||||
|
||||
when {
|
||||
setter != null -> IrCallImpl(
|
||||
startOffset, endOffset, type, setter.symbol,
|
||||
typeArgumentsCount = setter.typeParameters.size,
|
||||
valueArgumentsCount = setter.valueParameters.size,
|
||||
setterSymbol != null -> IrCallImpl(
|
||||
startOffset, endOffset, type, setterSymbol,
|
||||
typeArgumentsCount = firProperty.typeParameters.size,
|
||||
valueArgumentsCount = 1 + firProperty.contextReceivers.size,
|
||||
origin = origin,
|
||||
superQualifierSymbol = variableAssignment.dispatchReceiver.superQualifierSymbol()
|
||||
).apply {
|
||||
putValueArgument(putContextReceiverArguments(lValue), assignedValue)
|
||||
}
|
||||
|
||||
backingField != null -> IrSetFieldImpl(
|
||||
startOffset, endOffset, backingField.symbol, type,
|
||||
backingFieldSymbol != null -> IrSetFieldImpl(
|
||||
startOffset, endOffset, backingFieldSymbol, type,
|
||||
origin = null, // NB: to be consistent with PSI2IR, origin should be null here
|
||||
superQualifierSymbol = variableAssignment.dispatchReceiver.superQualifierSymbol()
|
||||
).apply {
|
||||
@@ -666,9 +668,10 @@ class CallAndReferenceGenerator(
|
||||
}
|
||||
|
||||
is IrSimpleFunctionSymbol -> {
|
||||
val firFunction = calleeReference.toResolvedFunctionSymbol()?.fir
|
||||
IrCallImpl(
|
||||
startOffset, endOffset, type, symbol,
|
||||
typeArgumentsCount = symbol.owner.typeParameters.size,
|
||||
typeArgumentsCount = firFunction?.typeParameters?.size ?: 0,
|
||||
valueArgumentsCount = 1,
|
||||
origin = origin
|
||||
).apply {
|
||||
@@ -694,14 +697,13 @@ class CallAndReferenceGenerator(
|
||||
}
|
||||
|
||||
@OptIn(IrSymbolInternals::class)
|
||||
private fun IrProperty.overriddenBackingFieldOrNull(): IrField? {
|
||||
return overriddenSymbols.firstNotNullOfOrNull {
|
||||
private fun IrPropertySymbol.overriddenBackingFieldOrNull(): IrFieldSymbol? {
|
||||
return owner.overriddenSymbols.firstNotNullOfOrNull {
|
||||
val owner = it.owner
|
||||
owner.backingField ?: owner.overriddenBackingFieldOrNull()
|
||||
owner.backingField?.symbol ?: it.overriddenBackingFieldOrNull()
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(IrSymbolInternals::class)
|
||||
fun convertToIrConstructorCall(annotation: FirAnnotation): IrExpression {
|
||||
val coneType = annotation.annotationTypeRef.coneTypeSafe<ConeLookupTagBasedType>()
|
||||
?.fullyExpandedType(session) as? ConeLookupTagBasedType
|
||||
@@ -714,7 +716,6 @@ class CallAndReferenceGenerator(
|
||||
)
|
||||
}
|
||||
|
||||
val irClass = symbol.owner
|
||||
val firConstructorSymbol = annotation.toResolvedCallableSymbol() as? FirConstructorSymbol
|
||||
?: run {
|
||||
// Fallback for FirReferencePlaceholderForResolvedAnnotations from jar
|
||||
@@ -732,7 +733,7 @@ class CallAndReferenceGenerator(
|
||||
}
|
||||
constructorSymbol
|
||||
} ?: return@convertWithOffsets IrErrorCallExpressionImpl(
|
||||
startOffset, endOffset, type, "No annotation constructor found: ${irClass.name}"
|
||||
startOffset, endOffset, type, "No annotation constructor found: $symbol"
|
||||
)
|
||||
|
||||
val irConstructor = declarationStorage.getIrConstructorSymbol(firConstructorSymbol)
|
||||
@@ -837,7 +838,6 @@ class CallAndReferenceGenerator(
|
||||
return Triple(valueParameters, argumentMapping, substitutor)
|
||||
}
|
||||
|
||||
@OptIn(IrSymbolInternals::class)
|
||||
internal fun IrExpression.applyCallArguments(
|
||||
statement: FirStatement?,
|
||||
): IrExpression {
|
||||
@@ -872,7 +872,7 @@ class CallAndReferenceGenerator(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val name = if (this is IrCallImpl) symbol.owner.name else "???"
|
||||
val name = if (this is IrCallImpl) symbol.signature.toString() else "???"
|
||||
IrErrorCallExpressionImpl(
|
||||
startOffset, endOffset, type,
|
||||
"Cannot bind $argumentsCount arguments to $name call with $valueArgumentsCount parameters"
|
||||
@@ -1049,7 +1049,6 @@ class CallAndReferenceGenerator(
|
||||
return this
|
||||
}
|
||||
|
||||
@OptIn(IrSymbolInternals::class)
|
||||
private fun IrExpression.applyImplicitIntegerCoercionIfNeeded(
|
||||
argument: FirExpression,
|
||||
parameter: FirValueParameter?
|
||||
@@ -1059,56 +1058,64 @@ class CallAndReferenceGenerator(
|
||||
if (parameter == null || !parameter.isMarkedWithImplicitIntegerCoercion) return this
|
||||
if (!argument.getExpectedType(parameter).fullyExpandedType(session).isUnsignedTypeOrNullableUnsignedType) return this
|
||||
|
||||
fun IrExpression.applyToElement(argument: FirExpression, conversionFunction: IrSimpleFunctionSymbol): IrExpression =
|
||||
if (argument.isIntegerLiteralOrOperatorCall() ||
|
||||
fun IrExpression.applyToElement(
|
||||
argument: FirExpression,
|
||||
firConversionFunction: FirNamedFunctionSymbol,
|
||||
irConversionFunction: IrSimpleFunctionSymbol,
|
||||
): IrExpression {
|
||||
return if (argument.isIntegerLiteralOrOperatorCall() ||
|
||||
argument.calleeReference?.toResolvedCallableSymbol()?.let {
|
||||
it.resolvedStatus.isConst && it.isMarkedWithImplicitIntegerCoercion
|
||||
} == true
|
||||
) {
|
||||
IrCallImpl(
|
||||
startOffset, endOffset,
|
||||
conversionFunction.owner.returnType,
|
||||
conversionFunction,
|
||||
firConversionFunction.fir.returnTypeRef.toIrType(),
|
||||
irConversionFunction,
|
||||
typeArgumentsCount = 0,
|
||||
valueArgumentsCount = 0
|
||||
).apply {
|
||||
extensionReceiver = this@applyToElement
|
||||
}
|
||||
} else this@applyToElement
|
||||
|
||||
if (parameter.isMarkedWithImplicitIntegerCoercion) {
|
||||
if (this is IrVarargImpl && argument is FirVarargArgumentsExpression) {
|
||||
|
||||
val targetTypeFqName = varargElementType.classFqName ?: return this
|
||||
val conversionFunctions = irBuiltIns.getNonBuiltInFunctionsByExtensionReceiver(
|
||||
Name.identifier("to" + targetTypeFqName.shortName().asString()),
|
||||
StandardNames.BUILT_INS_PACKAGE_NAME.asString()
|
||||
)
|
||||
if (conversionFunctions.isNotEmpty()) {
|
||||
elements.forEachIndexed { i, irVarargElement ->
|
||||
val targetFun = argument.arguments[i].resolvedType.toIrType().classifierOrNull?.let { conversionFunctions[it] }
|
||||
if (targetFun != null && irVarargElement is IrExpression) {
|
||||
elements[i] =
|
||||
irVarargElement.applyToElement(argument.arguments[i], targetFun)
|
||||
}
|
||||
}
|
||||
}
|
||||
return this
|
||||
} else {
|
||||
val targetIrType = parameter.returnTypeRef.toIrType()
|
||||
val targetTypeFqName = targetIrType.classFqName ?: return this
|
||||
val conversionFunctions = irBuiltIns.getNonBuiltInFunctionsByExtensionReceiver(
|
||||
Name.identifier("to" + targetTypeFqName.shortName().asString()),
|
||||
StandardNames.BUILT_INS_PACKAGE_NAME.asString()
|
||||
)
|
||||
val sourceTypeClassifier = argument.resolvedType.toIrType().classifierOrNull ?: return this
|
||||
|
||||
val conversionFunction = conversionFunctions[sourceTypeClassifier] ?: return this
|
||||
|
||||
return this.applyToElement(argument, conversionFunction)
|
||||
this@applyToElement
|
||||
}
|
||||
}
|
||||
return this
|
||||
|
||||
return when {
|
||||
parameter.isMarkedWithImplicitIntegerCoercion -> when {
|
||||
this is IrVarargImpl && argument is FirVarargArgumentsExpression -> {
|
||||
val targetTypeFqName = varargElementType.classFqName ?: return this
|
||||
val conversionFunctions = irBuiltIns.getNonBuiltInFunctionsWithFirCounterpartByExtensionReceiver(
|
||||
Name.identifier("to" + targetTypeFqName.shortName().asString()),
|
||||
StandardNames.BUILT_INS_PACKAGE_NAME.asString()
|
||||
)
|
||||
if (conversionFunctions.isNotEmpty()) {
|
||||
elements.forEachIndexed { i, irVarargElement ->
|
||||
if (irVarargElement !is IrExpression) return@forEachIndexed
|
||||
val argumentClassifier = argument.arguments[i].resolvedType.toIrType().classifierOrNull ?: return@forEachIndexed
|
||||
val (targetFirFun, targetIrFun) = conversionFunctions[argumentClassifier] ?: return@forEachIndexed
|
||||
elements[i] = irVarargElement.applyToElement(argument.arguments[i], targetFirFun, targetIrFun)
|
||||
}
|
||||
}
|
||||
this
|
||||
}
|
||||
else -> {
|
||||
val targetIrType = parameter.returnTypeRef.toIrType()
|
||||
val targetTypeFqName = targetIrType.classFqName ?: return this
|
||||
val conversionFunctions = irBuiltIns.getNonBuiltInFunctionsWithFirCounterpartByExtensionReceiver(
|
||||
Name.identifier("to" + targetTypeFqName.shortName().asString()),
|
||||
StandardNames.BUILT_INS_PACKAGE_NAME.asString()
|
||||
)
|
||||
val sourceTypeClassifier = argument.resolvedType.toIrType().classifierOrNull ?: return this
|
||||
|
||||
val (firConversionFunction, irConversionFunction) = conversionFunctions[sourceTypeClassifier] ?: return this
|
||||
|
||||
this.applyToElement(argument, firConversionFunction, irConversionFunction)
|
||||
}
|
||||
}
|
||||
else -> this
|
||||
}
|
||||
}
|
||||
|
||||
internal fun IrExpression.applyTypeArguments(access: FirQualifiedAccessExpression): IrExpression {
|
||||
@@ -1159,7 +1166,6 @@ class CallAndReferenceGenerator(
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(IrSymbolInternals::class)
|
||||
private fun IrExpression.applyTypeArguments(
|
||||
typeArguments: List<FirTypeProjection>?,
|
||||
typeParameters: List<FirTypeParameter>?,
|
||||
@@ -1185,7 +1191,7 @@ class CallAndReferenceGenerator(
|
||||
}
|
||||
return this
|
||||
} else {
|
||||
val name = if (this is IrCallImpl) symbol.owner.name else "???"
|
||||
val name = if (this is IrCallImpl) symbol.signature.toString() else "???"
|
||||
return IrErrorExpressionImpl(
|
||||
startOffset, endOffset, type,
|
||||
"Cannot bind $argumentsCount type arguments to $name call with $typeArgumentsCount type parameters"
|
||||
@@ -1213,7 +1219,6 @@ class CallAndReferenceGenerator(
|
||||
?: explicitReceiverExpression
|
||||
}
|
||||
|
||||
@OptIn(IrSymbolInternals::class)
|
||||
private fun IrExpression.applyReceivers(
|
||||
qualifiedAccess: FirQualifiedAccessExpression,
|
||||
explicitReceiverExpression: IrExpression?,
|
||||
@@ -1223,10 +1228,17 @@ class CallAndReferenceGenerator(
|
||||
val resolvedFirSymbol = qualifiedAccess.toResolvedCallableSymbol()
|
||||
if (resolvedFirSymbol?.dispatchReceiverType != null) {
|
||||
val baseDispatchReceiver = qualifiedAccess.findIrDispatchReceiver(explicitReceiverExpression)
|
||||
var firDispatchReceiver = qualifiedAccess.dispatchReceiver.takeUnless { it is FirNoReceiverExpression }
|
||||
if (firDispatchReceiver is FirPropertyAccessExpression && firDispatchReceiver.calleeReference is FirSuperReference) {
|
||||
firDispatchReceiver = firDispatchReceiver.dispatchReceiver
|
||||
}
|
||||
val notFromAny = !resolvedFirSymbol.isFunctionFromAny()
|
||||
val notAnInterface = firDispatchReceiver?.resolvedType?.toRegularClassSymbol(session)?.isInterface != true
|
||||
dispatchReceiver =
|
||||
if (!resolvedFirSymbol.isFunctionFromAny() || baseDispatchReceiver?.type?.classOrNull?.owner?.isInterface != true) {
|
||||
if (notFromAny || notAnInterface) {
|
||||
baseDispatchReceiver
|
||||
} else {
|
||||
requireNotNull(baseDispatchReceiver)
|
||||
// NB: for FE 1.0, this type cast is added by InterfaceObjectCallsLowering
|
||||
// However, it doesn't work for FIR due to different f/o structure
|
||||
// (FIR calls Any method directly, but FE 1.0 calls its interface f/o instead)
|
||||
@@ -1259,8 +1271,10 @@ class CallAndReferenceGenerator(
|
||||
}
|
||||
|
||||
is IrFieldAccessExpression -> {
|
||||
val ownerField = symbol.owner
|
||||
if (!ownerField.isStatic) {
|
||||
val firDeclaration = qualifiedAccess.toResolvedCallableSymbol()!!.fir.propertyIfBackingField
|
||||
// Top-level properties are considered as static in IR
|
||||
val fieldIsStatic = firDeclaration.isStatic || (firDeclaration is FirProperty && !firDeclaration.isLocal && firDeclaration.containingClassLookupTag() == null)
|
||||
if (!fieldIsStatic) {
|
||||
receiver = qualifiedAccess.findIrDispatchReceiver(explicitReceiverExpression)
|
||||
}
|
||||
}
|
||||
|
||||
+6
@@ -3717,6 +3717,12 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr
|
||||
runTest("compiler/testData/codegen/box/callableReference/referenceToGenericSyntheticProperty.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("referenceToTypealiasConstructorInLet.kt")
|
||||
public void testReferenceToTypealiasConstructorInLet() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/referenceToTypealiasConstructorInLet.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("staticMethod.kt")
|
||||
public void testStaticMethod() throws Exception {
|
||||
|
||||
+6
@@ -3717,6 +3717,12 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo
|
||||
runTest("compiler/testData/codegen/box/callableReference/referenceToGenericSyntheticProperty.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("referenceToTypealiasConstructorInLet.kt")
|
||||
public void testReferenceToTypealiasConstructorInLet() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/referenceToTypealiasConstructorInLet.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("staticMethod.kt")
|
||||
public void testStaticMethod() throws Exception {
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
// WITH_STDLIB
|
||||
// FULL_JDK
|
||||
|
||||
import java.util.EnumMap
|
||||
|
||||
enum class SomeEnum {
|
||||
A, B
|
||||
}
|
||||
|
||||
typealias SomeMap = EnumMap<SomeEnum, String>
|
||||
|
||||
fun test(oldMap: SomeMap, key: SomeEnum): String {
|
||||
val newMap = oldMap.let(::SomeMap)
|
||||
return newMap.getValue(key)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val map = EnumMap(mapOf(SomeEnum.A to "OK"))
|
||||
return test(map, SomeEnum.A)
|
||||
}
|
||||
+6
@@ -3717,6 +3717,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/callableReference/referenceToGenericSyntheticProperty.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("referenceToTypealiasConstructorInLet.kt")
|
||||
public void testReferenceToTypealiasConstructorInLet() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/referenceToTypealiasConstructorInLet.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("staticMethod.kt")
|
||||
public void testStaticMethod() throws Exception {
|
||||
|
||||
+6
@@ -3717,6 +3717,12 @@ public class IrBlackBoxCodegenWithIrInlinerTestGenerated extends AbstractIrBlack
|
||||
runTest("compiler/testData/codegen/box/callableReference/referenceToGenericSyntheticProperty.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("referenceToTypealiasConstructorInLet.kt")
|
||||
public void testReferenceToTypealiasConstructorInLet() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/referenceToTypealiasConstructorInLet.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("staticMethod.kt")
|
||||
public void testStaticMethod() throws Exception {
|
||||
|
||||
+5
@@ -3256,6 +3256,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/callableReference/referenceToGenericSyntheticProperty.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("referenceToTypealiasConstructorInLet.kt")
|
||||
public void testReferenceToTypealiasConstructorInLet() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/referenceToTypealiasConstructorInLet.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("staticMethod.kt")
|
||||
public void testStaticMethod() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/staticMethod.kt");
|
||||
|
||||
Reference in New Issue
Block a user