diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt index 80cd26d1616..21e84582487 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt @@ -7,8 +7,6 @@ package org.jetbrains.kotlin.fir import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration -import org.jetbrains.kotlin.fir.declarations.FirProperty -import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.impl.FirExpressionStub import org.jetbrains.kotlin.fir.expressions.impl.FirResolvedQualifierImpl @@ -35,9 +33,10 @@ import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.types.ConeKotlinErrorType import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.FirTypeRef -import org.jetbrains.kotlin.fir.types.coneTypeSafe import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder +import org.jetbrains.kotlin.resolve.calls.inference.model.SimpleConstraintSystemConstraintPosition import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator class FirCallResolver( @@ -221,65 +220,77 @@ class FirCallResolver( return resultExpression } - fun resolveCallableReference(callableReferenceAccess: FirCallableReferenceAccess, lhs: DoubleColonLHS?): FirCallableReferenceAccess { - val resultCollector = ReferencesCandidateCollector(this, resolutionStageRunner) + fun resolveCallableReference( + constraintSystemBuilder: ConstraintSystemBuilder, + resolvedCallableReferenceAtom: ResolvedCallableReferenceAtom + ): Boolean { + val callableReferenceAccess = resolvedCallableReferenceAtom.atom + val lhs = resolvedCallableReferenceAtom.lhs + val expectedType = resolvedCallableReferenceAtom.expectedType ?: return false + val result = CandidateCollector(this, resolutionStageRunner) val consumer = createCallableReferencesConsumerForLHS( - callableReferenceAccess, lhs, resultCollector + callableReferenceAccess, lhs, + result, expectedType, + constraintSystemBuilder ) towerResolver.runResolver(consumer, implicitReceiverStack.receiversAsReversed()) - - val result = resultCollector.results.firstOrNull() ?: return callableReferenceAccess - - val resultingType: ConeKotlinType = when (val fir = result.symbol.fir) { - is FirSimpleFunction -> createKFunctionType(fir, lhs) - is FirProperty -> createKPropertyType(fir) - else -> ConeKotlinErrorType("Unknown callable kind: ${fir::class}") + val bestCandidates = result.bestCandidates() + val noSuccessfulCandidates = result.currentApplicability < CandidateApplicability.SYNTHETIC_RESOLVED + val reducedCandidates = if (noSuccessfulCandidates) { + bestCandidates.toSet() + } else { + conflictResolver.chooseMaximallySpecificCandidates(bestCandidates, discriminateGenerics = false) } - callableReferenceAccess.replaceTypeRef(FirResolvedTypeRefImpl(null, resultingType)) - - return callableReferenceAccess.transformCalleeReference( - StoreNameReference, - FirNamedReferenceWithCandidate(callableReferenceAccess.psi, callableReferenceAccess.calleeReference.name, result) - ) - } - - private fun createKPropertyType(fir: FirProperty): ConeKotlinType { - TODO("not implemented") //To change body of created functions use File | Settings | File Templates. - } - - private fun createKFunctionType( - function: FirSimpleFunction, - lhs: DoubleColonLHS? - ): ConeKotlinType { - val receiverType = (lhs as? DoubleColonLHS.Type)?.type - val parameterTypes = function.valueParameters.map { - it.returnTypeRef.coneTypeSafe() ?: ConeKotlinErrorType("No type for parameter $it") + when { + noSuccessfulCandidates -> { + return false + } + reducedCandidates.size > 1 -> { + // TODO: add postponed atom + return true + } } - return createFunctionalType( - parameterTypes, receiverType = receiverType, - rawReturnType = function.returnTypeRef.coneTypeSafe() ?: ConeKotlinErrorType("No type for return type of $this") - ) + val chosenCandidate = reducedCandidates.single() + constraintSystemBuilder.runTransaction { + addOtherSystem(chosenCandidate.system.asReadOnlyStorage()) + + val position = SimpleConstraintSystemConstraintPosition //TODO + addSubtypeConstraint(chosenCandidate.resultingTypeForCallableReference!!, expectedType, position) + + true + } + + resolvedCallableReferenceAtom.resultingCandidate = Pair(chosenCandidate, result.currentApplicability) + + return true } private fun createCallableReferencesConsumerForLHS( callableReferenceAccess: FirCallableReferenceAccess, lhs: DoubleColonLHS?, - resultCollector: CandidateCollector + resultCollector: CandidateCollector, + expectedType: ConeKotlinType?, + outerConstraintSystemBuilder: ConstraintSystemBuilder? ): TowerDataConsumer { val name = callableReferenceAccess.calleeReference.name return when (lhs) { is DoubleColonLHS.Expression, null -> createCallableReferencesConsumerForReceiver( - name, resultCollector, callableReferenceAccess.explicitReceiver + name, resultCollector, callableReferenceAccess.explicitReceiver, expectedType, outerConstraintSystemBuilder, + lhs ) is DoubleColonLHS.Type -> createCallableReferencesConsumerForReceiver( - name, resultCollector, - FirExpressionStub(callableReferenceAccess.psi).apply { replaceTypeRef(FirResolvedTypeRefImpl(null, lhs.type)) } + name, + resultCollector, + FirExpressionStub(callableReferenceAccess.psi).apply { replaceTypeRef(FirResolvedTypeRefImpl(null, lhs.type)) }, + expectedType, + outerConstraintSystemBuilder, + lhs ) } } @@ -287,7 +298,10 @@ class FirCallResolver( private fun createCallableReferencesConsumerForReceiver( name: Name, resultCollector: CandidateCollector, - receiver: FirExpression? + receiver: FirExpression?, + expectedType: ConeKotlinType?, + outerConstraintSystemBuilder: ConstraintSystemBuilder?, + lhs: DoubleColonLHS? ): TowerDataConsumer { val info = CallInfo( CallKind.CallableReference, @@ -297,7 +311,10 @@ class FirCallResolver( emptyList(), session, file, - transformer.components.container + transformer.components.container, + expectedType, + outerConstraintSystemBuilder, + lhs ) { it.resultType } return createCallableReferencesConsumer(session, name, info, this, resultCollector) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SessionHolder.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SessionHolder.kt index ef4e078a3a9..fb1c338b03a 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SessionHolder.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SessionHolder.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.fir.resolve +import org.jetbrains.kotlin.fir.FirCallResolver import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSymbolOwner import org.jetbrains.kotlin.fir.declarations.FirDeclaration @@ -32,6 +33,8 @@ interface BodyResolveComponents : SessionHolder { val resolutionStageRunner: ResolutionStageRunner val scopeSession: ScopeSession val samResolver: FirSamResolver + val callResolver: FirCallResolver + val doubleColonExpressionResolver: FirDoubleColonExpressionResolver val AbstractFirBasedSymbol.phasedFir: D where D : FirDeclaration, D : FirSymbolOwner get() = phasedFir(session, FirResolvePhase.DECLARATIONS) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt index b83ac9fa0b3..8c44f81e521 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt @@ -17,7 +17,6 @@ import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder import org.jetbrains.kotlin.resolve.calls.inference.addSubtypeConstraintIfCompatible import org.jetbrains.kotlin.resolve.calls.inference.model.SimpleConstraintSystemConstraintPosition -import org.jetbrains.kotlin.resolve.calls.model.PostponedResolvedAtomMarker fun Candidate.resolveArgumentExpression( @@ -48,7 +47,7 @@ fun Candidate.resolveArgumentExpression( typeProvider ) // TODO:! - is FirCallableReferenceAccess -> preprocessCallableReference(csBuilder, argument, expectedType, sink) + is FirCallableReferenceAccess -> preprocessCallableReference(argument, expectedType) // NB: FirCallableReferenceAccess should be checked earlier is FirQualifiedAccessExpression -> resolvePlainExpressionArgument( csBuilder, diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallKind.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallKind.kt index 662bcbd70d0..5a57e8abaf7 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallKind.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallKind.kt @@ -29,7 +29,8 @@ sealed class CallKind { CreateFreshTypeVariableSubstitutorStage, CheckReceivers.Dispatch, CheckReceivers.Extension, - CheckArguments + CheckArguments, + EagerResolveOfCallableReferences ) } @@ -48,7 +49,8 @@ sealed class CallKind { override val resolutionSequence: List = listOf( CheckVisibility, DiscriminateSynthetics, - CreateFreshTypeVariableSubstitutorStage + CreateFreshTypeVariableSubstitutorStage, + CheckCallableReferenceExpectedType ) } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Candidate.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Candidate.kt index 74505b7fd37..60e939cc311 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Candidate.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Candidate.kt @@ -12,10 +12,13 @@ import org.jetbrains.kotlin.fir.declarations.FirValueParameter import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents +import org.jetbrains.kotlin.fir.resolve.DoubleColonLHS import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol +import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.FirTypeProjection import org.jetbrains.kotlin.fir.types.FirTypeRef +import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage import org.jetbrains.kotlin.resolve.calls.model.PostponedResolvedAtomMarker import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind @@ -31,6 +34,12 @@ class CallInfo( val session: FirSession, val containingFile: FirFile, val container: FirDeclaration, + + // Three properties for callable references only + val expectedType: ConeKotlinType? = null, + val outerCSBuilder: ConstraintSystemBuilder? = null, + val lhs: DoubleColonLHS? = null, + val typeProvider: (FirExpression) -> FirTypeRef? ) { val argumentCount get() = arguments.size @@ -50,7 +59,7 @@ class Candidate( val dispatchReceiverValue: ClassDispatchReceiverValue?, val implicitExtensionReceiverValue: ImplicitReceiverValue<*>?, val explicitReceiverKind: ExplicitReceiverKind, - private val bodyResolveComponents: BodyResolveComponents, + val bodyResolveComponents: BodyResolveComponents, private val baseSystem: ConstraintStorage, val callInfo: CallInfo ) { @@ -63,6 +72,7 @@ class Candidate( val samResolver get() = bodyResolveComponents.samResolver lateinit var substitutor: ConeSubstitutor + var resultingTypeForCallableReference: ConeKotlinType? = null var argumentMapping: Map? = null val postponedAtoms = mutableListOf() diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CandidateCollector.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CandidateCollector.kt index f72a492cf76..4210e713544 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CandidateCollector.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CandidateCollector.kt @@ -66,20 +66,6 @@ open class CandidateCollector( } } -class ReferencesCandidateCollector(components: BodyResolveComponents, resolutionStageRunner: ResolutionStageRunner) : - CandidateCollector(components, resolutionStageRunner) { - - val results = mutableListOf() - - override fun consumeCandidate(group: Int, candidate: Candidate): CandidateApplicability { - val applicability = resolutionStageRunner.processCandidate(candidate) - if (applicability >= CandidateApplicability.SYNTHETIC_RESOLVED) { - results.add(candidate) - } - return CandidateApplicability.SYNTHETIC_RESOLVED - } -} - // Collects properties that potentially could be invoke receivers, like 'propertyName()', // and initiates further invoke resolution by adding property-bound invoke consumers class InvokeReceiverCandidateCollector( @@ -113,6 +99,9 @@ class InvokeReceiverCandidateCollector( session, invokeCallInfo.containingFile, invokeCallInfo.container, + invokeCallInfo.expectedType, + invokeCallInfo.outerCSBuilder, + invokeCallInfo.lhs, invokeCallInfo.typeProvider ) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ConeOverloadConflictResolver.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ConeOverloadConflictResolver.kt index e064f444035..bbb032cf203 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ConeOverloadConflictResolver.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ConeOverloadConflictResolver.kt @@ -78,11 +78,15 @@ class ConeOverloadConflictResolver( } private fun createFlatSignature(call: Candidate, function: FirSimpleFunction): FlatSignature { + val valueParametersTypes = + call.resultingTypeForCallableReference?.typeArguments?.map { it as ConeKotlinType } + ?: (listOfNotNull(function.receiverTypeRef?.coneTypeUnsafe()) + + call.argumentMapping?.map { it.value.argumentType() }.orEmpty()) + return FlatSignature( call, function.typeParameters.map { it.symbol }, - listOfNotNull(function.receiverTypeRef?.coneTypeUnsafe()) + - call.argumentMapping?.map { it.value.argumentType() }.orEmpty(), + valueParametersTypes, function.receiverTypeRef != null, function.valueParameters.any { it.isVararg }, function.valueParameters.count { it.defaultValue != null }, @@ -253,4 +257,4 @@ class ConeSimpleConstraintSystemImpl(val system: NewConstraintSystemImpl) : Simp override val context: TypeSystemInferenceExtensionContext get() = system -} \ No newline at end of file +} diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ConsumerFactories.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ConsumerFactories.kt index 2b78fa20b5a..2a5c69d178b 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ConsumerFactories.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ConsumerFactories.kt @@ -72,6 +72,9 @@ fun createFunctionConsumer( bodyResolveComponents.session, callInfo.containingFile, callInfo.container, + callInfo.expectedType, + callInfo.outerCSBuilder, + callInfo.lhs, callInfo.typeProvider ) return PrioritizedTowerDataConsumer( diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/PostponedArguments.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/PostponedArguments.kt index 698e2b88f0d..de5b507ce37 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/PostponedArguments.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/PostponedArguments.kt @@ -7,13 +7,12 @@ package org.jetbrains.kotlin.fir.resolve.calls import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess +import org.jetbrains.kotlin.fir.resolve.DoubleColonLHS import org.jetbrains.kotlin.fir.resolve.constructType import org.jetbrains.kotlin.fir.resolve.firSymbolProvider import org.jetbrains.kotlin.fir.symbols.StandardClassIds -import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl import org.jetbrains.kotlin.fir.symbols.invoke import org.jetbrains.kotlin.fir.types.* -import org.jetbrains.kotlin.fir.types.impl.ConeClassTypeImpl import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder import org.jetbrains.kotlin.resolve.calls.model.PostponedResolvedAtomMarker import org.jetbrains.kotlin.utils.addToStdlib.safeAs @@ -44,18 +43,12 @@ fun Candidate.preprocessLambdaArgument( postponedAtoms += resolvedArgument } -fun preprocessCallableReference( - csBuilder: ConstraintSystemBuilder, +fun Candidate.preprocessCallableReference( argument: FirCallableReferenceAccess, - expectedType: ConeKotlinType, - sink: CheckerSink + expectedType: ConeKotlinType ) { - val type = argument.typeRef.coneTypeSafe() ?: return - val candidate = argument.candidate() ?: return resolvePlainArgumentType( - csBuilder, type, expectedType, sink, isReceiver = false, isSafeCall = false - ) - val argumentType = candidate.substitutor.substituteOrSelf(type) - resolvePlainArgumentType(csBuilder, argumentType, expectedType, sink, isReceiver = false, isSafeCall = false) + val lhs = bodyResolveComponents.doubleColonExpressionResolver.resolveDoubleColonLHS(argument) + postponedAtoms += EagerCallableReferenceAtom(argument, expectedType, lhs) } val ConeKotlinType.isBuiltinFunctionalType: Boolean @@ -211,3 +204,23 @@ class ResolvedLambdaAtom( override val inputTypes: Collection get() = receiver?.let { parameters + it } ?: parameters override val outputType: ConeKotlinType get() = returnType } + +abstract class ResolvedCallableReferenceAtom( + val atom: FirCallableReferenceAccess, + val expectedType: ConeKotlinType?, + val lhs: DoubleColonLHS? +) : PostponedResolvedAtomMarker { + override var analyzed: Boolean = false + + var resultingCandidate: Pair? = null +} + +class EagerCallableReferenceAtom( + atom: FirCallableReferenceAccess, + expectedType: ConeKotlinType?, + lhs: DoubleColonLHS? +) : ResolvedCallableReferenceAtom(atom, expectedType, lhs) { + + override val inputTypes: Collection get() = emptyList() + override val outputType: ConeKotlinType? get() = null +} diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/PostponedArgumentsAnalyzer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/PostponedArgumentsAnalyzer.kt index d439db203a3..885fc098399 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/PostponedArgumentsAnalyzer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/PostponedArgumentsAnalyzer.kt @@ -7,17 +7,23 @@ package org.jetbrains.kotlin.fir.resolve.calls import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction import org.jetbrains.kotlin.fir.expressions.FirExpression +import org.jetbrains.kotlin.fir.references.impl.FirErrorNamedReferenceImpl import org.jetbrains.kotlin.fir.resolve.constructType import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.transformers.StoreNameReference import org.jetbrains.kotlin.fir.symbols.StandardClassIds.Unit +import org.jetbrains.kotlin.fir.symbols.invoke import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.FirTypeRef +import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl import org.jetbrains.kotlin.resolve.calls.components.InferenceSession import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzer import org.jetbrains.kotlin.resolve.calls.inference.model.SimpleConstraintSystemConstraintPosition import org.jetbrains.kotlin.resolve.calls.model.PostponedResolvedAtomMarker -import org.jetbrains.kotlin.types.model.* -import org.jetbrains.kotlin.fir.symbols.invoke +import org.jetbrains.kotlin.types.model.StubTypeMarker +import org.jetbrains.kotlin.types.model.TypeVariableMarker +import org.jetbrains.kotlin.types.model.freshTypeConstructor +import org.jetbrains.kotlin.types.model.safeSubstitute interface LambdaAnalyzer { fun analyzeAndGetLambdaReturnArguments( @@ -36,7 +42,8 @@ class PostponedArgumentsAnalyzer( private val lambdaAnalyzer: LambdaAnalyzer, private val typeProvider: (FirExpression) -> FirTypeRef?, private val components: InferenceComponents, - private val candidate: Candidate + private val candidate: Candidate, + private val replacements: MutableMap ) { fun analyze( @@ -54,8 +61,7 @@ class PostponedArgumentsAnalyzer( // c, resolutionCallbacks, argument.transformToResolvedLambda(c.getBuilder()), diagnosticsHolder // ) -// is ResolvedCallableReferenceAtom -> -// callableReferenceResolver.processCallableReferenceArgument(c.getBuilder(), argument, diagnosticsHolder) + is ResolvedCallableReferenceAtom -> processCallableReference(argument) // // is ResolvedCollectionLiteralAtom -> TODO("Not supported") @@ -63,6 +69,31 @@ class PostponedArgumentsAnalyzer( } } + private fun processCallableReference(atom: ResolvedCallableReferenceAtom) { + val callableReferenceAccess = atom.atom + atom.analyzed = true + val (candidate, applicability) = atom.resultingCandidate ?: Pair(null, CandidateApplicability.INAPPLICABLE) + + val namedReference = when { + candidate == null || applicability < CandidateApplicability.SYNTHETIC_RESOLVED -> + FirErrorNamedReferenceImpl( + callableReferenceAccess.psi, + "Unresolved reference: ${callableReferenceAccess.calleeReference.name}" + ) + else -> FirNamedReferenceWithCandidate(callableReferenceAccess.psi, callableReferenceAccess.calleeReference.name, candidate) + } + + val transformedCalleeReference = callableReferenceAccess.transformCalleeReference( + StoreNameReference, + namedReference + ).apply { + if (candidate != null) { + replaceTypeRef(FirResolvedTypeRefImpl(null, candidate.resultingTypeForCallableReference!!)) + } + } + + replacements[callableReferenceAccess] = transformedCalleeReference + } private fun analyzeLambda( c: PostponedArgumentsAnalyzer.Context, diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolverParts.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolverParts.kt index 32c514f2641..fcd9147ab2a 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolverParts.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolverParts.kt @@ -7,17 +7,24 @@ package org.jetbrains.kotlin.fir.resolve.calls import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration +import org.jetbrains.kotlin.fir.declarations.FirProperty +import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction import org.jetbrains.kotlin.fir.declarations.visibility import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier +import org.jetbrains.kotlin.fir.resolve.DoubleColonLHS +import org.jetbrains.kotlin.fir.resolve.createFunctionalType import org.jetbrains.kotlin.fir.resolve.firProvider import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol +import org.jetbrains.kotlin.fir.types.ConeKotlinErrorType import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef +import org.jetbrains.kotlin.fir.types.coneTypeSafe import org.jetbrains.kotlin.load.java.JavaVisibilities import org.jetbrains.kotlin.name.FqName +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.* @@ -156,6 +163,69 @@ internal object CheckArguments : CheckerStage() { } } +internal object EagerResolveOfCallableReferences : CheckerStage() { + override suspend fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) { + for (atom in candidate.postponedAtoms.filterIsInstance()) { + if (!candidate.bodyResolveComponents.callResolver.resolveCallableReference(candidate.csBuilder, atom)) { + sink.yieldApplicability(CandidateApplicability.INAPPLICABLE) + } + } + } +} + +internal object CheckCallableReferenceExpectedType : CheckerStage() { + override suspend fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) { + val outerCsBuilder = callInfo.outerCSBuilder ?: return + val expectedType = callInfo.expectedType ?: return + val lhs = callInfo.lhs + + val resultingType: ConeKotlinType = when (val fir = candidate.symbol.fir) { + is FirSimpleFunction -> createKFunctionType(fir, lhs) + is FirProperty -> createKPropertyType(fir) + else -> ConeKotlinErrorType("Unknown callable kind: ${fir::class}") + }.let(candidate.substitutor::substituteOrSelf) + + candidate.resultingTypeForCallableReference = resultingType + + var isApplicable = true + + outerCsBuilder.runTransaction { + addOtherSystem(candidate.system.asReadOnlyStorage()) + + val position = SimpleConstraintSystemConstraintPosition //TODO + + addSubtypeConstraint(resultingType, expectedType, position) + isApplicable = !hasContradiction + + false + } + + if (!isApplicable) { + sink.yieldApplicability(CandidateApplicability.INAPPLICABLE) + } + } +} + +private fun createKPropertyType(fir: FirProperty): ConeKotlinType { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. +} + +private fun createKFunctionType( + function: FirSimpleFunction, + lhs: DoubleColonLHS? +): ConeKotlinType { + val receiverType = (lhs as? DoubleColonLHS.Type)?.type + val parameterTypes = function.valueParameters.map { + it.returnTypeRef.coneTypeSafe() ?: ConeKotlinErrorType("No type for parameter $it") + } + + return createFunctionalType( + parameterTypes, receiverType = receiverType, + rawReturnType = function.returnTypeRef.coneTypeSafe() ?: ConeKotlinErrorType("No type for return type of $function"), + isKFunctionType = true + ) +} + internal object DiscriminateSynthetics : CheckerStage() { override suspend fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) { if (candidate.symbol is SyntheticSymbol) { @@ -203,4 +273,4 @@ internal object CheckVisibility : CheckerStage() { } } } -} \ No newline at end of file +} diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt index 023c345e157..1589c802231 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt @@ -71,7 +71,7 @@ class FirCallCompleter( val replacements = mutableMapOf() val analyzer = - PostponedArgumentsAnalyzer(LambdaAnalyzerImpl(replacements), { it.resultType }, inferenceComponents, candidate) + PostponedArgumentsAnalyzer(LambdaAnalyzerImpl(replacements), { it.resultType }, inferenceComponents, candidate, replacements) completer.complete(candidate.system.asConstraintSystemCompleterContext(), completionMode, listOf(call), initialType) { analyzer.analyze(candidate.system.asPostponedArgumentsAnalyzerContext(), it) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt index 3ef01af5cc0..3e65c36e836 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt @@ -266,9 +266,7 @@ class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) : else callableReferenceAccess - val lhsResult = doubleColonExpressionResolver.resolveDoubleColonLHS(callableReferenceAccessWithTransformedLHS) - - return callResolver.resolveCallableReference(callableReferenceAccessWithTransformedLHS, lhsResult).compose() + return callableReferenceAccessWithTransformedLHS.compose() } override fun transformGetClassCall(getClassCall: FirGetClassCall, data: Any?): CompositeTransformResult { diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/differentLevels.kt b/compiler/fir/resolve/testData/diagnostics/callableReferences/differentLevels.kt new file mode 100644 index 00000000000..054f93258cf --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/differentLevels.kt @@ -0,0 +1,10 @@ +fun foo(x: () -> Int, y: Int) {} +fun bar(x: String): Int = 1 + +fun main() { + fun bar(): Int = 1 + fun foo(x: (String) -> Int, y: String) {} + + foo(::bar, 1) + foo(::bar, "") +} diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/differentLevels.txt b/compiler/fir/resolve/testData/diagnostics/callableReferences/differentLevels.txt new file mode 100644 index 00000000000..55714d65af2 --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/differentLevels.txt @@ -0,0 +1,17 @@ +FILE: differentLevels.kt + public final fun foo(x: R|kotlin/Function0|, y: R|kotlin/Int|): R|kotlin/Unit| { + } + public final fun bar(x: R|kotlin/String|): R|kotlin/Int| { + ^bar Int(1) + } + public final fun main(): R|kotlin/Unit| { + local final fun bar(): R|kotlin/Int| { + ^bar Int(1) + } + + local final fun foo(x: R|kotlin/Function1|, y: R|kotlin/String|): R|kotlin/Unit| { + } + + R|/foo|(::R|/bar|, Int(1)) + R|/foo|(::R|/bar|, String()) + } diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/ambiguityWhenNoApplicableCallableReferenceCandidate.kt b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/ambiguityWhenNoApplicableCallableReferenceCandidate.kt new file mode 100644 index 00000000000..7957a3751ef --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/ambiguityWhenNoApplicableCallableReferenceCandidate.kt @@ -0,0 +1,8 @@ +fun foo(x: Int) {} +fun foo(y: String) {} + +fun bar(f: (T) -> Unit) {} + +fun test() { + bar(::foo) +} diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/ambiguityWhenNoApplicableCallableReferenceCandidate.txt b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/ambiguityWhenNoApplicableCallableReferenceCandidate.txt new file mode 100644 index 00000000000..35acb943f3b --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/ambiguityWhenNoApplicableCallableReferenceCandidate.txt @@ -0,0 +1,10 @@ +FILE: ambiguityWhenNoApplicableCallableReferenceCandidate.kt + public final fun foo(x: R|kotlin/Int|): R|kotlin/Unit| { + } + public final fun foo(y: R|kotlin/String|): R|kotlin/Unit| { + } + public final fun bar(f: R|kotlin/Function1|): R|kotlin/Unit| { + } + public final fun test(): R|kotlin/Unit| { + R|/bar|(::#) + } diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/applicableCallableReferenceFromDistantScope.kt b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/applicableCallableReferenceFromDistantScope.kt new file mode 100644 index 00000000000..e1c3855a731 --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/applicableCallableReferenceFromDistantScope.kt @@ -0,0 +1,12 @@ +fun foo(s: String) {} + +object Scope { + fun foo(a: Int) {} + fun foo(b: Boolean) {} + + fun bar(f: (T) -> Unit): T = TODO() + + fun test() { + val s: String = bar(::foo) + } +} diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/applicableCallableReferenceFromDistantScope.txt b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/applicableCallableReferenceFromDistantScope.txt new file mode 100644 index 00000000000..a8ac23e6a06 --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/applicableCallableReferenceFromDistantScope.txt @@ -0,0 +1,23 @@ +FILE: applicableCallableReferenceFromDistantScope.kt + public final fun foo(s: R|kotlin/String|): R|kotlin/Unit| { + } + public final object Scope : R|kotlin/Any| { + private constructor(): R|Scope| { + super() + } + + public final fun foo(a: R|kotlin/Int|): R|kotlin/Unit| { + } + + public final fun foo(b: R|kotlin/Boolean|): R|kotlin/Unit| { + } + + public final fun bar(f: R|kotlin/Function1|): R|T| { + ^bar R|kotlin/TODO|() + } + + public final fun test(): R|kotlin/Unit| { + lval s: R|kotlin/String| = this@R|/Scope|.R|/Scope.bar|(::#) + } + + } diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/chooseCallableReferenceDependingOnInferredReceiver.kt b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/chooseCallableReferenceDependingOnInferredReceiver.kt new file mode 100644 index 00000000000..ba6186fb4cd --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/chooseCallableReferenceDependingOnInferredReceiver.kt @@ -0,0 +1,33 @@ +class A { + fun foo(i: A) {} + + fun baz(i: A) {} +} + +class B { + fun foo(s: B) {} + fun foo(c: Char) {} + + fun baz(s: B) {} +} + +fun bar(f: (T) -> Unit): T = TODO() + +fun test() { + myWith(A()) { + val t1 = bar(::foo) + + val t2 = bar(::baz) + + myWith(B()) { + val a: A = bar(::foo) + val b: B = bar(::foo) + + val t3 = bar(::baz) + + bar(::foo) + } + } +} + +inline fun myWith(receiver: T, block: T.() -> R): R = TODO() diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/chooseCallableReferenceDependingOnInferredReceiver.txt b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/chooseCallableReferenceDependingOnInferredReceiver.txt new file mode 100644 index 00000000000..e718a2f51d4 --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/chooseCallableReferenceDependingOnInferredReceiver.txt @@ -0,0 +1,48 @@ +FILE: chooseCallableReferenceDependingOnInferredReceiver.kt + public final class A : R|kotlin/Any| { + public constructor(): R|A| { + super() + } + + public final fun foo(i: R|A|): R|kotlin/Unit| { + } + + public final fun baz(i: R|A|): R|kotlin/Unit| { + } + + } + public final class B : R|kotlin/Any| { + public constructor(): R|B| { + super() + } + + public final fun foo(s: R|B|): R|kotlin/Unit| { + } + + public final fun foo(c: R|kotlin/Char|): R|kotlin/Unit| { + } + + public final fun baz(s: R|B|): R|kotlin/Unit| { + } + + } + public final fun bar(f: R|kotlin/Function1|): R|T| { + ^bar R|kotlin/TODO|() + } + public final fun test(): R|kotlin/Unit| { + R|/myWith|(R|/A.A|(), = myWith@fun (it: R|A|): R|kotlin/Unit| { + lval t1: = #(::foo#) + lval t2: = #(::baz#) + R|/myWith|(R|/B.B|(), = myWith@fun (it: R|B|): R|kotlin/Unit| { + lval a: R|A| = #(::foo#) + lval b: R|B| = #(::foo#) + lval t3: = #(::baz#) + #(::foo#) + } + ) + } + ) + } + public final inline fun myWith(receiver: R|T|, block: R|kotlin/Function1|): R|R| { + ^myWith R|kotlin/TODO|() + } diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/commonSupertypeFromReturnTypesOfCallableReference.kt b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/commonSupertypeFromReturnTypesOfCallableReference.kt new file mode 100644 index 00000000000..1e78886561e --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/commonSupertypeFromReturnTypesOfCallableReference.kt @@ -0,0 +1,12 @@ +interface Parent +interface Child1 : Parent +interface Child2 : Parent + +fun foo(): Child1 = TODO() +fun bar(): Child2 = TODO() + +fun select(x: K, y: K): K = TODO() + +fun test() { + val a = select(::foo, ::bar) +} diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/commonSupertypeFromReturnTypesOfCallableReference.txt b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/commonSupertypeFromReturnTypesOfCallableReference.txt new file mode 100644 index 00000000000..d74f5050e66 --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/commonSupertypeFromReturnTypesOfCallableReference.txt @@ -0,0 +1,19 @@ +FILE: commonSupertypeFromReturnTypesOfCallableReference.kt + public abstract interface Parent : R|kotlin/Any| { + } + public abstract interface Child1 : R|Parent| { + } + public abstract interface Child2 : R|Parent| { + } + public final fun foo(): R|Child1| { + ^foo R|kotlin/TODO|() + } + public final fun bar(): R|Child2| { + ^bar R|kotlin/TODO|() + } + public final fun select(x: R|K|, y: R|K|): R|K| { + ^select R|kotlin/TODO|() + } + public final fun test(): R|kotlin/Unit| { + lval a: R|kotlin/reflect/KFunction0| = R|/select||>(::R|/foo|, ::R|/bar|) + } diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/eagerAndPostponedCallableReferences.kt b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/eagerAndPostponedCallableReferences.kt new file mode 100644 index 00000000000..c74b1b4e19a --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/eagerAndPostponedCallableReferences.kt @@ -0,0 +1,26 @@ +interface A +interface B + +fun multiple(a: A) {} +fun multiple(b: B) {} + +fun singleA(a: A) {} +fun singleB(a: B) {} + +fun foo(f: (T) -> Unit, g: (T) -> Unit): T = TODO() + +fun test() { + val a1 = foo(::singleA, ::multiple) + + val a2 = foo(::singleB, ::multiple) + + val a3 = foo(::multiple, ::singleA) + + val a4 = foo(::multiple, ::singleB) + + val a5 = foo(::singleA, ::singleA) + + val a6 = foo(::singleA, ::singleB) + + foo(::multiple, ::multiple) +} diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/eagerAndPostponedCallableReferences.txt b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/eagerAndPostponedCallableReferences.txt new file mode 100644 index 00000000000..720447581bd --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/eagerAndPostponedCallableReferences.txt @@ -0,0 +1,25 @@ +FILE: eagerAndPostponedCallableReferences.kt + public abstract interface A : R|kotlin/Any| { + } + public abstract interface B : R|kotlin/Any| { + } + public final fun multiple(a: R|A|): R|kotlin/Unit| { + } + public final fun multiple(b: R|B|): R|kotlin/Unit| { + } + public final fun singleA(a: R|A|): R|kotlin/Unit| { + } + public final fun singleB(a: R|B|): R|kotlin/Unit| { + } + public final fun foo(f: R|kotlin/Function1|, g: R|kotlin/Function1|): R|T| { + ^foo R|kotlin/TODO|() + } + public final fun test(): R|kotlin/Unit| { + lval a1: R|A| = R|/foo|(::R|/singleA|, ::#) + lval a2: R|B| = R|/foo|(::R|/singleB|, ::#) + lval a3: R|A| = R|/foo|(::#, ::R|/singleA|) + lval a4: R|B| = R|/foo|(::#, ::R|/singleB|) + lval a5: R|A| = R|/foo|(::R|/singleA|, ::R|/singleA|) + lval a6: R|it(A & B)| = R|/foo|(::R|/singleA|, ::R|/singleB|) + R|/foo|(::#, ::#) + } diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/eagerResolveOfSingleCallableReference.kt b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/eagerResolveOfSingleCallableReference.kt new file mode 100644 index 00000000000..cb8ce6df121 --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/eagerResolveOfSingleCallableReference.kt @@ -0,0 +1,15 @@ +// !LANGUAGE: -NewInference +// !DIAGNOSTICS: -UNUSED_PARAMETER + +open class A +class B : A() + +class Or(left: A, right: A) : A() + +class Out + +fun test(ls: Out) { + ls.reduce(::Or) +} + +fun Out.reduce(operation: (S, T) -> S): S = TODO() diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/eagerResolveOfSingleCallableReference.txt b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/eagerResolveOfSingleCallableReference.txt new file mode 100644 index 00000000000..405ee2ff960 --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/eagerResolveOfSingleCallableReference.txt @@ -0,0 +1,31 @@ +FILE: eagerResolveOfSingleCallableReference.kt + public open class A : R|kotlin/Any| { + public constructor(): R|A| { + super() + } + + } + public final class B : R|A| { + public constructor(): R|B| { + super() + } + + } + public final class Or : R|A| { + public constructor(left: R|A|, right: R|A|): R|Or| { + super() + } + + } + public final class Out : R|kotlin/Any| { + public constructor(): R|Out| { + super() + } + + } + public final fun test(ls: R|Out|): R|kotlin/Unit| { + R|/ls|.R|/reduce|(::R|/Or.Or|) + } + public final fun R|Out|.reduce(operation: R|kotlin/Function2|): R|S| { + ^reduce R|kotlin/TODO|() + } diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/moreSpecificAmbiguousExtensions.kt b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/moreSpecificAmbiguousExtensions.kt new file mode 100644 index 00000000000..159f39d9611 --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/moreSpecificAmbiguousExtensions.kt @@ -0,0 +1,18 @@ +interface IA +interface IB : IA + +fun IA.extFun(x: IB) {} +fun IB.extFun(x: IA) {} + +fun test() { + val extFun1 = IA::extFun + val extFun2 = IB::extFun +} + +fun testWithExpectedType() { + val extFun_AB_A: IA.(IB) -> Unit = IA::extFun + val extFun_AA_B: IA.(IA) -> Unit = IB::extFun + val extFun_BB_A: IB.(IB) -> Unit = IA::extFun + val extFun_BA_B: IB.(IA) -> Unit = IB::extFun + val extFun_BB_B: IB.(IB) -> Unit = IB::extFun +} diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/moreSpecificAmbiguousExtensions.txt b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/moreSpecificAmbiguousExtensions.txt new file mode 100644 index 00000000000..988fa56e898 --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/moreSpecificAmbiguousExtensions.txt @@ -0,0 +1,20 @@ +FILE: moreSpecificAmbiguousExtensions.kt + public abstract interface IA : R|kotlin/Any| { + } + public abstract interface IB : R|IA| { + } + public final fun R|IA|.extFun(x: R|IB|): R|kotlin/Unit| { + } + public final fun R|IB|.extFun(x: R|IA|): R|kotlin/Unit| { + } + public final fun test(): R|kotlin/Unit| { + lval extFun1: = Q|IA|::extFun# + lval extFun2: = Q|IB|::extFun# + } + public final fun testWithExpectedType(): R|kotlin/Unit| { + lval extFun_AB_A: R|kotlin/Function2| = Q|IA|::extFun# + lval extFun_AA_B: R|kotlin/Function2| = Q|IB|::extFun# + lval extFun_BB_A: R|kotlin/Function2| = Q|IA|::extFun# + lval extFun_BA_B: R|kotlin/Function2| = Q|IB|::extFun# + lval extFun_BB_B: R|kotlin/Function2| = Q|IB|::extFun# + } diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/multipleOutersAndMultipleCallableReferences.kt b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/multipleOutersAndMultipleCallableReferences.kt new file mode 100644 index 00000000000..14981b64ade --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/multipleOutersAndMultipleCallableReferences.kt @@ -0,0 +1,13 @@ +interface Base +class Inv : Base + +fun foo(x: Int): Inv = TODO() +fun foo(y: String): Inv = TODO() + +fun bar(f: (T) -> Inv, p: String = "") {} + +fun bar(f: (T) -> Inv, p: Int = 4) {} + +fun test() { + bar(::foo) +} diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/multipleOutersAndMultipleCallableReferences.txt b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/multipleOutersAndMultipleCallableReferences.txt new file mode 100644 index 00000000000..e7b43e2144b --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/multipleOutersAndMultipleCallableReferences.txt @@ -0,0 +1,22 @@ +FILE: multipleOutersAndMultipleCallableReferences.kt + public abstract interface Base : R|kotlin/Any| { + } + public final class Inv : R|Base| { + public constructor(): R|Inv| { + super() + } + + } + public final fun foo(x: R|kotlin/Int|): R|Inv| { + ^foo R|kotlin/TODO|() + } + public final fun foo(y: R|kotlin/String|): R|Inv| { + ^foo R|kotlin/TODO|() + } + public final fun bar(f: R|kotlin/Function1>|, p: R|kotlin/String| = String()): R|kotlin/Unit| { + } + public final fun bar(f: R|kotlin/Function1>|, p: R|kotlin/Int| = Int(4)): R|kotlin/Unit| { + } + public final fun test(): R|kotlin/Unit| { + R|/bar|(::R|/foo|) + } diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/noAmbiguityBetweenTopLevelAndMemberProperty.kt b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/noAmbiguityBetweenTopLevelAndMemberProperty.kt new file mode 100644 index 00000000000..ceb1f86480e --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/noAmbiguityBetweenTopLevelAndMemberProperty.kt @@ -0,0 +1,14 @@ +import kotlin.reflect.KProperty0 +import kotlin.reflect.KProperty1 + +fun property(property: KProperty0): Int = 1 +fun property(property: KProperty1): String = "" + +val subject = "" + +class O { + val subject = "" +} + +val someProperty0 = property(::subject) +val someProperty1 = property(O::subject) diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/noAmbiguityBetweenTopLevelAndMemberProperty.txt b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/noAmbiguityBetweenTopLevelAndMemberProperty.txt new file mode 100644 index 00000000000..d6536e2916f --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/noAmbiguityBetweenTopLevelAndMemberProperty.txt @@ -0,0 +1,22 @@ +FILE: noAmbiguityBetweenTopLevelAndMemberProperty.kt + public final fun property(property: R|kotlin/reflect/KProperty0|): R|kotlin/Int| { + ^property Int(1) + } + public final fun property(property: R|kotlin/reflect/KProperty1|): R|kotlin/String| { + ^property String() + } + public final val subject: R|kotlin/String| = String() + public get(): R|kotlin/String| + public final class O : R|kotlin/Any| { + public constructor(): R|O| { + super() + } + + public final val subject: R|kotlin/String| = String() + public get(): R|kotlin/String| + + } + public final val someProperty0: = #(::subject#) + public get(): + public final val someProperty1: = #(Q|O|::subject#) + public get(): diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/overloadsBound.kt b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/overloadsBound.kt new file mode 100644 index 00000000000..ac5d6c3cf18 --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/overloadsBound.kt @@ -0,0 +1,10 @@ +class C { + fun xf1(){} + fun xf1(s: String){} +} + +fun foo(p: (String) -> Unit){} + +fun bar(c: C) { + foo(c::xf1) +} diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/overloadsBound.txt b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/overloadsBound.txt new file mode 100644 index 00000000000..b2ec3180d1e --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/overloadsBound.txt @@ -0,0 +1,18 @@ +FILE: overloadsBound.kt + public final class C : R|kotlin/Any| { + public constructor(): R|C| { + super() + } + + public final fun xf1(): R|kotlin/Unit| { + } + + public final fun xf1(s: R|kotlin/String|): R|kotlin/Unit| { + } + + } + public final fun foo(p: R|kotlin/Function1|): R|kotlin/Unit| { + } + public final fun bar(c: R|C|): R|kotlin/Unit| { + R|/foo|(R|/c|::R|/C.xf1|) + } diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/postponedResolveOfManyCallableReference.kt b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/postponedResolveOfManyCallableReference.kt new file mode 100644 index 00000000000..7abee0fb0ea --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/postponedResolveOfManyCallableReference.kt @@ -0,0 +1,16 @@ +interface A +interface B + +fun foo(i: A) {} +fun foo(b: B) {} + +fun bar1(f: (T) -> Unit): T = TODO() +fun bar2(f: (T) -> Unit, e: T) {} + +fun test(a: A, b: B) { + val expectedType1: A = bar1(::foo) + val expectedType2: B = bar1(::foo) + + bar2(::foo, a) + bar2(::foo, b) +} diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/postponedResolveOfManyCallableReference.txt b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/postponedResolveOfManyCallableReference.txt new file mode 100644 index 00000000000..6990668401e --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/postponedResolveOfManyCallableReference.txt @@ -0,0 +1,20 @@ +FILE: postponedResolveOfManyCallableReference.kt + public abstract interface A : R|kotlin/Any| { + } + public abstract interface B : R|kotlin/Any| { + } + public final fun foo(i: R|A|): R|kotlin/Unit| { + } + public final fun foo(b: R|B|): R|kotlin/Unit| { + } + public final fun bar1(f: R|kotlin/Function1|): R|T| { + ^bar1 R|kotlin/TODO|() + } + public final fun bar2(f: R|kotlin/Function1|, e: R|T|): R|kotlin/Unit| { + } + public final fun test(a: R|A|, b: R|B|): R|kotlin/Unit| { + lval expectedType1: R|A| = R|/bar1|(::#) + lval expectedType2: R|B| = R|/bar1|(::#) + R|/bar2|(::R|/foo|, R|/a|) + R|/bar2|(::R|/foo|, R|/b|) + } diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/resolveCallableReferencesAfterAllSimpleArguments.kt b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/resolveCallableReferencesAfterAllSimpleArguments.kt new file mode 100644 index 00000000000..698132bcb46 --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/resolveCallableReferencesAfterAllSimpleArguments.kt @@ -0,0 +1,12 @@ +interface A +interface B + +fun fooB(b: B) {} + +fun bar(f: (T) -> Unit, e: T) {} +fun baz(e: T, f: (T) -> Unit) {} + +fun test(a: A, b: B) { + baz(a, ::fooB) + bar(::fooB, a) +} diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/resolveCallableReferencesAfterAllSimpleArguments.txt b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/resolveCallableReferencesAfterAllSimpleArguments.txt new file mode 100644 index 00000000000..66826fcf1d3 --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/resolveCallableReferencesAfterAllSimpleArguments.txt @@ -0,0 +1,15 @@ +FILE: resolveCallableReferencesAfterAllSimpleArguments.kt + public abstract interface A : R|kotlin/Any| { + } + public abstract interface B : R|kotlin/Any| { + } + public final fun fooB(b: R|B|): R|kotlin/Unit| { + } + public final fun bar(f: R|kotlin/Function1|, e: R|T|): R|kotlin/Unit| { + } + public final fun baz(e: R|T|, f: R|kotlin/Function1|): R|kotlin/Unit| { + } + public final fun test(a: R|A|, b: R|B|): R|kotlin/Unit| { + #(R|/a|, ::fooB#) + #(::fooB#, R|/a|) + } diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/withGenericFun.kt b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/withGenericFun.kt new file mode 100644 index 00000000000..9d1c06de2e8 --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/withGenericFun.kt @@ -0,0 +1,7 @@ +fun apply(x: T, f: (T) -> R): R = f(x) + +fun foo(i: Int) {} +fun foo(s: String) {} + +val x1 = apply(1, ::foo) +val x2 = apply("hello", ::foo) diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/withGenericFun.txt b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/withGenericFun.txt new file mode 100644 index 00000000000..b908576d876 --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/withGenericFun.txt @@ -0,0 +1,12 @@ +FILE: withGenericFun.kt + public final fun apply(x: R|T|, f: R|kotlin/Function1|): R|R| { + ^apply R|/f|.R|FakeOverride|(R|/x|) + } + public final fun foo(i: R|kotlin/Int|): R|kotlin/Unit| { + } + public final fun foo(s: R|kotlin/String|): R|kotlin/Unit| { + } + public final val x1: R|kotlin/Unit| = R|/apply|(Int(1), ::R|/foo|) + public get(): R|kotlin/Unit| + public final val x2: R|kotlin/Unit| = R|/apply|(String(hello), ::R|/foo|) + public get(): R|kotlin/Unit| diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/manyCandidatesInference.kt b/compiler/fir/resolve/testData/diagnostics/callableReferences/manyCandidatesInference.kt new file mode 100644 index 00000000000..49caf8adee3 --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/manyCandidatesInference.kt @@ -0,0 +1,10 @@ +fun foo(x: () -> T, y: Int) {} +fun bar(x: E): Int = 1 + +fun main() { + fun bar(): Int = 1 + fun foo(x: (String) -> Int, y: String) {} + + foo(::bar, 1) + foo(::bar, "") +} diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/manyCandidatesInference.txt b/compiler/fir/resolve/testData/diagnostics/callableReferences/manyCandidatesInference.txt new file mode 100644 index 00000000000..c7b5d155dd0 --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/manyCandidatesInference.txt @@ -0,0 +1,17 @@ +FILE: manyCandidatesInference.kt + public final fun foo(x: R|kotlin/Function0|, y: R|kotlin/Int|): R|kotlin/Unit| { + } + public final fun bar(x: R|E|): R|kotlin/Int| { + ^bar Int(1) + } + public final fun main(): R|kotlin/Unit| { + local final fun bar(): R|kotlin/Int| { + ^bar Int(1) + } + + local final fun foo(x: R|kotlin/Function1|, y: R|kotlin/String|): R|kotlin/Unit| { + } + + R|/foo|(::R|/bar|, Int(1)) + R|/foo|(::R|/bar|, String()) + } diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/manyInnerCandidates.kt b/compiler/fir/resolve/testData/diagnostics/callableReferences/manyInnerCandidates.kt new file mode 100644 index 00000000000..2975ad00ae0 --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/manyInnerCandidates.kt @@ -0,0 +1,9 @@ +fun foo(x: (String) -> Int) {} + + +fun bar(y: Any): Int = 1 +fun bar(x: String): Int = 1 + +fun main() { + foo(::bar) +} diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/manyInnerCandidates.txt b/compiler/fir/resolve/testData/diagnostics/callableReferences/manyInnerCandidates.txt new file mode 100644 index 00000000000..f96d6585f4e --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/manyInnerCandidates.txt @@ -0,0 +1,12 @@ +FILE: manyInnerCandidates.kt + public final fun foo(x: R|kotlin/Function1|): R|kotlin/Unit| { + } + public final fun bar(y: R|kotlin/Any|): R|kotlin/Int| { + ^bar Int(1) + } + public final fun bar(x: R|kotlin/String|): R|kotlin/Int| { + ^bar Int(1) + } + public final fun main(): R|kotlin/Unit| { + R|/foo|(::R|/bar|) + } diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/manyInnerManyOuterCandidates.kt b/compiler/fir/resolve/testData/diagnostics/callableReferences/manyInnerManyOuterCandidates.kt new file mode 100644 index 00000000000..318a745ef72 --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/manyInnerManyOuterCandidates.kt @@ -0,0 +1,10 @@ +fun foo(x: (String) -> Int) {} +fun foo(x: () -> Int) {} + + +fun bar(): Int = 1 +fun bar(x: Double): Int = 1 + +fun main() { + foo(::bar) +} diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/manyInnerManyOuterCandidates.txt b/compiler/fir/resolve/testData/diagnostics/callableReferences/manyInnerManyOuterCandidates.txt new file mode 100644 index 00000000000..bca7c51c845 --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/manyInnerManyOuterCandidates.txt @@ -0,0 +1,14 @@ +FILE: manyInnerManyOuterCandidates.kt + public final fun foo(x: R|kotlin/Function1|): R|kotlin/Unit| { + } + public final fun foo(x: R|kotlin/Function0|): R|kotlin/Unit| { + } + public final fun bar(): R|kotlin/Int| { + ^bar Int(1) + } + public final fun bar(x: R|kotlin/Double|): R|kotlin/Int| { + ^bar Int(1) + } + public final fun main(): R|kotlin/Unit| { + R|/foo|(::R|/bar|) + } diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/manyInnermanyOuterCandidatesAmbiguity.kt b/compiler/fir/resolve/testData/diagnostics/callableReferences/manyInnermanyOuterCandidatesAmbiguity.kt new file mode 100644 index 00000000000..ffecc096110 --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/manyInnermanyOuterCandidatesAmbiguity.kt @@ -0,0 +1,10 @@ +fun foo(x: (String) -> Int) {} +fun foo(x: () -> Int) {} + + +fun bar(): Int = 1 +fun bar(x: String): Int = 1 + +fun main() { + foo(::bar) +} diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/manyInnermanyOuterCandidatesAmbiguity.txt b/compiler/fir/resolve/testData/diagnostics/callableReferences/manyInnermanyOuterCandidatesAmbiguity.txt new file mode 100644 index 00000000000..1447c09b482 --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/manyInnermanyOuterCandidatesAmbiguity.txt @@ -0,0 +1,14 @@ +FILE: manyInnermanyOuterCandidatesAmbiguity.kt + public final fun foo(x: R|kotlin/Function1|): R|kotlin/Unit| { + } + public final fun foo(x: R|kotlin/Function0|): R|kotlin/Unit| { + } + public final fun bar(): R|kotlin/Int| { + ^bar Int(1) + } + public final fun bar(x: R|kotlin/String|): R|kotlin/Int| { + ^bar Int(1) + } + public final fun main(): R|kotlin/Unit| { + #(::bar#) + } diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/manyOuterCandidates.kt b/compiler/fir/resolve/testData/diagnostics/callableReferences/manyOuterCandidates.kt new file mode 100644 index 00000000000..3cfbdde6269 --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/manyOuterCandidates.kt @@ -0,0 +1,9 @@ +fun foo(x: (String) -> Int) {} +fun foo(x: () -> Int) {} + + +fun bar(): Int = 1 + +fun main() { + foo(::bar) +} diff --git a/compiler/fir/resolve/testData/diagnostics/callableReferences/manyOuterCandidates.txt b/compiler/fir/resolve/testData/diagnostics/callableReferences/manyOuterCandidates.txt new file mode 100644 index 00000000000..fe57e04fc4a --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/callableReferences/manyOuterCandidates.txt @@ -0,0 +1,11 @@ +FILE: manyOuterCandidates.kt + public final fun foo(x: R|kotlin/Function1|): R|kotlin/Unit| { + } + public final fun foo(x: R|kotlin/Function0|): R|kotlin/Unit| { + } + public final fun bar(): R|kotlin/Int| { + ^bar Int(1) + } + public final fun main(): R|kotlin/Unit| { + R|/foo|(::R|/bar|) + } diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java index c91b54d36f4..1f9b736fd33 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java @@ -40,6 +40,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/fir/resolve/testData/diagnostics/callableReferences"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("differentLevels.kt") + public void testDifferentLevels() throws Exception { + runTest("compiler/fir/resolve/testData/diagnostics/callableReferences/differentLevels.kt"); + } + @TestMetadata("inferenceFromCallableReferenceType.kt") public void testInferenceFromCallableReferenceType() throws Exception { runTest("compiler/fir/resolve/testData/diagnostics/callableReferences/inferenceFromCallableReferenceType.kt"); @@ -50,6 +55,31 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest { runTest("compiler/fir/resolve/testData/diagnostics/callableReferences/inferenceFromExpectedType.kt"); } + @TestMetadata("manyCandidatesInference.kt") + public void testManyCandidatesInference() throws Exception { + runTest("compiler/fir/resolve/testData/diagnostics/callableReferences/manyCandidatesInference.kt"); + } + + @TestMetadata("manyInnerCandidates.kt") + public void testManyInnerCandidates() throws Exception { + runTest("compiler/fir/resolve/testData/diagnostics/callableReferences/manyInnerCandidates.kt"); + } + + @TestMetadata("manyInnerManyOuterCandidates.kt") + public void testManyInnerManyOuterCandidates() throws Exception { + runTest("compiler/fir/resolve/testData/diagnostics/callableReferences/manyInnerManyOuterCandidates.kt"); + } + + @TestMetadata("manyInnermanyOuterCandidatesAmbiguity.kt") + public void testManyInnermanyOuterCandidatesAmbiguity() throws Exception { + runTest("compiler/fir/resolve/testData/diagnostics/callableReferences/manyInnermanyOuterCandidatesAmbiguity.kt"); + } + + @TestMetadata("manyOuterCandidates.kt") + public void testManyOuterCandidates() throws Exception { + runTest("compiler/fir/resolve/testData/diagnostics/callableReferences/manyOuterCandidates.kt"); + } + @TestMetadata("simpleClassReceiver.kt") public void testSimpleClassReceiver() throws Exception { runTest("compiler/fir/resolve/testData/diagnostics/callableReferences/simpleClassReceiver.kt"); @@ -64,6 +94,84 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest { public void testSimpleNoReceiver() throws Exception { runTest("compiler/fir/resolve/testData/diagnostics/callableReferences/simpleNoReceiver.kt"); } + + @TestMetadata("compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class FromBasicDiagnosticTests extends AbstractFirDiagnosticsTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInFromBasicDiagnosticTests() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("ambiguityWhenNoApplicableCallableReferenceCandidate.kt") + public void testAmbiguityWhenNoApplicableCallableReferenceCandidate() throws Exception { + runTest("compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/ambiguityWhenNoApplicableCallableReferenceCandidate.kt"); + } + + @TestMetadata("applicableCallableReferenceFromDistantScope.kt") + public void testApplicableCallableReferenceFromDistantScope() throws Exception { + runTest("compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/applicableCallableReferenceFromDistantScope.kt"); + } + + @TestMetadata("chooseCallableReferenceDependingOnInferredReceiver.kt") + public void testChooseCallableReferenceDependingOnInferredReceiver() throws Exception { + runTest("compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/chooseCallableReferenceDependingOnInferredReceiver.kt"); + } + + @TestMetadata("commonSupertypeFromReturnTypesOfCallableReference.kt") + public void testCommonSupertypeFromReturnTypesOfCallableReference() throws Exception { + runTest("compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/commonSupertypeFromReturnTypesOfCallableReference.kt"); + } + + @TestMetadata("eagerAndPostponedCallableReferences.kt") + public void testEagerAndPostponedCallableReferences() throws Exception { + runTest("compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/eagerAndPostponedCallableReferences.kt"); + } + + @TestMetadata("eagerResolveOfSingleCallableReference.kt") + public void testEagerResolveOfSingleCallableReference() throws Exception { + runTest("compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/eagerResolveOfSingleCallableReference.kt"); + } + + @TestMetadata("moreSpecificAmbiguousExtensions.kt") + public void testMoreSpecificAmbiguousExtensions() throws Exception { + runTest("compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/moreSpecificAmbiguousExtensions.kt"); + } + + @TestMetadata("multipleOutersAndMultipleCallableReferences.kt") + public void testMultipleOutersAndMultipleCallableReferences() throws Exception { + runTest("compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/multipleOutersAndMultipleCallableReferences.kt"); + } + + @TestMetadata("noAmbiguityBetweenTopLevelAndMemberProperty.kt") + public void testNoAmbiguityBetweenTopLevelAndMemberProperty() throws Exception { + runTest("compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/noAmbiguityBetweenTopLevelAndMemberProperty.kt"); + } + + @TestMetadata("overloadsBound.kt") + public void testOverloadsBound() throws Exception { + runTest("compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/overloadsBound.kt"); + } + + @TestMetadata("postponedResolveOfManyCallableReference.kt") + public void testPostponedResolveOfManyCallableReference() throws Exception { + runTest("compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/postponedResolveOfManyCallableReference.kt"); + } + + @TestMetadata("resolveCallableReferencesAfterAllSimpleArguments.kt") + public void testResolveCallableReferencesAfterAllSimpleArguments() throws Exception { + runTest("compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/resolveCallableReferencesAfterAllSimpleArguments.kt"); + } + + @TestMetadata("withGenericFun.kt") + public void testWithGenericFun() throws Exception { + runTest("compiler/fir/resolve/testData/diagnostics/callableReferences/fromBasicDiagnosticTests/withGenericFun.kt"); + } + } } @TestMetadata("compiler/fir/resolve/testData/diagnostics/j+k") diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemBuilder.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemBuilder.kt index 71cf58dd8d5..cab322b2262 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemBuilder.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemBuilder.kt @@ -19,7 +19,10 @@ package org.jetbrains.kotlin.resolve.calls.inference import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzer import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintPosition import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage -import org.jetbrains.kotlin.resolve.calls.model.* +import org.jetbrains.kotlin.resolve.calls.model.CallableReferenceKotlinCallArgument +import org.jetbrains.kotlin.resolve.calls.model.KotlinCallArgument +import org.jetbrains.kotlin.resolve.calls.model.LHSResult +import org.jetbrains.kotlin.resolve.calls.model.SubKotlinCallArgument import org.jetbrains.kotlin.types.model.KotlinTypeMarker import org.jetbrains.kotlin.types.model.TypeConstructorMarker import org.jetbrains.kotlin.types.model.TypeSubstitutorMarker @@ -40,6 +43,8 @@ interface ConstraintSystemOperation { fun isPostponedTypeVariable(typeVariable: TypeVariableMarker): Boolean fun getProperSuperTypeConstructors(type: KotlinTypeMarker): List + + fun addOtherSystem(otherSystem: ConstraintStorage) } interface ConstraintSystemBuilder : ConstraintSystemOperation { @@ -70,4 +75,4 @@ fun PostponedArgumentsAnalyzer.Context.addSubsystemFromArgument(argument: Kotlin addSubsystemFromArgument(argument.lhsResult.safeAs()?.lshCallArgument) } } -} \ No newline at end of file +}