[FIR] Fix NO_RECEIVER_ALLOWED
If we do create an implicit invoke call, and then put the receiver into the argument list, we should mark it.
This commit is contained in:
committed by
Space Team
parent
eb11901d43
commit
9b786d35f8
+2
-1
@@ -16,7 +16,6 @@ import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.isLocalMember
|
||||
import org.jetbrains.kotlin.fir.analysis.getChild
|
||||
import org.jetbrains.kotlin.fir.builder.FirSyntaxErrors
|
||||
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.*
|
||||
import org.jetbrains.kotlin.fir.diagnostics.*
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
@@ -301,6 +300,8 @@ private fun mapInapplicableCandidateError(
|
||||
is MultipleContextReceiversApplicableForExtensionReceivers ->
|
||||
FirErrors.AMBIGUOUS_CALL_WITH_IMPLICIT_CONTEXT_RECEIVER.createOn(qualifiedAccessSource ?: source)
|
||||
|
||||
is NoReceiverAllowed -> FirErrors.NO_RECEIVER_ALLOWED.createOn(qualifiedAccessSource ?: source)
|
||||
|
||||
is NoApplicableValueForContextReceiver ->
|
||||
FirErrors.NO_CONTEXT_RECEIVER.createOn(
|
||||
qualifiedAccessSource ?: source,
|
||||
|
||||
+1
@@ -1074,6 +1074,7 @@ abstract class AbstractRawFirBuilder<T>(val baseSession: FirSession, val context
|
||||
arguments.add(receiver)
|
||||
arguments.addAll(firSelector.arguments)
|
||||
}
|
||||
isCallWithExplicitReceiver = true
|
||||
calleeReference = firSelector.calleeReference
|
||||
}
|
||||
} else {
|
||||
|
||||
+18
-4
@@ -76,6 +76,18 @@ internal object CheckExplicitReceiverConsistency : ResolutionStage() {
|
||||
|
||||
object CheckExtensionReceiver : ResolutionStage() {
|
||||
override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) {
|
||||
val callSite = callInfo.callSite
|
||||
|
||||
if (callSite is FirImplicitInvokeCall) {
|
||||
val isInvokeFromExtensionFunctionType = candidate.isInvokeFromExtensionFunctionType
|
||||
val isImplicitInvokeCallWithExplicitReceiver = callSite.isCallWithExplicitReceiver
|
||||
|
||||
// We do allow automatic conversion in the other direction, though
|
||||
if (!isInvokeFromExtensionFunctionType && isImplicitInvokeCallWithExplicitReceiver) {
|
||||
sink.reportDiagnostic(NoReceiverAllowed)
|
||||
}
|
||||
}
|
||||
|
||||
val expectedReceiverType = candidate.getExpectedReceiverType() ?: return
|
||||
val expectedType = candidate.substitutor.substituteOrSelf(expectedReceiverType.type)
|
||||
|
||||
@@ -506,10 +518,7 @@ internal object CheckArguments : CheckerStage() {
|
||||
candidate.symbol.lazyResolveToPhase(FirResolvePhase.STATUS)
|
||||
val argumentMapping =
|
||||
candidate.argumentMapping ?: error("Argument should be already mapped while checking arguments!")
|
||||
|
||||
val isInvokeFromExtensionFunctionType = candidate.explicitReceiverKind == DISPATCH_RECEIVER
|
||||
&& candidate.dispatchReceiver?.resolvedType?.isExtensionFunctionType == true
|
||||
&& (candidate.symbol as? FirNamedFunctionSymbol)?.name == OperatorNameConventions.INVOKE
|
||||
val isInvokeFromExtensionFunctionType = candidate.isInvokeFromExtensionFunctionType
|
||||
|
||||
for ((index, argument) in callInfo.arguments.withIndex()) {
|
||||
candidate.resolveArgument(
|
||||
@@ -543,6 +552,11 @@ internal object CheckArguments : CheckerStage() {
|
||||
}
|
||||
}
|
||||
|
||||
private val Candidate.isInvokeFromExtensionFunctionType: Boolean
|
||||
get() = explicitReceiverKind == DISPATCH_RECEIVER
|
||||
&& dispatchReceiver?.resolvedType?.isExtensionFunctionType == true
|
||||
&& (symbol as? FirNamedFunctionSymbol)?.name == OperatorNameConventions.INVOKE
|
||||
|
||||
internal fun Candidate.shouldHaveLowPriorityDueToSAM(bodyResolveComponents: BodyResolveComponents): Boolean {
|
||||
if (!usesSAM || isJavaApplicableCandidate()) return false
|
||||
return argumentMapping!!.values.any {
|
||||
|
||||
+2
@@ -142,6 +142,8 @@ class DslScopeViolation(val calleeSymbol: FirBasedSymbol<*>) : ResolutionDiagnos
|
||||
|
||||
class MultipleContextReceiversApplicableForExtensionReceivers : ResolutionDiagnostic(INAPPLICABLE)
|
||||
|
||||
object NoReceiverAllowed : ResolutionDiagnostic(INAPPLICABLE)
|
||||
|
||||
class NoApplicableValueForContextReceiver(
|
||||
val expectedContextReceiverType: ConeKotlinType
|
||||
) : ResolutionDiagnostic(INAPPLICABLE)
|
||||
|
||||
@@ -36,6 +36,7 @@ abstract class FirImplicitInvokeCall : FirFunctionCall() {
|
||||
abstract override val argumentList: FirArgumentList
|
||||
abstract override val calleeReference: FirNamedReference
|
||||
abstract override val origin: FirFunctionCallOrigin
|
||||
abstract val isCallWithExplicitReceiver: Boolean
|
||||
|
||||
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R =
|
||||
visitor.visitImplicitInvokeCall(this, data)
|
||||
|
||||
+2
@@ -35,6 +35,7 @@ open class FirImplicitInvokeCallBuilder : FirAbstractFunctionCallBuilder, FirAnn
|
||||
override val nonFatalDiagnostics: MutableList<ConeDiagnostic> = mutableListOf()
|
||||
override var argumentList: FirArgumentList = FirEmptyArgumentList
|
||||
override lateinit var calleeReference: FirNamedReference
|
||||
open var isCallWithExplicitReceiver: Boolean = false
|
||||
|
||||
override fun build(): FirImplicitInvokeCall {
|
||||
return FirImplicitInvokeCallImpl(
|
||||
@@ -49,6 +50,7 @@ open class FirImplicitInvokeCallBuilder : FirAbstractFunctionCallBuilder, FirAnn
|
||||
nonFatalDiagnostics.toMutableOrEmpty(),
|
||||
argumentList,
|
||||
calleeReference,
|
||||
isCallWithExplicitReceiver,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -38,6 +38,7 @@ internal class FirImplicitInvokeCallImpl(
|
||||
override var nonFatalDiagnostics: MutableOrEmptyList<ConeDiagnostic>,
|
||||
override var argumentList: FirArgumentList,
|
||||
override var calleeReference: FirNamedReference,
|
||||
override val isCallWithExplicitReceiver: Boolean,
|
||||
) : FirImplicitInvokeCall() {
|
||||
override val origin: FirFunctionCallOrigin = FirFunctionCallOrigin.Operator
|
||||
|
||||
|
||||
+4
-1
@@ -227,7 +227,10 @@ object BuilderConfigurator : AbstractFirBuilderConfigurator<FirTreeBuilder>(FirT
|
||||
}
|
||||
}
|
||||
builder(integerLiteralOperatorCall, config = configurationForFunctionCallBuilder)
|
||||
builder(implicitInvokeCall, config = configurationForFunctionCallBuilder)
|
||||
builder(implicitInvokeCall) {
|
||||
configurationForFunctionCallBuilder()
|
||||
defaultFalse("isCallWithExplicitReceiver")
|
||||
}
|
||||
|
||||
builder(getClassCall) {
|
||||
parents += callBuilder
|
||||
|
||||
+4
@@ -408,6 +408,10 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
|
||||
shouldBeAnInterface()
|
||||
}
|
||||
|
||||
implicitInvokeCall.configure {
|
||||
+booleanField("isCallWithExplicitReceiver")
|
||||
}
|
||||
|
||||
constructor.configure {
|
||||
+annotations
|
||||
+symbol("FirConstructorSymbol")
|
||||
|
||||
+1
-1
@@ -30,5 +30,5 @@ fun rain() {
|
||||
|
||||
5.(<!UNRESOLVED_REFERENCE!>::<!UNRESOLVED_REFERENCE!>x<!><!>)().inv()
|
||||
|
||||
5.(Int::x)().inv()
|
||||
<!NO_RECEIVER_ALLOWED!>5.(Int::x)()<!>.inv()
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
// ISSUE: KT-64891
|
||||
|
||||
fun test(f: (Int) -> Int) {
|
||||
2.(f)()
|
||||
<!NO_RECEIVER_ALLOWED!>2.(f)()<!>
|
||||
}
|
||||
Vendored
+1
-1
@@ -7,5 +7,5 @@ fun test1(f: String.() -> Unit) {
|
||||
fun test2(f: (Int) -> Int) {
|
||||
1.<!UNRESOLVED_REFERENCE!>f<!>(2)
|
||||
|
||||
2.(f)(<!TOO_MANY_ARGUMENTS!>2<!>)
|
||||
<!NO_RECEIVER_ALLOWED!>2.(f)(<!TOO_MANY_ARGUMENTS!>2<!>)<!>
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user