[FIR] Properly detect callable reference type according conversions
This commit is contained in:
@@ -42,6 +42,7 @@ object StandardClassIds {
|
|||||||
val String = "String".baseId()
|
val String = "String".baseId()
|
||||||
|
|
||||||
val KProperty = "KProperty".reflectId()
|
val KProperty = "KProperty".reflectId()
|
||||||
|
val KMutableProperty = "KMutableProperty".reflectId()
|
||||||
val KProperty0 = "KProperty0".reflectId()
|
val KProperty0 = "KProperty0".reflectId()
|
||||||
val KMutableProperty0 = "KMutableProperty0".reflectId()
|
val KMutableProperty0 = "KMutableProperty0".reflectId()
|
||||||
val KProperty1 = "KProperty1".reflectId()
|
val KProperty1 = "KProperty1".reflectId()
|
||||||
@@ -50,6 +51,7 @@ object StandardClassIds {
|
|||||||
val KMutableProperty2 = "KMutableProperty2".reflectId()
|
val KMutableProperty2 = "KMutableProperty2".reflectId()
|
||||||
val KFunction = "KFunction".reflectId()
|
val KFunction = "KFunction".reflectId()
|
||||||
val KClass = "KClass".reflectId()
|
val KClass = "KClass".reflectId()
|
||||||
|
val KCallable = "KCallable".reflectId()
|
||||||
|
|
||||||
val Comparable = "Comparable".baseId()
|
val Comparable = "Comparable".baseId()
|
||||||
val Number = "Number".baseId()
|
val Number = "Number".baseId()
|
||||||
|
|||||||
+402
@@ -0,0 +1,402 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.fir.resolve.calls
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.FirElement
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirNamedArgumentExpression
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.builder.buildNamedArgumentExpression
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.DoubleColonLHS
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.createFunctionalType
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnsupportedCallableReferenceTarget
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.inference.extractInputOutputTypesFromCallableReferenceExpectedType
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.inference.isSuspendFunctionType
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
|
import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
||||||
|
import org.jetbrains.kotlin.fir.visitors.FirVisitor
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.components.SuspendConversionStrategy
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemOperation
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.inference.model.SimpleConstraintSystemConstraintPosition
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
|
||||||
|
import org.jetbrains.kotlin.types.expressions.CoercionStrategy
|
||||||
|
|
||||||
|
|
||||||
|
internal object CheckCallableReferenceExpectedType : CheckerStage() {
|
||||||
|
override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) {
|
||||||
|
val outerCsBuilder = callInfo.outerCSBuilder ?: return
|
||||||
|
val expectedType = callInfo.expectedType
|
||||||
|
if (candidate.symbol !is FirCallableSymbol<*>) return
|
||||||
|
|
||||||
|
val resultingReceiverType = when (callInfo.lhs) {
|
||||||
|
is DoubleColonLHS.Type -> callInfo.lhs.type.takeIf { callInfo.explicitReceiver !is FirResolvedQualifier }
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
|
val fir: FirCallableDeclaration<*> = candidate.symbol.fir
|
||||||
|
|
||||||
|
val (rawResultingType, callableReferenceAdaptation) = buildReflectionType(fir, resultingReceiverType, callInfo, context)
|
||||||
|
val resultingType = candidate.substitutor.substituteOrSelf(rawResultingType)
|
||||||
|
|
||||||
|
if (callableReferenceAdaptation.needCompatibilityResolveForCallableReference()) {
|
||||||
|
sink.reportDiagnostic(LowerPriorityToPreserveCompatibilityDiagnostic)
|
||||||
|
}
|
||||||
|
|
||||||
|
candidate.resultingTypeForCallableReference = resultingType
|
||||||
|
candidate.usesSuspendConversion =
|
||||||
|
callableReferenceAdaptation?.suspendConversionStrategy == SuspendConversionStrategy.SUSPEND_CONVERSION
|
||||||
|
candidate.outerConstraintBuilderEffect = fun ConstraintSystemOperation.() {
|
||||||
|
addOtherSystem(candidate.system.asReadOnlyStorage())
|
||||||
|
|
||||||
|
val position = SimpleConstraintSystemConstraintPosition //TODO
|
||||||
|
|
||||||
|
if (expectedType != null) {
|
||||||
|
addSubtypeConstraint(resultingType, expectedType, position)
|
||||||
|
}
|
||||||
|
|
||||||
|
val declarationReceiverType: ConeKotlinType? =
|
||||||
|
(fir as? FirCallableMemberDeclaration<*>)?.receiverTypeRef?.coneType
|
||||||
|
?.let(candidate.substitutor::substituteOrSelf)
|
||||||
|
|
||||||
|
if (resultingReceiverType != null && declarationReceiverType != null) {
|
||||||
|
addSubtypeConstraint(resultingReceiverType, declarationReceiverType, position)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var isApplicable = true
|
||||||
|
|
||||||
|
outerCsBuilder.runTransaction {
|
||||||
|
candidate.outerConstraintBuilderEffect!!(this)
|
||||||
|
|
||||||
|
isApplicable = !hasContradiction
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isApplicable) {
|
||||||
|
sink.yieldDiagnostic(InapplicableCandidate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
val resultingReceiverType = when (callInfo.lhs) {
|
||||||
|
is DoubleColonLHS.Type -> callInfo.lhs.type.takeIf { callInfo.explicitReceiver !is FirResolvedQualifier }
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
private fun buildReflectionType(
|
||||||
|
fir: FirCallableDeclaration<*>,
|
||||||
|
receiverType: ConeKotlinType?,
|
||||||
|
callInfo: CallInfo,
|
||||||
|
context: ResolutionContext
|
||||||
|
): Pair<ConeKotlinType, CallableReferenceAdaptation?> {
|
||||||
|
val returnTypeRef = context.bodyResolveComponents.returnTypeCalculator.tryCalculateReturnType(fir)
|
||||||
|
return when (fir) {
|
||||||
|
is FirFunction -> {
|
||||||
|
val unboundReferenceTarget = if (receiverType != null) 1 else 0
|
||||||
|
val callableReferenceAdaptation =
|
||||||
|
getCallableReferenceAdaptation(context.session, fir, callInfo.expectedType, unboundReferenceTarget)
|
||||||
|
|
||||||
|
val parameters = mutableListOf<ConeKotlinType>()
|
||||||
|
|
||||||
|
val returnType = callableReferenceAdaptation?.let {
|
||||||
|
parameters += it.argumentTypes
|
||||||
|
if (it.coercionStrategy == CoercionStrategy.COERCION_TO_UNIT) {
|
||||||
|
context.session.builtinTypes.unitType.type
|
||||||
|
} else {
|
||||||
|
returnTypeRef.coneType
|
||||||
|
}
|
||||||
|
} ?: returnTypeRef.coneType.also {
|
||||||
|
fir.valueParameters.mapTo(parameters) { it.returnTypeRef.coneType }
|
||||||
|
}
|
||||||
|
|
||||||
|
val isSuspend = (fir as? FirSimpleFunction)?.isSuspend == true ||
|
||||||
|
callableReferenceAdaptation?.suspendConversionStrategy == SuspendConversionStrategy.SUSPEND_CONVERSION
|
||||||
|
return createFunctionalType(
|
||||||
|
parameters,
|
||||||
|
receiverType = receiverType,
|
||||||
|
rawReturnType = returnType,
|
||||||
|
isKFunctionType = true,
|
||||||
|
isSuspend = isSuspend
|
||||||
|
) to callableReferenceAdaptation
|
||||||
|
}
|
||||||
|
is FirVariable -> createKPropertyType(fir, receiverType, returnTypeRef) to null
|
||||||
|
else -> ConeClassErrorType(ConeUnsupportedCallableReferenceTarget(fir)) to null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class CallableReferenceAdaptation(
|
||||||
|
val argumentTypes: Array<ConeKotlinType>,
|
||||||
|
val coercionStrategy: CoercionStrategy,
|
||||||
|
val defaults: Int,
|
||||||
|
val mappedArguments: Map<FirValueParameter, ResolvedCallArgument>,
|
||||||
|
val suspendConversionStrategy: SuspendConversionStrategy
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun CallableReferenceAdaptation?.needCompatibilityResolveForCallableReference(): Boolean {
|
||||||
|
// KT-13934: check containing declaration for companion object
|
||||||
|
if (this == null) return false
|
||||||
|
return defaults != 0 ||
|
||||||
|
suspendConversionStrategy != SuspendConversionStrategy.NO_CONVERSION ||
|
||||||
|
coercionStrategy != CoercionStrategy.NO_COERCION ||
|
||||||
|
mappedArguments.values.any { it is ResolvedCallArgument.VarargArgument }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getCallableReferenceAdaptation(
|
||||||
|
session: FirSession,
|
||||||
|
function: FirFunction<*>,
|
||||||
|
expectedType: ConeKotlinType?,
|
||||||
|
unboundReceiverCount: Int
|
||||||
|
): CallableReferenceAdaptation? {
|
||||||
|
if (expectedType == null) return null
|
||||||
|
|
||||||
|
// Do not adapt references against KCallable type as it's impossible to map defaults/vararg to absent parameters of KCallable
|
||||||
|
if (expectedType.isKCallableType()) return null
|
||||||
|
|
||||||
|
val (inputTypes, returnExpectedType) = extractInputOutputTypesFromCallableReferenceExpectedType(expectedType, session) ?: return null
|
||||||
|
val expectedArgumentsCount = inputTypes.size - unboundReceiverCount
|
||||||
|
if (expectedArgumentsCount < 0) return null
|
||||||
|
|
||||||
|
val fakeArguments = createFakeArgumentsForReference(function, expectedArgumentsCount, inputTypes, unboundReceiverCount)
|
||||||
|
val argumentMapping = mapArguments(fakeArguments, function)
|
||||||
|
if (argumentMapping.diagnostics.any { !it.applicability.isSuccess }) return null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (A, B, C) -> Unit
|
||||||
|
* fun foo(a: A, b: B = B(), vararg c: C)
|
||||||
|
*/
|
||||||
|
var defaults = 0
|
||||||
|
var varargMappingState = VarargMappingState.UNMAPPED
|
||||||
|
val mappedArguments = linkedMapOf<FirValueParameter, ResolvedCallArgument>()
|
||||||
|
val mappedVarargElements = linkedMapOf<FirValueParameter, MutableList<FirExpression>>()
|
||||||
|
val mappedArgumentTypes = arrayOfNulls<ConeKotlinType?>(fakeArguments.size)
|
||||||
|
|
||||||
|
for ((valueParameter, resolvedArgument) in argumentMapping.parameterToCallArgumentMap) {
|
||||||
|
for (fakeArgument in resolvedArgument.arguments) {
|
||||||
|
val index = fakeArgument.index
|
||||||
|
val substitutedParameter = function.valueParameters.getOrNull(function.indexOf(valueParameter)) ?: continue
|
||||||
|
|
||||||
|
val mappedArgument: ConeKotlinType?
|
||||||
|
if (substitutedParameter.isVararg) {
|
||||||
|
val (varargType, newVarargMappingState) = varargParameterTypeByExpectedParameter(
|
||||||
|
inputTypes[index + unboundReceiverCount],
|
||||||
|
substitutedParameter,
|
||||||
|
varargMappingState
|
||||||
|
)
|
||||||
|
varargMappingState = newVarargMappingState
|
||||||
|
mappedArgument = varargType
|
||||||
|
|
||||||
|
when (newVarargMappingState) {
|
||||||
|
VarargMappingState.MAPPED_WITH_ARRAY -> {
|
||||||
|
// If we've already mapped an argument to this value parameter, it'll always be a type mismatch.
|
||||||
|
mappedArguments[valueParameter] = ResolvedCallArgument.SimpleArgument(fakeArgument)
|
||||||
|
}
|
||||||
|
VarargMappingState.MAPPED_WITH_PLAIN_ARGS -> {
|
||||||
|
mappedVarargElements.getOrPut(valueParameter) { ArrayList() }.add(fakeArgument)
|
||||||
|
}
|
||||||
|
VarargMappingState.UNMAPPED -> {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mappedArgument = substitutedParameter.returnTypeRef.coneType
|
||||||
|
mappedArguments[valueParameter] = resolvedArgument
|
||||||
|
}
|
||||||
|
|
||||||
|
mappedArgumentTypes[index] = mappedArgument
|
||||||
|
}
|
||||||
|
if (resolvedArgument == ResolvedCallArgument.DefaultArgument) {
|
||||||
|
defaults++
|
||||||
|
mappedArguments[valueParameter] = resolvedArgument
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mappedArgumentTypes.any { it == null }) return null
|
||||||
|
|
||||||
|
for ((valueParameter, varargElements) in mappedVarargElements) {
|
||||||
|
mappedArguments[valueParameter] = ResolvedCallArgument.VarargArgument(varargElements)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (valueParameter in function.valueParameters) {
|
||||||
|
if (valueParameter.isVararg && valueParameter !in mappedArguments) {
|
||||||
|
mappedArguments[valueParameter] = ResolvedCallArgument.VarargArgument(emptyList())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val coercionStrategy = if (returnExpectedType.isUnit && !function.returnTypeRef.isUnit)
|
||||||
|
CoercionStrategy.COERCION_TO_UNIT
|
||||||
|
else
|
||||||
|
CoercionStrategy.NO_COERCION
|
||||||
|
|
||||||
|
val adaptedArguments = if (expectedType.isBaseTypeForNumberedReferenceTypes)
|
||||||
|
emptyMap()
|
||||||
|
else
|
||||||
|
mappedArguments
|
||||||
|
|
||||||
|
val suspendConversionStrategy = if ((function as? FirSimpleFunction)?.isSuspend != true && expectedType.isSuspendFunctionType(session))
|
||||||
|
SuspendConversionStrategy.SUSPEND_CONVERSION
|
||||||
|
else
|
||||||
|
SuspendConversionStrategy.NO_CONVERSION
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
return CallableReferenceAdaptation(
|
||||||
|
mappedArgumentTypes as Array<ConeKotlinType>,
|
||||||
|
coercionStrategy,
|
||||||
|
defaults,
|
||||||
|
adaptedArguments,
|
||||||
|
suspendConversionStrategy
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ConeKotlinType?.isPotentiallyArray(): Boolean =
|
||||||
|
this != null && (this.arrayElementType() != null || this is ConeTypeVariableType)
|
||||||
|
|
||||||
|
private fun varargParameterTypeByExpectedParameter(
|
||||||
|
expectedParameterType: ConeKotlinType,
|
||||||
|
substitutedParameter: FirValueParameter,
|
||||||
|
varargMappingState: VarargMappingState,
|
||||||
|
): Pair<ConeKotlinType?, VarargMappingState> {
|
||||||
|
val elementType = substitutedParameter.returnTypeRef.coneType.arrayElementType()
|
||||||
|
?: error("Vararg parameter $substitutedParameter does not have vararg type")
|
||||||
|
|
||||||
|
return when (varargMappingState) {
|
||||||
|
VarargMappingState.UNMAPPED -> {
|
||||||
|
if (expectedParameterType.isPotentiallyArray()) {
|
||||||
|
elementType.createOutArrayType() to VarargMappingState.MAPPED_WITH_ARRAY
|
||||||
|
} else {
|
||||||
|
elementType to VarargMappingState.MAPPED_WITH_PLAIN_ARGS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VarargMappingState.MAPPED_WITH_PLAIN_ARGS -> {
|
||||||
|
if (expectedParameterType.isPotentiallyArray())
|
||||||
|
null to VarargMappingState.MAPPED_WITH_PLAIN_ARGS
|
||||||
|
else
|
||||||
|
elementType to VarargMappingState.MAPPED_WITH_PLAIN_ARGS
|
||||||
|
}
|
||||||
|
VarargMappingState.MAPPED_WITH_ARRAY ->
|
||||||
|
null to VarargMappingState.MAPPED_WITH_ARRAY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private enum class VarargMappingState {
|
||||||
|
UNMAPPED, MAPPED_WITH_PLAIN_ARGS, MAPPED_WITH_ARRAY
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirFunction<*>.indexOf(valueParameter: FirValueParameter): Int = valueParameters.indexOf(valueParameter)
|
||||||
|
|
||||||
|
private val ConeKotlinType.isUnit: Boolean
|
||||||
|
get() {
|
||||||
|
val type = this.lowerBoundIfFlexible()
|
||||||
|
if (type.isNullable) return false
|
||||||
|
val classId = type.classId ?: return false
|
||||||
|
return classId == StandardClassIds.Unit
|
||||||
|
}
|
||||||
|
|
||||||
|
private val ConeKotlinType.isBaseTypeForNumberedReferenceTypes: Boolean
|
||||||
|
get() {
|
||||||
|
val classId = lowerBoundIfFlexible().classId ?: return false
|
||||||
|
return when (classId) {
|
||||||
|
StandardClassIds.KProperty,
|
||||||
|
StandardClassIds.KMutableProperty,
|
||||||
|
StandardClassIds.KCallable -> true
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val FirExpression.index: Int
|
||||||
|
get() = when (this) {
|
||||||
|
is FirNamedArgumentExpression -> expression.index
|
||||||
|
is FirFakeArgumentForCallableReference -> index
|
||||||
|
else -> throw IllegalArgumentException()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createFakeArgumentsForReference(
|
||||||
|
function: FirFunction<*>,
|
||||||
|
expectedArgumentCount: Int,
|
||||||
|
inputTypes: List<ConeKotlinType>,
|
||||||
|
unboundReceiverCount: Int
|
||||||
|
): List<FirExpression> {
|
||||||
|
var afterVararg = false
|
||||||
|
var varargComponentType: ConeKotlinType? = null
|
||||||
|
var vararg = false
|
||||||
|
return (0 until expectedArgumentCount).map { index ->
|
||||||
|
val inputType = inputTypes.getOrNull(index + unboundReceiverCount)
|
||||||
|
if (vararg && varargComponentType != inputType) {
|
||||||
|
afterVararg = true
|
||||||
|
}
|
||||||
|
|
||||||
|
val valueParameter = function.valueParameters.getOrNull(index)
|
||||||
|
val name = if (afterVararg && valueParameter?.defaultValue != null)
|
||||||
|
valueParameter.name
|
||||||
|
else
|
||||||
|
null
|
||||||
|
|
||||||
|
if (valueParameter?.isVararg == true) {
|
||||||
|
varargComponentType = inputType
|
||||||
|
vararg = true
|
||||||
|
}
|
||||||
|
if (name != null) {
|
||||||
|
buildNamedArgumentExpression {
|
||||||
|
expression = FirFakeArgumentForCallableReference(index)
|
||||||
|
this.name = name
|
||||||
|
isSpread = false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
FirFakeArgumentForCallableReference(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class FirFakeArgumentForCallableReference(
|
||||||
|
val index: Int
|
||||||
|
) : FirExpression() {
|
||||||
|
override val source: FirSourceElement?
|
||||||
|
get() = null
|
||||||
|
|
||||||
|
override val typeRef: FirTypeRef
|
||||||
|
get() = error("should not be called")
|
||||||
|
|
||||||
|
override val annotations: List<FirAnnotationCall>
|
||||||
|
get() = error("should not be called")
|
||||||
|
|
||||||
|
override fun replaceTypeRef(newTypeRef: FirTypeRef) {
|
||||||
|
error("should not be called")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirNamedArgumentExpression {
|
||||||
|
error("should not be called")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
|
||||||
|
error("should not be called")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirElement {
|
||||||
|
error("should not be called")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ConeKotlinType.isKCallableType(): Boolean {
|
||||||
|
return this.classId == StandardClassIds.KCallable
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createKPropertyType(
|
||||||
|
propertyOrField: FirVariable<*>,
|
||||||
|
receiverType: ConeKotlinType?,
|
||||||
|
returnTypeRef: FirResolvedTypeRef
|
||||||
|
): ConeKotlinType {
|
||||||
|
val propertyType = returnTypeRef.type
|
||||||
|
return org.jetbrains.kotlin.fir.resolve.createKPropertyType(
|
||||||
|
receiverType, propertyType, isMutable = propertyOrField.isVar
|
||||||
|
)
|
||||||
|
}
|
||||||
+2
@@ -58,3 +58,5 @@ object HiddenCandidate : ResolutionDiagnostic(CandidateApplicability.HIDDEN)
|
|||||||
object ResolvedWithLowPriority : ResolutionDiagnostic(CandidateApplicability.RESOLVED_LOW_PRIORITY)
|
object ResolvedWithLowPriority : ResolutionDiagnostic(CandidateApplicability.RESOLVED_LOW_PRIORITY)
|
||||||
|
|
||||||
object InapplicableWrongReceiver : ResolutionDiagnostic(CandidateApplicability.INAPPLICABLE_WRONG_RECEIVER)
|
object InapplicableWrongReceiver : ResolutionDiagnostic(CandidateApplicability.INAPPLICABLE_WRONG_RECEIVER)
|
||||||
|
|
||||||
|
object LowerPriorityToPreserveCompatibilityDiagnostic : ResolutionDiagnostic(CandidateApplicability.RESOLVED_NEED_PRESERVE_COMPATIBILITY)
|
||||||
|
|||||||
@@ -7,8 +7,6 @@ package org.jetbrains.kotlin.fir.resolve.calls
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.fir.*
|
import org.jetbrains.kotlin.fir.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
|
|
||||||
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
|
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
|
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
|
||||||
@@ -24,8 +22,6 @@ import org.jetbrains.kotlin.fir.types.*
|
|||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
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.resolve.calls.inference.ConstraintSystemOperation
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.SimpleConstraintSystemConstraintPosition
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.*
|
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.*
|
||||||
|
|
||||||
@@ -196,165 +192,6 @@ internal object EagerResolveOfCallableReferences : CheckerStage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal object CheckCallableReferenceExpectedType : CheckerStage() {
|
|
||||||
override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) {
|
|
||||||
val outerCsBuilder = callInfo.outerCSBuilder ?: return
|
|
||||||
val expectedType = callInfo.expectedType
|
|
||||||
if (candidate.symbol !is FirCallableSymbol<*>) return
|
|
||||||
|
|
||||||
val resultingReceiverType = when (callInfo.lhs) {
|
|
||||||
is DoubleColonLHS.Type -> callInfo.lhs.type.takeIf { callInfo.explicitReceiver !is FirResolvedQualifier }
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
|
|
||||||
val fir: FirCallableDeclaration<*> = candidate.symbol.fir
|
|
||||||
|
|
||||||
val returnTypeRef = context.bodyResolveComponents.returnTypeCalculator.tryCalculateReturnType(fir)
|
|
||||||
// If the expected type is a suspend function type and the current argument of interest is a function reference, we need to do
|
|
||||||
// "suspend conversion." Here, during resolution, we bypass constraint system by making resulting type be KSuspendFunction.
|
|
||||||
// Then, during conversion, we need to create an adapter function and replace the function reference created here with an adapted
|
|
||||||
// callable reference.
|
|
||||||
// TODO: should refer to LanguageVersionSettings.SuspendConversion
|
|
||||||
val requireSuspendConversion = expectedType?.isSuspendFunctionType(callInfo.session) == true
|
|
||||||
val resultingType: ConeKotlinType = when (fir) {
|
|
||||||
is FirFunction -> callInfo.session.createAdaptedKFunctionType(
|
|
||||||
fir,
|
|
||||||
resultingReceiverType, returnTypeRef, expectedParameterTypes = expectedType?.typeArguments,
|
|
||||||
isSuspend = (fir as? FirSimpleFunction)?.isSuspend == true || requireSuspendConversion,
|
|
||||||
expectedReturnType = extractInputOutputTypesFromCallableReferenceExpectedType(expectedType, callInfo.session)?.outputType
|
|
||||||
)
|
|
||||||
is FirVariable<*> -> createKPropertyType(fir, resultingReceiverType, returnTypeRef)
|
|
||||||
else -> ConeKotlinErrorType(ConeSimpleDiagnostic("Unknown callable kind: ${fir::class}", DiagnosticKind.UnknownCallableKind))
|
|
||||||
}.let(candidate.substitutor::substituteOrSelf)
|
|
||||||
candidate.usesSuspendConversion = requireSuspendConversion
|
|
||||||
candidate.resultingTypeForCallableReference = resultingType
|
|
||||||
candidate.outerConstraintBuilderEffect = fun ConstraintSystemOperation.() {
|
|
||||||
addOtherSystem(candidate.system.asReadOnlyStorage())
|
|
||||||
|
|
||||||
val position = SimpleConstraintSystemConstraintPosition //TODO
|
|
||||||
|
|
||||||
if (expectedType != null) {
|
|
||||||
addSubtypeConstraint(resultingType, expectedType, position)
|
|
||||||
}
|
|
||||||
|
|
||||||
val declarationReceiverType: ConeKotlinType? =
|
|
||||||
(fir as? FirCallableMemberDeclaration<*>)?.receiverTypeRef?.coneType
|
|
||||||
?.let(candidate.substitutor::substituteOrSelf)
|
|
||||||
|
|
||||||
if (resultingReceiverType != null && declarationReceiverType != null) {
|
|
||||||
addSubtypeConstraint(resultingReceiverType, declarationReceiverType, position)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var isApplicable = true
|
|
||||||
|
|
||||||
outerCsBuilder.runTransaction {
|
|
||||||
candidate.outerConstraintBuilderEffect!!(this)
|
|
||||||
|
|
||||||
isApplicable = !hasContradiction
|
|
||||||
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isApplicable) {
|
|
||||||
sink.yieldDiagnostic(InapplicableCandidate)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createKPropertyType(
|
|
||||||
propertyOrField: FirVariable<*>,
|
|
||||||
receiverType: ConeKotlinType?,
|
|
||||||
returnTypeRef: FirResolvedTypeRef
|
|
||||||
): ConeKotlinType {
|
|
||||||
val propertyType = returnTypeRef.type
|
|
||||||
return createKPropertyType(
|
|
||||||
receiverType, propertyType, isMutable = propertyOrField.isVar
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun FirSession.createAdaptedKFunctionType(
|
|
||||||
function: FirFunction<*>,
|
|
||||||
receiverType: ConeKotlinType?,
|
|
||||||
returnTypeRef: FirResolvedTypeRef,
|
|
||||||
expectedParameterTypes: Array<out ConeTypeProjection>?,
|
|
||||||
isSuspend: Boolean,
|
|
||||||
expectedReturnType: ConeKotlinType?
|
|
||||||
): ConeKotlinType {
|
|
||||||
// The similar adaptations: defaults and coercion-to-unit happen at org.jetbrains.kotlin.resolve.calls.components.CallableReferencesCandidateFactory.getCallableReferenceAdaptation
|
|
||||||
val parameterTypes = mutableListOf<ConeKotlinType>()
|
|
||||||
val shift = if (receiverType != null) 1 else 0
|
|
||||||
val expectedParameterNumber =
|
|
||||||
if (expectedParameterTypes == null) null
|
|
||||||
// Drop the last one: return type, and the first one: receiver type, if needed
|
|
||||||
else expectedParameterTypes.size - 1 - shift
|
|
||||||
|
|
||||||
fun ConeKotlinType?.isPotentiallyArray(): Boolean =
|
|
||||||
this != null && (this.arrayElementType() != null || this is ConeTypeVariableType)
|
|
||||||
|
|
||||||
var lastVarargParameter: FirValueParameter? = null
|
|
||||||
for ((index, valueParameter) in function.valueParameters.withIndex()) {
|
|
||||||
// Update the last vararg parameter in preparation for adaptation.
|
|
||||||
if (valueParameter.isVararg) {
|
|
||||||
lastVarargParameter = valueParameter
|
|
||||||
}
|
|
||||||
// Pack value parameters until the expected parameter number is met.
|
|
||||||
if (expectedParameterNumber == null || index < expectedParameterNumber) {
|
|
||||||
// But, if the value parameter is vararg, make sure it matches with the expected parameter type.
|
|
||||||
if (expectedParameterTypes != null && valueParameter.isVararg) {
|
|
||||||
val expectedParameterType = (expectedParameterTypes[index + shift] as? ConeKotlinTypeProjection)?.type
|
|
||||||
if (!expectedParameterType.isPotentiallyArray()) {
|
|
||||||
// Expect an element. Will spread vararg parameter later.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
parameterTypes += valueParameter.returnTypeRef.coneType
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// After expected parameters are fulfilled, a value parameter which doesn't have a default value or isn't vararg should be added to
|
|
||||||
// the resulting type (so that it can reject incompatible function reference). In either case, we can't assume no actual arguments
|
|
||||||
// are given.
|
|
||||||
if (valueParameter.defaultValue == null && !valueParameter.isVararg) {
|
|
||||||
parameterTypes += valueParameter.returnTypeRef.coneType
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If a function with vararg is passed to a place where a spread of elements is expected, we can adapt the function reference to
|
|
||||||
// literally spread such vararg argument. E.g., foo(vararg xs: Char): String => bar(::foo) where bar(f: (Char, Char) -> String)
|
|
||||||
if (expectedParameterNumber != null &&
|
|
||||||
expectedParameterTypes != null &&
|
|
||||||
parameterTypes.size < expectedParameterNumber &&
|
|
||||||
lastVarargParameter != null
|
|
||||||
) {
|
|
||||||
val varargArrayType = lastVarargParameter.returnTypeRef.coneType
|
|
||||||
val varargElementType = varargArrayType.varargElementType()
|
|
||||||
val expectedParameterType = (expectedParameterTypes[parameterTypes.size + shift] as? ConeKotlinTypeProjection)?.type
|
|
||||||
// Expect an array or potentially array (i.e., type variable). Pass vararg parameter as-is.
|
|
||||||
if (expectedParameterType.isPotentiallyArray()) {
|
|
||||||
parameterTypes += varargArrayType
|
|
||||||
} else {
|
|
||||||
// Expect an element. Spread vararg parameter.
|
|
||||||
while (parameterTypes.size < expectedParameterNumber) {
|
|
||||||
parameterTypes += varargElementType
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val returnType =
|
|
||||||
if (expectedReturnType != null && typeContext.run { expectedReturnType.isUnit() })
|
|
||||||
expectedReturnType
|
|
||||||
else
|
|
||||||
returnTypeRef.type
|
|
||||||
|
|
||||||
return createFunctionalType(
|
|
||||||
parameterTypes,
|
|
||||||
receiverType = receiverType,
|
|
||||||
rawReturnType = returnType,
|
|
||||||
isKFunctionType = true,
|
|
||||||
isSuspend = isSuspend
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal object DiscriminateSynthetics : CheckerStage() {
|
internal object DiscriminateSynthetics : CheckerStage() {
|
||||||
override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) {
|
override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) {
|
||||||
if (candidate.symbol is SyntheticSymbol) {
|
if (candidate.symbol is SyntheticSymbol) {
|
||||||
|
|||||||
+6
@@ -5,7 +5,9 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.resolve.diagnostics
|
package org.jetbrains.kotlin.fir.resolve.diagnostics
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
||||||
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
||||||
|
import org.jetbrains.kotlin.fir.render
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.Candidate
|
import org.jetbrains.kotlin.fir.resolve.calls.Candidate
|
||||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||||
@@ -80,6 +82,10 @@ class ConeInstanceAccessBeforeSuperCall(val target: String) : ConeDiagnostic() {
|
|||||||
override val reason: String get() = "Cannot access ''${target}'' before superclass constructor has been called"
|
override val reason: String get() = "Cannot access ''${target}'' before superclass constructor has been called"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ConeUnsupportedCallableReferenceTarget(val fir: FirCallableDeclaration<*>) : ConeDiagnostic() {
|
||||||
|
override val reason: String get() = "Unsupported declaration for callable reference: ${fir.render()}"
|
||||||
|
}
|
||||||
|
|
||||||
private fun describeSymbol(symbol: AbstractFirBasedSymbol<*>): String {
|
private fun describeSymbol(symbol: AbstractFirBasedSymbol<*>): String {
|
||||||
return when (symbol) {
|
return when (symbol) {
|
||||||
is FirClassLikeSymbol<*> -> symbol.classId.asString()
|
is FirClassLikeSymbol<*> -> symbol.classId.asString()
|
||||||
|
|||||||
@@ -7,6 +7,10 @@ package org.jetbrains.kotlin.fir.types
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
||||||
|
|
||||||
|
fun ConeKotlinType.createOutArrayType(nullable: Boolean = false): ConeKotlinType {
|
||||||
|
return ConeKotlinTypeProjectionOut(this).createArrayOf(nullable)
|
||||||
|
}
|
||||||
|
|
||||||
fun ConeTypeProjection.createArrayOf(nullable: Boolean = false): ConeKotlinType {
|
fun ConeTypeProjection.createArrayOf(nullable: Boolean = false): ConeKotlinType {
|
||||||
if (this is ConeKotlinTypeProjection) {
|
if (this is ConeKotlinTypeProjection) {
|
||||||
val type = type.lowerBoundIfFlexible()
|
val type = type.lowerBoundIfFlexible()
|
||||||
|
|||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.resolve.calls.components
|
||||||
|
|
||||||
|
enum class SuspendConversionStrategy {
|
||||||
|
SUSPEND_CONVERSION, NO_CONVERSION
|
||||||
|
}
|
||||||
-4
@@ -88,10 +88,6 @@ class CallableReferenceAdaptation(
|
|||||||
val suspendConversionStrategy: SuspendConversionStrategy
|
val suspendConversionStrategy: SuspendConversionStrategy
|
||||||
)
|
)
|
||||||
|
|
||||||
enum class SuspendConversionStrategy {
|
|
||||||
SUSPEND_CONVERSION, NO_CONVERSION
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cases: class A {}, class B { companion object }, object C, enum class D { E }
|
* cases: class A {}, class B { companion object }, object C, enum class D { E }
|
||||||
* A::foo <-> Type
|
* A::foo <-> Type
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
// FILE: test.kt
|
// FILE: test.kt
|
||||||
|
|
||||||
fun checkNotEqual(x: Any, y: Any) {
|
fun checkNotEqual(x: Any, y: Any) {
|
||||||
|
|||||||
+2
-2
@@ -26,5 +26,5 @@ fun test() {
|
|||||||
|
|
||||||
<!UNRESOLVED_REFERENCE!>B::bas<!>
|
<!UNRESOLVED_REFERENCE!>B::bas<!>
|
||||||
|
|
||||||
::fas
|
<!UNRESOLVED_REFERENCE!>::fas<!>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ fun test() {
|
|||||||
usePrimitiveIntArray(::intVararg)
|
usePrimitiveIntArray(::intVararg)
|
||||||
<!INAPPLICABLE_CANDIDATE!>useIntArray<!>(<!UNRESOLVED_REFERENCE!>::intVararg<!>)
|
<!INAPPLICABLE_CANDIDATE!>useIntArray<!>(<!UNRESOLVED_REFERENCE!>::intVararg<!>)
|
||||||
<!INAPPLICABLE_CANDIDATE!>useMixedStringArgs1<!>(<!UNRESOLVED_REFERENCE!>::stringVararg<!>)
|
<!INAPPLICABLE_CANDIDATE!>useMixedStringArgs1<!>(<!UNRESOLVED_REFERENCE!>::stringVararg<!>)
|
||||||
useMixedStringArgs2(::stringVararg)
|
<!INAPPLICABLE_CANDIDATE!>useMixedStringArgs2<!>(<!UNRESOLVED_REFERENCE!>::stringVararg<!>)
|
||||||
<!INAPPLICABLE_CANDIDATE!>useMixedStringArgs3<!>(<!UNRESOLVED_REFERENCE!>::stringVararg<!>)
|
<!INAPPLICABLE_CANDIDATE!>useMixedStringArgs3<!>(<!UNRESOLVED_REFERENCE!>::stringVararg<!>)
|
||||||
useTwoStringArrays(::stringVararg)
|
<!INAPPLICABLE_CANDIDATE!>useTwoStringArrays<!>(<!UNRESOLVED_REFERENCE!>::stringVararg<!>)
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-8
@@ -107,26 +107,26 @@ FILE fqName:<root> fileName:/caoWithAdaptationForSam.kt
|
|||||||
BLOCK type=kotlin.Unit origin=null
|
BLOCK type=kotlin.Unit origin=null
|
||||||
VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:<root>.A [val]
|
VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:<root>.A [val]
|
||||||
GET_OBJECT 'CLASS OBJECT name:A modality:FINAL visibility:public superTypes:[kotlin.Any]' type=<root>.A
|
GET_OBJECT 'CLASS OBJECT name:A modality:FINAL visibility:public superTypes:[kotlin.Any]' type=<root>.A
|
||||||
VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:kotlin.reflect.KFunction0<kotlin.Int> [val]
|
VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:kotlin.reflect.KFunction1<kotlin.IntArray, kotlin.Int> [val]
|
||||||
FUNCTION_REFERENCE 'public final fun withVararg (vararg xs: kotlin.Int): kotlin.Int declared in <root>' type=kotlin.reflect.KFunction0<kotlin.Int> origin=null reflectionTarget=<same>
|
FUNCTION_REFERENCE 'public final fun withVararg (vararg xs: kotlin.Int): kotlin.Int declared in <root>' type=kotlin.reflect.KFunction1<kotlin.IntArray, kotlin.Int> origin=null reflectionTarget=<same>
|
||||||
ERROR_CALL 'Unresolved reference: <Inapplicable(INAPPLICABLE): /set>#' type=kotlin.Unit
|
ERROR_CALL 'Unresolved reference: <Inapplicable(INAPPLICABLE): /set>#' type=kotlin.Unit
|
||||||
GET_VAR 'val tmp_1: kotlin.reflect.KFunction0<kotlin.Int> [val] declared in <root>.test1' type=kotlin.reflect.KFunction0<kotlin.Int> origin=null
|
GET_VAR 'val tmp_1: kotlin.reflect.KFunction1<kotlin.IntArray, kotlin.Int> [val] declared in <root>.test1' type=kotlin.reflect.KFunction1<kotlin.IntArray, kotlin.Int> origin=null
|
||||||
CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
|
CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
|
||||||
$this: ERROR_CALL 'Unresolved reference: <Inapplicable(INAPPLICABLE): /get>#' type=kotlin.Int
|
$this: ERROR_CALL 'Unresolved reference: <Inapplicable(INAPPLICABLE): /get>#' type=kotlin.Int
|
||||||
GET_VAR 'val tmp_1: kotlin.reflect.KFunction0<kotlin.Int> [val] declared in <root>.test1' type=kotlin.reflect.KFunction0<kotlin.Int> origin=null
|
GET_VAR 'val tmp_1: kotlin.reflect.KFunction1<kotlin.IntArray, kotlin.Int> [val] declared in <root>.test1' type=kotlin.reflect.KFunction1<kotlin.IntArray, kotlin.Int> origin=null
|
||||||
other: CONST Int type=kotlin.Int value=1
|
other: CONST Int type=kotlin.Int value=1
|
||||||
FUN name:test2 visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
FUN name:test2 visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
BLOCK type=kotlin.Unit origin=null
|
BLOCK type=kotlin.Unit origin=null
|
||||||
VAR IR_TEMPORARY_VARIABLE name:tmp_2 type:<root>.B [val]
|
VAR IR_TEMPORARY_VARIABLE name:tmp_2 type:<root>.B [val]
|
||||||
GET_OBJECT 'CLASS OBJECT name:B modality:FINAL visibility:public superTypes:[kotlin.Any]' type=<root>.B
|
GET_OBJECT 'CLASS OBJECT name:B modality:FINAL visibility:public superTypes:[kotlin.Any]' type=<root>.B
|
||||||
VAR IR_TEMPORARY_VARIABLE name:tmp_3 type:kotlin.reflect.KFunction0<kotlin.Int> [val]
|
VAR IR_TEMPORARY_VARIABLE name:tmp_3 type:kotlin.reflect.KFunction1<kotlin.IntArray, kotlin.Int> [val]
|
||||||
FUNCTION_REFERENCE 'public final fun withVararg (vararg xs: kotlin.Int): kotlin.Int declared in <root>' type=kotlin.reflect.KFunction0<kotlin.Int> origin=null reflectionTarget=<same>
|
FUNCTION_REFERENCE 'public final fun withVararg (vararg xs: kotlin.Int): kotlin.Int declared in <root>' type=kotlin.reflect.KFunction1<kotlin.IntArray, kotlin.Int> origin=null reflectionTarget=<same>
|
||||||
ERROR_CALL 'Unresolved reference: <Inapplicable(INAPPLICABLE): /set>#' type=kotlin.Unit
|
ERROR_CALL 'Unresolved reference: <Inapplicable(INAPPLICABLE): /set>#' type=kotlin.Unit
|
||||||
GET_VAR 'val tmp_3: kotlin.reflect.KFunction0<kotlin.Int> [val] declared in <root>.test2' type=kotlin.reflect.KFunction0<kotlin.Int> origin=null
|
GET_VAR 'val tmp_3: kotlin.reflect.KFunction1<kotlin.IntArray, kotlin.Int> [val] declared in <root>.test2' type=kotlin.reflect.KFunction1<kotlin.IntArray, kotlin.Int> origin=null
|
||||||
CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
|
CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
|
||||||
$this: ERROR_CALL 'Unresolved reference: <Inapplicable(INAPPLICABLE): /get>#' type=kotlin.Int
|
$this: ERROR_CALL 'Unresolved reference: <Inapplicable(INAPPLICABLE): /get>#' type=kotlin.Int
|
||||||
GET_VAR 'val tmp_3: kotlin.reflect.KFunction0<kotlin.Int> [val] declared in <root>.test2' type=kotlin.reflect.KFunction0<kotlin.Int> origin=null
|
GET_VAR 'val tmp_3: kotlin.reflect.KFunction1<kotlin.IntArray, kotlin.Int> [val] declared in <root>.test2' type=kotlin.reflect.KFunction1<kotlin.IntArray, kotlin.Int> origin=null
|
||||||
other: CONST Int type=kotlin.Int value=1
|
other: CONST Int type=kotlin.Int value=1
|
||||||
FUN name:test3 visibility:public modality:FINAL <> (fn:kotlin.Function1<kotlin.Int, kotlin.Unit>) returnType:kotlin.Unit
|
FUN name:test3 visibility:public modality:FINAL <> (fn:kotlin.Function1<kotlin.Int, kotlin.Unit>) returnType:kotlin.Unit
|
||||||
VALUE_PARAMETER name:fn index:0 type:kotlin.Function1<kotlin.Int, kotlin.Unit>
|
VALUE_PARAMETER name:fn index:0 type:kotlin.Function1<kotlin.Int, kotlin.Unit>
|
||||||
|
|||||||
-73
@@ -1,73 +0,0 @@
|
|||||||
FILE fqName:<root> fileName:/funWithDefaultParametersAsKCallableStar.kt
|
|
||||||
FUN name:defaultsOnly visibility:public modality:FINAL <> (x:kotlin.String) returnType:kotlin.Int
|
|
||||||
VALUE_PARAMETER name:x index:0 type:kotlin.String
|
|
||||||
EXPRESSION_BODY
|
|
||||||
CONST String type=kotlin.String value=""
|
|
||||||
BLOCK_BODY
|
|
||||||
RETURN type=kotlin.Nothing from='public final fun defaultsOnly (x: kotlin.String): kotlin.Int declared in <root>'
|
|
||||||
CONST Int type=kotlin.Int value=1
|
|
||||||
FUN name:regularAndDefaults visibility:public modality:FINAL <> (x1:kotlin.String, x2:kotlin.String) returnType:kotlin.Int
|
|
||||||
VALUE_PARAMETER name:x1 index:0 type:kotlin.String
|
|
||||||
VALUE_PARAMETER name:x2 index:1 type:kotlin.String
|
|
||||||
EXPRESSION_BODY
|
|
||||||
CONST String type=kotlin.String value=""
|
|
||||||
BLOCK_BODY
|
|
||||||
RETURN type=kotlin.Nothing from='public final fun regularAndDefaults (x1: kotlin.String, x2: kotlin.String): kotlin.Int declared in <root>'
|
|
||||||
CONST Int type=kotlin.Int value=1
|
|
||||||
FUN name:varargs visibility:public modality:FINAL <> (xs:kotlin.Array<out kotlin.String>) returnType:kotlin.Int
|
|
||||||
VALUE_PARAMETER name:xs index:0 type:kotlin.Array<out kotlin.String> varargElementType:kotlin.String [vararg]
|
|
||||||
BLOCK_BODY
|
|
||||||
RETURN type=kotlin.Nothing from='public final fun varargs (vararg xs: kotlin.String): kotlin.Int declared in <root>'
|
|
||||||
CONST Int type=kotlin.Int value=1
|
|
||||||
CLASS CLASS name:C modality:FINAL visibility:public superTypes:[kotlin.Any]
|
|
||||||
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.C
|
|
||||||
CONSTRUCTOR visibility:public <> (x:kotlin.String) returnType:<root>.C [primary]
|
|
||||||
VALUE_PARAMETER name:x index:0 type:kotlin.String
|
|
||||||
EXPRESSION_BODY
|
|
||||||
CONST String type=kotlin.String value=""
|
|
||||||
BLOCK_BODY
|
|
||||||
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in kotlin.Any'
|
|
||||||
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:C modality:FINAL visibility:public superTypes:[kotlin.Any]'
|
|
||||||
PROPERTY name:x visibility:public modality:FINAL [val]
|
|
||||||
FIELD PROPERTY_BACKING_FIELD name:x type:kotlin.String visibility:private [final]
|
|
||||||
EXPRESSION_BODY
|
|
||||||
GET_VAR 'x: kotlin.String declared in <root>.C.<init>' type=kotlin.String origin=INITIALIZE_PROPERTY_FROM_PARAMETER
|
|
||||||
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-x> visibility:public modality:FINAL <> ($this:<root>.C) returnType:kotlin.String
|
|
||||||
correspondingProperty: PROPERTY name:x visibility:public modality:FINAL [val]
|
|
||||||
$this: VALUE_PARAMETER name:<this> type:<root>.C
|
|
||||||
BLOCK_BODY
|
|
||||||
RETURN type=kotlin.Nothing from='public final fun <get-x> (): kotlin.String declared in <root>.C'
|
|
||||||
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:x type:kotlin.String visibility:private [final]' type=kotlin.String origin=null
|
|
||||||
receiver: GET_VAR '<this>: <root>.C declared in <root>.C.<get-x>' type=<root>.C origin=null
|
|
||||||
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
|
|
||||||
overridden:
|
|
||||||
public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any
|
|
||||||
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
|
|
||||||
VALUE_PARAMETER name:other index:0 type:kotlin.Any?
|
|
||||||
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override]
|
|
||||||
overridden:
|
|
||||||
public open fun hashCode (): kotlin.Int declared in kotlin.Any
|
|
||||||
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
|
|
||||||
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override]
|
|
||||||
overridden:
|
|
||||||
public open fun toString (): kotlin.String declared in kotlin.Any
|
|
||||||
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
|
|
||||||
FUN name:useKCallableStar visibility:public modality:FINAL <> (fn:kotlin.reflect.KCallable<*>) returnType:kotlin.Unit
|
|
||||||
VALUE_PARAMETER name:fn index:0 type:kotlin.reflect.KCallable<*>
|
|
||||||
BLOCK_BODY
|
|
||||||
FUN name:testDefaultsOnlyStar visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
|
||||||
BLOCK_BODY
|
|
||||||
CALL 'public final fun useKCallableStar (fn: kotlin.reflect.KCallable<*>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
|
|
||||||
fn: FUNCTION_REFERENCE 'public final fun defaultsOnly (x: kotlin.String): kotlin.Int declared in <root>' type=kotlin.reflect.KFunction0<kotlin.Int> origin=null reflectionTarget=<same>
|
|
||||||
FUN name:testRegularAndDefaultsStar visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
|
||||||
BLOCK_BODY
|
|
||||||
CALL 'public final fun useKCallableStar (fn: kotlin.reflect.KCallable<*>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
|
|
||||||
fn: FUNCTION_REFERENCE 'public final fun regularAndDefaults (x1: kotlin.String, x2: kotlin.String): kotlin.Int declared in <root>' type=kotlin.reflect.KFunction1<kotlin.String, kotlin.Int> origin=null reflectionTarget=<same>
|
|
||||||
FUN name:testVarargsStar visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
|
||||||
BLOCK_BODY
|
|
||||||
CALL 'public final fun useKCallableStar (fn: kotlin.reflect.KCallable<*>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
|
|
||||||
fn: FUNCTION_REFERENCE 'public final fun varargs (vararg xs: kotlin.String): kotlin.Int declared in <root>' type=kotlin.reflect.KFunction0<kotlin.Int> origin=null reflectionTarget=<same>
|
|
||||||
FUN name:testCtorStar visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
|
||||||
BLOCK_BODY
|
|
||||||
CALL 'public final fun useKCallableStar (fn: kotlin.reflect.KCallable<*>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
|
|
||||||
fn: FUNCTION_REFERENCE 'public constructor <init> (x: kotlin.String) [primary] declared in <root>.C' type=kotlin.reflect.KFunction0<<root>.C> origin=null reflectionTarget=<same>
|
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// WITH_REFLECT
|
// WITH_REFLECT
|
||||||
import kotlin.reflect.KCallable
|
import kotlin.reflect.KCallable
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user