[FIR] Resolve infix calls to infix functions only

Implements INFIX_MODIFIER_REQUIRED diagnostics
This commit is contained in:
Andrey Zinovyev
2021-05-14 15:22:43 +03:00
committed by TeamCityServer
parent df14deb5a0
commit b1c8669b43
46 changed files with 174 additions and 94 deletions
@@ -153,15 +153,28 @@ class FirCallResolver(
towerResolver.reset()
val result = towerResolver.runResolver(info, transformer.resolutionContext)
val bestCandidates = result.bestCandidates()
var reducedCandidates = if (!result.currentApplicability.isSuccess) {
bestCandidates.toSet()
} else {
fun chooseMostSpecific(): Set<Candidate> {
val onSuperReference = (explicitReceiver as? FirQualifiedAccessExpression)?.calleeReference is FirSuperReference
conflictResolver.chooseMaximallySpecificCandidates(
return conflictResolver.chooseMaximallySpecificCandidates(
bestCandidates, discriminateGenerics = true, discriminateAbstracts = onSuperReference
)
}
var reducedCandidates = if (!result.currentApplicability.isSuccess) {
val distinctApplicabilities = bestCandidates.flatMapTo(mutableSetOf()) { candidate ->
candidate.diagnostics.map { it.applicability }
}
//if all candidates have the same kind on inApplicability - try to choose the most specific one
if (distinctApplicabilities.size == 1 && distinctApplicabilities.single() > CandidateApplicability.INAPPLICABLE) {
chooseMostSpecific()
} else {
bestCandidates.toSet()
}
} else {
chooseMostSpecific()
}
reducedCandidates = overloadByLambdaReturnTypeResolver.reduceCandidates(qualifiedAccess, bestCandidates, reducedCandidates)
return ResolutionResult(info, result.currentApplicability, reducedCandidates)
@@ -39,6 +39,7 @@ sealed class CallKind(vararg resolutionSequence: ResolutionStage) {
CheckDispatchReceiver,
CheckExtensionReceiver,
CheckArguments,
CheckInfixCall,
EagerResolveOfCallableReferences,
CheckLowPriorityInOverloadResolution,
PostponedVariablesInitializerResolutionStage
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.fir.declarations.FirFunction
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirNamedArgumentExpression
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.resolve.ForbiddenNamedArgumentsTarget
import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability
@@ -101,4 +102,6 @@ class NullForNotNullType(
class ManyLambdaExpressionArguments(
val argument: FirExpression
) : ResolutionDiagnostic(INAPPLICABLE_ARGUMENTS_MAPPING_ERROR)
) : ResolutionDiagnostic(INAPPLICABLE_ARGUMENTS_MAPPING_ERROR)
class InfixCallOfNonInfixFunction(val function: FirNamedFunctionSymbol) : ResolutionDiagnostic(INAPPLICABLE_MODIFIER)
@@ -9,15 +9,14 @@ import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.fir.FirSymbolOwner
import org.jetbrains.kotlin.fir.FirVisibilityChecker
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.references.FirSuperReference
import org.jetbrains.kotlin.fir.resolve.inference.*
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.symbols.SyntheticSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.*
@@ -267,3 +266,16 @@ internal object PostponedVariablesInitializerResolutionStage : ResolutionStage()
}
}
}
internal object CheckInfixCall : CheckerStage() {
override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) {
if (callInfo.callSite is FirFunctionCall) {
if (callInfo.callSite.origin == FirFunctionCallOrigin.INFIX) {
val functionSymbol = candidate.symbol as? FirNamedFunctionSymbol ?: return
if (!functionSymbol.fir.isInfix) {
sink.reportDiagnostic(InfixCallOfNonInfixFunction(functionSymbol))
}
}
}
}
}
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.builder.FirBuilderDsl
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirArgumentList
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirFunctionCallOrigin
import org.jetbrains.kotlin.fir.expressions.builder.FirCallBuilder
import org.jetbrains.kotlin.fir.expressions.builder.FirExpressionBuilder
import org.jetbrains.kotlin.fir.expressions.builder.FirQualifiedAccessBuilder
@@ -43,6 +44,7 @@ class FirIntegerOperatorCall @FirImplementationDetail constructor(
extensionReceiver,
argumentList,
calleeReference,
FirFunctionCallOrigin.OPERATOR
)
@FirBuilderDsl