FIR: Rework receivers processing in resolution

- Put extensionReceiver to candidate even if it's explicit (for sake of clarity)
- Split CheckReceiver (dispatch part should only check nullability)
This commit is contained in:
Denis Zharkov
2020-11-15 13:10:54 +03:00
parent e2099a0307
commit f97cc0b62d
40 changed files with 194 additions and 213 deletions
@@ -0,0 +1,16 @@
interface A {
val list: List<String>
}
interface B {
val list: MutableList<String>
}
fun B.foo(a: A?) {
list.plusAssign(mutableListOf(""))
with(a) {
list.plusAssign(mutableListOf(""))
list += mutableListOf("")
}
}
@@ -0,0 +1,19 @@
FILE: plusAssignNullable.kt
public abstract interface A : R|kotlin/Any| {
public abstract val list: R|kotlin/collections/List<kotlin/String>|
public get(): R|kotlin/collections/List<kotlin/String>|
}
public abstract interface B : R|kotlin/Any| {
public abstract val list: R|kotlin/collections/MutableList<kotlin/String>|
public get(): R|kotlin/collections/MutableList<kotlin/String>|
}
public final fun R|B|.foo(a: R|A?|): R|kotlin/Unit| {
this@R|/foo|.R|/B.list|.R|kotlin/collections/plusAssign|<R|kotlin/String|>(R|kotlin/collections/mutableListOf|<R|kotlin/String|>(vararg(String())))
R|kotlin/with|<R|A?|, R|kotlin/Unit|>(R|<local>/a|, <L> = with@fun R|A?|.<anonymous>(): R|kotlin/Unit| <kind=EXACTLY_ONCE> {
this@R|/foo|.R|/B.list|.R|kotlin/collections/plusAssign|<R|kotlin/String|>(R|kotlin/collections/mutableListOf|<R|kotlin/String|>(vararg(String())))
this@R|/foo|.R|/B.list|.R|kotlin/collections/plusAssign|<R|kotlin/String|>(R|kotlin/collections/mutableListOf|<R|kotlin/String|>(vararg(String())))
}
)
}
@@ -208,6 +208,11 @@ public class FirDiagnosticsWithStdlibTestGenerated extends AbstractFirDiagnostic
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/nullableTypeParameter.kt"); runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/nullableTypeParameter.kt");
} }
@TestMetadata("plusAssignNullable.kt")
public void testPlusAssignNullable() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/plusAssignNullable.kt");
}
@TestMetadata("problems.kt") @TestMetadata("problems.kt")
public void testProblems() throws Exception { public void testProblems() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/problems.kt"); runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/problems.kt");
@@ -12,8 +12,8 @@ sealed class CallKind(vararg resolutionSequence: ResolutionStage) {
CheckExplicitReceiverConsistency, CheckExplicitReceiverConsistency,
NoTypeArguments, NoTypeArguments,
CreateFreshTypeVariableSubstitutorStage, CreateFreshTypeVariableSubstitutorStage,
CheckReceivers.Dispatch, CheckDispatchReceiver,
CheckReceivers.Extension, CheckExtensionReceiver,
CheckLowPriorityInOverloadResolution, CheckLowPriorityInOverloadResolution,
PostponedVariablesInitializerResolutionStage PostponedVariablesInitializerResolutionStage
) )
@@ -33,8 +33,8 @@ sealed class CallKind(vararg resolutionSequence: ResolutionStage) {
CheckExplicitReceiverConsistency, CheckExplicitReceiverConsistency,
MapTypeArguments, MapTypeArguments,
CreateFreshTypeVariableSubstitutorStage, CreateFreshTypeVariableSubstitutorStage,
CheckReceivers.Dispatch, CheckDispatchReceiver,
CheckReceivers.Extension, CheckExtensionReceiver,
CheckArguments, CheckArguments,
EagerResolveOfCallableReferences, EagerResolveOfCallableReferences,
CheckLowPriorityInOverloadResolution, CheckLowPriorityInOverloadResolution,
@@ -47,8 +47,8 @@ sealed class CallKind(vararg resolutionSequence: ResolutionStage) {
CheckExplicitReceiverConsistency, CheckExplicitReceiverConsistency,
MapTypeArguments, MapTypeArguments,
CreateFreshTypeVariableSubstitutorStage, CreateFreshTypeVariableSubstitutorStage,
CheckReceivers.Dispatch, CheckDispatchReceiver,
CheckReceivers.Extension, CheckExtensionReceiver,
CheckArguments, CheckArguments,
EagerResolveOfCallableReferences EagerResolveOfCallableReferences
) )
@@ -58,8 +58,8 @@ sealed class CallKind(vararg resolutionSequence: ResolutionStage) {
DiscriminateSynthetics, DiscriminateSynthetics,
NoTypeArguments, NoTypeArguments,
CreateFreshTypeVariableSubstitutorStage, CreateFreshTypeVariableSubstitutorStage,
CheckReceivers.Dispatch, CheckDispatchReceiver,
CheckReceivers.Extension, CheckExtensionReceiver,
CheckCallableReferenceExpectedType, CheckCallableReferenceExpectedType,
CheckLowPriorityInOverloadResolution CheckLowPriorityInOverloadResolution
) )
@@ -102,8 +102,8 @@ class ResolutionSequenceBuilder(
if (checkExplicitReceiverConsistency) add(CheckExplicitReceiverConsistency) if (checkExplicitReceiverConsistency) add(CheckExplicitReceiverConsistency)
if (mapTypeArguments) add(MapTypeArguments) else add(NoTypeArguments) if (mapTypeArguments) add(MapTypeArguments) else add(NoTypeArguments)
if (checkArguments || checkDispatchReceiver || checkExtensionReceiver) add(CreateFreshTypeVariableSubstitutorStage) if (checkArguments || checkDispatchReceiver || checkExtensionReceiver) add(CreateFreshTypeVariableSubstitutorStage)
if (checkDispatchReceiver) add(CheckReceivers.Dispatch) if (checkDispatchReceiver) add(CheckDispatchReceiver)
if (checkExtensionReceiver) add(CheckReceivers.Extension) if (checkExtensionReceiver) add(CheckExtensionReceiver)
if (checkArguments) add(CheckArguments) if (checkArguments) add(CheckArguments)
if (resolveCallableReferenceArguments) add(EagerResolveOfCallableReferences) if (resolveCallableReferenceArguments) add(EagerResolveOfCallableReferences)
if (checkLowPriorityInOverloadResolution) add(CheckLowPriorityInOverloadResolution) if (checkLowPriorityInOverloadResolution) add(CheckLowPriorityInOverloadResolution)
@@ -15,7 +15,6 @@ import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.builder.buildArgumentList import org.jetbrains.kotlin.fir.expressions.builder.buildArgumentList
import org.jetbrains.kotlin.fir.expressions.impl.FirExpressionStub import org.jetbrains.kotlin.fir.expressions.impl.FirExpressionStub
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression 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.DoubleColonLHS
import org.jetbrains.kotlin.fir.resolve.inference.InferenceComponents import org.jetbrains.kotlin.fir.resolve.inference.InferenceComponents
import org.jetbrains.kotlin.fir.resolve.inference.PostponedResolvedAtom import org.jetbrains.kotlin.fir.resolve.inference.PostponedResolvedAtom
@@ -81,7 +80,7 @@ data class CallInfo(
class Candidate( class Candidate(
val symbol: AbstractFirBasedSymbol<*>, val symbol: AbstractFirBasedSymbol<*>,
val dispatchReceiverValue: ReceiverValue?, val dispatchReceiverValue: ReceiverValue?,
val implicitExtensionReceiverValue: ImplicitReceiverValue<*>?, val extensionReceiverValue: ReceiverValue?,
val explicitReceiverKind: ExplicitReceiverKind, val explicitReceiverKind: ExplicitReceiverKind,
val constraintSystemFactory: InferenceComponents.ConstraintSystemFactory, val constraintSystemFactory: InferenceComponents.ConstraintSystemFactory,
private val baseSystem: ConstraintStorage, private val baseSystem: ConstraintStorage,
@@ -128,18 +127,11 @@ class Candidate(
var passedStages: Int = 0 var passedStages: Int = 0
fun dispatchReceiverExpression(): FirExpression = when (explicitReceiverKind) { fun dispatchReceiverExpression(): FirExpression =
ExplicitReceiverKind.DISPATCH_RECEIVER, ExplicitReceiverKind.BOTH_RECEIVERS -> dispatchReceiverValue?.receiverExpression?.takeIf { it !is FirExpressionStub } ?: FirNoReceiverExpression
callInfo.explicitReceiver?.takeIf { it !is FirExpressionStub } ?: FirNoReceiverExpression
else -> dispatchReceiverValue?.receiverExpression ?: FirNoReceiverExpression
}
fun extensionReceiverExpression(): FirExpression = when (explicitReceiverKind) { fun extensionReceiverExpression(): FirExpression =
ExplicitReceiverKind.EXTENSION_RECEIVER, ExplicitReceiverKind.BOTH_RECEIVERS -> extensionReceiverValue?.receiverExpression?.takeIf { it !is FirExpressionStub } ?: FirNoReceiverExpression
callInfo.explicitReceiver?.takeIf { it !is FirExpressionStub } ?: FirNoReceiverExpression
else ->
implicitExtensionReceiverValue?.receiverExpression ?: FirNoReceiverExpression
}
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
@@ -52,11 +52,11 @@ class CandidateFactory private constructor(
explicitReceiverKind: ExplicitReceiverKind, explicitReceiverKind: ExplicitReceiverKind,
scope: FirScope?, scope: FirScope?,
dispatchReceiverValue: ReceiverValue? = null, dispatchReceiverValue: ReceiverValue? = null,
implicitExtensionReceiverValue: ImplicitReceiverValue<*>? = null, extensionReceiverValue: ReceiverValue? = null,
builtInExtensionFunctionReceiverValue: ReceiverValue? = null builtInExtensionFunctionReceiverValue: ReceiverValue? = null
): Candidate { ): Candidate {
return Candidate( return Candidate(
symbol, dispatchReceiverValue, implicitExtensionReceiverValue, symbol, dispatchReceiverValue, extensionReceiverValue,
explicitReceiverKind, context.inferenceComponents.constraintSystemFactory, baseSystem, explicitReceiverKind, context.inferenceComponents.constraintSystemFactory, baseSystem,
builtInExtensionFunctionReceiverValue?.receiverExpression?.let { builtInExtensionFunctionReceiverValue?.receiverExpression?.let {
callInfo.withReceiverAsArgument(it) callInfo.withReceiverAsArgument(it)
@@ -78,7 +78,7 @@ class CandidateFactory private constructor(
return Candidate( return Candidate(
symbol, symbol,
dispatchReceiverValue = null, dispatchReceiverValue = null,
implicitExtensionReceiverValue = null, extensionReceiverValue = null,
explicitReceiverKind = ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, explicitReceiverKind = ExplicitReceiverKind.NO_EXPLICIT_RECEIVER,
context.inferenceComponents.constraintSystemFactory, context.inferenceComponents.constraintSystemFactory,
baseSystem, baseSystem,
@@ -22,8 +22,11 @@ import org.jetbrains.kotlin.fir.scopes.FirTypeScope
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.ConeKotlinErrorType
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.coneTypeSafe
interface Receiver interface Receiver
@@ -51,7 +54,7 @@ abstract class AbstractExplicitReceiverValue<E : FirExpression> : AbstractExplic
get() = explicitReceiver get() = explicitReceiver
} }
internal class ExpressionReceiverValue( class ExpressionReceiverValue(
override val explicitReceiver: FirExpression override val explicitReceiver: FirExpression
) : AbstractExplicitReceiverValue<FirExpression>(), ReceiverValue ) : AbstractExplicitReceiverValue<FirExpression>(), ReceiverValue
@@ -22,8 +22,8 @@ import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.* import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.*
import org.jetbrains.kotlin.types.AbstractNullabilityChecker
abstract class ResolutionStage { abstract class ResolutionStage {
abstract suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) abstract suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext)
@@ -57,52 +57,44 @@ internal object CheckExplicitReceiverConsistency : ResolutionStage() {
} }
} }
internal sealed class CheckReceivers : ResolutionStage() { object CheckExtensionReceiver : ResolutionStage() {
object Dispatch : CheckReceivers() {
override fun ExplicitReceiverKind.shouldBeCheckedAgainstImplicit(): Boolean {
return this == EXTENSION_RECEIVER // For NO_EXPLICIT_RECEIVER we can check extension receiver only
}
override fun ExplicitReceiverKind.shouldBeCheckedAgainstExplicit(): Boolean {
return this == DISPATCH_RECEIVER || this == BOTH_RECEIVERS
}
override fun Candidate.getReceiverType(context: ResolutionContext): ConeKotlinType? {
return dispatchReceiverValue?.type
}
}
object Extension : CheckReceivers() {
override fun ExplicitReceiverKind.shouldBeCheckedAgainstImplicit(): Boolean {
return this == DISPATCH_RECEIVER || this == NO_EXPLICIT_RECEIVER
}
override fun ExplicitReceiverKind.shouldBeCheckedAgainstExplicit(): Boolean {
return this == EXTENSION_RECEIVER || this == BOTH_RECEIVERS
}
override fun Candidate.getReceiverType(context: ResolutionContext): ConeKotlinType? {
val callableSymbol = symbol as? FirCallableSymbol<*> ?: return null
val callable = callableSymbol.fir
val receiverType = callable.receiverTypeRef?.coneType
if (receiverType != null) return receiverType
val returnTypeRef = callable.returnTypeRef as? FirResolvedTypeRef ?: return null
if (!returnTypeRef.type.isExtensionFunctionType(context.session)) return null
return (returnTypeRef.type.typeArguments.firstOrNull() as? ConeKotlinTypeProjection)?.type
}
}
abstract fun Candidate.getReceiverType(context: ResolutionContext): ConeKotlinType?
abstract fun ExplicitReceiverKind.shouldBeCheckedAgainstExplicit(): Boolean
abstract fun ExplicitReceiverKind.shouldBeCheckedAgainstImplicit(): Boolean
override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) { override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) {
val expectedReceiverType = candidate.getReceiverType(context) val expectedReceiverType = candidate.getReceiverType(context) ?: return
val explicitReceiverExpression = callInfo.explicitReceiver
val explicitReceiverKind = candidate.explicitReceiverKind
val argumentExtensionReceiverValue = candidate.extensionReceiverValue ?: return
val expectedType = candidate.substitutor.substituteOrSelf(expectedReceiverType.type)
val argumentType = captureFromTypeParameterUpperBoundIfNeeded(
argumentType = argumentExtensionReceiverValue.type,
expectedType = expectedType,
session = context.session
)
candidate.resolvePlainArgumentType(
candidate.csBuilder,
argumentType = argumentType,
expectedType = expectedType,
sink = sink,
context = context,
isReceiver = true,
isDispatch = false,
)
sink.yieldIfNeed()
}
private fun Candidate.getReceiverType(context: ResolutionContext): ConeKotlinType? {
val callableSymbol = symbol as? FirCallableSymbol<*> ?: return null
val callable = callableSymbol.fir
val receiverType = callable.receiverTypeRef?.coneType
if (receiverType != null) return receiverType
val returnTypeRef = callable.returnTypeRef as? FirResolvedTypeRef ?: return null
if (!returnTypeRef.type.isExtensionFunctionType(context.session)) return null
return (returnTypeRef.type.typeArguments.firstOrNull() as? ConeKotlinTypeProjection)?.type
}
}
object CheckDispatchReceiver : ResolutionStage() {
override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) {
val explicitReceiverExpression = callInfo.explicitReceiver
if (explicitReceiverExpression.isSuperCall()) { if (explicitReceiverExpression.isSuperCall()) {
val status = candidate.symbol.fir as? FirMemberDeclaration val status = candidate.symbol.fir as? FirMemberDeclaration
if (status?.modality == Modality.ABSTRACT) { if (status?.modality == Modality.ABSTRACT) {
@@ -110,49 +102,17 @@ internal sealed class CheckReceivers : ResolutionStage() {
} }
} }
if (expectedReceiverType != null) { val dispatchReceiverValueType = candidate.dispatchReceiverValue?.type ?: return
if (explicitReceiverExpression != null &&
explicitReceiverKind.shouldBeCheckedAgainstExplicit() && if (!AbstractNullabilityChecker.isSubtypeOfAny(context.session.typeContext, dispatchReceiverValueType)) {
!explicitReceiverExpression.isSuperReferenceExpression() sink.yieldDiagnostic(InapplicableWrongReceiver)
) {
candidate.resolvePlainExpressionArgument(
candidate.csBuilder,
argument = explicitReceiverExpression,
expectedType = candidate.substitutor.substituteOrSelf(expectedReceiverType),
sink = sink,
context = context,
isReceiver = true,
isDispatch = this is Dispatch
)
sink.yieldIfNeed()
} else {
val argumentExtensionReceiverValue = candidate.implicitExtensionReceiverValue
if (argumentExtensionReceiverValue != null && explicitReceiverKind.shouldBeCheckedAgainstImplicit()) {
val expectedType = candidate.substitutor.substituteOrSelf(expectedReceiverType.type)
val argumentType = captureFromTypeParameterUpperBoundIfNeeded(
argumentType = argumentExtensionReceiverValue.type,
expectedType = expectedType,
session = context.session
)
candidate.resolvePlainArgumentType(
candidate.csBuilder,
argumentType = argumentType,
expectedType = expectedType,
sink = sink,
context = context,
isReceiver = true,
isDispatch = this is Dispatch
)
sink.yieldIfNeed()
}
}
} }
} }
}
private fun FirExpression?.isSuperCall(): Boolean { private fun FirExpression?.isSuperCall(): Boolean {
if (this !is FirQualifiedAccessExpression) return false if (this !is FirQualifiedAccessExpression) return false
return calleeReference is FirSuperReference return calleeReference is FirSuperReference
}
} }
private fun FirExpression.isSuperReferenceExpression(): Boolean { private fun FirExpression.isSuperReferenceExpression(): Boolean {
@@ -65,9 +65,8 @@ class FirTowerResolver(
} }
else -> { else -> {
if (receiver is FirQualifiedAccessExpression) { if (receiver is FirQualifiedAccessExpression) {
val calleeReference = receiver.calleeReference if (receiver.calleeReference is FirSuperReference) {
if (calleeReference is FirSuperReference) { manager.enqueueResolverTask { mainTask.runResolverForSuperReceiver(info, receiver) }
manager.enqueueResolverTask { mainTask.runResolverForSuperReceiver(info, receiver.typeRef) }
return return
} }
} }
@@ -108,7 +107,7 @@ class FirTowerResolver(
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER,
scope, scope,
dispatchReceiver, dispatchReceiver,
implicitExtensionReceiverValue = null, extensionReceiverValue = null,
builtInExtensionFunctionReceiverValue = null builtInExtensionFunctionReceiverValue = null
), ),
context context
@@ -14,7 +14,10 @@ import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.typeContext import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.ConeStarProjection
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.constructClassType
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
@@ -68,19 +71,13 @@ internal class TowerLevelHandler {
CallKind.CallableReference -> { CallKind.CallableReference -> {
val stubReceiver = info.stubReceiver val stubReceiver = info.stubReceiver
if (stubReceiver != null) { if (stubReceiver != null) {
val stubReceiverValue = ExpressionReceiverValue(stubReceiver)
val stubProcessor = TowerScopeLevelProcessor( val stubProcessor = TowerScopeLevelProcessor(
info.explicitReceiver, info.explicitReceiver,
if (towerLevel is MemberScopeTowerLevel && towerLevel.dispatchReceiver is AbstractExplicitReceiver<*>) { explicitReceiverKind,
ExplicitReceiverKind.DISPATCH_RECEIVER
} else {
ExplicitReceiverKind.EXTENSION_RECEIVER
},
collector, collector,
stubReceiverCandidateFactory!!, group stubReceiverCandidateFactory!!, group
) )
val towerLevelWithStubReceiver = towerLevel.replaceReceiverValue(stubReceiverValue) towerLevel.processFunctionsAndProperties(info.name, stubProcessor)
towerLevelWithStubReceiver.processFunctionsAndProperties(info.name, stubProcessor)
// NB: we don't perform this for implicit Unit // NB: we don't perform this for implicit Unit
if (!collector.isSuccess() && info.explicitReceiver?.typeRef !is FirImplicitBuiltinTypeRef) { if (!collector.isSuccess() && info.explicitReceiver?.typeRef !is FirImplicitBuiltinTypeRef) {
towerLevel.processFunctionsAndProperties(info.name, processor) towerLevel.processFunctionsAndProperties(info.name, processor)
@@ -147,18 +144,17 @@ private class TowerScopeLevelProcessor(
override fun consumeCandidate( override fun consumeCandidate(
symbol: AbstractFirBasedSymbol<*>, symbol: AbstractFirBasedSymbol<*>,
dispatchReceiverValue: ReceiverValue?, dispatchReceiverValue: ReceiverValue?,
implicitExtensionReceiverValue: ImplicitReceiverValue<*>?, extensionReceiverValue: ReceiverValue?,
scope: FirScope, scope: FirScope,
builtInExtensionFunctionReceiverValue: ReceiverValue? builtInExtensionFunctionReceiverValue: ReceiverValue?
) { ) {
// Check explicit extension receiver for default package members // Check explicit extension receiver for default package members
if (symbol is FirNamedFunctionSymbol && dispatchReceiverValue == null && if (symbol is FirNamedFunctionSymbol && dispatchReceiverValue == null &&
(implicitExtensionReceiverValue == null) != (explicitReceiver == null) && extensionReceiverValue != null &&
explicitReceiver !is FirResolvedQualifier && explicitReceiver !is FirResolvedQualifier &&
symbol.callableId.packageName.startsWith(defaultPackage) symbol.callableId.packageName.startsWith(defaultPackage)
) { ) {
val extensionReceiverType = explicitReceiver?.typeRef?.coneTypeSafe() val extensionReceiverType = extensionReceiverValue.type as? ConeClassLikeType
?: implicitExtensionReceiverValue?.type as? ConeClassLikeType
if (extensionReceiverType != null) { if (extensionReceiverType != null) {
val declarationReceiverType = (symbol as? FirCallableSymbol<*>)?.fir?.receiverTypeRef?.coneType val declarationReceiverType = (symbol as? FirCallableSymbol<*>)?.fir?.receiverTypeRef?.coneType
if (declarationReceiverType is ConeClassLikeType) { if (declarationReceiverType is ConeClassLikeType) {
@@ -183,7 +179,7 @@ private class TowerScopeLevelProcessor(
explicitReceiverKind, explicitReceiverKind,
scope, scope,
dispatchReceiverValue, dispatchReceiverValue,
implicitExtensionReceiverValue, extensionReceiverValue,
builtInExtensionFunctionReceiverValue builtInExtensionFunctionReceiverValue
), candidateFactory.context ), candidateFactory.context
) )
@@ -9,7 +9,6 @@ import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirConstructor import org.jetbrains.kotlin.fir.declarations.FirConstructor
import org.jetbrains.kotlin.fir.declarations.isInner import org.jetbrains.kotlin.fir.declarations.isInner
import org.jetbrains.kotlin.fir.dispatchReceiverClassOrNull import org.jetbrains.kotlin.fir.dispatchReceiverClassOrNull
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.builder.buildResolvedQualifier import org.jetbrains.kotlin.fir.expressions.builder.buildResolvedQualifier
import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.calls.* import org.jetbrains.kotlin.fir.resolve.calls.*
@@ -21,9 +20,6 @@ import org.jetbrains.kotlin.fir.scopes.processClassifiersByName
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.ConeClassLikeType import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.ConeNullability
import org.jetbrains.kotlin.fir.types.withNullability
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
@@ -45,7 +41,7 @@ interface TowerScopeLevel {
fun consumeCandidate( fun consumeCandidate(
symbol: T, symbol: T,
dispatchReceiverValue: ReceiverValue?, dispatchReceiverValue: ReceiverValue?,
implicitExtensionReceiverValue: ImplicitReceiverValue<*>?, extensionReceiverValue: ReceiverValue?,
scope: FirScope, scope: FirScope,
builtInExtensionFunctionReceiverValue: ReceiverValue? = null builtInExtensionFunctionReceiverValue: ReceiverValue? = null
) )
@@ -69,7 +65,7 @@ abstract class SessionBasedTowerLevel(val session: FirSession) : TowerScopeLevel
class MemberScopeTowerLevel( class MemberScopeTowerLevel(
session: FirSession, session: FirSession,
private val bodyResolveComponents: BodyResolveComponents, private val bodyResolveComponents: BodyResolveComponents,
val dispatchReceiver: ReceiverValue, val dispatchReceiverValue: ReceiverValue,
private val extensionReceiver: ReceiverValue? = null, private val extensionReceiver: ReceiverValue? = null,
private val implicitExtensionInvokeMode: Boolean = false, private val implicitExtensionInvokeMode: Boolean = false,
private val scopeSession: ScopeSession private val scopeSession: ScopeSession
@@ -79,7 +75,7 @@ class MemberScopeTowerLevel(
processScopeMembers: FirScope.(processor: (T) -> Unit) -> Unit processScopeMembers: FirScope.(processor: (T) -> Unit) -> Unit
): ProcessorAction { ): ProcessorAction {
var empty = true var empty = true
val scope = dispatchReceiver.scope(session, scopeSession) ?: return ProcessorAction.NONE val scope = dispatchReceiverValue.scope(session, scopeSession) ?: return ProcessorAction.NONE
scope.processScopeMembers { candidate -> scope.processScopeMembers { candidate ->
empty = false empty = false
if (candidate is FirCallableSymbol<*> && if (candidate is FirCallableSymbol<*> &&
@@ -89,24 +85,23 @@ class MemberScopeTowerLevel(
if ((fir as? FirConstructor)?.isInner == false) { if ((fir as? FirConstructor)?.isInner == false) {
return@processScopeMembers return@processScopeMembers
} }
val dispatchReceiverValue = NotNullableReceiverValue(dispatchReceiver)
output.consumeCandidate( output.consumeCandidate(
candidate, dispatchReceiverValue, candidate, dispatchReceiverValue,
implicitExtensionReceiverValue = extensionReceiver as? ImplicitReceiverValue<*>, extensionReceiverValue = extensionReceiver,
scope scope
) )
if (implicitExtensionInvokeMode) { if (implicitExtensionInvokeMode) {
output.consumeCandidate( output.consumeCandidate(
candidate, dispatchReceiverValue, candidate, dispatchReceiverValue,
implicitExtensionReceiverValue = null, extensionReceiverValue = null,
scope, scope,
builtInExtensionFunctionReceiverValue = this.extensionReceiver builtInExtensionFunctionReceiverValue = this.extensionReceiver
) )
} }
} else if (candidate is FirClassLikeSymbol<*>) { } else if (candidate is FirClassLikeSymbol<*>) {
output.consumeCandidate(candidate, null, extensionReceiver as? ImplicitReceiverValue<*>, scope) output.consumeCandidate(candidate, null, extensionReceiver, scope)
} }
} }
@@ -114,7 +109,7 @@ class MemberScopeTowerLevel(
val withSynthetic = FirSyntheticPropertiesScope(session, scope) val withSynthetic = FirSyntheticPropertiesScope(session, scope)
withSynthetic.processScopeMembers { symbol -> withSynthetic.processScopeMembers { symbol ->
empty = false empty = false
output.consumeCandidate(symbol, NotNullableReceiverValue(dispatchReceiver), null, scope) output.consumeCandidate(symbol, dispatchReceiverValue, null, scope)
} }
} }
return if (empty) ProcessorAction.NONE else ProcessorAction.NEXT return if (empty) ProcessorAction.NONE else ProcessorAction.NEXT
@@ -221,7 +216,7 @@ class ScopeTowerLevel(
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
processor.consumeCandidate( processor.consumeCandidate(
unwrappedCandidate as T, dispatchReceiverValue, unwrappedCandidate as T, dispatchReceiverValue,
implicitExtensionReceiverValue = extensionReceiver as? ImplicitReceiverValue<*>, extensionReceiverValue = extensionReceiver,
scope scope
) )
} }
@@ -252,7 +247,7 @@ class ScopeTowerLevel(
empty = false empty = false
processor.consumeCandidate( processor.consumeCandidate(
it as T, dispatchReceiverValue = null, it as T, dispatchReceiverValue = null,
implicitExtensionReceiverValue = null, extensionReceiverValue = null,
scope = scope scope = scope
) )
} }
@@ -261,13 +256,6 @@ class ScopeTowerLevel(
} }
} }
class NotNullableReceiverValue(val value: ReceiverValue) : ReceiverValue {
override val type: ConeKotlinType
get() = value.type.withNullability(ConeNullability.NOT_NULL)
override val receiverExpression: FirExpression
get() = value.receiverExpression
}
private fun FirCallableSymbol<*>.hasExtensionReceiver(): Boolean { private fun FirCallableSymbol<*>.hasExtensionReceiver(): Boolean {
return fir.receiverTypeRef != null return fir.receiverTypeRef != null
} }
@@ -1,6 +1,5 @@
// !LANGUAGE: +InlineClasses // !LANGUAGE: +InlineClasses
// IGNORE_BACKEND: JVM // IGNORE_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_LIGHT_ANALYSIS // IGNORE_LIGHT_ANALYSIS
inline class IC(val x: String) inline class IC(val x: String)
@@ -7,8 +7,8 @@ public interface J {
// FILE: test.kt // FILE: test.kt
fun f1(x: Int?): Any = <!UNRESOLVED_REFERENCE!>x::hashCode<!> fun f1(x: Int?): Any = <!UNRESOLVED_REFERENCE!>x::hashCode<!>
fun <T> f2(t: T): Any = t::hashCode fun <T> f2(t: T): Any = <!UNRESOLVED_REFERENCE!>t::hashCode<!>
fun <S : String?> f3(s: S): Any = s::hashCode fun <S : String?> f3(s: S): Any = <!UNRESOLVED_REFERENCE!>s::hashCode<!>
fun <U : Any> f4(u: U?): Any = <!UNRESOLVED_REFERENCE!>u::hashCode<!> fun <U : Any> f4(u: U?): Any = <!UNRESOLVED_REFERENCE!>u::hashCode<!>
fun f5(c: List<*>): Any = <!UNRESOLVED_REFERENCE!>c[0]::hashCode<!> fun f5(c: List<*>): Any = <!UNRESOLVED_REFERENCE!>c[0]::hashCode<!>
@@ -14,11 +14,11 @@ fun test() {
} }
fun check() { fun check() {
[1, 2] checkType { <!INAPPLICABLE_CANDIDATE!>_<!><Array<Int>>() } [1, 2] <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Array<Int>>() }
[""] checkType { <!INAPPLICABLE_CANDIDATE!>_<!><Array<String>>() } [""] <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Array<String>>() }
val f: IntArray = [1] val f: IntArray = [1]
[f] checkType { <!INAPPLICABLE_CANDIDATE!>_<!><Array<IntArray>>() } [f] <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Array<IntArray>>() }
[1, ""] checkType { <!INAPPLICABLE_CANDIDATE!>_<!><Array<Any>>() } [1, ""] <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><Array<Any>>() }
} }
@@ -11,7 +11,7 @@ fun test() {
const val <T> a3 = 0 const val <T> a3 = 0
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit val <T> a4 = 0<!> <!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit val <T> a4 = 0<!>
val <T> a5 by Delegate<Int>() val <T> a5 by Delegate<Int>()
val <T> a6 by Delegate<<!UNRESOLVED_REFERENCE!>T<!>>() val <T> a6 by <!INAPPLICABLE_CANDIDATE!>Delegate<<!UNRESOLVED_REFERENCE!>T<!>>()<!>
} }
class Delegate<F> { class Delegate<F> {
@@ -11,7 +11,7 @@ fun test() {
const val <T> a3 = 0 const val <T> a3 = 0
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit val <T> a4 = 0<!> <!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit val <T> a4 = 0<!>
val <T> a5 by Delegate<Int>() val <T> a5 by Delegate<Int>()
val <T> a6 by Delegate<<!UNRESOLVED_REFERENCE!>T<!>>() val <T> a6 by <!INAPPLICABLE_CANDIDATE!>Delegate<<!UNRESOLVED_REFERENCE!>T<!>>()<!>
} }
class Delegate<F> { class Delegate<F> {
@@ -5,7 +5,7 @@
import kotlin.reflect.KProperty import kotlin.reflect.KProperty
class B { class B {
val c by <!INAPPLICABLE_CANDIDATE!>Delegate<!>(<!UNRESOLVED_REFERENCE!>ag<!>) val c by <!INAPPLICABLE_CANDIDATE!><!INAPPLICABLE_CANDIDATE!>Delegate<!>(<!UNRESOLVED_REFERENCE!>ag<!>)<!>
} }
class Delegate<T: Any>(val init: T) { class Delegate<T: Any>(val init: T) {
@@ -5,5 +5,5 @@ fun interface Bar {
operator fun Bar.plus(b: Bar): String = invoke() + b.invoke() operator fun Bar.plus(b: Bar): String = invoke() + b.invoke()
fun box(): String { fun box(): String {
return { "O" } + { "K" } return { "O" } <!INAPPLICABLE_CANDIDATE!>+<!> { "K" }
} }
@@ -7,4 +7,4 @@ object Z {
infix fun add(b : Foo.() -> Unit) : Z = Z infix fun add(b : Foo.() -> Unit) : Z = Z
} }
val t2 = Z <!INAPPLICABLE_CANDIDATE!>add<!> { } { } val t2 = Z <!INAPPLICABLE_CANDIDATE!>add<!> <!INAPPLICABLE_CANDIDATE!>{ } { }<!>
@@ -1,6 +1,6 @@
fun <E : String?, T : ((CharSequence) -> Unit)?> foo(x: E, y: T) { fun <E : String?, T : ((CharSequence) -> Unit)?> foo(x: E, y: T) {
if (x != null) { if (x != null) {
y(x) <!INAPPLICABLE_CANDIDATE!>y<!>(x)
} }
if (y != null) { if (y != null) {
@@ -10,4 +10,4 @@ fun <E : String?, T : ((CharSequence) -> Unit)?> foo(x: E, y: T) {
if (x != null && y != null) { if (x != null && y != null) {
y(x) y(x)
} }
} }
@@ -1,6 +1,6 @@
fun <T : Any?> foo(x: T) { fun <T : Any?> foo(x: T) {
if (x is String?) { if (x is String?) {
x.length x.<!INAPPLICABLE_CANDIDATE!>length<!>
if (x != null) { if (x != null) {
x.length x.length
@@ -24,7 +24,7 @@ fun <T : CharSequence?> foo(x: T) {
x?.bar1() x?.bar1()
} }
x.length x.<!INAPPLICABLE_CANDIDATE!>length<!>
if (x is String) { if (x is String) {
x.length x.length
@@ -23,7 +23,7 @@ fun <T : String?> T.foo() {
this?.bar1() this?.bar1()
} }
length <!INAPPLICABLE_CANDIDATE!>length<!>
if (this is String) { if (this is String) {
length length
@@ -33,4 +33,4 @@ fun <T : String?> T.foo() {
bar2() bar2()
bar3() bar3()
} }
} }
@@ -7,7 +7,7 @@ fun CharSequence?.bar2() {}
fun <T : CharSequence> T.bar3() {} fun <T : CharSequence> T.bar3() {}
fun <T : String?> foo(x: T) { fun <T : String?> foo(x: T) {
x.length x.<!INAPPLICABLE_CANDIDATE!>length<!>
x?.length x?.length
if (1 == 1) { if (1 == 1) {
@@ -14,14 +14,14 @@ class A<T> {
fun foo2(a: A<out CharSequence>, b: A<in CharSequence>) { fun foo2(a: A<out CharSequence>, b: A<in CharSequence>) {
a.<!INAPPLICABLE_CANDIDATE!>foo1<!>(Out<CharSequence>()) a.<!INAPPLICABLE_CANDIDATE!>foo1<!>(Out<CharSequence>())
a.foo1<<!UPPER_BOUND_VIOLATED!>Out<CharSequence><!>>(Out()) a.<!INAPPLICABLE_CANDIDATE!>foo1<!><Out<CharSequence>>(Out())
a.foo1(Out()) a.foo1(Out())
a.foo1(Out<Nothing>()) a.foo1(Out<Nothing>())
a.foo2(Inv()) a.foo2(Inv())
a.<!INAPPLICABLE_CANDIDATE!>foo2<!>(Inv<CharSequence>()) a.<!INAPPLICABLE_CANDIDATE!>foo2<!>(Inv<CharSequence>())
a.foo2<<!UPPER_BOUND_VIOLATED!>Inv<CharSequence><!>>(Inv()) a.<!INAPPLICABLE_CANDIDATE!>foo2<!><Inv<CharSequence>>(Inv())
a.foo3(In()) a.foo3(In())
a.foo3(In<CharSequence>()) a.foo3(In<CharSequence>())
@@ -33,11 +33,11 @@ fun foo2(a: A<out CharSequence>, b: A<in CharSequence>) {
b.foo2(Inv()) b.foo2(Inv())
b.<!INAPPLICABLE_CANDIDATE!>foo2<!>(Inv<CharSequence>()) b.<!INAPPLICABLE_CANDIDATE!>foo2<!>(Inv<CharSequence>())
b.foo2<<!UPPER_BOUND_VIOLATED!>Inv<CharSequence><!>>(Inv()) b.<!INAPPLICABLE_CANDIDATE!>foo2<!><Inv<CharSequence>>(Inv())
b.<!INAPPLICABLE_CANDIDATE!>foo3<!>(In<CharSequence>()) b.<!INAPPLICABLE_CANDIDATE!>foo3<!>(In<CharSequence>())
b.foo3<<!UPPER_BOUND_VIOLATED!>In<CharSequence><!>>(In()) b.<!INAPPLICABLE_CANDIDATE!>foo3<!><In<CharSequence>>(In())
b.foo3(In<Any?>()) b.foo3(In<Any?>())
b.foo3(In()) b.foo3(In())
@@ -30,7 +30,7 @@ fun A.test2() {
} }
fun A?.test3() { fun A?.test3() {
foo() // error <!INAPPLICABLE_CANDIDATE!>foo<!>() // error
<!INAPPLICABLE_CANDIDATE!>bar<!>() // error <!INAPPLICABLE_CANDIDATE!>bar<!>() // error
buzz() buzz()
@@ -32,7 +32,7 @@ fun test() {
foo() foo()
} }
with(platformN) { with(platformN) {
foo() <!INAPPLICABLE_CANDIDATE!>foo<!>()
} }
with(platformJ) { with(platformJ) {
foo() foo()
@@ -15,5 +15,5 @@ val test5: List<TNString?> = TODO()
val test6: () -> List<TNString> = TODO() val test6: () -> List<TNString> = TODO()
fun test(x: TNString) { fun test(x: TNString) {
x.hashCode() x.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
} }
@@ -17,7 +17,7 @@ fun CharSequence?.isNullOrEmpty(): Boolean {
fun smartcastOnReceiver(s: String?) { fun smartcastOnReceiver(s: String?) {
with(s) { with(s) {
if (isNullOrEmpty()) { if (isNullOrEmpty()) {
length <!INAPPLICABLE_CANDIDATE!>length<!>
} }
else { else {
length length
@@ -32,7 +32,7 @@ fun mixedReceiver(s: String?) {
} }
} else { } else {
with(s) { with(s) {
length <!INAPPLICABLE_CANDIDATE!>length<!>
} }
} }
} }
@@ -17,7 +17,7 @@ fun CharSequence?.isNullOrEmpty(): Boolean {
fun smartcastOnReceiver(s: String?) { fun smartcastOnReceiver(s: String?) {
with(s) { with(s) {
if (isNullOrEmpty()) { if (isNullOrEmpty()) {
length <!INAPPLICABLE_CANDIDATE!>length<!>
} }
else { else {
length length
@@ -32,7 +32,7 @@ fun mixedReceiver(s: String?) {
} }
} else { } else {
with(s) { with(s) {
length <!INAPPLICABLE_CANDIDATE!>length<!>
} }
} }
} }
@@ -9,17 +9,17 @@ package testPackCase1
fun case1(a: A, c: C) { fun case1(a: A, c: C) {
<!DEBUG_INFO_CALL("fqName: fqName is unknown; typeCall: unresolved"), INAPPLICABLE_CANDIDATE!>a?.b += c<!> <!DEBUG_INFO_CALL("fqName: testPackCase1.B.plusAssign; typeCall: operator function")!>a?.b += c<!>
a?.b .<!DEBUG_INFO_CALL("fqName: fqName is unknown; typeCall: unresolved")!><!INAPPLICABLE_CANDIDATE!>plusAssign<!>(c)<!> a?.b .<!DEBUG_INFO_CALL("fqName: testPackCase1.B.plusAssign; typeCall: operator function")!>plusAssign(c)<!>
val x = { val x = {
<!DEBUG_INFO_CALL("fqName: fqName is unknown; typeCall: unresolved"), INAPPLICABLE_CANDIDATE!>a?.b += c<!> <!DEBUG_INFO_CALL("fqName: testPackCase1.B.plusAssign; typeCall: operator function")!>a?.b += c<!>
a?.b.<!DEBUG_INFO_CALL("fqName: fqName is unknown; typeCall: unresolved")!><!INAPPLICABLE_CANDIDATE!>plusAssign<!>(c)<!> a?.b.<!DEBUG_INFO_CALL("fqName: testPackCase1.B.plusAssign; typeCall: operator function")!>plusAssign(c)<!>
}() }()
<!DEBUG_INFO_CALL("fqName: fqName is unknown; typeCall: unresolved"), INAPPLICABLE_CANDIDATE!>a?.b += { c }()<!> <!DEBUG_INFO_CALL("fqName: testPackCase1.B.plusAssign; typeCall: operator function")!>a?.b += { c }()<!>
a?.b.<!DEBUG_INFO_CALL("fqName: fqName is unknown; typeCall: unresolved")!><!INAPPLICABLE_CANDIDATE!>plusAssign<!>({ c }())<!> a?.b.<!DEBUG_INFO_CALL("fqName: testPackCase1.B.plusAssign; typeCall: operator function")!>plusAssign({ c }())<!>
} }
class A(val b: B) class A(val b: B)
@@ -103,8 +103,8 @@ fun case_7() {
// TESTCASE NUMBER: 8 // TESTCASE NUMBER: 8
fun case_8(x: TypealiasNullableString) { fun case_8(x: TypealiasNullableString) {
if (x !== null === null && <!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableString")!>x<!> != null != null) <!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableString")!>x<!>.get(0) if (x !== null === null && <!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableString")!>x<!> != null != null) <!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableString")!>x<!>.<!INAPPLICABLE_CANDIDATE!>get<!>(0)
if (x !== null != null && <!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableString")!>x<!> != null === null) <!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableString")!>x<!>.get(0) if (x !== null != null && <!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableString")!>x<!> != null === null) <!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableString")!>x<!>.<!INAPPLICABLE_CANDIDATE!>get<!>(0)
} }
// TESTCASE NUMBER: 9 // TESTCASE NUMBER: 9
@@ -20,7 +20,7 @@ inline fun <reified T, reified K> case_1(x: T) {
inline fun <reified T, reified K> case_2(x: T) { inline fun <reified T, reified K> case_2(x: T) {
x as K x as K
<!DEBUG_INFO_EXPRESSION_TYPE("K & T & T")!>x<!> <!DEBUG_INFO_EXPRESSION_TYPE("K & T & T")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("K & T & T")!>x<!>.equals(x) <!DEBUG_INFO_EXPRESSION_TYPE("K & T & T")!>x<!>.<!INAPPLICABLE_CANDIDATE!>equals<!>(x)
} }
/* /*
@@ -49,7 +49,7 @@ inline fun <reified T, reified K> case_4(x: T?) {
inline fun <reified T, reified K> case_5(x: T) { inline fun <reified T, reified K> case_5(x: T) {
if (x is K?) { if (x is K?) {
<!DEBUG_INFO_EXPRESSION_TYPE("K? & T & T")!>x<!> <!DEBUG_INFO_EXPRESSION_TYPE("K? & T & T")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("K? & T & T")!>x<!>.equals(x) <!DEBUG_INFO_EXPRESSION_TYPE("K? & T & T")!>x<!>.<!INAPPLICABLE_CANDIDATE!>equals<!>(x)
} }
} }
@@ -22,8 +22,8 @@ fun case_2(a: Any?) {
} }
})() })()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any & kotlin.Any?")!>a<!> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>a<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any & kotlin.Any?")!>a<!>.equals(10) <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>a<!>.<!INAPPLICABLE_CANDIDATE!>equals<!>(10)
} }
// TESTCASE NUMBER: 3 // TESTCASE NUMBER: 3
@@ -75,7 +75,7 @@ fun <T> case_6(x: T) {
fun <T> case_7(x: T) { fun <T> case_7(x: T) {
if (x is Int? || x is Float?) { if (x is Int? || x is Float?) {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number? & kotlin.Comparable<kotlin.Int & kotlin.Float>? & T & T")!>x<!> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number? & kotlin.Comparable<kotlin.Int & kotlin.Float>? & T & T")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number? & kotlin.Comparable<kotlin.Int & kotlin.Float>? & T & T")!>x<!>.toByte() <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number? & kotlin.Comparable<kotlin.Int & kotlin.Float>? & T & T")!>x<!>.<!INAPPLICABLE_CANDIDATE!>toByte<!>()
} }
} }
@@ -86,7 +86,7 @@ fun <T> case_7(x: T) {
inline fun <reified T> case_8(x: T) { inline fun <reified T> case_8(x: T) {
if (x is Int? || x is Float?) { if (x is Int? || x is Float?) {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number? & kotlin.Comparable<kotlin.Int & kotlin.Float>? & T & T")!>x<!> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number? & kotlin.Comparable<kotlin.Int & kotlin.Float>? & T & T")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number? & kotlin.Comparable<kotlin.Int & kotlin.Float>? & T & T")!>x<!>.toByte() <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number? & kotlin.Comparable<kotlin.Int & kotlin.Float>? & T & T")!>x<!>.<!INAPPLICABLE_CANDIDATE!>toByte<!>()
} }
} }
@@ -8,7 +8,7 @@ fun <T, K> case_1(x: T?, y: K?) {
y as K y as K
val z = <!DEBUG_INFO_EXPRESSION_TYPE("T & T?")!>x<!> ?: <!DEBUG_INFO_EXPRESSION_TYPE("K & K?")!>y<!> val z = <!DEBUG_INFO_EXPRESSION_TYPE("T & T?")!>x<!> ?: <!DEBUG_INFO_EXPRESSION_TYPE("K & K?")!>y<!>
<!DEBUG_INFO_EXPRESSION_TYPE("T & T?")!>x<!>.equals(10) <!DEBUG_INFO_EXPRESSION_TYPE("T & T?")!>x<!>.<!INAPPLICABLE_CANDIDATE!>equals<!>(10)
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>z<!> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>z<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>z<!>.<!INAPPLICABLE_CANDIDATE!>equals<!>(10) <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>z<!>.<!INAPPLICABLE_CANDIDATE!>equals<!>(10)
} }
@@ -18,5 +18,5 @@ inline fun <reified T: Any, reified K: T?> case_2(y: K?) {
y as K y as K
<!DEBUG_INFO_EXPRESSION_TYPE("K & K?")!>y<!> <!DEBUG_INFO_EXPRESSION_TYPE("K & K?")!>y<!>
<!DEBUG_INFO_EXPRESSION_TYPE("K & K?")!>y<!>.equals(10) <!DEBUG_INFO_EXPRESSION_TYPE("K & K?")!>y<!>.<!INAPPLICABLE_CANDIDATE!>equals<!>(10)
} }
@@ -8,7 +8,7 @@ fun <T> case_1(x: T) {
if (y != x) { if (y != x) {
<!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!> <!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.equals(null) <!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.<!INAPPLICABLE_CANDIDATE!>equals<!>(null)
<!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.propT <!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.propT
<!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.<!INAPPLICABLE_CANDIDATE!>propAny<!> <!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.<!INAPPLICABLE_CANDIDATE!>propAny<!>
<!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.propNullableT <!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.propNullableT
@@ -17,7 +17,7 @@ fun <T> case_1(x: T) {
<!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.<!INAPPLICABLE_CANDIDATE!>funAny<!>() <!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.<!INAPPLICABLE_CANDIDATE!>funAny<!>()
<!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.funNullableT() <!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.funNullableT()
<!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.funNullableAny() <!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.funNullableAny()
<!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.apply { equals(null) } <!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.apply { <!INAPPLICABLE_CANDIDATE!>equals<!>(null) }
<!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.apply { propT } <!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.apply { propT }
<!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.apply { <!INAPPLICABLE_CANDIDATE!>propAny<!> } <!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.apply { <!INAPPLICABLE_CANDIDATE!>propAny<!> }
<!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.apply { propNullableT } <!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.apply { propNullableT }
@@ -25,8 +25,8 @@ fun <T> case_1(x: T) {
<!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.apply { funT() } <!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.apply { funT() }
<!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.apply { <!INAPPLICABLE_CANDIDATE!>funAny<!>() } <!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.apply { <!INAPPLICABLE_CANDIDATE!>funAny<!>() }
<!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.apply { funNullableT() } <!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.apply { funNullableT() }
<!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.apply { funNullableAny(); <!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.equals(null) } <!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.apply { funNullableAny(); <!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.<!INAPPLICABLE_CANDIDATE!>equals<!>(null) }
<!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.also { <!DEBUG_INFO_EXPRESSION_TYPE("T")!>it<!>.equals(null) } <!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.also { <!DEBUG_INFO_EXPRESSION_TYPE("T")!>it<!>.<!INAPPLICABLE_CANDIDATE!>equals<!>(null) }
<!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.also { <!DEBUG_INFO_EXPRESSION_TYPE("T")!>it<!>.propT } <!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.also { <!DEBUG_INFO_EXPRESSION_TYPE("T")!>it<!>.propT }
<!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.also { <!DEBUG_INFO_EXPRESSION_TYPE("T")!>it<!>.<!INAPPLICABLE_CANDIDATE!>propAny<!> } <!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.also { <!DEBUG_INFO_EXPRESSION_TYPE("T")!>it<!>.<!INAPPLICABLE_CANDIDATE!>propAny<!> }
<!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.also { <!DEBUG_INFO_EXPRESSION_TYPE("T")!>it<!>.propNullableT } <!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.also { <!DEBUG_INFO_EXPRESSION_TYPE("T")!>it<!>.propNullableT }
@@ -51,7 +51,7 @@ fun <T> case_2(x: T?, y: Nothing?) {
<!DEBUG_INFO_EXPRESSION_TYPE("T?")!>x<!>.<!INAPPLICABLE_CANDIDATE!>funAny<!>() <!DEBUG_INFO_EXPRESSION_TYPE("T?")!>x<!>.<!INAPPLICABLE_CANDIDATE!>funAny<!>()
<!DEBUG_INFO_EXPRESSION_TYPE("T?")!>x<!>.funNullableT() <!DEBUG_INFO_EXPRESSION_TYPE("T?")!>x<!>.funNullableT()
<!DEBUG_INFO_EXPRESSION_TYPE("T?")!>x<!>.funNullableAny() <!DEBUG_INFO_EXPRESSION_TYPE("T?")!>x<!>.funNullableAny()
<!DEBUG_INFO_EXPRESSION_TYPE("T?")!>x<!>.apply { equals(null) } <!DEBUG_INFO_EXPRESSION_TYPE("T?")!>x<!>.apply { <!INAPPLICABLE_CANDIDATE!>equals<!>(null) }
<!DEBUG_INFO_EXPRESSION_TYPE("T?")!>x<!>.apply { propT } <!DEBUG_INFO_EXPRESSION_TYPE("T?")!>x<!>.apply { propT }
<!DEBUG_INFO_EXPRESSION_TYPE("T?")!>x<!>.apply { <!INAPPLICABLE_CANDIDATE!>propAny<!> } <!DEBUG_INFO_EXPRESSION_TYPE("T?")!>x<!>.apply { <!INAPPLICABLE_CANDIDATE!>propAny<!> }
<!DEBUG_INFO_EXPRESSION_TYPE("T?")!>x<!>.apply { propNullableT } <!DEBUG_INFO_EXPRESSION_TYPE("T?")!>x<!>.apply { propNullableT }
@@ -334,7 +334,7 @@ fun <T> case_24(x: Inv<out T?>?, y: Nothing?) {
fun case_25(x: Int?) { fun case_25(x: Int?) {
val x = (l@ { val x = (l@ {
if (x == null) return@l if (x == null) return@l
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int & kotlin.Int")!>x<!> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int & kotlin.Int?")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int & kotlin.Int?")!>x<!>.inv() <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int & kotlin.Int?")!>x<!>.inv()
})() })()
} }
@@ -660,7 +660,7 @@ fun case_44(x: Inv<out Inv<out Inv<out Inv<out Inv<out Inv<out Inv<out Number>>>
fun <T> case_45(x: T) { fun <T> case_45(x: T) {
val y = (l@ { val y = (l@ {
if (x == null) return@l if (x == null) return@l
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & T!!")!>x<!> <!DEBUG_INFO_EXPRESSION_TYPE("T!! & T")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & T")!>x<!>.equals(null) <!DEBUG_INFO_EXPRESSION_TYPE("T!! & T")!>x<!>.equals(null)
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & T")!>x<!>.propT <!DEBUG_INFO_EXPRESSION_TYPE("T!! & T")!>x<!>.propT
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & T")!>x<!>.propAny <!DEBUG_INFO_EXPRESSION_TYPE("T!! & T")!>x<!>.propAny
@@ -677,7 +677,7 @@ fun <T> case_45(x: T) {
fun <T> case_46(x: T?) { fun <T> case_46(x: T?) {
(l@ { (l@ {
if (x === null) return@l if (x === null) return@l
<!DEBUG_INFO_EXPRESSION_TYPE("T?!! & T?!!")!>x<!> <!DEBUG_INFO_EXPRESSION_TYPE("T?!! & T?")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("T?!! & T?")!>x<!>.equals(null) <!DEBUG_INFO_EXPRESSION_TYPE("T?!! & T?")!>x<!>.equals(null)
<!DEBUG_INFO_EXPRESSION_TYPE("T?!! & T?")!>x<!>.propT <!DEBUG_INFO_EXPRESSION_TYPE("T?!! & T?")!>x<!>.propT
<!DEBUG_INFO_EXPRESSION_TYPE("T?!! & T?")!>x<!>.propAny <!DEBUG_INFO_EXPRESSION_TYPE("T?!! & T?")!>x<!>.propAny
@@ -244,7 +244,7 @@ fun <T>case_18(x: T, f: Boolean) {
while (f) { while (f) {
if (false || false || false || x == nullableNothingProperty) break if (false || false || false || x == nullableNothingProperty) break
<!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!> <!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.equals(null) <!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.<!INAPPLICABLE_CANDIDATE!>equals<!>(null)
<!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.propT <!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.propT
<!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.<!INAPPLICABLE_CANDIDATE!>propAny<!> <!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.<!INAPPLICABLE_CANDIDATE!>propAny<!>
<!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.propNullableT <!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>.propNullableT
@@ -261,7 +261,7 @@ fun <K, V>case_19(map: MutableMap<K, V>, y: Nothing?) {
for ((k, v) in map) { for ((k, v) in map) {
if (k !== implicitNullableNothingProperty && true && v != y) else { break } if (k !== implicitNullableNothingProperty && true && v != y) else { break }
<!DEBUG_INFO_EXPRESSION_TYPE("K")!>k<!> <!DEBUG_INFO_EXPRESSION_TYPE("K")!>k<!>
<!DEBUG_INFO_EXPRESSION_TYPE("K")!>k<!>.equals(null) <!DEBUG_INFO_EXPRESSION_TYPE("K")!>k<!>.<!INAPPLICABLE_CANDIDATE!>equals<!>(null)
<!DEBUG_INFO_EXPRESSION_TYPE("K")!>k<!>.propT <!DEBUG_INFO_EXPRESSION_TYPE("K")!>k<!>.propT
<!DEBUG_INFO_EXPRESSION_TYPE("K")!>k<!>.<!INAPPLICABLE_CANDIDATE!>propAny<!> <!DEBUG_INFO_EXPRESSION_TYPE("K")!>k<!>.<!INAPPLICABLE_CANDIDATE!>propAny<!>
<!DEBUG_INFO_EXPRESSION_TYPE("K")!>k<!>.propNullableT <!DEBUG_INFO_EXPRESSION_TYPE("K")!>k<!>.propNullableT
@@ -271,7 +271,7 @@ fun <K, V>case_19(map: MutableMap<K, V>, y: Nothing?) {
<!DEBUG_INFO_EXPRESSION_TYPE("K")!>k<!>.funNullableT() <!DEBUG_INFO_EXPRESSION_TYPE("K")!>k<!>.funNullableT()
<!DEBUG_INFO_EXPRESSION_TYPE("K")!>k<!>.funNullableAny() <!DEBUG_INFO_EXPRESSION_TYPE("K")!>k<!>.funNullableAny()
<!DEBUG_INFO_EXPRESSION_TYPE("V")!>v<!> <!DEBUG_INFO_EXPRESSION_TYPE("V")!>v<!>
<!DEBUG_INFO_EXPRESSION_TYPE("V")!>v<!>.equals(null) <!DEBUG_INFO_EXPRESSION_TYPE("V")!>v<!>.<!INAPPLICABLE_CANDIDATE!>equals<!>(null)
<!DEBUG_INFO_EXPRESSION_TYPE("V")!>v<!>.propT <!DEBUG_INFO_EXPRESSION_TYPE("V")!>v<!>.propT
<!DEBUG_INFO_EXPRESSION_TYPE("V")!>v<!>.<!INAPPLICABLE_CANDIDATE!>propAny<!> <!DEBUG_INFO_EXPRESSION_TYPE("V")!>v<!>.<!INAPPLICABLE_CANDIDATE!>propAny<!>
<!DEBUG_INFO_EXPRESSION_TYPE("V")!>v<!>.propNullableT <!DEBUG_INFO_EXPRESSION_TYPE("V")!>v<!>.propNullableT
@@ -68,7 +68,11 @@ class SingleCandidateResolver(
resolutionParameters.callableSymbol, resolutionParameters.callableSymbol,
explicitReceiverKind = explicitReceiverKind, explicitReceiverKind = explicitReceiverKind,
dispatchReceiverValue = dispatchReceiverValue, dispatchReceiverValue = dispatchReceiverValue,
implicitExtensionReceiverValue = implicitExtensionReceiverValue, extensionReceiverValue =
if (explicitReceiverKind.isExtensionReceiver)
callInfo.explicitReceiver?.let { ExpressionReceiverValue(it) }
else
implicitExtensionReceiverValue,
scope = null, scope = null,
) )