FIR2IR: use information about callable reference adaptation from resolve

This commit is contained in:
Mikhail Glukhikh
2021-02-11 11:28:20 +03:00
parent dcad9c84fc
commit 8bab208322
23 changed files with 169 additions and 88 deletions
@@ -12,7 +12,10 @@ import org.jetbrains.kotlin.fir.backend.convertWithOffsets
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
import org.jetbrains.kotlin.fir.references.FirResolvedCallableReference
import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.resolve.calls.FirFakeArgumentForCallableReference
import org.jetbrains.kotlin.fir.resolve.calls.ResolvedCallArgument
import org.jetbrains.kotlin.fir.resolve.inference.* import org.jetbrains.kotlin.fir.resolve.inference.*
import org.jetbrains.kotlin.fir.types.ConeClassLikeType import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.ConeKotlinType
@@ -29,10 +32,7 @@ import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
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.IrSimpleType import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.isUnit
import org.jetbrains.kotlin.ir.types.typeOrNull
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
@@ -58,7 +58,7 @@ internal class AdapterGenerator(
function: IrFunction function: IrFunction
): Boolean = ): Boolean =
needSuspendConversion(type, function) || needCoercionToUnit(type, function) || needSuspendConversion(type, function) || needCoercionToUnit(type, function) ||
needVarargSpread(callableReferenceAccess, type, function) needVarargSpread(callableReferenceAccess)
/** /**
* For example, * For example,
@@ -96,26 +96,11 @@ internal class AdapterGenerator(
* *
* At the use site, instead of referenced, we can put the adapter: { a, b -> referenced(a, b) } * At the use site, instead of referenced, we can put the adapter: { a, b -> referenced(a, b) }
*/ */
private fun needVarargSpread( private fun needVarargSpread(callableReferenceAccess: FirCallableReferenceAccess): Boolean {
callableReferenceAccess: FirCallableReferenceAccess,
type: IrSimpleType,
function: IrFunction
): Boolean {
// Unbound callable reference 'A::foo' // Unbound callable reference 'A::foo'
val shift = if (callableReferenceAccess.explicitReceiver is FirResolvedQualifier) 1 else 0 return (callableReferenceAccess.calleeReference as? FirResolvedCallableReference)?.mappedArguments?.any {
val typeArguments = type.arguments it.value is ResolvedCallArgument.VarargArgument || it.value is ResolvedCallArgument.DefaultArgument
// Drop the return type from type arguments } == true
val expectedParameterSize = typeArguments.size - 1 - shift
if (expectedParameterSize < function.valueParameters.size) {
return false
}
var hasSpreadCase = false
function.valueParameters.forEachIndexed { index, irValueParameter ->
if (irValueParameter.isVararg && typeArguments[shift + index] == irValueParameter.varargElementType) {
hasSpreadCase = true
}
}
return hasSpreadCase
} }
internal fun ConeKotlinType.kFunctionTypeToFunctionType(): IrSimpleType = internal fun ConeKotlinType.kFunctionTypeToFunctionType(): IrSimpleType =
@@ -138,7 +123,7 @@ internal class AdapterGenerator(
callableReferenceAccess, startOffset, endOffset, firAdaptee!!, adaptee, type, boundDispatchReceiver, boundExtensionReceiver callableReferenceAccess, startOffset, endOffset, firAdaptee!!, adaptee, type, boundDispatchReceiver, boundExtensionReceiver
) )
val irCall = createAdapteeCallForCallableReference( val irCall = createAdapteeCallForCallableReference(
callableReferenceAccess, adapteeSymbol, irAdapterFunction, boundDispatchReceiver, boundExtensionReceiver callableReferenceAccess, firAdaptee, adapteeSymbol, irAdapterFunction, boundDispatchReceiver, boundExtensionReceiver
) )
irAdapterFunction.body = irFactory.createBlockBody(startOffset, endOffset) { irAdapterFunction.body = irFactory.createBlockBody(startOffset, endOffset) {
if (expectedReturnType?.isUnit() == true) { if (expectedReturnType?.isUnit() == true) {
@@ -268,6 +253,7 @@ internal class AdapterGenerator(
private fun createAdapteeCallForCallableReference( private fun createAdapteeCallForCallableReference(
callableReferenceAccess: FirCallableReferenceAccess, callableReferenceAccess: FirCallableReferenceAccess,
firAdaptee: FirFunction<*>,
adapteeSymbol: IrFunctionSymbol, adapteeSymbol: IrFunctionSymbol,
adapterFunction: IrFunction, adapterFunction: IrFunction,
boundDispatchReceiver: IrExpression?, boundDispatchReceiver: IrExpression?,
@@ -296,6 +282,7 @@ internal class AdapterGenerator(
} }
var adapterParameterIndex = 0 var adapterParameterIndex = 0
var parameterShift = 0
if (boundDispatchReceiver != null || boundExtensionReceiver != null) { if (boundDispatchReceiver != null || boundExtensionReceiver != null) {
val receiverValue = IrGetValueImpl( val receiverValue = IrGetValueImpl(
startOffset, endOffset, adapterFunction.extensionReceiverParameter!!.symbol, IrStatementOrigin.ADAPTED_FUNCTION_REFERENCE startOffset, endOffset, adapterFunction.extensionReceiverParameter!!.symbol, IrStatementOrigin.ADAPTED_FUNCTION_REFERENCE
@@ -312,50 +299,56 @@ internal class AdapterGenerator(
) )
if (adapteeFunction.extensionReceiverParameter != null) { if (adapteeFunction.extensionReceiverParameter != null) {
irCall.extensionReceiver = adaptedReceiverValue irCall.extensionReceiver = adaptedReceiverValue
adapterParameterIndex++
} else { } else {
irCall.dispatchReceiver = adaptedReceiverValue irCall.dispatchReceiver = adaptedReceiverValue
} }
parameterShift++
} }
adapteeFunction.valueParameters.mapIndexed { index, valueParameter -> val mappedArguments = (callableReferenceAccess.calleeReference as? FirResolvedCallableReference)?.mappedArguments
when {
valueParameter.isVararg -> { fun buildIrGetValueArgument(argument: FirExpression): IrGetValue {
if (adapterFunction.valueParameters.size <= index) { val parameterIndex = (argument as? FirFakeArgumentForCallableReference)?.index ?: adapterParameterIndex
irCall.putValueArgument(index, null) adapterParameterIndex++
return adapterFunction.valueParameters[parameterIndex + parameterShift].toIrGetValue(startOffset, endOffset)
}
adapteeFunction.valueParameters.zip(firAdaptee.valueParameters).mapIndexed { index, (valueParameter, firParameter) ->
when (val mappedArgument = mappedArguments?.get(firParameter)) {
is ResolvedCallArgument.VarargArgument -> {
val valueArgument = if (mappedArgument.arguments.isEmpty()) {
null
} else { } else {
val adaptedValueArgument = val adaptedValueArgument = IrVarargImpl(
IrVarargImpl(startOffset, endOffset, valueParameter.type, valueParameter.varargElementType!!) startOffset, endOffset,
var neitherArrayNorSpread = false valueParameter.type, valueParameter.varargElementType!!,
while (adapterParameterIndex < adapterFunction.valueParameters.size) { )
val irValueArgument = for (argument in mappedArgument.arguments) {
adapterFunction.valueParameters[adapterParameterIndex].toIrGetValue(startOffset, endOffset) val irValueArgument = buildIrGetValueArgument(argument)
if (irValueArgument.type == valueParameter.type) { adaptedValueArgument.addElement(irValueArgument)
adaptedValueArgument.addElement(IrSpreadElementImpl(startOffset, endOffset, irValueArgument))
adapterParameterIndex++
break
} else if (irValueArgument.type == valueParameter.varargElementType) {
adaptedValueArgument.addElement(irValueArgument)
adapterParameterIndex++
} else {
neitherArrayNorSpread = true
break
}
}
if (neitherArrayNorSpread) {
irCall.putValueArgument(index, null)
} else {
irCall.putValueArgument(index, adaptedValueArgument)
} }
adaptedValueArgument
} }
irCall.putValueArgument(index, valueArgument)
} }
valueParameter.hasDefaultValue() -> { ResolvedCallArgument.DefaultArgument -> {
irCall.putValueArgument(index, null) irCall.putValueArgument(index, null)
} }
else -> { is ResolvedCallArgument.SimpleArgument -> {
irCall.putValueArgument( val irValueArgument = buildIrGetValueArgument(mappedArgument.callArgument)
index, adapterFunction.valueParameters[adapterParameterIndex++].toIrGetValue(startOffset, endOffset) if (valueParameter.isVararg) {
) irCall.putValueArgument(
index, IrVarargImpl(
startOffset, endOffset,
valueParameter.type, valueParameter.varargElementType!!,
listOf(IrSpreadElementImpl(startOffset, endOffset, irValueArgument))
)
)
} else {
irCall.putValueArgument(index, irValueArgument)
}
}
null -> {
} }
} }
} }
@@ -51,8 +51,7 @@ internal object CheckCallableReferenceExpectedType : CheckerStage() {
} }
candidate.resultingTypeForCallableReference = resultingType candidate.resultingTypeForCallableReference = resultingType
candidate.usesSuspendConversion = candidate.callableReferenceAdaptation = callableReferenceAdaptation
callableReferenceAdaptation?.suspendConversionStrategy == SuspendConversionStrategy.SUSPEND_CONVERSION
candidate.outerConstraintBuilderEffect = fun ConstraintSystemOperation.() { candidate.outerConstraintBuilderEffect = fun ConstraintSystemOperation.() {
addOtherSystem(candidate.system.asReadOnlyStorage()) addOtherSystem(candidate.system.asReadOnlyStorage())
@@ -133,7 +132,7 @@ internal class CallableReferenceAdaptation(
val argumentTypes: Array<ConeKotlinType>, val argumentTypes: Array<ConeKotlinType>,
val coercionStrategy: CoercionStrategy, val coercionStrategy: CoercionStrategy,
val defaults: Int, val defaults: Int,
val mappedArguments: Map<FirValueParameter, ResolvedCallArgument>, val mappedArguments: CallableReferenceMappedArguments,
val suspendConversionStrategy: SuspendConversionStrategy val suspendConversionStrategy: SuspendConversionStrategy
) )
@@ -351,7 +350,7 @@ private fun createFakeArgumentsForReference(
} }
} }
private class FirFakeArgumentForCallableReference( class FirFakeArgumentForCallableReference(
val index: Int val index: Int
) : FirExpression() { ) : FirExpression() {
override val source: FirSourceElement? override val source: FirSourceElement?
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.ConeTypeVariable import org.jetbrains.kotlin.fir.types.ConeTypeVariable
import org.jetbrains.kotlin.fir.types.FirTypeProjection import org.jetbrains.kotlin.fir.types.FirTypeProjection
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.components.SuspendConversionStrategy
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemOperation import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemOperation
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
@@ -97,6 +98,13 @@ class Candidate(
var resultingTypeForCallableReference: ConeKotlinType? = null var resultingTypeForCallableReference: ConeKotlinType? = null
var outerConstraintBuilderEffect: (ConstraintSystemOperation.() -> Unit)? = null var outerConstraintBuilderEffect: (ConstraintSystemOperation.() -> Unit)? = null
var usesSAM: Boolean = false var usesSAM: Boolean = false
internal var callableReferenceAdaptation: CallableReferenceAdaptation? = null
set(value) {
field = value
usesSuspendConversion = value?.suspendConversionStrategy == SuspendConversionStrategy.SUSPEND_CONVERSION
}
var usesSuspendConversion: Boolean = false var usesSuspendConversion: Boolean = false
var argumentMapping: LinkedHashMap<FirExpression, FirValueParameter>? = null var argumentMapping: LinkedHashMap<FirExpression, FirValueParameter>? = null
@@ -18,7 +18,6 @@ import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
import org.jetbrains.kotlin.fir.resolve.defaultParameterResolver import org.jetbrains.kotlin.fir.resolve.defaultParameterResolver
import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import java.util.*
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
import kotlin.collections.LinkedHashMap import kotlin.collections.LinkedHashMap
import kotlin.collections.component1 import kotlin.collections.component1
@@ -14,10 +14,8 @@ import org.jetbrains.kotlin.fir.references.builder.buildErrorNamedReference
import org.jetbrains.kotlin.fir.references.builder.buildResolvedCallableReference import org.jetbrains.kotlin.fir.references.builder.buildResolvedCallableReference
import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference
import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.calls.Candidate import org.jetbrains.kotlin.fir.resolve.calls.*
import org.jetbrains.kotlin.fir.resolve.calls.FirErrorReferenceWithCandidate import org.jetbrains.kotlin.fir.resolve.calls.CallableReferenceAdaptation
import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate
import org.jetbrains.kotlin.fir.resolve.calls.varargElementType
import org.jetbrains.kotlin.fir.resolve.dfa.FirDataFlowAnalyzer import org.jetbrains.kotlin.fir.resolve.dfa.FirDataFlowAnalyzer
import org.jetbrains.kotlin.fir.resolve.inference.* import org.jetbrains.kotlin.fir.resolve.inference.*
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
@@ -295,6 +293,7 @@ class FirCallCompletionResultsWriterTransformer(
name = calleeReference.name name = calleeReference.name
resolvedSymbol = calleeReference.candidateSymbol resolvedSymbol = calleeReference.candidateSymbol
inferredTypeArguments.addAll(computeTypeArgumentTypes(calleeReference.candidate)) inferredTypeArguments.addAll(computeTypeArgumentTypes(calleeReference.candidate))
mappedArguments = subCandidate.callableReferenceAdaptation?.mappedArguments ?: emptyMap()
}, },
).transformDispatchReceiver(StoreReceiver, subCandidate.dispatchReceiverExpression()) ).transformDispatchReceiver(StoreReceiver, subCandidate.dispatchReceiverExpression())
.transformExtensionReceiver(StoreReceiver, subCandidate.extensionReceiverExpression()) .transformExtensionReceiver(StoreReceiver, subCandidate.extensionReceiverExpression())
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.fir.references package org.jetbrains.kotlin.fir.references
import org.jetbrains.kotlin.fir.FirSourceElement import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.resolve.calls.CallableReferenceMappedArguments
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
@@ -22,6 +23,7 @@ abstract class FirResolvedCallableReference : FirResolvedNamedReference() {
abstract override val candidateSymbol: AbstractFirBasedSymbol<*>? abstract override val candidateSymbol: AbstractFirBasedSymbol<*>?
abstract override val resolvedSymbol: AbstractFirBasedSymbol<*> abstract override val resolvedSymbol: AbstractFirBasedSymbol<*>
abstract val inferredTypeArguments: List<ConeKotlinType> abstract val inferredTypeArguments: List<ConeKotlinType>
abstract val mappedArguments: CallableReferenceMappedArguments
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitResolvedCallableReference(this, data) override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitResolvedCallableReference(this, data)
} }
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.builder.FirBuilderDsl import org.jetbrains.kotlin.fir.builder.FirBuilderDsl
import org.jetbrains.kotlin.fir.references.FirResolvedCallableReference import org.jetbrains.kotlin.fir.references.FirResolvedCallableReference
import org.jetbrains.kotlin.fir.references.impl.FirResolvedCallableReferenceImpl import org.jetbrains.kotlin.fir.references.impl.FirResolvedCallableReferenceImpl
import org.jetbrains.kotlin.fir.resolve.calls.CallableReferenceMappedArguments
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.visitors.* import org.jetbrains.kotlin.fir.visitors.*
@@ -26,6 +27,7 @@ class FirResolvedCallableReferenceBuilder {
lateinit var name: Name lateinit var name: Name
lateinit var resolvedSymbol: AbstractFirBasedSymbol<*> lateinit var resolvedSymbol: AbstractFirBasedSymbol<*>
val inferredTypeArguments: MutableList<ConeKotlinType> = mutableListOf() val inferredTypeArguments: MutableList<ConeKotlinType> = mutableListOf()
lateinit var mappedArguments: CallableReferenceMappedArguments
fun build(): FirResolvedCallableReference { fun build(): FirResolvedCallableReference {
return FirResolvedCallableReferenceImpl( return FirResolvedCallableReferenceImpl(
@@ -33,6 +35,7 @@ class FirResolvedCallableReferenceBuilder {
name, name,
resolvedSymbol, resolvedSymbol,
inferredTypeArguments, inferredTypeArguments,
mappedArguments,
) )
} }
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.references.impl
import org.jetbrains.kotlin.fir.FirSourceElement import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.references.FirResolvedCallableReference import org.jetbrains.kotlin.fir.references.FirResolvedCallableReference
import org.jetbrains.kotlin.fir.resolve.calls.CallableReferenceMappedArguments
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
@@ -22,6 +23,7 @@ internal class FirResolvedCallableReferenceImpl(
override val name: Name, override val name: Name,
override val resolvedSymbol: AbstractFirBasedSymbol<*>, override val resolvedSymbol: AbstractFirBasedSymbol<*>,
override val inferredTypeArguments: MutableList<ConeKotlinType>, override val inferredTypeArguments: MutableList<ConeKotlinType>,
override val mappedArguments: CallableReferenceMappedArguments,
) : FirResolvedCallableReference() { ) : FirResolvedCallableReference() {
override val candidateSymbol: AbstractFirBasedSymbol<*>? get() = null override val candidateSymbol: AbstractFirBasedSymbol<*>? get() = null
@@ -1,10 +1,11 @@
/* /*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
package org.jetbrains.kotlin.fir.resolve.calls package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirExpression
sealed class ResolvedCallArgument { sealed class ResolvedCallArgument {
@@ -24,3 +25,5 @@ sealed class ResolvedCallArgument {
class VarargArgument(override val arguments: List<FirExpression>) : ResolvedCallArgument() class VarargArgument(override val arguments: List<FirExpression>) : ResolvedCallArgument()
} }
typealias CallableReferenceMappedArguments = Map<FirValueParameter, ResolvedCallArgument>
@@ -535,6 +535,7 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
resolvedCallableReference.configure { resolvedCallableReference.configure {
+fieldList("inferredTypeArguments", coneKotlinTypeType) +fieldList("inferredTypeArguments", coneKotlinTypeType)
+field("mappedArguments", callableReferenceMappedArgumentsType)
} }
delegateFieldReference.configure { delegateFieldReference.configure {
@@ -86,3 +86,5 @@ val declarationAttributesType = generatedType("declarations", "FirDeclarationAtt
val annotationResolveStatusType = generatedType("expressions", "FirAnnotationResolveStatus") val annotationResolveStatusType = generatedType("expressions", "FirAnnotationResolveStatus")
val exhaustivenessStatusType = generatedType("expressions", "ExhaustivenessStatus") val exhaustivenessStatusType = generatedType("expressions", "ExhaustivenessStatus")
val callableReferenceMappedArgumentsType = type("fir.resolve.calls", "CallableReferenceMappedArguments")
@@ -1,5 +1,4 @@
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME // WITH_RUNTIME
package test package test
@@ -1,5 +1,4 @@
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_REFLECT // WITH_REFLECT
import kotlin.reflect.* import kotlin.reflect.*
@@ -20,13 +20,22 @@ fun C.extensionBoth(i: Int, s: String = "", vararg t: String) {
} }
fun testExtensionVararg() { fun testExtensionVararg() {
use(f = ::extensionVararg) use(f = local fun extensionVararg(p0: C, p1: Int) {
p0.extensionVararg(i = p1)
}
)
} }
fun testExtensionDefault() { fun testExtensionDefault() {
use(f = ::extensionDefault) use(f = local fun extensionDefault(p0: C, p1: Int) {
p0.extensionDefault(i = p1)
}
)
} }
fun testExtensionBoth() { fun testExtensionBoth() {
use(f = ::extensionBoth) use(f = local fun extensionBoth(p0: C, p1: Int) {
p0.extensionBoth(i = p1)
}
)
} }
@@ -44,12 +44,33 @@ FILE fqName:<root> fileName:/adaptedExtensionFunctions.kt
FUN name:testExtensionVararg visibility:public modality:FINAL <> () returnType:kotlin.Unit FUN name:testExtensionVararg visibility:public modality:FINAL <> () returnType:kotlin.Unit
BLOCK_BODY BLOCK_BODY
CALL 'public final fun use (f: @[ExtensionFunctionType] kotlin.Function2<<root>.C, kotlin.Int, kotlin.Unit>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null CALL 'public final fun use (f: @[ExtensionFunctionType] kotlin.Function2<<root>.C, kotlin.Int, kotlin.Unit>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
f: FUNCTION_REFERENCE 'public final fun extensionVararg (i: kotlin.Int, vararg s: kotlin.String): kotlin.Unit declared in <root>' type=kotlin.reflect.KFunction2<<root>.C, kotlin.Int, kotlin.Unit> origin=null reflectionTarget=<same> f: FUN_EXPR type=kotlin.Function2<<root>.C, kotlin.Int, kotlin.Unit> origin=ADAPTED_FUNCTION_REFERENCE
FUN ADAPTER_FOR_CALLABLE_REFERENCE name:extensionVararg visibility:local modality:FINAL <> (p0:<root>.C, p1:kotlin.Int) returnType:kotlin.Unit
VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:p0 index:0 type:<root>.C
VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:p1 index:1 type:kotlin.Int
BLOCK_BODY
CALL 'public final fun extensionVararg (i: kotlin.Int, vararg s: kotlin.String): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
$receiver: GET_VAR 'p0: <root>.C declared in <root>.testExtensionVararg.extensionVararg' type=<root>.C origin=null
i: GET_VAR 'p1: kotlin.Int declared in <root>.testExtensionVararg.extensionVararg' type=kotlin.Int origin=null
FUN name:testExtensionDefault visibility:public modality:FINAL <> () returnType:kotlin.Unit FUN name:testExtensionDefault visibility:public modality:FINAL <> () returnType:kotlin.Unit
BLOCK_BODY BLOCK_BODY
CALL 'public final fun use (f: @[ExtensionFunctionType] kotlin.Function2<<root>.C, kotlin.Int, kotlin.Unit>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null CALL 'public final fun use (f: @[ExtensionFunctionType] kotlin.Function2<<root>.C, kotlin.Int, kotlin.Unit>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
f: FUNCTION_REFERENCE 'public final fun extensionDefault (i: kotlin.Int, s: kotlin.String): kotlin.Unit declared in <root>' type=kotlin.reflect.KFunction2<<root>.C, kotlin.Int, kotlin.Unit> origin=null reflectionTarget=<same> f: FUN_EXPR type=kotlin.Function2<<root>.C, kotlin.Int, kotlin.Unit> origin=ADAPTED_FUNCTION_REFERENCE
FUN ADAPTER_FOR_CALLABLE_REFERENCE name:extensionDefault visibility:local modality:FINAL <> (p0:<root>.C, p1:kotlin.Int) returnType:kotlin.Unit
VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:p0 index:0 type:<root>.C
VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:p1 index:1 type:kotlin.Int
BLOCK_BODY
CALL 'public final fun extensionDefault (i: kotlin.Int, s: kotlin.String): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
$receiver: GET_VAR 'p0: <root>.C declared in <root>.testExtensionDefault.extensionDefault' type=<root>.C origin=null
i: GET_VAR 'p1: kotlin.Int declared in <root>.testExtensionDefault.extensionDefault' type=kotlin.Int origin=null
FUN name:testExtensionBoth visibility:public modality:FINAL <> () returnType:kotlin.Unit FUN name:testExtensionBoth visibility:public modality:FINAL <> () returnType:kotlin.Unit
BLOCK_BODY BLOCK_BODY
CALL 'public final fun use (f: @[ExtensionFunctionType] kotlin.Function2<<root>.C, kotlin.Int, kotlin.Unit>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null CALL 'public final fun use (f: @[ExtensionFunctionType] kotlin.Function2<<root>.C, kotlin.Int, kotlin.Unit>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
f: FUNCTION_REFERENCE 'public final fun extensionBoth (i: kotlin.Int, s: kotlin.String, vararg t: kotlin.String): kotlin.Unit declared in <root>' type=kotlin.reflect.KFunction2<<root>.C, kotlin.Int, kotlin.Unit> origin=null reflectionTarget=<same> f: FUN_EXPR type=kotlin.Function2<<root>.C, kotlin.Int, kotlin.Unit> origin=ADAPTED_FUNCTION_REFERENCE
FUN ADAPTER_FOR_CALLABLE_REFERENCE name:extensionBoth visibility:local modality:FINAL <> (p0:<root>.C, p1:kotlin.Int) returnType:kotlin.Unit
VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:p0 index:0 type:<root>.C
VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:p1 index:1 type:kotlin.Int
BLOCK_BODY
CALL 'public final fun extensionBoth (i: kotlin.Int, s: kotlin.String, vararg t: kotlin.String): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
$receiver: GET_VAR 'p0: <root>.C declared in <root>.testExtensionBoth.extensionBoth' type=<root>.C origin=null
i: GET_VAR 'p1: kotlin.Int declared in <root>.testExtensionBoth.extensionBoth' type=kotlin.Int origin=null
@@ -20,7 +20,10 @@ fun use(fn: Function0<Any>): Any {
} }
fun testFn(): Any { fun testFn(): Any {
return use(fn = ::foo) return use(fn = local fun foo(): String {
return foo()
}
)
} }
fun testCtor(): Any { fun testCtor(): Any {
@@ -49,7 +49,11 @@ FILE fqName:<root> fileName:/kt37131.kt
BLOCK_BODY BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun testFn (): kotlin.Any declared in <root>' RETURN type=kotlin.Nothing from='public final fun testFn (): kotlin.Any declared in <root>'
CALL 'public final fun use (fn: kotlin.Function0<kotlin.Any>): kotlin.Any declared in <root>' type=kotlin.Any origin=null CALL 'public final fun use (fn: kotlin.Function0<kotlin.Any>): kotlin.Any declared in <root>' type=kotlin.Any origin=null
fn: FUNCTION_REFERENCE 'public final fun foo (x: kotlin.String): kotlin.String declared in <root>' type=kotlin.reflect.KFunction0<kotlin.String> origin=null reflectionTarget=<same> fn: FUN_EXPR type=kotlin.Function0<kotlin.String> origin=ADAPTED_FUNCTION_REFERENCE
FUN ADAPTER_FOR_CALLABLE_REFERENCE name:foo visibility:local modality:FINAL <> () returnType:kotlin.String
BLOCK_BODY
RETURN type=kotlin.Nothing from='local final fun foo (): kotlin.String declared in <root>.testFn'
CALL 'public final fun foo (x: kotlin.String): kotlin.String declared in <root>' type=kotlin.String origin=null
FUN name:testCtor visibility:public modality:FINAL <> () returnType:kotlin.Any FUN name:testCtor visibility:public modality:FINAL <> () returnType:kotlin.Any
BLOCK_BODY BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun testCtor (): kotlin.Any declared in <root>' RETURN type=kotlin.Nothing from='public final fun testCtor (): kotlin.Any declared in <root>'
@@ -32,7 +32,7 @@ object Obj : A {
fun testUnbound() { fun testUnbound() {
use1(fn = local fun foo(p0: A, p1: Int) { use1(fn = local fun foo(p0: A, p1: Int) {
p0.foo() p0.foo(xs = [p1])
} }
) )
} }
@@ -67,6 +67,8 @@ FILE fqName:<root> fileName:/unboundMemberReferenceWithAdaptedArguments.kt
BLOCK_BODY BLOCK_BODY
CALL 'public open fun foo (vararg xs: kotlin.Int): kotlin.Int declared in <root>.A' type=kotlin.Int origin=null CALL 'public open fun foo (vararg xs: kotlin.Int): kotlin.Int declared in <root>.A' type=kotlin.Int origin=null
$this: GET_VAR 'p0: <root>.A declared in <root>.testUnbound.foo' type=<root>.A origin=null $this: GET_VAR 'p0: <root>.A declared in <root>.testUnbound.foo' type=<root>.A origin=null
xs: VARARG type=kotlin.IntArray varargElementType=kotlin.Int
GET_VAR 'p1: kotlin.Int declared in <root>.testUnbound.foo' type=kotlin.Int origin=null
FUN name:testBound visibility:public modality:FINAL <> (a:<root>.A) returnType:kotlin.Unit FUN name:testBound visibility:public modality:FINAL <> (a:<root>.A) returnType:kotlin.Unit
VALUE_PARAMETER name:a index:0 type:<root>.A VALUE_PARAMETER name:a index:0 type:<root>.A
BLOCK_BODY BLOCK_BODY
@@ -35,7 +35,10 @@ object Host {
} }
fun testDefault(): String { fun testDefault(): String {
return use(fn = ::fnWithDefault) return use(fn = local fun fnWithDefault(p0: Int): String {
return fnWithDefault(a = p0)
}
)
} }
fun testVararg(): String { fun testVararg(): String {
@@ -63,9 +66,15 @@ fun testImportedObjectMember(): String {
} }
fun testDefault0(): String { fun testDefault0(): String {
return use0(fn = ::fnWithDefaults) return use0(fn = local fun fnWithDefaults(): String {
return fnWithDefaults()
}
)
} }
fun testVararg0(): String { fun testVararg0(): String {
return use0(fn = ::fnWithVarargs) return use0(fn = local fun fnWithVarargs(): String {
return fnWithVarargs()
}
)
} }
@@ -67,7 +67,13 @@ FILE fqName:<root> fileName:/withAdaptedArguments.kt
BLOCK_BODY BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun testDefault (): kotlin.String declared in <root>' RETURN type=kotlin.Nothing from='public final fun testDefault (): kotlin.String declared in <root>'
CALL 'public final fun use (fn: kotlin.Function1<kotlin.Int, kotlin.String>): kotlin.String declared in <root>' type=kotlin.String origin=null CALL 'public final fun use (fn: kotlin.Function1<kotlin.Int, kotlin.String>): kotlin.String declared in <root>' type=kotlin.String origin=null
fn: FUNCTION_REFERENCE 'public final fun fnWithDefault (a: kotlin.Int, b: kotlin.Int): kotlin.String declared in <root>' type=kotlin.reflect.KFunction1<kotlin.Int, kotlin.String> origin=null reflectionTarget=<same> fn: FUN_EXPR type=kotlin.Function1<kotlin.Int, kotlin.String> origin=ADAPTED_FUNCTION_REFERENCE
FUN ADAPTER_FOR_CALLABLE_REFERENCE name:fnWithDefault visibility:local modality:FINAL <> (p0:kotlin.Int) returnType:kotlin.String
VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:p0 index:0 type:kotlin.Int
BLOCK_BODY
RETURN type=kotlin.Nothing from='local final fun fnWithDefault (p0: kotlin.Int): kotlin.String declared in <root>.testDefault'
CALL 'public final fun fnWithDefault (a: kotlin.Int, b: kotlin.Int): kotlin.String declared in <root>' type=kotlin.String origin=null
a: GET_VAR 'p0: kotlin.Int declared in <root>.testDefault.fnWithDefault' type=kotlin.Int origin=null
FUN name:testVararg visibility:public modality:FINAL <> () returnType:kotlin.String FUN name:testVararg visibility:public modality:FINAL <> () returnType:kotlin.String
BLOCK_BODY BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun testVararg (): kotlin.String declared in <root>' RETURN type=kotlin.Nothing from='public final fun testVararg (): kotlin.String declared in <root>'
@@ -109,9 +115,17 @@ FILE fqName:<root> fileName:/withAdaptedArguments.kt
BLOCK_BODY BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun testDefault0 (): kotlin.String declared in <root>' RETURN type=kotlin.Nothing from='public final fun testDefault0 (): kotlin.String declared in <root>'
CALL 'public final fun use0 (fn: kotlin.Function0<kotlin.String>): kotlin.String declared in <root>' type=kotlin.String origin=null CALL 'public final fun use0 (fn: kotlin.Function0<kotlin.String>): kotlin.String declared in <root>' type=kotlin.String origin=null
fn: FUNCTION_REFERENCE 'public final fun fnWithDefaults (a: kotlin.Int, b: kotlin.Int): kotlin.String declared in <root>' type=kotlin.reflect.KFunction0<kotlin.String> origin=null reflectionTarget=<same> fn: FUN_EXPR type=kotlin.Function0<kotlin.String> origin=ADAPTED_FUNCTION_REFERENCE
FUN ADAPTER_FOR_CALLABLE_REFERENCE name:fnWithDefaults visibility:local modality:FINAL <> () returnType:kotlin.String
BLOCK_BODY
RETURN type=kotlin.Nothing from='local final fun fnWithDefaults (): kotlin.String declared in <root>.testDefault0'
CALL 'public final fun fnWithDefaults (a: kotlin.Int, b: kotlin.Int): kotlin.String declared in <root>' type=kotlin.String origin=null
FUN name:testVararg0 visibility:public modality:FINAL <> () returnType:kotlin.String FUN name:testVararg0 visibility:public modality:FINAL <> () returnType:kotlin.String
BLOCK_BODY BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun testVararg0 (): kotlin.String declared in <root>' RETURN type=kotlin.Nothing from='public final fun testVararg0 (): kotlin.String declared in <root>'
CALL 'public final fun use0 (fn: kotlin.Function0<kotlin.String>): kotlin.String declared in <root>' type=kotlin.String origin=null CALL 'public final fun use0 (fn: kotlin.Function0<kotlin.String>): kotlin.String declared in <root>' type=kotlin.String origin=null
fn: FUNCTION_REFERENCE 'public final fun fnWithVarargs (vararg xs: kotlin.Int): kotlin.String declared in <root>' type=kotlin.reflect.KFunction0<kotlin.String> origin=null reflectionTarget=<same> fn: FUN_EXPR type=kotlin.Function0<kotlin.String> origin=ADAPTED_FUNCTION_REFERENCE
FUN ADAPTER_FOR_CALLABLE_REFERENCE name:fnWithVarargs visibility:local modality:FINAL <> () returnType:kotlin.String
BLOCK_BODY
RETURN type=kotlin.Nothing from='local final fun fnWithVarargs (): kotlin.String declared in <root>.testVararg0'
CALL 'public final fun fnWithVarargs (vararg xs: kotlin.Int): kotlin.String declared in <root>' type=kotlin.String origin=null
@@ -48,5 +48,8 @@ fun testArrayAsVararg() {
} }
fun testArrayAndDefaults() { fun testArrayAndDefaults() {
useStringArray(fn = ::zap) useStringArray(fn = local fun zap(p0: Array<out String>) {
zap(b = [*p0])
}
)
} }
@@ -82,4 +82,11 @@ FILE fqName:<root> fileName:/withVarargViewedAsArray.kt
FUN name:testArrayAndDefaults visibility:public modality:FINAL <> () returnType:kotlin.Unit FUN name:testArrayAndDefaults visibility:public modality:FINAL <> () returnType:kotlin.Unit
BLOCK_BODY BLOCK_BODY
CALL 'public final fun useStringArray (fn: kotlin.Function1<kotlin.Array<kotlin.String>, kotlin.Unit>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null CALL 'public final fun useStringArray (fn: kotlin.Function1<kotlin.Array<kotlin.String>, kotlin.Unit>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
fn: FUNCTION_REFERENCE 'public final fun zap (vararg b: kotlin.String, k: kotlin.Int): kotlin.Unit declared in <root>' type=kotlin.reflect.KFunction1<kotlin.Array<out kotlin.String>, kotlin.Unit> origin=null reflectionTarget=<same> fn: FUN_EXPR type=kotlin.Function1<kotlin.Array<out kotlin.String>, kotlin.Unit> origin=ADAPTED_FUNCTION_REFERENCE
FUN ADAPTER_FOR_CALLABLE_REFERENCE name:zap visibility:local modality:FINAL <> (p0:kotlin.Array<out kotlin.String>) returnType:kotlin.Unit
VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:p0 index:0 type:kotlin.Array<out kotlin.String>
BLOCK_BODY
CALL 'public final fun zap (vararg b: kotlin.String, k: kotlin.Int): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
b: VARARG type=kotlin.Array<out kotlin.String> varargElementType=kotlin.String
SPREAD_ELEMENT
GET_VAR 'p0: kotlin.Array<out kotlin.String> declared in <root>.testArrayAndDefaults.zap' type=kotlin.Array<out kotlin.String> origin=null