From edb1273355d8c9c2cd362e0c5d37abfdc5dd9da2 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Tue, 8 Sep 2020 12:33:40 +0300 Subject: [PATCH] [FIR] Report ResolutionDiagnostics instead of applicability in resolve --- .../kotlin/fir/resolve/calls/Arguments.kt | 9 +++-- .../kotlin/fir/resolve/calls/CheckerSink.kt | 20 +++++++---- ...CreateFreshTypeVariableSubstitutorStage.kt | 3 +- .../fir/resolve/calls/ResolutionDiagnostic.kt | 8 +++++ .../resolve/calls/ResolutionStageRunner.kt | 5 +-- .../fir/resolve/calls/ResolutionStages.kt | 35 +++++++------------ .../fir/resolve/calls/TypeArgumentMapping.kt | 5 ++- 7 files changed, 44 insertions(+), 41 deletions(-) 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 b482a5ce630..f5178aca604 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 @@ -28,7 +28,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.tower.CandidateApplicability import org.jetbrains.kotlin.types.model.CaptureStatus fun Candidate.resolveArgumentExpression( @@ -202,7 +201,7 @@ fun Candidate.resolvePlainExpressionArgument( private fun Candidate.checkApplicabilityForIntegerOperatorCall(sink: CheckerSink, argument: FirExpression) { if (symbol.fir !is FirIntegerOperator) return if (argument !is FirConstExpression<*> && argument !is FirIntegerOperatorCall) { - sink.reportApplicability(CandidateApplicability.INAPPLICABLE) + sink.reportDiagnostic(InapplicableCandidate) } } @@ -265,7 +264,7 @@ private fun checkApplicabilityForArgumentType( if (expectedType == null) return if (isReceiver && isDispatch) { if (!expectedType.isNullable && argumentType.isMarkedNullable) { - sink.reportApplicability(CandidateApplicability.INAPPLICABLE_WRONG_RECEIVER) + sink.reportDiagnostic(InapplicableWrongReceiver) } return } @@ -278,10 +277,10 @@ private fun checkApplicabilityForArgumentType( val nullableExpectedType = expectedType.withNullability(ConeNullability.NULLABLE, sink.components.session.typeContext) if (csBuilder.addSubtypeConstraintIfCompatible(argumentType, nullableExpectedType, position)) { - sink.reportApplicability(CandidateApplicability.INAPPLICABLE_WRONG_RECEIVER) // TODO + sink.reportDiagnostic(InapplicableWrongReceiver) // TODO } else { csBuilder.addSubtypeConstraint(argumentType, expectedType, position) - sink.reportApplicability(CandidateApplicability.INAPPLICABLE_WRONG_RECEIVER) + sink.reportDiagnostic(InapplicableWrongReceiver) } } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CheckerSink.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CheckerSink.kt index c18effb46f6..c804ff78576 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CheckerSink.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CheckerSink.kt @@ -12,7 +12,7 @@ import org.jetbrains.kotlin.resolve.calls.tower.isSuccess import kotlin.coroutines.Continuation abstract class CheckerSink { - abstract fun reportApplicability(new: CandidateApplicability) + abstract fun reportDiagnostic(diagnostic: ResolutionDiagnostic) abstract val components: InferenceComponents @@ -29,8 +29,8 @@ suspend inline fun CheckerSink.yieldIfNeed() { } } -suspend inline fun CheckerSink.yieldApplicability(new: CandidateApplicability) { - reportApplicability(new) +suspend inline fun CheckerSink.yieldDiagnostic(diagnostic: ResolutionDiagnostic) { + reportDiagnostic(diagnostic) yieldIfNeed() } @@ -39,11 +39,17 @@ class CheckerSinkImpl( var continuation: Continuation? = null, val stopOnFirstError: Boolean = true ) : CheckerSink() { - var current = CandidateApplicability.RESOLVED + var currentApplicability = CandidateApplicability.RESOLVED private set - override fun reportApplicability(new: CandidateApplicability) { - if (new < current) current = new + private val _diagnostics: MutableList = mutableListOf() + + val diagnostics: List + get() = _diagnostics + + override fun reportDiagnostic(diagnostic: ResolutionDiagnostic) { + _diagnostics += diagnostic + if (diagnostic.applicability < currentApplicability) currentApplicability = diagnostic.applicability } @PrivateForInline @@ -53,6 +59,6 @@ class CheckerSinkImpl( } override val needYielding: Boolean - get() = stopOnFirstError && !current.isSuccess + get() = stopOnFirstError && !currentApplicability.isSuccess } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CreateFreshTypeVariableSubstitutorStage.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CreateFreshTypeVariableSubstitutorStage.kt index 9f874ffd335..45e837be44d 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CreateFreshTypeVariableSubstitutorStage.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CreateFreshTypeVariableSubstitutorStage.kt @@ -19,7 +19,6 @@ import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.impl.FirTypePlaceholderProjection import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemOperation import org.jetbrains.kotlin.resolve.calls.inference.model.SimpleConstraintSystemConstraintPosition -import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability internal object CreateFreshTypeVariableSubstitutorStage : ResolutionStage() { override suspend fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) { @@ -37,7 +36,7 @@ internal object CreateFreshTypeVariableSubstitutorStage : ResolutionStage() { // bad function -- error on declaration side if (csBuilder.hasContradiction) { - sink.yieldApplicability(CandidateApplicability.INAPPLICABLE) //TODO: auto report it + sink.yieldDiagnostic(InapplicableCandidate) //TODO: auto report it return } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionDiagnostic.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionDiagnostic.kt index 46c5b2967e3..eec75c61f95 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionDiagnostic.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionDiagnostic.kt @@ -50,3 +50,11 @@ class NameNotFound( override val argument: FirExpression, val function: FirFunction<*> ) : InapplicableArgumentDiagnostic() + +object InapplicableCandidate : ResolutionDiagnostic(CandidateApplicability.INAPPLICABLE) + +object HiddenCandidate : ResolutionDiagnostic(CandidateApplicability.HIDDEN) + +object ResolvedWithLowPriority : ResolutionDiagnostic(CandidateApplicability.RESOLVED_LOW_PRIORITY) + +object InapplicableWrongReceiver : ResolutionDiagnostic(CandidateApplicability.INAPPLICABLE_WRONG_RECEIVER) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStageRunner.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStageRunner.kt index 42929bf2477..ce3781e57e4 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStageRunner.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStageRunner.kt @@ -36,10 +36,11 @@ class ResolutionStageRunner(val components: InferenceComponents) { while (!finished) { sink.continuation!!.resume(Unit) - if (!sink.current.isSuccess) { + if (!sink.currentApplicability.isSuccess) { break } } - return sink.current + candidate.diagnostics += sink.diagnostics + return sink.currentApplicability } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt index 68047bf07fc..ce0f7a19fee 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt @@ -28,9 +28,6 @@ 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.tower.CandidateApplicability -import org.jetbrains.kotlin.utils.addToStdlib.min - abstract class ResolutionStage { abstract suspend fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) @@ -46,17 +43,17 @@ internal object CheckExplicitReceiverConsistency : ResolutionStage() { when (receiverKind) { NO_EXPLICIT_RECEIVER -> { if (explicitReceiver != null && explicitReceiver !is FirResolvedQualifier && !explicitReceiver.isSuperReferenceExpression()) { - return sink.yieldApplicability(CandidateApplicability.INAPPLICABLE_WRONG_RECEIVER) + return sink.yieldDiagnostic(InapplicableWrongReceiver) } } EXTENSION_RECEIVER, DISPATCH_RECEIVER -> { if (explicitReceiver == null) { - return sink.yieldApplicability(CandidateApplicability.INAPPLICABLE_WRONG_RECEIVER) + return sink.yieldDiagnostic(InapplicableWrongReceiver) } } BOTH_RECEIVERS -> { if (explicitReceiver == null) { - return sink.yieldApplicability(CandidateApplicability.INAPPLICABLE_WRONG_RECEIVER) + return sink.yieldDiagnostic(InapplicableWrongReceiver) } // Here we should also check additional invoke receiver } @@ -152,20 +149,14 @@ private fun FirExpression.isSuperReferenceExpression(): Boolean { internal object MapArguments : ResolutionStage() { override suspend fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) { - val symbol = candidate.symbol as? FirFunctionSymbol<*> ?: return sink.reportApplicability(CandidateApplicability.HIDDEN) + val symbol = candidate.symbol as? FirFunctionSymbol<*> ?: return sink.reportDiagnostic(HiddenCandidate) val function = symbol.fir val mapping = mapArguments(callInfo.arguments, function) candidate.argumentMapping = mapping.toArgumentToParameterMapping() - var applicability = CandidateApplicability.RESOLVED - mapping.diagnostics.forEach { - candidate.diagnostics += it - applicability = min(applicability, it.applicability) - } - if (applicability < CandidateApplicability.RESOLVED) { - return sink.yieldApplicability(applicability) - } + mapping.diagnostics.forEach(sink::reportDiagnostic) + sink.yieldIfNeed() } } @@ -182,7 +173,7 @@ internal object CheckArguments : CheckerStage() { sink = sink ) if (candidate.system.hasContradiction) { - sink.yieldApplicability(CandidateApplicability.INAPPLICABLE) + sink.yieldDiagnostic(InapplicableCandidate) } sink.yieldIfNeed() } @@ -195,7 +186,7 @@ internal object EagerResolveOfCallableReferences : CheckerStage() { for (atom in candidate.postponedAtoms) { if (atom is ResolvedCallableReferenceAtom) { if (!candidate.bodyResolveComponents.callResolver.resolveCallableReference(candidate.csBuilder, atom)) { - sink.yieldApplicability(CandidateApplicability.INAPPLICABLE) + sink.yieldDiagnostic(InapplicableCandidate) } } } @@ -264,7 +255,7 @@ internal object CheckCallableReferenceExpectedType : CheckerStage() { } if (!isApplicable) { - sink.yieldApplicability(CandidateApplicability.INAPPLICABLE) + sink.yieldDiagnostic(InapplicableCandidate) } } } @@ -366,7 +357,7 @@ private fun FirSession.createAdaptedKFunctionType( internal object DiscriminateSynthetics : CheckerStage() { override suspend fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) { if (candidate.symbol is SyntheticSymbol) { - sink.reportApplicability(CandidateApplicability.RESOLVED_LOW_PRIORITY) + sink.reportDiagnostic(ResolvedWithLowPriority) } } } @@ -389,7 +380,7 @@ internal object CheckVisibility : CheckerStage() { if (classSymbol is FirRegularClassSymbol) { if (classSymbol.fir.classKind.isSingleton) { - sink.yieldApplicability(CandidateApplicability.HIDDEN) + sink.yieldDiagnostic(HiddenCandidate) } checkVisibility(classSymbol.fir, classSymbol, sink, candidate, visibilityChecker) } @@ -404,7 +395,7 @@ internal object CheckVisibility : CheckerStage() { visibilityChecker: FirVisibilityChecker ): Boolean { if (!visibilityChecker.isVisible(declaration, symbol, candidate)) { - sink.yieldApplicability(CandidateApplicability.HIDDEN) + sink.yieldDiagnostic(HiddenCandidate) return false } return true @@ -428,7 +419,7 @@ internal object CheckLowPriorityInOverloadResolution : CheckerStage() { } if (hasLowPriorityAnnotation) { - sink.reportApplicability(CandidateApplicability.RESOLVED_LOW_PRIORITY) + sink.reportDiagnostic(ResolvedWithLowPriority) } } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/TypeArgumentMapping.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/TypeArgumentMapping.kt index fa94f3ea348..1cc970118bf 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/TypeArgumentMapping.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/TypeArgumentMapping.kt @@ -8,7 +8,6 @@ package org.jetbrains.kotlin.fir.resolve.calls import org.jetbrains.kotlin.fir.declarations.FirTypeParameterRefsOwner import org.jetbrains.kotlin.fir.types.FirTypeProjection import org.jetbrains.kotlin.fir.types.impl.FirTypePlaceholderProjection -import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability sealed class TypeArgumentMapping { abstract operator fun get(typeParameterIndex: Int): FirTypeProjection @@ -38,7 +37,7 @@ internal object MapTypeArguments : ResolutionStage() { candidate.typeArgumentMapping = TypeArgumentMapping.Mapped(typeArguments) } else { candidate.typeArgumentMapping = TypeArgumentMapping.Mapped(emptyList()) - sink.yieldApplicability(CandidateApplicability.INAPPLICABLE) + sink.yieldDiagnostic(InapplicableCandidate) } } } @@ -46,7 +45,7 @@ internal object MapTypeArguments : ResolutionStage() { internal object NoTypeArguments : ResolutionStage() { override suspend fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) { if (callInfo.typeArguments.isNotEmpty()) { - sink.yieldApplicability(CandidateApplicability.INAPPLICABLE) + sink.yieldDiagnostic(InapplicableCandidate) } candidate.typeArgumentMapping = TypeArgumentMapping.NoExplicitArguments }