FIR2IR: apply SAM conversion to arguments of functional type.
This commit is contained in:
committed by
Mikhail Glukhikh
parent
599c5dd474
commit
615636ed55
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.backend
|
||||
|
||||
import com.intellij.psi.PsiCompiledElement
|
||||
import org.jetbrains.kotlin.KtNodeTypes
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
@@ -41,6 +42,7 @@ import org.jetbrains.kotlin.ir.types.impl.IrErrorTypeImpl
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.ir.util.functions
|
||||
import org.jetbrains.kotlin.ir.util.isFakeOverride
|
||||
import org.jetbrains.kotlin.ir.util.properties
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments
|
||||
@@ -472,6 +474,7 @@ fun FirClass<*>.getSamIfAny(): FirSimpleFunction? =
|
||||
val IrType.isSamType: Boolean
|
||||
get() {
|
||||
val irClass = classOrNull ?: return false
|
||||
if (irClass.owner.kind != ClassKind.INTERFACE) return false
|
||||
val am = irClass.functions.singleOrNull { it.owner.modality == Modality.ABSTRACT }
|
||||
return am != null
|
||||
}
|
||||
|
||||
+16
-10
@@ -17,6 +17,8 @@ import org.jetbrains.kotlin.fir.references.FirReference
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.FirSuperReference
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.isExtensionFunctionType
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.isFunctional
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.isBuiltinFunctionalType
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
@@ -27,10 +29,7 @@ import org.jetbrains.kotlin.fir.types.*
|
||||
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.expressions.IrErrorCallExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
||||
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
@@ -417,17 +416,24 @@ internal class CallAndReferenceGenerator(
|
||||
argument: FirExpression,
|
||||
parameter: FirValueParameter?
|
||||
): IrExpression {
|
||||
if (parameter == null ||
|
||||
parameter.returnTypeRef.coneTypeSafe<ConeKotlinType>()?.isBuiltinFunctionalType(session) == true
|
||||
) return this
|
||||
if (argument !is FirLambdaArgumentExpression) return this
|
||||
if (argument.expression !is FirAnonymousFunction) return this
|
||||
if (argument.expression.typeRef == parameter.returnTypeRef) return this
|
||||
if (parameter == null || !needSamConversion(argument, parameter)) {
|
||||
return this
|
||||
}
|
||||
val samType = parameter.returnTypeRef.toIrType()
|
||||
// Make sure the converted IrType owner indeed has a single abstract method, since FunctionReferenceLowering relies on it.
|
||||
if (!samType.isSamType) return this
|
||||
return IrTypeOperatorCallImpl(this.startOffset, this.endOffset, samType, IrTypeOperator.SAM_CONVERSION, samType, this)
|
||||
}
|
||||
|
||||
private fun needSamConversion(argument: FirExpression, parameter: FirValueParameter): Boolean {
|
||||
// If the expected type is a built-in functional type, we don't need SAM conversion.
|
||||
if (parameter.returnTypeRef.coneTypeSafe<ConeKotlinType>()?.isBuiltinFunctionalType(session) == true) {
|
||||
return false
|
||||
}
|
||||
// On the other hand, the actual type should be a functional type.
|
||||
return argument.isFunctional(session)
|
||||
}
|
||||
|
||||
private fun IrExpression.applyTypeArguments(access: FirQualifiedAccess): IrExpression {
|
||||
return when (this) {
|
||||
is IrMemberAccessExpressionBase -> {
|
||||
|
||||
@@ -31,7 +31,6 @@ import org.jetbrains.kotlin.resolve.calls.inference.model.SimpleConstraintSystem
|
||||
import org.jetbrains.kotlin.types.model.CaptureStatus
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
|
||||
fun Candidate.resolveArgumentExpression(
|
||||
/*
|
||||
csBuilder: ConstraintSystemBuilder,
|
||||
@@ -310,11 +309,7 @@ private fun Candidate.getExpectedTypeWithSAMConversion(
|
||||
val firFunction = symbol.fir as? FirFunction<*> ?: return null
|
||||
if (!samResolver.shouldRunSamConversionForFunction(firFunction)) return null
|
||||
|
||||
val argumentIsFunctional = when ((argument as? FirWrappedArgumentExpression)?.expression ?: argument) {
|
||||
is FirAnonymousFunction, is FirCallableReferenceAccess -> true
|
||||
else -> argument.typeRef.coneTypeSafe<ConeKotlinType>()?.isBuiltinFunctionalType(session) == true
|
||||
}
|
||||
if (!argumentIsFunctional) return null
|
||||
if (!argument.isFunctional(session)) return null
|
||||
|
||||
// TODO: resolvedCall.registerArgumentWithSamConversion(argument, SamConversionDescription(convertedTypeByOriginal, convertedTypeByCandidate!!))
|
||||
|
||||
@@ -323,6 +318,12 @@ private fun Candidate.getExpectedTypeWithSAMConversion(
|
||||
} ?: return null
|
||||
}
|
||||
|
||||
fun FirExpression.isFunctional(session: FirSession): Boolean =
|
||||
when ((this as? FirWrappedArgumentExpression)?.expression ?: this) {
|
||||
is FirAnonymousFunction, is FirCallableReferenceAccess -> true
|
||||
else -> typeRef.coneTypeSafe<ConeKotlinType>()?.isBuiltinFunctionalType(session) == true
|
||||
}
|
||||
|
||||
internal fun FirExpression.getExpectedType(
|
||||
session: FirSession,
|
||||
parameter: FirValueParameter/*, languageVersionSettings: LanguageVersionSettings*/
|
||||
@@ -340,7 +341,6 @@ internal fun FirExpression.getExpectedType(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun ConeKotlinType.varargElementType(session: FirSession): ConeKotlinType {
|
||||
return this.arrayElementType(session) ?: error("Failed to extract! ${this.render()}!")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user