Refactoring & clarification: implement new FIR tower resolver

This commit is contained in:
Mikhail Glukhikh
2020-01-10 18:58:42 +03:00
parent a3ab763f0b
commit 14204a842a
125 changed files with 1804 additions and 1085 deletions
@@ -209,9 +209,7 @@ class FirCallResolver(
typeArguments.addAll(qualifiedAccess.typeArguments)
resultType = if (classId.isLocal) {
typeForQualifierByDeclaration(referencedSymbol.fir, resultType, session)
?: resultType.resolvedTypeFromPrototype(
session.builtinTypes.unitType.type//StandardClassIds.Unit(symbolProvider).constructType(emptyArray(), isNullable = false)
)
?: session.builtinTypes.unitType
} else {
typeForQualifier(this)
}
@@ -252,7 +250,8 @@ class FirCallResolver(
val result = towerResolver.runResolver(
implicitReceiverStack.receiversAsReversed(),
info,
collector = CandidateCollector(this, resolutionStageRunner)
collector = CandidateCollector(this, resolutionStageRunner),
manager = TowerResolveManager(towerResolver)
)
val bestCandidates = result.bestCandidates()
val noSuccessfulCandidates = result.currentApplicability < CandidateApplicability.SYNTHETIC_RESOLVED
@@ -316,7 +315,7 @@ class FirCallResolver(
fun <T> selectCandidateFromGivenCandidates(call: T, name: Name, candidates: Collection<Candidate>): T where T : FirResolvable, T : FirCall {
val result = CandidateCollector(this, resolutionStageRunner)
candidates.forEach { result.consumeCandidate(0, it) }
candidates.forEach { result.consumeCandidate(TowerGroup.Start, it) }
val bestCandidates = result.bestCandidates()
val reducedCandidates = if (result.currentApplicability < CandidateApplicability.SYNTHETIC_RESOLVED) {
bestCandidates.toSet()
@@ -325,9 +325,7 @@ fun BodyResolveComponents.typeForQualifier(resolvedQualifier: FirResolvedQualifi
}
}
// TODO: Handle no value type here
return resultType.resolvedTypeFromPrototype(
session.builtinTypes.unitType.type
)
return session.builtinTypes.unitType
}
internal fun typeForReifiedParameterReference(parameterReference: FirResolvedReifiedParameterReference): FirTypeRef {
@@ -361,7 +359,8 @@ internal fun typeForQualifierByDeclaration(declaration: FirDeclaration, resultTy
fun <T : FirResolvable> BodyResolveComponents.typeFromCallee(access: T): FirResolvedTypeRef {
val makeNullable: Boolean by lazy {
if (access is FirQualifiedAccess && access.safe) {
val explicitReceiver = access.explicitReceiver!!
val explicitReceiver = access.explicitReceiver
?: throw AssertionError("Safe call without explicit receiver: ${access.render()}")
val receiverResultType = explicitReceiver.resultType
if (receiverResultType is FirResolvedTypeRef) {
receiverResultType.type.isNullable
@@ -46,22 +46,28 @@ data class CallInfo(
) {
val argumentCount get() = arguments.size
fun noStubReceiver(): CallInfo =
if (stubReceiver == null) this else CallInfo(
callKind, name, explicitReceiver, arguments,
isSafeCall, typeArguments, session, containingFile, implicitReceiverStack, expectedType, outerCSBuilder, lhs, null
)
fun replaceWithVariableAccess(): CallInfo =
CallInfo(
CallKind.VariableAccess, name, explicitReceiver, emptyList(),
isSafeCall, typeArguments, session, containingFile, implicitReceiverStack, expectedType, outerCSBuilder, lhs
isSafeCall, typeArguments, session, containingFile, implicitReceiverStack, expectedType, outerCSBuilder, lhs, stubReceiver
)
fun replaceExplicitReceiver(explicitReceiver: FirExpression): CallInfo =
fun replaceExplicitReceiver(explicitReceiver: FirExpression?): CallInfo =
CallInfo(
callKind, name, explicitReceiver, arguments,
isSafeCall, typeArguments, session, containingFile, implicitReceiverStack, expectedType, outerCSBuilder, lhs
isSafeCall, typeArguments, session, containingFile, implicitReceiverStack, expectedType, outerCSBuilder, lhs, stubReceiver
)
fun withReceiverAsArgument(receiverExpression: FirExpression): CallInfo =
CallInfo(
callKind, name, explicitReceiver, listOf(receiverExpression) + arguments,
isSafeCall, typeArguments, session, containingFile, implicitReceiverStack, expectedType, outerCSBuilder, lhs
isSafeCall, typeArguments, session, containingFile, implicitReceiverStack, expectedType, outerCSBuilder, lhs, stubReceiver
)
}
@@ -5,39 +5,34 @@
package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
import org.jetbrains.kotlin.fir.expressions.impl.FirQualifiedAccessExpressionImpl
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
import org.jetbrains.kotlin.fir.resolve.transformQualifiedAccessUsingSmartcastInfo
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.types.isExtensionFunctionType
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.util.OperatorNameConventions
open class CandidateCollector(
val components: BodyResolveComponents,
val resolutionStageRunner: ResolutionStageRunner
private val resolutionStageRunner: ResolutionStageRunner
) {
private val groupNumbers = mutableListOf<Int>()
private val groupNumbers = mutableListOf<TowerGroup>()
private val candidates = mutableListOf<Candidate>()
var currentApplicability = CandidateApplicability.HIDDEN
private set
private var currentGroup = TowerGroup.Start
fun newDataSet() {
groupNumbers.clear()
candidates.clear()
currentApplicability = CandidateApplicability.HIDDEN
}
open fun consumeCandidate(group: Int, candidate: Candidate): CandidateApplicability {
open fun consumeCandidate(group: TowerGroup, candidate: Candidate): CandidateApplicability {
val applicability = resolutionStageRunner.processCandidate(candidate)
if (applicability > currentApplicability) {
groupNumbers.clear()
candidates.clear()
currentApplicability = applicability
currentGroup = group
}
if (applicability == currentApplicability) {
@@ -71,58 +66,3 @@ open class CandidateCollector(
}
}
// Collects properties that potentially could be invoke receivers, like 'propertyName()',
// and initiates further invoke resolution by adding property-bound invoke consumers
class InvokeReceiverCandidateCollector(
private val towerResolver: FirTowerResolver,
private val invokeCallInfo: CallInfo,
components: BodyResolveComponents,
private val invokeConsumer: AccumulatingTowerDataConsumer,
resolutionStageRunner: ResolutionStageRunner
) : CandidateCollector(components, resolutionStageRunner) {
private fun createBoundInvokeConsumer(boundInvokeCallInfo: CallInfo): TowerDataConsumer {
return createSimpleFunctionConsumer(
components.session, OperatorNameConventions.INVOKE,
boundInvokeCallInfo, components, towerResolver.collector
)
}
private fun createExplicitReceiverForInvoke(candidate: Candidate): FirQualifiedAccessExpressionImpl {
val symbol = candidate.symbol as FirCallableSymbol<*>
return FirQualifiedAccessExpressionImpl(null).apply {
calleeReference = FirNamedReferenceWithCandidate(
null,
symbol.callableId.callableName,
candidate
)
dispatchReceiver = candidate.dispatchReceiverExpression()
typeRef = towerResolver.typeCalculator.tryCalculateReturnType(symbol.firUnsafe())
}
}
override fun consumeCandidate(group: Int, candidate: Candidate): CandidateApplicability {
val applicability = super.consumeCandidate(group, candidate)
if (applicability >= CandidateApplicability.SYNTHETIC_RESOLVED) {
val symbol = candidate.symbol as FirCallableSymbol<*>
val extensionReceiverExpression = candidate.extensionReceiverExpression()
val useExtensionReceiverAsArgument =
symbol.fir.receiverTypeRef == null &&
candidate.explicitReceiverKind == ExplicitReceiverKind.EXTENSION_RECEIVER &&
symbol.fir.returnTypeRef.isExtensionFunctionType()
val explicitReceiver = createExplicitReceiverForInvoke(candidate).apply {
extensionReceiver = extensionReceiverExpression.takeIf { !useExtensionReceiverAsArgument } ?: FirNoReceiverExpression
}.let {
components.transformQualifiedAccessUsingSmartcastInfo(it)
}
val boundInvokeCallInfo = invokeCallInfo.replaceExplicitReceiver(explicitReceiver).let {
if (useExtensionReceiverAsArgument) it.withReceiverAsArgument(extensionReceiverExpression)
else it
}
invokeConsumer.addConsumerAndProcessAccumulatedData(createBoundInvokeConsumer(boundInvokeCallInfo))
}
return applicability
}
}
@@ -13,19 +13,30 @@ import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzer
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
class CandidateFactory(
class CandidateFactory private constructor(
val bodyResolveComponents: BodyResolveComponents,
private val callInfo: CallInfo
val callInfo: CallInfo,
private val baseSystem: ConstraintStorage
) {
private val baseSystem: ConstraintStorage
init {
val system = bodyResolveComponents.inferenceComponents.createConstraintSystem()
callInfo.arguments.forEach {
system.addSubsystemFromExpression(it)
companion object {
private fun buildBaseSystem(bodyResolveComponents: BodyResolveComponents, callInfo: CallInfo): ConstraintStorage {
val system = bodyResolveComponents.inferenceComponents.createConstraintSystem()
callInfo.arguments.forEach {
system.addSubsystemFromExpression(it)
}
return system.asReadOnlyStorage()
}
baseSystem = system.asReadOnlyStorage()
}
constructor(bodyResolveComponents: BodyResolveComponents, callInfo: CallInfo) :
this(bodyResolveComponents, callInfo, buildBaseSystem(bodyResolveComponents, callInfo))
fun replaceCallInfo(callInfo: CallInfo): CandidateFactory {
if (this.callInfo.arguments.size != callInfo.arguments.size) {
throw AssertionError("Incorrect replacement of call info in CandidateFactory")
}
return CandidateFactory(bodyResolveComponents, callInfo, baseSystem)
}
fun createCandidate(
@@ -1,125 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
import org.jetbrains.kotlin.name.Name
fun createVariableAndObjectConsumer(
session: FirSession,
name: Name,
callInfo: CallInfo,
bodyResolveComponents: BodyResolveComponents,
resultCollector: CandidateCollector
): TowerDataConsumer {
return PrioritizedTowerDataConsumer(
resultCollector,
createSimpleConsumer(
session,
name,
TowerScopeLevel.Token.Properties,
callInfo,
bodyResolveComponents,
resultCollector
),
createSimpleConsumer(
session,
name,
TowerScopeLevel.Token.Objects,
callInfo,
bodyResolveComponents,
resultCollector
)
)
}
fun createSimpleFunctionConsumer(
session: FirSession,
name: Name,
callInfo: CallInfo,
bodyResolveComponents: BodyResolveComponents,
resultCollector: CandidateCollector
): TowerDataConsumer {
return createSimpleConsumer(
session,
name,
TowerScopeLevel.Token.Functions,
callInfo,
bodyResolveComponents,
resultCollector
)
}
fun createFunctionConsumer(
session: FirSession,
name: Name,
callInfo: CallInfo,
bodyResolveComponents: BodyResolveComponents,
resultCollector: CandidateCollector,
towerResolver: FirTowerResolver
): TowerDataConsumer {
val varCallInfo = callInfo.replaceWithVariableAccess()
return PrioritizedTowerDataConsumer(
resultCollector,
createSimpleConsumer(
session,
name,
TowerScopeLevel.Token.Functions,
callInfo,
bodyResolveComponents,
resultCollector
),
AccumulatingTowerDataConsumer(resultCollector).apply {
initialConsumer = createSimpleConsumer(
session,
name,
TowerScopeLevel.Token.Properties,
varCallInfo,
bodyResolveComponents,
InvokeReceiverCandidateCollector(
towerResolver,
invokeCallInfo = callInfo,
components = bodyResolveComponents,
invokeConsumer = this,
resolutionStageRunner = resultCollector.resolutionStageRunner
)
)
}
)
}
fun createSimpleConsumer(
session: FirSession,
name: Name,
token: TowerScopeLevel.Token<*>,
callInfo: CallInfo,
bodyResolveComponents: BodyResolveComponents,
resultCollector: CandidateCollector
): TowerDataConsumer {
val factory = CandidateFactory(bodyResolveComponents, callInfo)
val explicitReceiver = callInfo.explicitReceiver
return if (explicitReceiver != null) {
ExplicitReceiverTowerDataConsumer(session, name, token, qualifierOrExpressionReceiver(explicitReceiver), factory, resultCollector)
} else {
NoExplicitReceiverTowerDataConsumer(session, name, token, factory, resultCollector)
}
}
fun createCallableReferencesConsumer(
session: FirSession,
name: Name,
callInfo: CallInfo,
bodyResolveComponents: BodyResolveComponents,
resultCollector: CandidateCollector
): TowerDataConsumer {
// TODO: Use SamePriorityConsumer
return PrioritizedTowerDataConsumer(
resultCollector,
createSimpleConsumer(session, name, TowerScopeLevel.Token.Functions, callInfo, bodyResolveComponents, resultCollector),
createSimpleConsumer(session, name, TowerScopeLevel.Token.Properties, callInfo, bodyResolveComponents, resultCollector)
)
}
@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.FirTypeParametersOwner
import org.jetbrains.kotlin.fir.declarations.expandedConeType
import org.jetbrains.kotlin.fir.declarations.impl.FirClassImpl
@@ -17,10 +16,8 @@ import org.jetbrains.kotlin.fir.expressions.impl.FirThisReceiverExpressionImpl
import org.jetbrains.kotlin.fir.references.impl.FirImplicitThisReference
import org.jetbrains.kotlin.fir.renderWithType
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.impl.*
import org.jetbrains.kotlin.fir.scopes.scope
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.*
@@ -57,9 +54,11 @@ class ClassDispatchReceiverValue(klassSymbol: FirClassSymbol<*>) : ReceiverValue
}
// TODO: should inherit just Receiver, not ReceiverValue
abstract class AbstractExplicitReceiver<E : FirExpression> : ReceiverValue {
abstract class AbstractExplicitReceiver<E : FirExpression> : Receiver {
abstract val explicitReceiver: FirExpression
}
abstract class AbstractExplicitReceiverValue<E : FirExpression> : AbstractExplicitReceiver<E>(), ReceiverValue {
override val type: ConeKotlinType
get() = explicitReceiver.typeRef.coneTypeSafe()
?: ConeKotlinErrorType("No type calculated for: ${explicitReceiver.renderWithType()}") // TODO: assert here
@@ -68,11 +67,6 @@ abstract class AbstractExplicitReceiver<E : FirExpression> : ReceiverValue {
get() = explicitReceiver
}
fun qualifierOrExpressionReceiver(explicitReceiver: FirExpression): AbstractExplicitReceiver<*> {
if (explicitReceiver is FirResolvedQualifier) return QualifierReceiver(explicitReceiver)
return ExpressionReceiverValue(explicitReceiver)
}
class QualifierReceiver(override val explicitReceiver: FirResolvedQualifier) : AbstractExplicitReceiver<FirResolvedQualifier>() {
private fun getClassSymbolWithCallablesScope(
classId: ClassId,
@@ -95,7 +89,7 @@ class QualifierReceiver(override val explicitReceiver: FirResolvedQualifier) : A
return null to null
}
override fun scope(useSiteSession: FirSession, scopeSession: ScopeSession): FirScope? {
fun qualifierScope(useSiteSession: FirSession, scopeSession: ScopeSession): FirScope? {
val classId = explicitReceiver.classId ?: return null
val (classSymbol, callablesScope) = getClassSymbolWithCallablesScope(classId, useSiteSession, scopeSession)
@@ -107,22 +101,21 @@ class QualifierReceiver(override val explicitReceiver: FirResolvedQualifier) : A
useSiteSession.firSymbolProvider.getNestedClassifierScope(classId)
}
val qualifierScope = FirQualifierScope(callablesScope, classifierScope)
if ((klass as? FirRegularClass)?.companionObject == null) {
return qualifierScope
}
val companionScope = super.scope(useSiteSession, scopeSession) ?: return qualifierScope
return FirCompositeScope(qualifierScope, companionScope)
return FirQualifierScope(callablesScope, classifierScope)
}
return super.scope(useSiteSession, scopeSession)
return null
}
override fun scope(useSiteSession: FirSession, scopeSession: ScopeSession): FirScope? {
return qualifierScope(useSiteSession, scopeSession)
}
}
private class ExpressionReceiverValue(
internal class ExpressionReceiverValue(
override val explicitReceiver: FirExpression
) : AbstractExplicitReceiver<FirExpression>(), ReceiverValue
) : AbstractExplicitReceiverValue<FirExpression>(), ReceiverValue
abstract class ImplicitReceiverValue<S : AbstractFirBasedSymbol<*>>(
sealed class ImplicitReceiverValue<S : AbstractFirBasedSymbol<*>>(
val boundSymbol: S,
type: ConeKotlinType,
private val useSiteSession: FirSession,
@@ -148,20 +141,29 @@ abstract class ImplicitReceiverValue<S : AbstractFirBasedSymbol<*>>(
}
}
class ImplicitDispatchReceiverValue(
internal enum class ImplicitDispatchReceiverKind {
REGULAR,
COMPANION,
COMPANION_FROM_SUPERTYPE
}
class ImplicitDispatchReceiverValue internal constructor(
boundSymbol: FirClassSymbol<*>,
type: ConeKotlinType,
useSiteSession: FirSession,
scopeSession: ScopeSession
scopeSession: ScopeSession,
private val kind: ImplicitDispatchReceiverKind = ImplicitDispatchReceiverKind.REGULAR
) : ImplicitReceiverValue<FirClassSymbol<*>>(boundSymbol, type, useSiteSession, scopeSession) {
val implicitCompanionScopes: List<FirScope> = run {
val klass = boundSymbol.fir as? FirRegularClass ?: return@run emptyList()
listOfNotNull(klass.companionObject?.scope(ConeSubstitutor.Empty, useSiteSession, scopeSession)) +
lookupSuperTypes(klass, lookupInterfaces = false, deep = true, useSiteSession = useSiteSession).mapNotNull {
val superClass = (it as? ConeClassLikeType)?.lookupTag?.toSymbol(useSiteSession)?.fir as? FirRegularClass
superClass?.companionObject?.scope(ConeSubstitutor.Empty, useSiteSession, scopeSession)
}
}
internal constructor(
boundSymbol: FirClassSymbol<*>, useSiteSession: FirSession, scopeSession: ScopeSession, kind: ImplicitDispatchReceiverKind
) : this(
boundSymbol, boundSymbol.constructType(typeArguments = emptyArray(), isNullable = false),
useSiteSession, scopeSession, kind
)
val implicitCompanion: Boolean get() = kind != ImplicitDispatchReceiverKind.REGULAR
val companionFromSupertype: Boolean get() = kind == ImplicitDispatchReceiverKind.COMPANION_FROM_SUPERTYPE
}
class ImplicitExtensionReceiverValue(
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -10,396 +10,459 @@ import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.impl.FirImportImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedImportImpl
import org.jetbrains.kotlin.fir.declarations.isCompanion
import org.jetbrains.kotlin.fir.declarations.isInner
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
import org.jetbrains.kotlin.fir.expressions.impl.FirQualifiedAccessExpressionImpl
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
import org.jetbrains.kotlin.fir.resolve.calls.TowerDataKind.*
import org.jetbrains.kotlin.fir.resolve.transformQualifiedAccessUsingSmartcastInfo
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.ProcessorAction.NONE
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.impl.FirExplicitSimpleImportingScope
import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.scopes.impl.FirStaticScope
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.ConeIntegerLiteralType
import org.jetbrains.kotlin.fir.types.coneTypeSafe
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.descriptorUtil.HIDES_MEMBERS_NAME_LIST
import org.jetbrains.kotlin.util.OperatorNameConventions
enum class TowerDataKind {
EMPTY, // Corresponds to stub tower level which is replaced by receiver-related level
TOWER_LEVEL // Corresponds to real tower level which may process elements itself
}
class FirTowerResolver(
val typeCalculator: ReturnTypeCalculator,
val components: BodyResolveComponents,
resolutionStageRunner: ResolutionStageRunner,
val topLevelScopes: List<FirScope>,
val localScopes: List<FirLocalScope>
private val topLevelScopes: List<FirScope>,
private val localScopes: List<FirLocalScope>
) {
val session: FirSession get() = components.session
private val session: FirSession get() = components.session
private val collector = CandidateCollector(components, resolutionStageRunner)
private val manager = TowerResolveManager(this)
private lateinit var implicitReceivers: List<ImplicitReceiver>
private fun processImplicitReceiver(
towerDataConsumer: TowerDataConsumer,
implicitReceiverValue: ImplicitReceiverValue<*>,
nonEmptyLocalScopes: List<FirLocalScope>,
oldGroup: Int
): Int {
var group = oldGroup
// Member (no explicit receiver) / extension member (with explicit receiver) access via implicit receiver
// class Foo(val x: Int) {
// fun Bar.baz() {}
// fun test() { x }
// fun test(b: Bar) { b.baz() }
// }
towerDataConsumer.consume(
TOWER_LEVEL,
MemberScopeTowerLevel(session, components, dispatchReceiver = implicitReceiverValue, scopeSession = components.scopeSession),
group++
)
private data class ImplicitReceiver(val receiver: ImplicitReceiverValue<*>, val usableAsValue: Boolean, val depth: Int)
// class Foo {
// fun foo(block: Foo.() -> Unit) {
// block()
// }
// }
// invokeExtension on local variable
towerDataConsumer.consume(
EMPTY,
TowerScopeLevel.OnlyImplicitReceiver(implicitReceiverValue),
group++
)
//TowerData.OnlyImplicitReceiver(implicitReceiver).process()?.let { return it }
// Same receiver is dispatch & extension
// class Foo {
// fun Foo.bar() {}
// fun test() { bar() }
// }
towerDataConsumer.consume(
TOWER_LEVEL,
MemberScopeTowerLevel(
session, components,
dispatchReceiver = implicitReceiverValue,
implicitExtensionReceiver = implicitReceiverValue,
scopeSession = components.scopeSession
),
group++
)
for (scope in nonEmptyLocalScopes) {
// Local scope extensions via implicit receiver
// class Foo {
// fun test() {
// fun Foo.bar() {}
// bar()
// }
// }
towerDataConsumer.consume(
TOWER_LEVEL,
ScopeTowerLevel(session, components, scope, implicitExtensionReceiver = implicitReceiverValue),
group++
)
}
var blockDispatchReceivers = false
for (implicitDispatchReceiverValue in implicitReceiverValues) {
val implicitScope = implicitDispatchReceiverValue.implicitScope
if (implicitScope != null) {
// Extensions in outer object
// object Outer {
// fun Nested.foo() {}
// class Nested {
// fun test() { foo() }
// }
// }
towerDataConsumer.consume(
TOWER_LEVEL,
ScopeTowerLevel(session, components, implicitScope, implicitExtensionReceiver = implicitReceiverValue),
group++
)
}
if (implicitDispatchReceiverValue is ImplicitDispatchReceiverValue) {
val implicitCompanionScopes = implicitDispatchReceiverValue.implicitCompanionScopes
for (implicitCompanionScope in implicitCompanionScopes) {
// Extension in companion
// class My {
// companion object { fun My.foo() {} }
// fun test() { foo() }
// }
towerDataConsumer.consume(
TOWER_LEVEL,
ScopeTowerLevel(session, components, implicitCompanionScope, implicitExtensionReceiver = implicitReceiverValue),
group++
)
}
if (blockDispatchReceivers) {
continue
}
if ((implicitDispatchReceiverValue.boundSymbol.fir as? FirRegularClass)?.isInner == false) {
blockDispatchReceivers = true
private fun prepareImplicitReceivers(implicitReceiverValues: List<ImplicitReceiverValue<*>>): List<ImplicitReceiver> {
var depth = 0
var firstDispatchValue = true
val explicitCompanions = mutableListOf<FirRegularClassSymbol>()
implicitReceivers = implicitReceiverValues.mapNotNull {
val usableAsValue = when (it) {
is ImplicitExtensionReceiverValue -> true
is ImplicitDispatchReceiverValue -> {
val symbol = it.boundSymbol
val klass = symbol.fir as? FirRegularClass
if (!it.implicitCompanion && klass?.isCompanion == true) {
explicitCompanions += klass.symbol
}
if (firstDispatchValue) {
if (!it.implicitCompanion &&
klass?.isInner == false &&
!symbol.classId.isLocal
) {
firstDispatchValue = false
}
true
} else {
symbol.fir.classKind == ClassKind.OBJECT
}
}
}
if (implicitDispatchReceiverValue !== implicitReceiverValue) {
// Two different implicit receivers (dispatch & extension)
// class A
// class B {
// fun A.foo() {}
// }
// fun test(a: A, b: B) {
// with(a) { with(b) { foo() } }
// }
towerDataConsumer.consume(
TOWER_LEVEL,
MemberScopeTowerLevel(
session, components,
scopeSession = components.scopeSession,
dispatchReceiver = implicitDispatchReceiverValue,
implicitExtensionReceiver = implicitReceiverValue
),
group++
)
}
if (it is ImplicitDispatchReceiverValue && it.implicitCompanion && it.boundSymbol in explicitCompanions) null
else ImplicitReceiver(it, usableAsValue, depth++)
}
return group
return implicitReceivers
}
private fun processTopLevelScope(
towerDataConsumer: TowerDataConsumer,
topLevelScope: FirScope,
oldGroup: Int,
extensionsOnly: Boolean = false
): Int {
var group = oldGroup
// Top-level extensions via implicit receiver
// fun Foo.bar() {}
// class Foo {
// fun test() { bar() }
// }
for (implicitReceiverValue in implicitReceiverValues) {
if (towerDataConsumer.consume(
TOWER_LEVEL,
ScopeTowerLevel(
session, components, topLevelScope,
implicitExtensionReceiver = implicitReceiverValue,
extensionsOnly = extensionsOnly
),
group++
) == NONE
) {
return group
}
}
// Member of top-level scope & importing scope
// val x = 0
// fun test() { x }
towerDataConsumer.consume(TOWER_LEVEL, ScopeTowerLevel(session, components, topLevelScope), group++)
return group
}
fun reset() {
collector.newDataSet()
}
val collector = CandidateCollector(components, resolutionStageRunner)
private lateinit var towerDataConsumer: TowerDataConsumer
private lateinit var implicitReceiverValues: List<ImplicitReceiverValue<*>>
private fun towerDataConsumer(info: CallInfo, collector: CandidateCollector): TowerDataConsumer {
return when (info.callKind) {
CallKind.VariableAccess -> {
createVariableAndObjectConsumer(session, info.name, info, components, collector)
}
CallKind.Function -> {
createFunctionConsumer(session, info.name, info, components, collector, this)
}
CallKind.CallableReference -> {
if (info.stubReceiver == null) {
createCallableReferencesConsumer(session, info.name, info, components, collector)
} else {
PrioritizedTowerDataConsumer(
collector,
createCallableReferencesConsumer(
session, info.name, info.replaceExplicitReceiver(info.stubReceiver), components, collector
),
createCallableReferencesConsumer(
session, info.name, info, components, collector
)
)
}
}
else -> throw AssertionError("Unsupported call kind in tower resolver: ${info.callKind}")
}
}
private fun createExplicitReceiverForInvoke(candidate: Candidate): FirQualifiedAccessExpressionImpl {
val symbol = candidate.symbol as FirCallableSymbol<*>
return FirQualifiedAccessExpressionImpl(null).apply {
calleeReference = FirNamedReferenceWithCandidate(
null,
symbol.callableId.callableName,
candidate
)
dispatchReceiver = candidate.dispatchReceiverExpression()
typeRef = typeCalculator.tryCalculateReturnType(symbol.firUnsafe())
}
}
// Only case when qualifiedReceiver is a package (no classId) is handled here
private fun runResolverForFullyQualifiedReceiver(
implicitReceiverValues: List<ImplicitReceiverValue<*>>,
private fun runResolverForQualifierReceiver(
info: CallInfo,
collector: CandidateCollector,
qualifiedReceiver: FirResolvedQualifier
resolvedQualifier: FirResolvedQualifier,
manager: TowerResolveManager
): CandidateCollector {
val qualifierScope = FirExplicitSimpleImportingScope(
listOf(
FirResolvedImportImpl(
FirImportImpl(null, FqName.topLevel(info.name), false, null),
qualifiedReceiver.packageFqName,
qualifiedReceiver.relativeClassFqName
)
), session, components.scopeSession
)
val candidateFactory = CandidateFactory(components, info)
val qualifierScope = if (resolvedQualifier.classId == null) {
FirExplicitSimpleImportingScope(
listOf(
FirResolvedImportImpl(
FirImportImpl(source = null, importedFqName = FqName.topLevel(info.name), isAllUnder = false, aliasName = null),
resolvedQualifier.packageFqName,
relativeClassName = null
)
), session, components.scopeSession
)
} else {
QualifierReceiver(resolvedQualifier).qualifierScope(session, components.scopeSession)
}
when (info.callKind) {
CallKind.VariableAccess -> {
qualifierScope.processPropertiesByName(info.name) {
collector.consumeCandidate(0, candidateFactory.createCandidate(it, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER))
if (qualifierScope != null) {
manager.processLevel(
ScopeTowerLevel(session, components, qualifierScope), info.noStubReceiver(), TowerGroup.Qualifier
)
if (collector.isSuccess()) return collector
}
if (resolvedQualifier.classId != null) {
val typeRef = resolvedQualifier.typeRef
// NB: yet built-in Unit is used for "no-value" type
if (info.callKind == CallKind.CallableReference) {
if (info.stubReceiver != null || typeRef !is FirImplicitBuiltinTypeRef) {
runResolverForExpressionReceiver(info, collector, resolvedQualifier, manager)
}
qualifierScope.processClassifiersByName(info.name) {
if (it is FirClassSymbol<*> && it.fir.classKind == ClassKind.OBJECT) {
collector.consumeCandidate(0, candidateFactory.createCandidate(it, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER))
} else {
if (typeRef !is FirImplicitBuiltinTypeRef) {
runResolverForExpressionReceiver(info, collector, resolvedQualifier, manager)
}
}
}
manager.processQueuedLevelsForInvoke(groupLimit = TowerGroup.Last)
return collector
}
private fun runResolverForNoReceiver(
info: CallInfo,
collector: CandidateCollector,
manager: TowerResolveManager
): CandidateCollector {
val shouldProcessExtensionsBeforeMembers =
info.callKind == CallKind.Function && info.name in HIDES_MEMBERS_NAME_LIST
if (shouldProcessExtensionsBeforeMembers) {
// Special case (extension hides member)
for ((index, topLevelScope) in topLevelScopes.withIndex()) {
for ((implicitReceiverValue, usableAsValue, depth) in implicitReceivers) {
if (!usableAsValue) continue
manager.processLevel(
ScopeTowerLevel(
session, components, topLevelScope, extensionReceiver = implicitReceiverValue, extensionsOnly = true
), info, TowerGroup.TopPrioritized(index).Implicit(depth)
)
if (collector.isSuccess()) return collector
}
}
}
val nonEmptyLocalScopes = mutableListOf<FirLocalScope>()
val emptyTopLevelScopes = mutableSetOf<FirScope>()
for ((index, localScope) in localScopes.withIndex()) {
val result = manager.processLevel(
ScopeTowerLevel(session, components, localScope), info, TowerGroup.Local(index)
)
if (collector.isSuccess()) return collector
if (result != ProcessorAction.NONE) {
nonEmptyLocalScopes += localScope
}
}
val implicitReceiverValuesWithEmptyScopes = mutableSetOf<ImplicitReceiverValue<*>>()
for ((implicitReceiverValue, usableAsValue, depth) in implicitReceivers) {
// NB: companions are processed via implicitReceiverValues!
val parentGroup = TowerGroup.Implicit(depth)
if (usableAsValue) {
val implicitResult = manager.processLevel(
MemberScopeTowerLevel(
session, components, dispatchReceiver = implicitReceiverValue, scopeSession = components.scopeSession
), info, parentGroup.Member
)
if (collector.isSuccess()) return collector
if (implicitResult == ProcessorAction.NONE) {
implicitReceiverValuesWithEmptyScopes += implicitReceiverValue
}
for ((localIndex, localScope) in nonEmptyLocalScopes.withIndex()) {
manager.processLevel(
ScopeTowerLevel(
session, components, localScope, extensionReceiver = implicitReceiverValue
), info, parentGroup.Local(localIndex)
)
if (collector.isSuccess()) return collector
}
for ((implicitDispatchReceiverValue, usable, dispatchDepth) in implicitReceivers) {
if (!usable) continue
if (implicitDispatchReceiverValue in implicitReceiverValuesWithEmptyScopes) continue
manager.processLevel(
MemberScopeTowerLevel(
session,
components,
dispatchReceiver = implicitDispatchReceiverValue,
extensionReceiver = implicitReceiverValue,
scopeSession = components.scopeSession
), info, parentGroup.Implicit(dispatchDepth)
)
if (collector.isSuccess()) return collector
}
for ((topIndex, topLevelScope) in topLevelScopes.withIndex()) {
if (topLevelScope in emptyTopLevelScopes) continue
val result = manager.processLevel(
ScopeTowerLevel(
session, components, topLevelScope, extensionReceiver = implicitReceiverValue
), info, parentGroup.Top(topIndex)
)
if (collector.isSuccess()) return collector
if (result == ProcessorAction.NONE) {
emptyTopLevelScopes += topLevelScope
}
}
}
CallKind.Function -> {
qualifierScope.processFunctionsAndConstructorsByName(info.name, session, components) {
collector.consumeCandidate(0, candidateFactory.createCandidate(it, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER))
}
val invokeReceiverCollector = CandidateCollector(components, components.resolutionStageRunner)
val invokeReceiverCandidateFactory = CandidateFactory(
components,
info.replaceWithVariableAccess()
)
qualifierScope.processPropertiesByName(info.name) {
invokeReceiverCollector.consumeCandidate(
0, invokeReceiverCandidateFactory.createCandidate(it, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER)
if (implicitReceiverValue is ImplicitDispatchReceiverValue) {
val scope = implicitReceiverValue.scope(session, components.scopeSession)
if (scope != null) {
manager.processLevel(
ScopeTowerLevel(
session,
components,
FirStaticScope(scope)
), info, parentGroup.Static(depth)
)
}
if (invokeReceiverCollector.isSuccess()) {
for (invokeReceiverCandidate in invokeReceiverCollector.bestCandidates()) {
val invokeReceiverExpression = createExplicitReceiverForInvoke(invokeReceiverCandidate).let {
components.transformQualifiedAccessUsingSmartcastInfo(it)
}
runResolver(
implicitReceiverValues,
info.copy(explicitReceiver = invokeReceiverExpression, name = OperatorNameConventions.INVOKE),
collector
)
}
}
}
CallKind.CallableReference -> return collector
else -> throw AssertionError("Unsupported call kind in tower resolver: ${info.callKind}")
}
for ((index, topLevelScope) in topLevelScopes.withIndex()) {
// NB: this check does not work for variables
// because we do not search for objects if we have extension receiver
if (info.callKind != CallKind.VariableAccess && topLevelScope in emptyTopLevelScopes) continue
manager.processLevel(
ScopeTowerLevel(session, components, topLevelScope), info, TowerGroup.Top(index)
)
if (collector.isSuccess()) return collector
}
manager.processQueuedLevelsForInvoke(groupLimit = TowerGroup.Last)
return collector
}
private fun runResolverForExpressionReceiver(
info: CallInfo,
collector: CandidateCollector,
receiver: FirExpression,
manager: TowerResolveManager
): CandidateCollector {
val explicitReceiverValue = ExpressionReceiverValue(receiver)
val shouldProcessExtensionsBeforeMembers =
info.callKind == CallKind.Function && info.name in HIDES_MEMBERS_NAME_LIST
if (shouldProcessExtensionsBeforeMembers) {
// Special case (extension hides member)
for ((index, topLevelScope) in topLevelScopes.withIndex()) {
manager.processLevel(
ScopeTowerLevel(
session, components, topLevelScope, extensionReceiver = explicitReceiverValue, extensionsOnly = true
), info, TowerGroup.TopPrioritized(index), ExplicitReceiverKind.EXTENSION_RECEIVER
)
if (collector.isSuccess()) return collector
}
}
manager.processLevel(
MemberScopeTowerLevel(
session, components, dispatchReceiver = explicitReceiverValue, scopeSession = components.scopeSession
), info, TowerGroup.Member, ExplicitReceiverKind.DISPATCH_RECEIVER
)
if (collector.isSuccess()) return collector
val shouldProcessExplicitReceiverScopeOnly =
info.callKind == CallKind.Function && info.explicitReceiver?.typeRef?.coneTypeSafe<ConeIntegerLiteralType>() != null
if (shouldProcessExplicitReceiverScopeOnly) {
// Special case (integer literal type)
return collector
}
val nonEmptyLocalScopes = mutableListOf<FirLocalScope>()
for ((index, localScope) in localScopes.withIndex()) {
manager.enqueueLevelForInvoke(
ScopeTowerLevel(session, components, localScope), info, TowerGroup.Local(index),
InvokeResolveMode.RECEIVER_FOR_INVOKE_BUILTIN_EXTENSION
)
val result = manager.processLevel(
ScopeTowerLevel(
session, components, localScope, extensionReceiver = explicitReceiverValue
), info, TowerGroup.Local(index), ExplicitReceiverKind.EXTENSION_RECEIVER
)
if (collector.isSuccess()) return collector
if (result != ProcessorAction.NONE) {
nonEmptyLocalScopes += localScope
}
}
for ((implicitReceiverValue, usableAsValue, depth) in implicitReceivers) {
if (!usableAsValue) continue
// NB: companions are processed via implicitReceiverValues!
val parentGroup = TowerGroup.Implicit(depth)
manager.enqueueLevelForInvoke(
MemberScopeTowerLevel(
session, components, dispatchReceiver = implicitReceiverValue, scopeSession = components.scopeSession
), info, parentGroup.Member, InvokeResolveMode.RECEIVER_FOR_INVOKE_BUILTIN_EXTENSION
)
manager.processLevel(
MemberScopeTowerLevel(
session, components,
dispatchReceiver = implicitReceiverValue, extensionReceiver = explicitReceiverValue,
scopeSession = components.scopeSession
), info, parentGroup.Member, ExplicitReceiverKind.EXTENSION_RECEIVER
)
if (collector.isSuccess()) return collector
for ((localIndex, localScope) in nonEmptyLocalScopes.withIndex()) {
manager.enqueueLevelForInvoke(
ScopeTowerLevel(
session, components, localScope, extensionReceiver = implicitReceiverValue
), info, parentGroup.Local(localIndex), InvokeResolveMode.RECEIVER_FOR_INVOKE_BUILTIN_EXTENSION
)
}
for ((implicitDispatchReceiverValue, usable, dispatchDepth) in implicitReceivers) {
if (!usable) continue
manager.enqueueLevelForInvoke(
MemberScopeTowerLevel(
session,
components,
dispatchReceiver = implicitDispatchReceiverValue,
extensionReceiver = implicitReceiverValue,
scopeSession = components.scopeSession
), info, parentGroup.Implicit(dispatchDepth),
InvokeResolveMode.RECEIVER_FOR_INVOKE_BUILTIN_EXTENSION
)
}
for ((topIndex, topLevelScope) in topLevelScopes.withIndex()) {
manager.enqueueLevelForInvoke(
ScopeTowerLevel(
session, components, topLevelScope, extensionReceiver = implicitReceiverValue
), info, parentGroup.Top(topIndex), InvokeResolveMode.RECEIVER_FOR_INVOKE_BUILTIN_EXTENSION
)
}
}
for ((index, topLevelScope) in topLevelScopes.withIndex()) {
manager.enqueueLevelForInvoke(
ScopeTowerLevel(session, components, topLevelScope), info, TowerGroup.Top(index),
InvokeResolveMode.RECEIVER_FOR_INVOKE_BUILTIN_EXTENSION
)
manager.processLevel(
ScopeTowerLevel(
session, components, topLevelScope, extensionReceiver = explicitReceiverValue
), info, TowerGroup.Top(index), ExplicitReceiverKind.EXTENSION_RECEIVER
)
if (collector.isSuccess()) return collector
}
manager.processQueuedLevelsForInvoke(groupLimit = TowerGroup.Last)
return collector
}
internal fun enqueueResolverForInvoke(
info: CallInfo,
invokeReceiverValue: ExpressionReceiverValue,
manager: TowerResolveManager
) {
manager.enqueueLevelForInvoke(
MemberScopeTowerLevel(
session, components, dispatchReceiver = invokeReceiverValue, scopeSession = components.scopeSession
), info, TowerGroup.Member,
InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER,
ExplicitReceiverKind.DISPATCH_RECEIVER
)
for ((index, localScope) in localScopes.withIndex()) {
manager.enqueueLevelForInvoke(
ScopeTowerLevel(
session, components, localScope, extensionReceiver = invokeReceiverValue
), info, TowerGroup.Local(index),
InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER,
ExplicitReceiverKind.EXTENSION_RECEIVER
)
}
for ((implicitReceiverValue, usable, depth) in implicitReceivers) {
if (!usable) continue
// NB: companions are processed via implicitReceiverValues!
val parentGroup = TowerGroup.Implicit(depth)
manager.enqueueLevelForInvoke(
MemberScopeTowerLevel(
session, components,
dispatchReceiver = implicitReceiverValue, extensionReceiver = invokeReceiverValue,
scopeSession = components.scopeSession
), info, parentGroup.Member,
InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER,
ExplicitReceiverKind.EXTENSION_RECEIVER
)
}
for ((index, topLevelScope) in topLevelScopes.withIndex()) {
manager.enqueueLevelForInvoke(
ScopeTowerLevel(
session, components, topLevelScope, extensionReceiver = invokeReceiverValue
), info, TowerGroup.Top(index),
InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER,
ExplicitReceiverKind.EXTENSION_RECEIVER
)
}
}
// Here we already know extension receiver for invoke, and it's stated in info as first argument
internal fun enqueueResolverForBuiltinInvokeExtensionWithExplicitArgument(
info: CallInfo,
invokeReceiverValue: ExpressionReceiverValue,
manager: TowerResolveManager
) {
manager.enqueueLevelForInvoke(
MemberScopeTowerLevel(
session, components, dispatchReceiver = invokeReceiverValue,
scopeSession = components.scopeSession
), info, TowerGroup.Member,
InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER,
ExplicitReceiverKind.DISPATCH_RECEIVER
)
}
// Here we don't know extension receiver for invoke, assuming it's one of implicit receivers
internal fun enqueueResolverForBuiltinInvokeExtensionWithImplicitArgument(
info: CallInfo,
invokeReceiverValue: ExpressionReceiverValue,
manager: TowerResolveManager
) {
for ((implicitReceiverValue, usable, depth) in implicitReceivers) {
if (!usable) continue
val parentGroup = TowerGroup.Implicit(depth)
manager.enqueueLevelForInvoke(
MemberScopeTowerLevel(
session, components, dispatchReceiver = invokeReceiverValue,
extensionReceiver = implicitReceiverValue,
implicitExtensionInvokeMode = true,
scopeSession = components.scopeSession
), info, parentGroup.InvokeExtension,
InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER,
ExplicitReceiverKind.DISPATCH_RECEIVER
)
}
}
fun runResolver(
implicitReceiverValues: List<ImplicitReceiverValue<*>>,
info: CallInfo,
collector: CandidateCollector = this.collector
collector: CandidateCollector = this.collector,
manager: TowerResolveManager = this.manager
): CandidateCollector {
this.implicitReceiverValues = implicitReceiverValues
val receiver = info.explicitReceiver
if (receiver is FirResolvedQualifier && receiver.classId == null) {
return runResolverForFullyQualifiedReceiver(implicitReceiverValues, info, collector, receiver)
// TODO: add flag receiver / non-receiver position
prepareImplicitReceivers(implicitReceiverValues)
val candidateFactory = CandidateFactory(components, info)
manager.candidateFactory = candidateFactory
if (info.callKind == CallKind.CallableReference && info.stubReceiver != null) {
manager.stubReceiverCandidateFactory = candidateFactory.replaceCallInfo(info.replaceExplicitReceiver(info.stubReceiver))
}
towerDataConsumer = towerDataConsumer(info, collector)
val shouldProcessExtensionsBeforeMembers =
info.callKind == CallKind.Function && info.name in HIDES_MEMBERS_NAME_LIST
val shouldProcessExplicitReceiverScopeOnly =
info.callKind == CallKind.Function && info.explicitReceiver?.typeRef?.coneTypeSafe<ConeIntegerLiteralType>() != null
var group = 0
// Specific case when extension should be processed before members (Kotlin forEach vs Java forEach)
if (shouldProcessExtensionsBeforeMembers) {
for (topLevelScope in topLevelScopes) {
group = processTopLevelScope(towerDataConsumer, topLevelScope, group, extensionsOnly = true)
}
}
// Member of explicit receiver' type (this stage does nothing without explicit receiver)
// class Foo(val x: Int)
// fun test(f: Foo) { f.x }
towerDataConsumer.consume(EMPTY, TowerScopeLevel.Empty, group++)
if (shouldProcessExplicitReceiverScopeOnly) {
return collector
}
// Member of local scope
// fun test(x: Int) = x
val nonEmptyLocalScopes = mutableListOf<FirLocalScope>()
for (scope in localScopes) {
if (towerDataConsumer.consume(TOWER_LEVEL, ScopeTowerLevel(session, components, scope), group++) != NONE) {
nonEmptyLocalScopes += scope
}
}
var blockDispatchReceivers = false
// Member of implicit receiver' type *and* relevant scope
for (implicitReceiverValue in implicitReceiverValues) {
if (!blockDispatchReceivers || implicitReceiverValue !is ImplicitDispatchReceiverValue) {
// Direct use of implicit receiver (see inside)
group = processImplicitReceiver(towerDataConsumer, implicitReceiverValue, nonEmptyLocalScopes, group)
}
val implicitScope = implicitReceiverValue.implicitScope
if (implicitScope != null) {
// Regular implicit receiver scope (outer objects, statics)
// object Outer {
// val x = 0
// class Nested { val y = x }
// }
towerDataConsumer.consume(TOWER_LEVEL, ScopeTowerLevel(session, components, implicitScope), group++)
}
if (implicitReceiverValue is ImplicitDispatchReceiverValue) {
val implicitCompanionScopes = implicitReceiverValue.implicitCompanionScopes
for (implicitCompanionScope in implicitCompanionScopes) {
// Companion scope bound to implicit receiver scope
// class Outer {
// companion object { val x = 0 }
// class Nested { val y = x }
// }
towerDataConsumer.consume(TOWER_LEVEL, ScopeTowerLevel(session, components, implicitCompanionScope), group++)
}
if ((implicitReceiverValue.boundSymbol.fir as? FirRegularClass)?.isInner == false) {
blockDispatchReceivers = true
manager.resultCollector = collector
if (info.callKind == CallKind.Function) {
manager.invokeReceiverCollector = CandidateCollector(components, components.resolutionStageRunner)
manager.invokeReceiverCandidateFactory = CandidateFactory(components, info.replaceWithVariableAccess())
if (info.explicitReceiver != null) {
with(manager.invokeReceiverCandidateFactory) {
manager.invokeBuiltinExtensionReceiverCandidateFactory = replaceCallInfo(callInfo.replaceExplicitReceiver(null))
}
}
}
for (topLevelScope in topLevelScopes) {
group = processTopLevelScope(towerDataConsumer, topLevelScope, group)
return when (val receiver = info.explicitReceiver) {
is FirResolvedQualifier -> runResolverForQualifierReceiver(info, collector, receiver, manager)
null -> runResolverForNoReceiver(info, collector, manager)
else -> runResolverForExpressionReceiver(info, collector, receiver, manager)
}
return collector
}
}
fun reset() {
collector.newDataSet()
manager.reset()
}
}
@@ -74,7 +74,8 @@ class PostponedArgumentsAnalyzer(
val callableReferenceAccess = atom.reference
atom.analyzed = true
val (candidate, applicability) = atom.resultingCandidate ?: Pair(null, CandidateApplicability.INAPPLICABLE)
val (candidate, applicability) = atom.resultingCandidate
?: Pair(null, CandidateApplicability.INAPPLICABLE)
val namedReference = when {
candidate == null || applicability < CandidateApplicability.SYNTHETIC_RESOLVED ->
@@ -40,14 +40,19 @@ internal object CheckExplicitReceiverConsistency : ResolutionStage() {
// TODO: add invoke cases
when (receiverKind) {
NO_EXPLICIT_RECEIVER -> {
if (explicitReceiver != null && explicitReceiver !is FirResolvedQualifier)
if (explicitReceiver != null && explicitReceiver !is FirResolvedQualifier) {
return sink.yieldApplicability(CandidateApplicability.WRONG_RECEIVER)
}
}
EXTENSION_RECEIVER, DISPATCH_RECEIVER -> {
if (explicitReceiver == null) return sink.yieldApplicability(CandidateApplicability.WRONG_RECEIVER)
if (explicitReceiver == null) {
return sink.yieldApplicability(CandidateApplicability.WRONG_RECEIVER)
}
}
BOTH_RECEIVERS -> {
if (explicitReceiver == null) return sink.yieldApplicability(CandidateApplicability.WRONG_RECEIVER)
if (explicitReceiver == null) {
return sink.yieldApplicability(CandidateApplicability.WRONG_RECEIVER)
}
// Here we should also check additional invoke receiver
}
}
@@ -284,13 +289,11 @@ internal object CheckVisibility : CheckerStage() {
private fun ImplicitReceiverStack.canSeePrivateMemberOf(ownerId: ClassId): Boolean {
for (implicitReceiverValue in receiversAsReversed()) {
if (implicitReceiverValue !is ImplicitDispatchReceiverValue) continue
if (implicitReceiverValue.companionFromSupertype) continue
val boundSymbol = implicitReceiverValue.boundSymbol
if (boundSymbol.classId.isSame(ownerId)) {
return true
}
if (boundSymbol is FirRegularClassSymbol && boundSymbol.fir.companionObject?.symbol?.classId?.isSame(ownerId) == true) {
return true
}
}
return false
}
@@ -316,6 +319,7 @@ internal object CheckVisibility : CheckerStage() {
val visited = mutableSetOf<ClassId>()
for (implicitReceiverValue in receiversAsReversed()) {
if (implicitReceiverValue !is ImplicitDispatchReceiverValue) continue
if (implicitReceiverValue.companionFromSupertype) continue
val boundSymbol = implicitReceiverValue.boundSymbol
val superTypes = boundSymbol.fir.superConeTypes
for (superType in superTypes) {
@@ -1,266 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.resolve.constructClassType
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.ConeStarProjection
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.types.AbstractTypeChecker
abstract class TowerDataConsumer {
abstract val resultCollector: CandidateCollector
abstract fun consume(
kind: TowerDataKind,
towerScopeLevel: TowerScopeLevel,
group: Int
): ProcessorAction
private var stopGroup = Int.MAX_VALUE
fun skipGroup(group: Int): Boolean {
if (stopGroup == Int.MAX_VALUE && resultCollector.isSuccess()) {
stopGroup = group
}
if (group >= stopGroup) return true
return false
}
}
class PrioritizedTowerDataConsumer(
override val resultCollector: CandidateCollector,
private vararg val consumers: TowerDataConsumer
) : TowerDataConsumer() {
override fun consume(
kind: TowerDataKind,
towerScopeLevel: TowerScopeLevel,
group: Int
): ProcessorAction {
if (skipGroup(group)) return ProcessorAction.NEXT
var empty = true
for ((index, consumer) in consumers.withIndex()) {
when (val action = consumer.consume(kind, towerScopeLevel, group * consumers.size + index)) {
ProcessorAction.STOP -> return action
ProcessorAction.NEXT -> empty = false
}
}
return if (empty) ProcessorAction.NONE else ProcessorAction.NEXT
}
}
// Yet is used exclusively for invokes:
// - initialConsumer consumes property which is invoke receiver
// - additionalConsumers consume invoke calls themselves
class AccumulatingTowerDataConsumer(
override val resultCollector: CandidateCollector
) : TowerDataConsumer() {
lateinit var initialConsumer: TowerDataConsumer
private val additionalConsumers = mutableListOf<TowerDataConsumer>()
private data class TowerData(val kind: TowerDataKind, val level: TowerScopeLevel, val group: Int)
private val accumulatedTowerData = mutableListOf<TowerData>()
override fun consume(
kind: TowerDataKind,
towerScopeLevel: TowerScopeLevel,
group: Int
): ProcessorAction {
if (skipGroup(group)) return ProcessorAction.NEXT
accumulatedTowerData += TowerData(kind, towerScopeLevel, group)
var empty = true
when (val action = initialConsumer.consume(kind, towerScopeLevel, group)) {
ProcessorAction.STOP -> return action
ProcessorAction.NEXT -> empty = false
}
for (consumer in additionalConsumers) {
when (val action = consumer.consume(kind, towerScopeLevel, group)) {
ProcessorAction.STOP -> return action
ProcessorAction.NEXT -> empty = false
}
}
return if (empty) ProcessorAction.NONE else ProcessorAction.NEXT
}
fun addConsumerAndProcessAccumulatedData(consumer: TowerDataConsumer): ProcessorAction {
additionalConsumers += consumer
if (accumulatedTowerData.isEmpty()) return ProcessorAction.NEXT
for ((kind, level, group) in accumulatedTowerData.asSequence().take(accumulatedTowerData.size - 1)) {
if (consumer.consume(kind, level, group).stop()) {
return ProcessorAction.STOP
}
}
return ProcessorAction.NEXT
}
}
class ExplicitReceiverTowerDataConsumer<T : AbstractFirBasedSymbol<*>>(
val session: FirSession,
val name: Name,
val token: TowerScopeLevel.Token<T>,
val explicitReceiver: AbstractExplicitReceiver<*>,
val candidateFactory: CandidateFactory,
override val resultCollector: CandidateCollector
) : TowerDataConsumer() {
companion object {
val defaultPackage = Name.identifier("kotlin")
}
override fun consume(
kind: TowerDataKind,
towerScopeLevel: TowerScopeLevel,
group: Int
): ProcessorAction {
if (skipGroup(group)) return ProcessorAction.NEXT
return when (kind) {
TowerDataKind.EMPTY -> {
MemberScopeTowerLevel(
session, resultCollector.components, explicitReceiver,
implicitExtensionReceiver = (towerScopeLevel as? TowerScopeLevel.OnlyImplicitReceiver)?.implicitReceiverValue,
implicitExtensionInvokeMode = towerScopeLevel is TowerScopeLevel.OnlyImplicitReceiver,
scopeSession = candidateFactory.bodyResolveComponents.scopeSession
).processElementsByName(
token,
name,
explicitReceiver = null,
processor = EmptyKindTowerProcessor(group)
)
}
TowerDataKind.TOWER_LEVEL -> {
if (token == TowerScopeLevel.Token.Objects) return ProcessorAction.NEXT
towerScopeLevel.processElementsByName(
token,
name,
explicitReceiver = explicitReceiver,
processor = TowerLevelKindTowerProcessor(group)
)
}
}
}
private inner class EmptyKindTowerProcessor(val group: Int) : TowerScopeLevel.TowerScopeLevelProcessor<T> {
override fun consumeCandidate(
symbol: T,
dispatchReceiverValue: ReceiverValue?,
implicitExtensionReceiverValue: ImplicitReceiverValue<*>?,
builtInExtensionFunctionReceiverValue: ReceiverValue?
) {
resultCollector.consumeCandidate(
group,
candidateFactory.createCandidate(
symbol,
ExplicitReceiverKind.DISPATCH_RECEIVER,
dispatchReceiverValue,
implicitExtensionReceiverValue,
builtInExtensionFunctionReceiverValue
)
)
}
}
private inner class TowerLevelKindTowerProcessor(val group: Int) : TowerScopeLevel.TowerScopeLevelProcessor<T> {
override fun consumeCandidate(
symbol: T,
dispatchReceiverValue: ReceiverValue?,
implicitExtensionReceiverValue: ImplicitReceiverValue<*>?,
builtInExtensionFunctionReceiverValue: ReceiverValue?
) {
if (symbol is FirNamedFunctionSymbol && symbol.callableId.packageName.startsWith(defaultPackage)) {
val explicitReceiverType = explicitReceiver.type
if (dispatchReceiverValue == null && explicitReceiverType is ConeClassLikeType) {
val declarationReceiverTypeRef =
(symbol as? FirCallableSymbol<*>)?.fir?.receiverTypeRef as? FirResolvedTypeRef
val declarationReceiverType = declarationReceiverTypeRef?.type
if (declarationReceiverType is ConeClassLikeType) {
if (!AbstractTypeChecker.isSubtypeOf(
candidateFactory.bodyResolveComponents.inferenceComponents.ctx,
explicitReceiverType,
declarationReceiverType.lookupTag.constructClassType(
declarationReceiverType.typeArguments.map { ConeStarProjection }.toTypedArray(),
isNullable = true
)
)
) {
return
}
}
}
}
val candidate = candidateFactory.createCandidate(
symbol,
ExplicitReceiverKind.EXTENSION_RECEIVER,
dispatchReceiverValue,
implicitExtensionReceiverValue,
builtInExtensionFunctionReceiverValue
)
resultCollector.consumeCandidate(
group,
candidate
)
}
}
}
class NoExplicitReceiverTowerDataConsumer<T : AbstractFirBasedSymbol<*>>(
val session: FirSession,
val name: Name,
val token: TowerScopeLevel.Token<T>,
val candidateFactory: CandidateFactory,
override val resultCollector: CandidateCollector
) : TowerDataConsumer() {
override fun consume(
kind: TowerDataKind,
towerScopeLevel: TowerScopeLevel,
group: Int
): ProcessorAction {
if (skipGroup(group)) return ProcessorAction.NEXT
return when (kind) {
TowerDataKind.TOWER_LEVEL -> {
towerScopeLevel.processElementsByName(
token,
name,
explicitReceiver = null,
processor = TowerLevelProcessorImpl(group)
)
}
else -> ProcessorAction.NEXT
}
}
private inner class TowerLevelProcessorImpl(val group: Int) : TowerScopeLevel.TowerScopeLevelProcessor<T> {
override fun consumeCandidate(
symbol: T,
dispatchReceiverValue: ReceiverValue?,
implicitExtensionReceiverValue: ImplicitReceiverValue<*>?,
builtInExtensionFunctionReceiverValue: ReceiverValue?
) {
resultCollector.consumeCandidate(
group,
candidateFactory.createCandidate(
symbol,
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER,
dispatchReceiverValue,
implicitExtensionReceiverValue,
builtInExtensionFunctionReceiverValue
)
)
}
}
}
@@ -0,0 +1,104 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.resolve.calls
sealed class TowerGroupKind(private val index: Int) : Comparable<TowerGroupKind> {
abstract class WithDepth(index: Int, val depth: Int) : TowerGroupKind(index)
object Start : TowerGroupKind(Integer.MIN_VALUE)
class Weakened(depth: Int) : WithDepth(-10, depth)
object Qualifier : TowerGroupKind(0)
class TopPrioritized(depth: Int) : WithDepth(1, depth)
object Member : TowerGroupKind(2)
class Local(depth: Int) : WithDepth(3, depth)
class Implicit(depth: Int) : WithDepth(4, depth)
object InvokeExtension : TowerGroupKind(5)
class Top(depth: Int) : WithDepth(6, depth)
class Static(depth: Int) : WithDepth(7, depth)
object Last : TowerGroupKind(Integer.MAX_VALUE)
override fun compareTo(other: TowerGroupKind): Int {
val indexResult = index.compareTo(other.index)
if (indexResult != 0) return indexResult
if (this is WithDepth && other is WithDepth) {
return depth.compareTo(other.depth)
}
return 0
}
}
@Suppress("FunctionName", "unused", "PropertyName")
class TowerGroup private constructor(private val list: List<TowerGroupKind>) : Comparable<TowerGroup> {
companion object {
private fun kindOf(kind: TowerGroupKind): TowerGroup = TowerGroup(listOf(kind))
val Start = kindOf(TowerGroupKind.Start)
val Qualifier = kindOf(TowerGroupKind.Qualifier)
val Member = kindOf(TowerGroupKind.Member)
fun Local(depth: Int) = kindOf(TowerGroupKind.Local(depth))
fun Implicit(depth: Int) = kindOf(TowerGroupKind.Implicit(depth))
fun Top(depth: Int) = kindOf(TowerGroupKind.Top(depth))
fun TopPrioritized(depth: Int) = kindOf(TowerGroupKind.TopPrioritized(depth))
fun Static(depth: Int) = kindOf(TowerGroupKind.Static(depth))
val Last = kindOf(TowerGroupKind.Last)
}
private fun kindOf(kind: TowerGroupKind): TowerGroup = TowerGroup(list + kind)
fun Weakened(depth: Int) = kindOf(TowerGroupKind.Weakened(depth))
val Qualifier get() = kindOf(TowerGroupKind.Qualifier)
val Member get() = kindOf(TowerGroupKind.Member)
fun Local(depth: Int) = kindOf(TowerGroupKind.Local(depth))
fun Implicit(depth: Int) = kindOf(TowerGroupKind.Implicit(depth))
val InvokeExtension get() = kindOf(TowerGroupKind.InvokeExtension)
fun Top(depth: Int) = kindOf(TowerGroupKind.Top(depth))
fun Static(depth: Int) = kindOf(TowerGroupKind.Static(depth))
override fun compareTo(other: TowerGroup): Int {
var index = 0
while (index < list.size) {
if (index >= other.list.size) return 1
when {
list[index] < other.list[index] -> return -1
list[index] > other.list[index] -> return 1
}
index++
}
if (index < other.list.size) return -1
return 0
}
}
fun main() {
println(TowerGroup.Member < TowerGroup.Last)
println(TowerGroup.Member < TowerGroup.Member.Weakened(1))
println(TowerGroup.Member.Weakened(1) < TowerGroup.Member)
}
@@ -0,0 +1,25 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
internal class TowerInvokeResolveQuery(
val towerLevel: SessionBasedTowerLevel,
val callInfo: CallInfo,
val explicitReceiverKind: ExplicitReceiverKind,
val group: TowerGroup,
val mode: InvokeResolveMode
) : Comparable<TowerInvokeResolveQuery> {
override fun compareTo(other: TowerInvokeResolveQuery): Int {
return group.compareTo(other.group)
}
}
enum class InvokeResolveMode {
IMPLICIT_CALL_ON_GIVEN_RECEIVER,
RECEIVER_FOR_INVOKE_BUILTIN_EXTENSION
}
@@ -6,10 +6,7 @@
package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
import org.jetbrains.kotlin.fir.declarations.FirConstructor
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
import org.jetbrains.kotlin.fir.declarations.isStatic
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
import org.jetbrains.kotlin.fir.resolve.ScopeSession
@@ -18,11 +15,11 @@ import org.jetbrains.kotlin.fir.resolve.withNullability
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.impl.FirAbstractImportingScope
import org.jetbrains.kotlin.fir.scopes.impl.FirQualifierScope
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.ConeNullability
import org.jetbrains.kotlin.fir.types.isExtensionFunctionType
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.utils.addToStdlib.cast
@@ -39,7 +36,6 @@ interface TowerScopeLevel {
fun <T : AbstractFirBasedSymbol<*>> processElementsByName(
token: Token<T>,
name: Name,
explicitReceiver: AbstractExplicitReceiver<*>?,
processor: TowerScopeLevelProcessor<T>
): ProcessorAction
@@ -51,19 +47,6 @@ interface TowerScopeLevel {
builtInExtensionFunctionReceiverValue: ReceiverValue? = null
)
}
abstract class StubTowerScopeLevel : TowerScopeLevel {
override fun <T : AbstractFirBasedSymbol<*>> processElementsByName(
token: Token<T>,
name: Name,
explicitReceiver: AbstractExplicitReceiver<*>?,
processor: TowerScopeLevelProcessor<T>
): ProcessorAction = ProcessorAction.NEXT
}
object Empty : StubTowerScopeLevel()
class OnlyImplicitReceiver(val implicitReceiverValue: ImplicitReceiverValue<*>) : StubTowerScopeLevel()
}
abstract class SessionBasedTowerLevel(val session: FirSession) : TowerScopeLevel {
@@ -77,12 +60,11 @@ abstract class SessionBasedTowerLevel(val session: FirSession) : TowerScopeLevel
}
}
protected fun FirCallableSymbol<*>.hasConsistentExtensionReceiver(extensionReceiver: ReceiverValue?): Boolean {
return when {
extensionReceiver != null -> hasExtensionReceiver()
else -> fir.receiverTypeRef == null
}
protected fun FirCallableSymbol<*>.hasConsistentExtensionReceiver(extensionReceiver: Receiver?): Boolean {
return (extensionReceiver != null) == hasExtensionReceiver()
}
open fun replaceReceiverValue(receiverValue: ReceiverValue) = this
}
// This is more like "dispatch receiver-based tower level"
@@ -93,73 +75,82 @@ abstract class SessionBasedTowerLevel(val session: FirSession) : TowerScopeLevel
// or given implicit or explicit receiver, otherwise
class MemberScopeTowerLevel(
session: FirSession,
val bodyResolveComponents: BodyResolveComponents,
private val bodyResolveComponents: BodyResolveComponents,
val dispatchReceiver: ReceiverValue,
val implicitExtensionReceiver: ImplicitReceiverValue<*>? = null,
val extensionReceiver: ReceiverValue? = null,
val implicitExtensionInvokeMode: Boolean = false,
val scopeSession: ScopeSession
) : SessionBasedTowerLevel(session) {
private fun <T : AbstractFirBasedSymbol<*>> processMembers(
output: TowerScopeLevel.TowerScopeLevelProcessor<T>,
explicitExtensionReceiver: AbstractExplicitReceiver<*>?,
processScopeMembers: FirScope.(processor: (T) -> Unit) -> Unit
) {
if (implicitExtensionReceiver != null && explicitExtensionReceiver != null) return
val extensionReceiver = implicitExtensionReceiver ?: explicitExtensionReceiver
val scope = dispatchReceiver.scope(session, scopeSession) ?: return
): ProcessorAction {
var empty = true
val scope = dispatchReceiver.scope(session, scopeSession) ?: return ProcessorAction.NONE
scope.processScopeMembers { candidate ->
empty = false
if (candidate is FirCallableSymbol<*> &&
(implicitExtensionInvokeMode || candidate.hasConsistentExtensionReceiver(extensionReceiver))
) {
val fir = candidate.fir
if ((fir as? FirCallableMemberDeclaration<*>)?.isStatic == true || (fir as? FirConstructor)?.isInner == false) {
return@processScopeMembers
}
val dispatchReceiverValue = NotNullableReceiverValue(dispatchReceiver)
if (implicitExtensionInvokeMode) {
output.consumeCandidate(
candidate, dispatchReceiverValue,
implicitExtensionReceiverValue = implicitExtensionReceiver
implicitExtensionReceiverValue = extensionReceiver as? ImplicitReceiverValue<*>
)
output.consumeCandidate(
candidate, dispatchReceiverValue,
implicitExtensionReceiverValue = null,
builtInExtensionFunctionReceiverValue = implicitExtensionReceiver
builtInExtensionFunctionReceiverValue = this.extensionReceiver
)
} else {
output.consumeCandidate(candidate, dispatchReceiverValue, implicitExtensionReceiver, null)
output.consumeCandidate(candidate, dispatchReceiverValue, extensionReceiver as? ImplicitReceiverValue<*>)
}
} else if (candidate is FirClassLikeSymbol<*>) {
output.consumeCandidate(candidate, null, implicitExtensionReceiver, null)
output.consumeCandidate(candidate, null, extensionReceiver as? ImplicitReceiverValue<*>)
}
}
val withSynthetic = FirSyntheticPropertiesScope(session, scope)
withSynthetic.processScopeMembers { symbol ->
output.consumeCandidate(symbol, NotNullableReceiverValue(dispatchReceiver), implicitExtensionReceiver, null)
output.consumeCandidate(symbol, NotNullableReceiverValue(dispatchReceiver), extensionReceiver as? ImplicitReceiverValue<*>)
}
return if (empty) ProcessorAction.NONE else ProcessorAction.NEXT
}
override fun <T : AbstractFirBasedSymbol<*>> processElementsByName(
token: TowerScopeLevel.Token<T>,
name: Name,
explicitReceiver: AbstractExplicitReceiver<*>?,
processor: TowerScopeLevel.TowerScopeLevelProcessor<T>
): ProcessorAction {
val isInvoke = name == OperatorNameConventions.INVOKE && token == TowerScopeLevel.Token.Functions
if (implicitExtensionInvokeMode && !isInvoke) {
return ProcessorAction.NEXT
}
val explicitExtensionReceiver = if (dispatchReceiver == explicitReceiver) null else explicitReceiver
val noInnerConstructors = dispatchReceiver is QualifierReceiver
when (token) {
TowerScopeLevel.Token.Properties -> processMembers(processor, explicitExtensionReceiver) { symbol ->
return when (token) {
TowerScopeLevel.Token.Properties -> processMembers(processor) { symbol ->
this.processPropertiesByName(name, symbol.cast())
}
TowerScopeLevel.Token.Functions -> processMembers(processor, explicitExtensionReceiver) { symbol ->
this.processFunctionsAndConstructorsByName(name, session, bodyResolveComponents, noInnerConstructors, symbol.cast())
TowerScopeLevel.Token.Functions -> processMembers(processor) { symbol ->
this.processFunctionsAndConstructorsByName(
name, session, bodyResolveComponents,
noInnerConstructors = false, processor = symbol.cast()
)
}
TowerScopeLevel.Token.Objects -> processMembers(processor, explicitExtensionReceiver) { symbol ->
TowerScopeLevel.Token.Objects -> processMembers(processor) { symbol ->
this.processClassifiersByName(name, symbol.cast())
}
}
return ProcessorAction.NEXT
}
override fun replaceReceiverValue(receiverValue: ReceiverValue): SessionBasedTowerLevel {
return MemberScopeTowerLevel(
session, bodyResolveComponents, receiverValue, extensionReceiver, implicitExtensionInvokeMode, scopeSession
)
}
}
@@ -174,10 +165,10 @@ class ScopeTowerLevel(
session: FirSession,
private val bodyResolveComponents: BodyResolveComponents,
val scope: FirScope,
val implicitExtensionReceiver: ImplicitReceiverValue<*>? = null,
val extensionReceiver: ReceiverValue? = null,
private val extensionsOnly: Boolean = false
) : SessionBasedTowerLevel(session) {
private fun FirCallableSymbol<*>.hasConsistentReceivers(extensionReceiver: ReceiverValue?): Boolean =
private fun FirCallableSymbol<*>.hasConsistentReceivers(extensionReceiver: Receiver?): Boolean =
when {
extensionsOnly && !hasExtensionReceiver() -> false
!hasConsistentExtensionReceiver(extensionReceiver) -> false
@@ -188,43 +179,43 @@ class ScopeTowerLevel(
override fun <T : AbstractFirBasedSymbol<*>> processElementsByName(
token: TowerScopeLevel.Token<T>,
name: Name,
explicitReceiver: AbstractExplicitReceiver<*>?,
processor: TowerScopeLevel.TowerScopeLevelProcessor<T>
): ProcessorAction {
if (explicitReceiver != null && implicitExtensionReceiver != null) {
return ProcessorAction.NEXT
}
val extensionReceiver = explicitReceiver ?: implicitExtensionReceiver
var empty = true
@Suppress("UNCHECKED_CAST")
when (token) {
TowerScopeLevel.Token.Properties -> scope.processPropertiesByName(name) { candidate ->
empty = false
if (candidate.hasConsistentReceivers(extensionReceiver)) {
processor.consumeCandidate(
candidate as T, dispatchReceiverValue = null,
implicitExtensionReceiverValue = implicitExtensionReceiver
implicitExtensionReceiverValue = extensionReceiver as? ImplicitReceiverValue<*>
)
}
}
TowerScopeLevel.Token.Functions -> scope.processFunctionsAndConstructorsByName(
name,
session,
bodyResolveComponents
bodyResolveComponents,
noInnerConstructors = scope is FirQualifierScope
) { candidate ->
empty = false
if (candidate.hasConsistentReceivers(extensionReceiver)) {
processor.consumeCandidate(
candidate as T, dispatchReceiverValue = null,
implicitExtensionReceiverValue = implicitExtensionReceiver
implicitExtensionReceiverValue = extensionReceiver as? ImplicitReceiverValue<*>
)
}
}
TowerScopeLevel.Token.Objects -> scope.processClassifiersByName(name) {
empty = false
processor.consumeCandidate(
it as T, dispatchReceiverValue = null,
implicitExtensionReceiverValue = null
)
}
}
return ProcessorAction.NEXT
return if (empty) ProcessorAction.NONE else ProcessorAction.NEXT
}
}
@@ -246,6 +237,5 @@ fun FirCallableDeclaration<*>.dispatchReceiverValue(session: FirSession): ClassD
}
private fun FirCallableSymbol<*>.hasExtensionReceiver(): Boolean {
if (fir.receiverTypeRef != null) return true
return fir.returnTypeRef.isExtensionFunctionType()
return fir.receiverTypeRef != null
}
@@ -0,0 +1,306 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
import org.jetbrains.kotlin.fir.expressions.impl.FirQualifiedAccessExpressionImpl
import org.jetbrains.kotlin.fir.resolve.constructClassType
import org.jetbrains.kotlin.fir.resolve.transformQualifiedAccessUsingSmartcastInfo
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.util.OperatorNameConventions
import java.util.*
class TowerResolveManager internal constructor(private val towerResolver: FirTowerResolver) {
private val queue = PriorityQueue<TowerInvokeResolveQuery>()
private var group = TowerGroup.Start
lateinit var candidateFactory: CandidateFactory
lateinit var invokeOnGivenReceiverCandidateFactory: CandidateFactory
lateinit var invokeReceiverCandidateFactory: CandidateFactory
lateinit var invokeBuiltinExtensionReceiverCandidateFactory: CandidateFactory
lateinit var stubReceiverCandidateFactory: CandidateFactory
lateinit var resultCollector: CandidateCollector
lateinit var invokeReceiverCollector: CandidateCollector
private class TowerScopeLevelProcessor(
val explicitReceiver: FirExpression?,
val explicitReceiverKind: ExplicitReceiverKind,
val resultCollector: CandidateCollector,
val candidateFactory: CandidateFactory,
val group: TowerGroup
) : TowerScopeLevel.TowerScopeLevelProcessor<AbstractFirBasedSymbol<*>> {
override fun consumeCandidate(
symbol: AbstractFirBasedSymbol<*>,
dispatchReceiverValue: ReceiverValue?,
implicitExtensionReceiverValue: ImplicitReceiverValue<*>?,
builtInExtensionFunctionReceiverValue: ReceiverValue?
) {
// Check explicit extension receiver for default package members
if (symbol is FirNamedFunctionSymbol && dispatchReceiverValue == null &&
(implicitExtensionReceiverValue == null) != (explicitReceiver == null) &&
explicitReceiver !is FirResolvedQualifier &&
symbol.callableId.packageName.startsWith(defaultPackage)
) {
val extensionReceiverType = explicitReceiver?.typeRef?.coneTypeSafe()
?: implicitExtensionReceiverValue?.type as? ConeClassLikeType
if (extensionReceiverType != null) {
val declarationReceiverTypeRef =
(symbol as? FirCallableSymbol<*>)?.fir?.receiverTypeRef as? FirResolvedTypeRef
val declarationReceiverType = declarationReceiverTypeRef?.type
if (declarationReceiverType is ConeClassLikeType) {
if (!AbstractTypeChecker.isSubtypeOf(
candidateFactory.bodyResolveComponents.inferenceComponents.ctx,
extensionReceiverType,
declarationReceiverType.lookupTag.constructClassType(
declarationReceiverType.typeArguments.map { ConeStarProjection }.toTypedArray(),
isNullable = true
)
)
) {
return
}
}
}
}
// ---
resultCollector.consumeCandidate(
group, candidateFactory.createCandidate(
symbol,
explicitReceiverKind,
dispatchReceiverValue,
implicitExtensionReceiverValue,
builtInExtensionFunctionReceiverValue
)
)
}
companion object {
val defaultPackage = Name.identifier("kotlin")
}
}
private inner class LevelHandler(
val info: CallInfo,
val explicitReceiverKind: ExplicitReceiverKind,
val group: TowerGroup
) {
private fun createExplicitReceiverForInvoke(candidate: Candidate): FirQualifiedAccessExpressionImpl {
val symbol = candidate.symbol as FirCallableSymbol<*>
return FirQualifiedAccessExpressionImpl(null).apply {
calleeReference = FirNamedReferenceWithCandidate(
null,
symbol.callableId.callableName,
candidate
)
dispatchReceiver = candidate.dispatchReceiverExpression()
typeRef = towerResolver.typeCalculator.tryCalculateReturnType(symbol.firUnsafe())
}
}
fun SessionBasedTowerLevel.handleLevel(invokeResolveMode: InvokeResolveMode? = null): ProcessorAction {
var result = ProcessorAction.NONE
val processor =
TowerScopeLevelProcessor(
info.explicitReceiver,
explicitReceiverKind,
resultCollector,
// TODO: performance?
if (invokeResolveMode == InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER) {
invokeOnGivenReceiverCandidateFactory
} else candidateFactory,
group
)
when (info.callKind) {
CallKind.VariableAccess -> {
result += processElementsByName(TowerScopeLevel.Token.Properties, info.name, processor)
// TODO: more accurate condition, or process properties/object in some other way
if (!resultCollector.isSuccess() &&
(this !is ScopeTowerLevel || this.extensionReceiver == null)
) {
result += processElementsByName(TowerScopeLevel.Token.Objects, info.name, processor)
}
}
CallKind.Function -> {
val invokeBuiltinExtensionMode =
invokeResolveMode == InvokeResolveMode.RECEIVER_FOR_INVOKE_BUILTIN_EXTENSION
if (!invokeBuiltinExtensionMode) {
result += processElementsByName(TowerScopeLevel.Token.Functions, info.name, processor)
}
if (invokeResolveMode == InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER ||
resultCollector.isSuccess()
) {
return result
}
val invokeReceiverProcessor = TowerScopeLevelProcessor(
info.explicitReceiver,
explicitReceiverKind,
invokeReceiverCollector,
if (invokeBuiltinExtensionMode) invokeBuiltinExtensionReceiverCandidateFactory
else invokeReceiverCandidateFactory,
group
)
invokeReceiverCollector.newDataSet()
result += processElementsByName(TowerScopeLevel.Token.Properties, info.name, invokeReceiverProcessor)
if (invokeReceiverCollector.isSuccess()) {
for (invokeReceiverCandidate in invokeReceiverCollector.bestCandidates()) {
val symbol = invokeReceiverCandidate.symbol as FirCallableSymbol<*>
val isExtensionFunctionType = symbol.fir.returnTypeRef.isExtensionFunctionType()
if (invokeBuiltinExtensionMode && !isExtensionFunctionType) {
continue
}
val extensionReceiverExpression = invokeReceiverCandidate.extensionReceiverExpression()
val useImplicitReceiverAsBuiltinInvokeArgument =
!invokeBuiltinExtensionMode && isExtensionFunctionType &&
invokeReceiverCandidate.explicitReceiverKind == ExplicitReceiverKind.NO_EXPLICIT_RECEIVER
val invokeReceiverExpression = createExplicitReceiverForInvoke(invokeReceiverCandidate).let {
if (!invokeBuiltinExtensionMode) {
it.extensionReceiver = extensionReceiverExpression
// NB: this should fix problem in DFA (KT-36014)
it.explicitReceiver = info.explicitReceiver
it.safe = info.isSafeCall
}
towerResolver.components.transformQualifiedAccessUsingSmartcastInfo(it)
}
val invokeFunctionInfo =
info.copy(explicitReceiver = invokeReceiverExpression, name = OperatorNameConventions.INVOKE).let {
when {
invokeBuiltinExtensionMode -> it.withReceiverAsArgument(info.explicitReceiver!!)
else -> it
}
}
val explicitReceiver = ExpressionReceiverValue(invokeReceiverExpression)
invokeOnGivenReceiverCandidateFactory = CandidateFactory(towerResolver.components, invokeFunctionInfo)
when {
invokeBuiltinExtensionMode -> {
towerResolver.enqueueResolverForBuiltinInvokeExtensionWithExplicitArgument(
invokeFunctionInfo, explicitReceiver, this@TowerResolveManager
)
}
useImplicitReceiverAsBuiltinInvokeArgument -> {
towerResolver.enqueueResolverForBuiltinInvokeExtensionWithImplicitArgument(
invokeFunctionInfo, explicitReceiver, this@TowerResolveManager
)
towerResolver.enqueueResolverForInvoke(
invokeFunctionInfo, explicitReceiver, this@TowerResolveManager
)
}
else -> {
towerResolver.enqueueResolverForInvoke(
invokeFunctionInfo, explicitReceiver, this@TowerResolveManager
)
}
}
}
processQueuedLevelsForInvoke()
}
}
CallKind.CallableReference -> {
val stubReceiver = info.stubReceiver
if (stubReceiver != null) {
val stubReceiverValue = ExpressionReceiverValue(stubReceiver)
val stubProcessor = TowerScopeLevelProcessor(
info.explicitReceiver,
if (this is MemberScopeTowerLevel && dispatchReceiver is AbstractExplicitReceiver<*>) {
ExplicitReceiverKind.DISPATCH_RECEIVER
} else {
ExplicitReceiverKind.EXTENSION_RECEIVER
},
resultCollector,
stubReceiverCandidateFactory, group
)
val towerLevelWithStubReceiver = replaceReceiverValue(stubReceiverValue)
with(towerLevelWithStubReceiver) {
result += processElementsByName(TowerScopeLevel.Token.Functions, info.name, stubProcessor)
result += processElementsByName(TowerScopeLevel.Token.Properties, info.name, stubProcessor)
}
// NB: we don't perform this for implicit Unit
if (!resultCollector.isSuccess() && info.explicitReceiver?.typeRef !is FirImplicitBuiltinTypeRef) {
result += processElementsByName(TowerScopeLevel.Token.Functions, info.name, processor)
result += processElementsByName(TowerScopeLevel.Token.Properties, info.name, processor)
}
} else {
result += processElementsByName(TowerScopeLevel.Token.Functions, info.name, processor)
result += processElementsByName(TowerScopeLevel.Token.Properties, info.name, processor)
}
}
else -> {
throw AssertionError("Unsupported call kind in tower resolver: ${info.callKind}")
}
}
return result
}
}
fun reset() {
queue.clear()
group = TowerGroup.Start
}
fun processLevel(
towerLevel: SessionBasedTowerLevel,
callInfo: CallInfo,
group: TowerGroup,
explicitReceiverKind: ExplicitReceiverKind = ExplicitReceiverKind.NO_EXPLICIT_RECEIVER
): ProcessorAction {
assert(group > this.group) {
"Incorrect TowerGroup processing order (c) Mikhail Glukhikh"
}
this.group = group
val result = with(LevelHandler(callInfo, explicitReceiverKind, group)) {
towerLevel.handleLevel()
}
processQueuedLevelsForInvoke()
return result
}
fun enqueueLevelForInvoke(
towerLevel: SessionBasedTowerLevel,
callInfo: CallInfo,
group: TowerGroup,
mode: InvokeResolveMode,
explicitReceiverKind: ExplicitReceiverKind = ExplicitReceiverKind.NO_EXPLICIT_RECEIVER
) {
if (callInfo.callKind == CallKind.Function) {
queue.add(TowerInvokeResolveQuery(towerLevel, callInfo, explicitReceiverKind, group, mode))
}
}
fun processQueuedLevelsForInvoke(groupLimit: TowerGroup = this.group) {
while (queue.isNotEmpty()) {
if (queue.peek().group > groupLimit) {
break
}
val query = queue.poll()
with(LevelHandler(query.callInfo, query.explicitReceiverKind, query.group)) {
query.towerLevel.handleLevel(invokeResolveMode = query.mode)
}
}
}
}
@@ -15,8 +15,7 @@ import org.jetbrains.kotlin.fir.diagnostics.FirSimpleDiagnostic
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirStatement
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.calls.ImplicitDispatchReceiverValue
import org.jetbrains.kotlin.fir.resolve.calls.ImplicitExtensionReceiverValue
import org.jetbrains.kotlin.fir.resolve.calls.*
import org.jetbrains.kotlin.fir.resolve.calls.extractLambdaInfoFromFunctionalType
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.transformers.*
@@ -493,8 +492,24 @@ class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer)
type: ConeKotlinType,
block: () -> T
): T {
val implicitCompanionValues = mutableListOf<ImplicitReceiverValue<*>>()
val implicitReceiverValue = when (owner) {
is FirClass<*> -> {
// Questionable: performance
(owner as? FirRegularClass)?.companionObject?.let { companion ->
implicitCompanionValues += ImplicitDispatchReceiverValue(
companion.symbol, session, scopeSession, kind = ImplicitDispatchReceiverKind.COMPANION
)
}
lookupSuperTypes(owner, lookupInterfaces = false, deep = true, useSiteSession = session).mapNotNull {
val superClass = (it as? ConeClassLikeType)?.lookupTag?.toSymbol(session)?.fir as? FirRegularClass
superClass?.companionObject?.let { companion ->
implicitCompanionValues += ImplicitDispatchReceiverValue(
companion.symbol, session, scopeSession, kind = ImplicitDispatchReceiverKind.COMPANION_FROM_SUPERTYPE
)
}
}
// ---
ImplicitDispatchReceiverValue(owner.symbol, type, session, scopeSession)
}
is FirFunction<*> -> {
@@ -507,9 +522,15 @@ class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer)
throw IllegalArgumentException("Incorrect label & receiver owner: ${owner.javaClass}")
}
}
for (implicitCompanionValue in implicitCompanionValues.asReversed()) {
implicitReceiverStack.add(null, implicitCompanionValue)
}
implicitReceiverStack.add(labelName, implicitReceiverValue)
val result = block()
implicitReceiverStack.pop(labelName)
for (implicitCompanionValue in implicitCompanionValues) {
implicitReceiverStack.pop(null)
}
return result
}
@@ -14,10 +14,7 @@ import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.impl.FirErrorExpressionImpl
import org.jetbrains.kotlin.fir.expressions.impl.FirFunctionCallImpl
import org.jetbrains.kotlin.fir.expressions.impl.FirVariableAssignmentImpl
import org.jetbrains.kotlin.fir.references.FirDelegateFieldReference
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.references.FirSuperReference
import org.jetbrains.kotlin.fir.references.FirThisReference
import org.jetbrains.kotlin.fir.references.*
import org.jetbrains.kotlin.fir.references.impl.FirErrorNamedReferenceImpl
import org.jetbrains.kotlin.fir.references.impl.FirExplicitThisReference
import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference
@@ -81,8 +81,6 @@ class KotlinScopeProvider(
): FirScope? {
return when (klass.classKind) {
ClassKind.ENUM_CLASS -> FirStaticScope(declaredMemberScope(klass))
// TODO: should be wrapped with FirStaticScope, non-static callables should be processed separately
ClassKind.OBJECT -> getUseSiteMemberScope(klass, ConeSubstitutor.Empty, useSiteSession, scopeSession)
else -> null
}
}
@@ -10,11 +10,18 @@ import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.declarations.isStatic
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
import org.jetbrains.kotlin.name.Name
class FirStaticScope(private val delegateScope: FirScope) : FirScope() {
override fun processClassifiersByName(name: Name, processor: (FirClassifierSymbol<*>) -> Unit) {
delegateScope.processClassifiersByName(name) {
processor(it)
}
}
override fun processFunctionsByName(
name: Name,
processor: (FirFunctionSymbol<*>) -> Unit
@@ -0,0 +1,30 @@
package org.jetbrains.kotlin.codegen.range.inExpression
class CallBasedInExpressionGenerator(
val codegen: ExpressionCodegen,
operatorReference: KtSimpleNameExpression
) : InExpressionGenerator {
private val resolvedCall = operatorReference.<!UNRESOLVED_REFERENCE!>getResolvedCallWithAssert<!>(codegen.<!UNRESOLVED_REFERENCE!>bindingContext<!>)
private val isInverted = operatorReference.<!UNRESOLVED_REFERENCE!>getReferencedNameElementType<!>() == <!UNRESOLVED_REFERENCE!>KtTokens<!>.<!UNRESOLVED_REFERENCE!>NOT_IN<!>
override fun generate(argument: StackValue): BranchedValue =
gen(argument).<!INAPPLICABLE_CANDIDATE!>let<!> { if (isInverted) <!UNRESOLVED_REFERENCE!>Invert<!>(<!UNRESOLVED_REFERENCE!>it<!>) else <!UNRESOLVED_REFERENCE!>it<!> }
private fun gen(argument: StackValue): BranchedValue =
object : BranchedValue(argument, null, argument.<!UNRESOLVED_REFERENCE!>type<!>, <!UNRESOLVED_REFERENCE!>Opcodes<!>.<!UNRESOLVED_REFERENCE!>IFEQ<!>) {
override fun putSelector(type: Type, kotlinType: KotlinType?, v: InstructionAdapter) {
invokeFunction(v)
<!UNRESOLVED_REFERENCE!>coerceTo<!>(type, kotlinType, v)
}
override fun condJump(jumpLabel: Label, v: InstructionAdapter, jumpIfFalse: Boolean) {
invokeFunction(v)
v.<!UNRESOLVED_REFERENCE!>visitJumpInsn<!>(if (jumpIfFalse) <!UNRESOLVED_REFERENCE!>Opcodes<!>.<!UNRESOLVED_REFERENCE!>IFEQ<!> else <!UNRESOLVED_REFERENCE!>Opcodes<!>.<!UNRESOLVED_REFERENCE!>IFNE<!>, jumpLabel)
}
private fun invokeFunction(v: InstructionAdapter) {
val result = codegen.<!UNRESOLVED_REFERENCE!>invokeFunction<!>(resolvedCall.<!UNRESOLVED_REFERENCE!>call<!>, resolvedCall, <!UNRESOLVED_REFERENCE!>none<!>())
result.<!UNRESOLVED_REFERENCE!>put<!>(result.<!UNRESOLVED_REFERENCE!>type<!>, result.<!UNRESOLVED_REFERENCE!>kotlinType<!>, v)
}
}
}
@@ -0,0 +1,64 @@
FILE: CallBasedInExpressionGenerator.kt
public final class CallBasedInExpressionGenerator : R|class error: Symbol not found, for `InExpressionGenerator`| {
public constructor(codegen: R|class error: Symbol not found, for `ExpressionCodegen`|, operatorReference: R|class error: Symbol not found, for `KtSimpleNameExpression`|): R|org/jetbrains/kotlin/codegen/range/inExpression/CallBasedInExpressionGenerator| {
super<R|kotlin/Any|>()
}
public final val codegen: R|class error: Symbol not found, for `ExpressionCodegen`| = R|<local>/codegen|
public get(): R|class error: Symbol not found, for `ExpressionCodegen`|
private final val resolvedCall: <ERROR TYPE REF: Unresolved name: getResolvedCallWithAssert> = R|<local>/operatorReference|.<Unresolved name: getResolvedCallWithAssert>#(R|<local>/codegen|.<Unresolved name: bindingContext>#)
private get(): <ERROR TYPE REF: Unresolved name: getResolvedCallWithAssert>
private final val isInverted: R|kotlin/Boolean| = ==(R|<local>/operatorReference|.<Unresolved name: getReferencedNameElementType>#(), <Unresolved name: KtTokens>#.<Unresolved name: NOT_IN>#)
private get(): R|kotlin/Boolean|
public final override fun generate(argument: R|class error: Symbol not found, for `StackValue`|): R|class error: Symbol not found, for `BranchedValue`| {
^generate R?C|org/jetbrains/kotlin/codegen/range/inExpression/CallBasedInExpressionGenerator.gen|(R|<local>/argument|).<Inapplicable(WRONG_RECEIVER): [kotlin/let]>#(<L> = let@fun <anonymous>(): R|class error: Can't resolve when expression| {
when () {
this@R|org/jetbrains/kotlin/codegen/range/inExpression/CallBasedInExpressionGenerator|.R|org/jetbrains/kotlin/codegen/range/inExpression/CallBasedInExpressionGenerator.isInverted| -> {
<Unresolved name: Invert>#(<Unresolved name: it>#)
}
else -> {
<Unresolved name: it>#
}
}
}
)
}
private final fun gen(argument: R|class error: Symbol not found, for `StackValue`|): R|class error: Symbol not found, for `BranchedValue`| {
^gen object : R|class error: Symbol not found, for `BranchedValue`| {
private constructor(): R|class error: Symbol not found, for `BranchedValue`| {
super<R|class error: Symbol not found, for `BranchedValue`|>(R|<local>/argument|, Null(null), R|<local>/argument|.<Unresolved name: type>#, <Unresolved name: Opcodes>#.<Unresolved name: IFEQ>#)
}
public final override fun putSelector(type: R|class error: Symbol not found, for `Type`|, kotlinType: R|class error: Symbol not found, for `KotlinType?`|, v: R|class error: Symbol not found, for `InstructionAdapter`|): R|kotlin/Unit| {
this@R|/anonymous|.R|/anonymous.invokeFunction|(R|<local>/v|)
<Unresolved name: coerceTo>#(R|<local>/type|, R|<local>/kotlinType|, R|<local>/v|)
}
public final override fun condJump(jumpLabel: R|class error: Symbol not found, for `Label`|, v: R|class error: Symbol not found, for `InstructionAdapter`|, jumpIfFalse: R|kotlin/Boolean|): R|kotlin/Unit| {
this@R|/anonymous|.R|/anonymous.invokeFunction|(R|<local>/v|)
R|<local>/v|.<Unresolved name: visitJumpInsn>#(when () {
R|<local>/jumpIfFalse| -> {
<Unresolved name: Opcodes>#.<Unresolved name: IFEQ>#
}
else -> {
<Unresolved name: Opcodes>#.<Unresolved name: IFNE>#
}
}
, R|<local>/jumpLabel|)
}
private final fun invokeFunction(v: R|class error: Symbol not found, for `InstructionAdapter`|): R|kotlin/Unit| {
lval result: <ERROR TYPE REF: Unresolved name: invokeFunction> = this@R|org/jetbrains/kotlin/codegen/range/inExpression/CallBasedInExpressionGenerator|.R|org/jetbrains/kotlin/codegen/range/inExpression/CallBasedInExpressionGenerator.codegen|.<Unresolved name: invokeFunction>#(this@R|org/jetbrains/kotlin/codegen/range/inExpression/CallBasedInExpressionGenerator|.R|org/jetbrains/kotlin/codegen/range/inExpression/CallBasedInExpressionGenerator.resolvedCall|.<Unresolved name: call>#, this@R|org/jetbrains/kotlin/codegen/range/inExpression/CallBasedInExpressionGenerator|.R|org/jetbrains/kotlin/codegen/range/inExpression/CallBasedInExpressionGenerator.resolvedCall|, <Unresolved name: none>#())
R|<local>/result|.<Unresolved name: put>#(R|<local>/result|.<Unresolved name: type>#, R|<local>/result|.<Unresolved name: kotlinType>#, R|<local>/v|)
}
}
}
}
@@ -0,0 +1,10 @@
class Factory {
sealed class Function {
object Default
}
companion object {
val f = Function
val x = Function.Default
}
}
@@ -0,0 +1,34 @@
FILE: classifierAccessFromCompanion.kt
public final class Factory : R|kotlin/Any| {
public constructor(): R|Factory| {
super<R|kotlin/Any|>()
}
public sealed class Function : R|kotlin/Any| {
public constructor(): R|Factory.Function| {
super<R|kotlin/Any|>()
}
public final object Default : R|kotlin/Any| {
private constructor(): R|Factory.Function.Default| {
super<R|kotlin/Any|>()
}
}
}
public final companion object Companion : R|kotlin/Any| {
private constructor(): R|Factory.Companion| {
super<R|kotlin/Any|>()
}
public final val f: R|kotlin/Unit| = Q|Factory.Function|
public get(): R|kotlin/Unit|
public final val x: R|Factory.Function.Default| = Q|Factory.Function.Default|
public get(): R|Factory.Function.Default|
}
}
@@ -18,7 +18,7 @@ FILE: companion.kt
}
public final fun bar(): R|kotlin/Unit| {
R|/A.Companion.foo|()
this@R|/A.Companion|.R|/A.Companion.foo|()
}
}
@@ -15,7 +15,7 @@ FILE: companionExtension.kt
}
public final fun test(): R|kotlin/Unit| {
this@R|/My|.R|/My.Companion.foo|()
(this@R|/My.Companion|, this@R|/My|).R|/My.Companion.foo|()
}
}
@@ -9,5 +9,5 @@ class My {
}
fun Your.foo() {
val x = ::Nested // Still should be error
val x = <!UNRESOLVED_REFERENCE!>::Nested<!> // Still should be error
}
@@ -23,5 +23,5 @@ FILE: errCallable.kt
}
public final fun R|Your|.foo(): R|kotlin/Unit| {
lval x: R|kotlin/reflect/KFunction0<Your.Nested>| = ::R|/Your.Nested.Nested|
lval x: <ERROR TYPE REF: No result type for initializer> = ::<Unresolved name: Nested>#
}
@@ -0,0 +1,13 @@
open class Base {
companion object {
val some = 0
}
}
class Outer {
val codegen = ""
inner class Inner : Base() {
val c = codegen
}
}
@@ -0,0 +1,36 @@
FILE: innerWithSuperCompanion.kt
public open class Base : R|kotlin/Any| {
public constructor(): R|Base| {
super<R|kotlin/Any|>()
}
public final companion object Companion : R|kotlin/Any| {
private constructor(): R|Base.Companion| {
super<R|kotlin/Any|>()
}
public final val some: R|kotlin/Int| = Int(0)
public get(): R|kotlin/Int|
}
}
public final class Outer : R|kotlin/Any| {
public constructor(): R|Outer| {
super<R|kotlin/Any|>()
}
public final val codegen: R|kotlin/String| = String()
public get(): R|kotlin/String|
public final inner class Inner : R|Base| {
public constructor(): R|Outer.Inner| {
super<R|Base|>()
}
public final val c: R|kotlin/String| = this@R|/Outer|.R|/Outer.codegen|
public get(): R|kotlin/String|
}
}
@@ -0,0 +1,10 @@
object X
class Y {
fun f(op: X.() -> Unit) {
X.op()
val x = X
x.op()
}
}
@@ -0,0 +1,19 @@
FILE: extensionOnObject.kt
public final object X : R|kotlin/Any| {
private constructor(): R|X| {
super<R|kotlin/Any|>()
}
}
public final class Y : R|kotlin/Any| {
public constructor(): R|Y| {
super<R|kotlin/Any|>()
}
public final fun f(op: R|X.() -> kotlin/Unit|): R|kotlin/Unit| {
R|<local>/op|.R|FakeOverride<kotlin/Function1.invoke: R|kotlin/Unit|>|(Q|X|)
lval x: R|X| = Q|X|
R|<local>/op|.R|FakeOverride<kotlin/Function1.invoke: R|kotlin/Unit|>|(R|<local>/x|)
}
}
@@ -1,8 +1,10 @@
fun String.invoke() = this
operator fun String.invoke() = this
val some = ""
fun sss() {
val some = 10
<!INAPPLICABLE_CANDIDATE!>some<!>() // Should be inapplicable
// Should be resolved to top-level some,
// because with local some invoke isn't applicable
some()
}
@@ -1,10 +1,10 @@
FILE: incorrectInvokeReceiver.kt
public final fun R|kotlin/String|.invoke(): R|kotlin/String| {
public final operator fun R|kotlin/String|.invoke(): R|kotlin/String| {
^invoke this@R|/invoke|
}
public final val some: R|kotlin/String| = String()
public get(): R|kotlin/String|
public final fun sss(): R|kotlin/Unit| {
lval some: R|kotlin/Int| = Int(10)
<Inapplicable(WRONG_RECEIVER): [/invoke]>#()
R|/some|.R|/invoke|()
}
@@ -12,10 +12,11 @@ class Foo {
val Buz.foobar: Bar get() = Bar()
fun FooBar.chk(buz: Buz) {
// NB: really this example is unresolvable (in old FE too)
// local/buz is extension receiver of foobar
// this@Foo is dispatch receiver of foobar
// Foo/foobar is dispatch receiver of invoke
// this@chk is extension receiver of invoke
buz.foobar()
buz.<!UNRESOLVED_REFERENCE!>foobar<!>()
}
}
@@ -32,7 +32,7 @@ FILE: threeReceivers.kt
}
public final fun R|FooBar|.chk(buz: R|Buz|): R|kotlin/Unit| {
((this@R|/Foo|, R|<local>/buz|).R|/Foo.foobar|, this@R|/Foo.chk|).R|/Bar.invoke|()
R|<local>/buz|.<Unresolved name: foobar>#()
}
}
@@ -0,0 +1,26 @@
class C
class B
class A {
val B.foo: C.() -> Unit get() = null
}
fun <T, R> with(arg: T, f: T.() -> R): R = arg.f()
fun test(a: A, b: B, c: C) {
with(a) {
with(c) {
b.foo(c)
// [this@a,b].foo.invoke(c)
}
with(b) {
c.foo()
// [this@a,this@b].foo.invoke(c)
with(c) {
foo()
// [this@a,this@b].foo.invoke(this@c)
}
}
}
}
@@ -0,0 +1,44 @@
FILE: threeReceiversCorrect.kt
public final class C : R|kotlin/Any| {
public constructor(): R|C| {
super<R|kotlin/Any|>()
}
}
public final class B : R|kotlin/Any| {
public constructor(): R|B| {
super<R|kotlin/Any|>()
}
}
public final class A : R|kotlin/Any| {
public constructor(): R|A| {
super<R|kotlin/Any|>()
}
public final val R|B|.foo: R|C.() -> kotlin/Unit|
public get(): R|C.() -> kotlin/Unit| {
^ Null(null)
}
}
public final fun <T, R> with(arg: R|T|, f: R|T.() -> R|): R|R| {
^with R|<local>/f|.R|FakeOverride<kotlin/Function1.invoke: R|R|>|(R|<local>/arg|)
}
public final fun test(a: R|A|, b: R|B|, c: R|C|): R|kotlin/Unit| {
R|/with|<R|A|, R|kotlin/Unit|>(R|<local>/a|, <L> = with@fun R|A|.<anonymous>(): R|kotlin/Unit| {
R|/with|<R|C|, R|kotlin/Unit|>(R|<local>/c|, <L> = with@fun R|C|.<anonymous>(): R|kotlin/Unit| {
(this@R|special/anonymous|, R|<local>/b|).R|/A.foo|.R|FakeOverride<kotlin/Function1.invoke: R|kotlin/Unit|>|(R|<local>/c|)
}
)
R|/with|<R|B|, R|kotlin/Unit|>(R|<local>/b|, <L> = with@fun R|B|.<anonymous>(): R|kotlin/Unit| {
this@R|special/anonymous|.R|/A.foo|.R|FakeOverride<kotlin/Function1.invoke: R|kotlin/Unit|>|(R|<local>/c|)
R|/with|<R|C|, R|kotlin/Unit|>(R|<local>/c|, <L> = with@fun R|C|.<anonymous>(): R|kotlin/Unit| {
(this@R|special/anonymous|, this@R|special/anonymous|).R|/A.foo|.R|FakeOverride<kotlin/Function1.invoke: R|kotlin/Unit|>|(this@R|special/anonymous|)
}
)
}
)
}
)
}
@@ -1,5 +1,5 @@
FILE: test.kt
public final fun test(): R|kotlin/Unit| {
lval staticReference: R|kotlin/reflect/KMutableProperty1<JavaClass, ft<kotlin/String, kotlin/String?>!>| = Q|JavaClass|::R|/JavaClass.staticField|
lval staticReference: R|kotlin/reflect/KMutableProperty0<ft<kotlin/String, kotlin/String?>!>| = Q|JavaClass|::R|/JavaClass.staticField|
lval nonStaticReference: R|kotlin/reflect/KMutableProperty1<JavaClass, ft<kotlin/String, kotlin/String?>!>| = Q|JavaClass|::R|/JavaClass.nonStaticField|
}
@@ -0,0 +1,11 @@
class Outer {
fun foo() {
class Local {
fun bar() {
val x = y
}
}
}
val y = ""
}
@@ -0,0 +1,24 @@
FILE: localClassAccessesContainingClass.kt
public final class Outer : R|kotlin/Any| {
public constructor(): R|Outer| {
super<R|kotlin/Any|>()
}
public final fun foo(): R|kotlin/Unit| {
local final class Local : R|kotlin/Any| {
public constructor(): R|Outer.Local| {
super<R|kotlin/Any|>()
}
public final fun bar(): R|kotlin/Unit| {
lval x: R|kotlin/String| = this@R|/Outer|.R|/Outer.y|
}
}
}
public final val y: R|kotlin/String| = String()
public get(): R|kotlin/String|
}
@@ -0,0 +1,8 @@
class A {
class Nested
fun main() {
val x = ::Nested
val y = A::Nested
}
}
@@ -0,0 +1,19 @@
FILE: nestedConstructorCallable.kt
public final class A : R|kotlin/Any| {
public constructor(): R|A| {
super<R|kotlin/Any|>()
}
public final class Nested : R|kotlin/Any| {
public constructor(): R|A.Nested| {
super<R|kotlin/Any|>()
}
}
public final fun main(): R|kotlin/Unit| {
lval x: R|kotlin/reflect/KFunction0<A.Nested>| = ::R|/A.Nested.Nested|
lval y: R|kotlin/reflect/KFunction0<A.Nested>| = Q|A|::R|/A.Nested.Nested|
}
}
@@ -0,0 +1,10 @@
object A {
object B {
object A
}
}
object B
val err = B.<!UNRESOLVED_REFERENCE!>A<!>.<!UNRESOLVED_REFERENCE!>B<!>
val correct = A.B.A
@@ -0,0 +1,31 @@
FILE: nestedObjects.kt
public final object A : R|kotlin/Any| {
private constructor(): R|A| {
super<R|kotlin/Any|>()
}
public final object B : R|kotlin/Any| {
private constructor(): R|A.B| {
super<R|kotlin/Any|>()
}
public final object A : R|kotlin/Any| {
private constructor(): R|A.B.A| {
super<R|kotlin/Any|>()
}
}
}
}
public final object B : R|kotlin/Any| {
private constructor(): R|B| {
super<R|kotlin/Any|>()
}
}
public final val err: <ERROR TYPE REF: Unresolved name: B> = Q|B|.<Unresolved name: A>#.<Unresolved name: B>#
public get(): <ERROR TYPE REF: Unresolved name: B>
public final val correct: R|A.B.A| = Q|A.B.A|
public get(): R|A.B.A|
@@ -0,0 +1,45 @@
// FILE: Base.java
public class Base {
protected String foo() { return ""; }
}
// FILE: O.kt
open class Wrapper(val b: Boolean)
object O {
private class Derived(private val bar: Int) : Base() {
private inner class Some(val z: Boolean) {
fun test() {
val x = bar
val o = object : Wrapper(z) {
fun local() {
val y = foo()
}
val oo = object {
val zz = z
}
}
}
}
fun test() {
val x = bar
val o = object {
fun local() {
val y = foo()
}
}
}
}
}
class Generator(val codegen: Any) {
private fun gen(): Any =
object : Wrapper(true) {
private fun invokeFunction() {
val c = codegen
val cc = codegen.hashCode()
}
}
}
@@ -0,0 +1,102 @@
FILE: O.kt
public open class Wrapper : R|kotlin/Any| {
public constructor(b: R|kotlin/Boolean|): R|Wrapper| {
super<R|kotlin/Any|>()
}
public final val b: R|kotlin/Boolean| = R|<local>/b|
public get(): R|kotlin/Boolean|
}
public final object O : R|kotlin/Any| {
private constructor(): R|O| {
super<R|kotlin/Any|>()
}
private final class Derived : R|Base| {
public constructor(bar: R|kotlin/Int|): R|O.Derived| {
super<R|Base|>()
}
private final val bar: R|kotlin/Int| = R|<local>/bar|
private get(): R|kotlin/Int|
private final inner class Some : R|kotlin/Any| {
public constructor(z: R|kotlin/Boolean|): R|O.Derived.Some| {
super<R|kotlin/Any|>()
}
public final val z: R|kotlin/Boolean| = R|<local>/z|
public get(): R|kotlin/Boolean|
public final fun test(): R|kotlin/Unit| {
lval x: R|kotlin/Int| = this@R|/O.Derived|.R|/O.Derived.bar|
lval o: R|anonymous| = object : R|Wrapper| {
private constructor(): R|Wrapper| {
super<R|Wrapper|>(this@R|/O.Derived.Some|.R|/O.Derived.Some.z|)
}
public final fun local(): R|kotlin/Unit| {
lval y: R|ft<kotlin/String, kotlin/String?>!| = this@R|/O.Derived|.R|/Base.foo|()
}
public final val oo: R|anonymous| = object : R|kotlin/Any| {
private constructor(): R|kotlin/Any| {
super<R|kotlin/Any|>()
}
public final val zz: R|kotlin/Boolean| = R|<local>/z|
public get(): R|kotlin/Boolean|
}
public get(): R|anonymous|
}
}
}
public final fun test(): R|kotlin/Unit| {
lval x: R|kotlin/Int| = this@R|/O.Derived|.R|/O.Derived.bar|
lval o: R|anonymous| = object : R|kotlin/Any| {
private constructor(): R|kotlin/Any| {
super<R|kotlin/Any|>()
}
public final fun local(): R|kotlin/Unit| {
lval y: R|ft<kotlin/String, kotlin/String?>!| = this@R|/O.Derived|.R|/Base.foo|()
}
}
}
}
}
public final class Generator : R|kotlin/Any| {
public constructor(codegen: R|kotlin/Any|): R|Generator| {
super<R|kotlin/Any|>()
}
public final val codegen: R|kotlin/Any| = R|<local>/codegen|
public get(): R|kotlin/Any|
private final fun gen(): R|kotlin/Any| {
^gen object : R|Wrapper| {
private constructor(): R|Wrapper| {
super<R|Wrapper|>(Boolean(true))
}
private final fun invokeFunction(): R|kotlin/Unit| {
lval c: R|kotlin/Any| = this@R|/Generator|.R|/Generator.codegen|
lval cc: R|kotlin/Int| = this@R|/Generator|.R|/Generator.codegen|.R|kotlin/Any.hashCode|()
}
}
}
}
@@ -15,11 +15,11 @@ FILE: outerObject.kt
super<R|kotlin/Any|>()
}
public final val y: R|kotlin/Int| = R|/Outer.x|
public final val y: R|kotlin/Int| = this@R|/Outer|.R|/Outer.x|
public get(): R|kotlin/Int|
public final fun test(): R|kotlin/Unit| {
this@R|/Outer.Nested|.R|/Outer.foo|()
(this@R|/Outer|, this@R|/Outer.Nested|).R|/Outer.foo|()
}
}
@@ -11,8 +11,8 @@ FILE: first.kt
public final fun baz(): R|kotlin/Unit| {
this@R|/Private|.R|/Private.bar|()
this@R|/Private|.R|/Private.Nested.Nested|()
R|/Private.Companion.fromCompanion|()
R|/Private.Nested.Nested|()
this@R|/Private.Companion|.R|/Private.Companion.fromCompanion|()
Q|Private.NotCompanion|.<Inapplicable(HIDDEN): [/Private.NotCompanion.foo]>#()
}
@@ -23,7 +23,7 @@ FILE: first.kt
public final fun foo(): R|kotlin/Unit| {
this@R|/Private|.R|/Private.bar|()
R|/Private.Companion.fromCompanion|()
this@R|/Private.Companion|.R|/Private.Companion.fromCompanion|()
Q|Private.NotCompanion|.<Inapplicable(HIDDEN): [/Private.NotCompanion.foo]>#()
}
@@ -35,7 +35,7 @@ FILE: first.kt
}
public final fun foo(): R|kotlin/Unit| {
R|/Private.Companion.fromCompanion|()
this@R|/Private.Companion|.R|/Private.Companion.fromCompanion|()
Q|Private.NotCompanion|.<Inapplicable(HIDDEN): [/Private.NotCompanion.foo]>#()
}
@@ -9,7 +9,7 @@ FILE: protectedVisibility.kt
public final fun baz(): R|kotlin/Unit| {
this@R|/Protected|.R|/Protected.bar|()
this@R|/Protected|.R|/Protected.Nested.Nested|().R|/Protected.Nested.foo|()
R|/Protected.Nested.Nested|().R|/Protected.Nested.foo|()
}
public final inner class Inner : R|kotlin/Any| {
@@ -58,9 +58,9 @@ FILE: protectedVisibility.kt
public final fun foo(): R|kotlin/Unit| {
this@R|/Derived|.R|/Protected.bar|()
this@R|/Derived|.R|/Protected.Nested.Nested|().R|/Protected.Nested.foo|()
this@R|/Derived|.R|/Protected.Nested.Nested|().<Inapplicable(HIDDEN): [/Protected.Nested.bar]>#()
R|/Protected.Companion.fromCompanion|()
R|/Protected.Nested.Nested|().R|/Protected.Nested.foo|()
R|/Protected.Nested.Nested|().<Inapplicable(HIDDEN): [/Protected.Nested.bar]>#()
this@R|/Protected.Companion|.R|/Protected.Companion.fromCompanion|()
<Inapplicable(HIDDEN): [/Protected.Companion.protectedFromCompanion]>#()
}
@@ -10,7 +10,7 @@ class A {
}
val ab = A.B // property
val abc = A.B.<!UNRESOLVED_REFERENCE!>C<!> // object
val abc = A.B.C // object
object D {
class E {
@@ -34,5 +34,5 @@ enum class G {
}
}
val gh = G.<!AMBIGUITY!>H<!> // companion property
val gv = G.<!AMBIGUITY!>values<!>() // static function
val gh = G.H // companion property
val gv = G.values() // static function
@@ -29,10 +29,10 @@ FILE: qualifierPriority.kt
}
}
public final val ab: R|kotlin/String| = Q|A|.R|/A.Companion.B|
public get(): R|kotlin/String|
public final val abc: <ERROR TYPE REF: Unresolved name: C> = Q|A|.R|/A.Companion.B|.<Unresolved name: C>#
public get(): <ERROR TYPE REF: Unresolved name: C>
public final val ab: R|A.B| = Q|A.B|
public get(): R|A.B|
public final val abc: R|A.B.C| = Q|A.B.C|
public get(): R|A.B.C|
public final object D : R|kotlin/Any| {
private constructor(): R|D| {
super<R|kotlin/Any|>()
@@ -94,7 +94,7 @@ FILE: qualifierPriority.kt
}
}
public final val gh: <ERROR TYPE REF: Ambiguity: H, [/G.H, /G.Companion.H]> = Q|G|.<Ambiguity: H, [/G.H, /G.Companion.H]>#
public get(): <ERROR TYPE REF: Ambiguity: H, [/G.H, /G.Companion.H]>
public final val gv: <ERROR TYPE REF: Ambiguity: values, [/G.values, /G.Companion.values]> = Q|G|.<Ambiguity: values, [/G.values, /G.Companion.values]>#()
public get(): <ERROR TYPE REF: Ambiguity: values, [/G.values, /G.Companion.values]>
public final val gh: R|G| = Q|G|.R|/G.H|
public get(): R|G|
public final val gv: R|kotlin/Array<G>| = Q|G|.R|/G.values|()
public get(): R|kotlin/Array<G>|
@@ -6,7 +6,7 @@ class C {
class Nested {
fun test() {
err()
<!UNRESOLVED_REFERENCE!>err<!>()
}
}
}
@@ -18,7 +18,7 @@ FILE: receiverConsistency.kt
}
public final fun test(): R|kotlin/Unit| {
R|/C.err|()
<Unresolved name: err>#()
}
}
@@ -76,7 +76,7 @@ FILE: enums.kt
}
public final val g: R|kotlin/Double| = R|/Planet.Companion.G|.R|kotlin/Double.times|(R|<local>/m|).R|kotlin/Double.div|(R|<local>/r|.R|kotlin/Double.times|(R|<local>/r|))
public final val g: R|kotlin/Double| = this@R|/Planet.Companion|.R|/Planet.Companion.G|.R|kotlin/Double.times|(R|<local>/m|).R|kotlin/Double.div|(R|<local>/r|.R|kotlin/Double.times|(R|<local>/r|))
public get(): R|kotlin/Double|
public abstract fun sayHello(): R|kotlin/Unit|
+2 -2
View File
@@ -64,14 +64,14 @@ FILE: localObject.kt
^ Int(1)
}
public final val z: R|kotlin/Int| = R|/run|<R|kotlin/Int|>(<L> = run@fun <anonymous>(): R|kotlin/Int| {
public final val z: R|kotlin/Int| = this@R|/TestProperty|.R|kotlin/run|<R|TestProperty|, R|kotlin/Int|>(<L> = run@fun R|TestProperty|.<anonymous>(): R|kotlin/Int| <kind=EXACTLY_ONCE> {
lval obj: R|anonymous| = object : R|Foo| {
private constructor(): R|kotlin/Any| {
super<R|kotlin/Any|>()
}
public final override fun foo(): R|kotlin/Int| {
^foo this@R|/TestProperty|.R|/TestProperty.x|.R|kotlin/Int.plus|(Int(1))
^foo this@R|special/anonymous|.R|/TestProperty.x|.R|kotlin/Int.plus|(Int(1))
}
}
+1 -1
View File
@@ -22,7 +22,7 @@ class Owner {
}
fun err() {
foo()
<!UNRESOLVED_REFERENCE!>foo<!>()
this.<!UNRESOLVED_REFERENCE!>foo<!>()
}
}
+2 -2
View File
@@ -10,7 +10,7 @@ FILE: simple.kt
}
public final fun bar(): R|kotlin/Unit| {
lval n: R|Owner.Nested| = this@R|/Owner|.R|/Owner.Nested.Nested|()
lval n: R|Owner.Nested| = R|/Owner.Nested.Nested|()
R|<local>/n|.R|/Owner.Nested.baz|()
}
@@ -30,7 +30,7 @@ FILE: simple.kt
}
public final fun err(): R|kotlin/Unit| {
R|/Owner.foo|()
<Unresolved name: foo>#()
this@R|/Owner.Nested|.<Unresolved name: foo>#()
}
@@ -40,12 +40,12 @@ FILE: nestedClassNameClash.kt
}
public final fun test_5(): R|kotlin/Unit| {
lval result: R|Foo.Result| = this@R|/Foo|.R|/Foo.Result.Result|()
lval result: R|Foo.Result| = R|/Foo.Result.Result|()
this@R|/Foo|.R|/Foo.saveResult|(R|<local>/result|)
}
private final fun getResult(): R|Foo.Result| {
^getResult this@R|/Foo|.R|/Foo.Result.Result|()
^getResult R|/Foo.Result.Result|()
}
private final fun saveResults(results: R|kotlin/collections/List<Foo.Result>|): R|kotlin/Unit| {
+1 -1
View File
@@ -12,7 +12,7 @@ FILE: nestedReturnType.kt
}
public final fun foo(): R|Some.Nested| {
^foo this@R|/Some|.R|/Some.Nested.Nested|()
^foo R|/Some.Nested.Nested|()
}
}
@@ -10,7 +10,7 @@ FILE: nestedClassContructor.kt
}
public final fun copy(): R|A.B| {
^copy this@R|/A.B|.R|/A.B.B|()
^copy R|/A.B.B|()
}
}
@@ -46,7 +46,7 @@ FILE: nestedClassContructor.kt
public final fun foo(): R|kotlin/Unit| {
lval a: R|A| = R|/A.A|()
lval c: R|A.C| = this@R|/E|.R|/A.C.C|()
lval c: R|A.C| = R|/A.C.C|()
}
}
@@ -24,5 +24,5 @@ FILE: qualifierWithCompanion.kt
local final fun R|my/A|.invoke(): R|kotlin/Unit| {
}
R|my/xx|.R|<local>/invoke|()
Q|my|.R|my/xx|.R|<local>/invoke|()
}
@@ -30,13 +30,16 @@ fun foo3(x: (String) -> Int) {}
fun main() {
foo1(KotlinClass::baz)
foo2(KotlinClass::baz)
// Ambiguity (companion/class)
<!AMBIGUITY!>foo3<!>(KotlinClass::baz)
// Type mismatch
<!INAPPLICABLE_CANDIDATE!>foo1<!>(KotlinClass::bar)
foo2(KotlinClass::bar)
foo3(KotlinClass::bar)
foo1(KotlinClass2::bar)
// Type mismatch
<!INAPPLICABLE_CANDIDATE!>foo2<!>(KotlinClass2::bar)
foo3(KotlinClass2::bar)
}
@@ -57,6 +57,6 @@ FILE: main.kt
R|/foo2|(Q|KotlinClass|::R|/JavaClass.bar|)
R|/foo3|(Q|KotlinClass|::R|/JavaClass.bar|)
R|/foo1|(Q|KotlinClass2|::R|/KotlinClass2.Companion.bar|)
<Inapplicable(INAPPLICABLE): [/foo2]>#(Q|KotlinClass2|::R|/JavaClass.bar|)
<Inapplicable(INAPPLICABLE): [/foo2]>#(Q|KotlinClass2|::R|/KotlinClass2.bar|)
R|/foo3|(Q|KotlinClass2|::R|/KotlinClass2.Companion.bar|)
}
@@ -15,7 +15,7 @@ FILE: hashTableWithForEach.kt
R|/DEBUG| -> {
^ Q|java/util/Collections|.R|java/util/Collections.unmodifiableSet|<R|kotlin/collections/MutableMap.MutableEntry<K, V>|>(R|kotlin/collections/mutableSetOf|<R|kotlin/collections/MutableMap.MutableEntry<K, V>|>().R|kotlin/apply|<R|kotlin/collections/MutableSet<kotlin/collections/MutableMap.MutableEntry<K, V>>|>(<L> = apply@fun R|kotlin/collections/MutableSet<kotlin/collections/MutableMap.MutableEntry<K, V>>|.<anonymous>(): R|kotlin/Unit| <kind=EXACTLY_ONCE> {
this@R|/SomeHashTable|.R|FakeOverride</SomeHashTable.forEach: R|kotlin/Unit|>|(<L> = forEach@fun <anonymous>(key: R|K|, value: R|V|): R|kotlin/Unit| {
this@R|special/anonymous|.R|FakeOverride<kotlin/collections/MutableSet.add: R|kotlin/Boolean|>|(this@R|/SomeHashTable|.R|/SomeHashTable.Entry.Entry|<R|K|, R|V|>(R|<local>/key|, R|<local>/value|))
this@R|special/anonymous|.R|FakeOverride<kotlin/collections/MutableSet.add: R|kotlin/Boolean|>|(R|/SomeHashTable.Entry.Entry|<R|K|, R|V|>(R|<local>/key|, R|<local>/value|))
}
)
}
@@ -31,7 +31,7 @@ FILE: implicitReceiverOrder.kt
R|kotlin/with|<R|B|, R|kotlin/Int|>(R|<local>/b|, <L> = with@fun R|B|.<anonymous>(): R|kotlin/Int| <kind=EXACTLY_ONCE> {
R|kotlin/with|<R|A|, R|kotlin/Int|>(R|<local>/a|, <L> = with@fun R|A|.<anonymous>(): R|kotlin/Int| <kind=EXACTLY_ONCE> {
this@R|special/anonymous|.R|/A.foo|()
this@R|special/anonymous|.R|/B.bar|()
(this@R|special/anonymous|, this@R|special/anonymous|).R|/B.bar|()
}
)
}
@@ -39,7 +39,7 @@ FILE: implicitReceiverOrder.kt
R|kotlin/with|<R|A|, R|kotlin/Int|>(R|<local>/a|, <L> = with@fun R|A|.<anonymous>(): R|kotlin/Int| <kind=EXACTLY_ONCE> {
R|kotlin/with|<R|B|, R|kotlin/Int|>(R|<local>/b|, <L> = with@fun R|B|.<anonymous>(): R|kotlin/Int| <kind=EXACTLY_ONCE> {
this@R|special/anonymous|.R|/B.foo|()
this@R|special/anonymous|.R|/A.bar|()
(this@R|special/anonymous|, this@R|special/anonymous|).R|/A.bar|()
}
)
}
@@ -5,7 +5,7 @@ FILE: User.kt
}
public final fun foo(): R|kotlin/Unit| {
lval sc: R|AbstractClass.StaticClass| = this@R|/User|.R|/AbstractClass.StaticClass.StaticClass|()
lval sc: R|AbstractClass.StaticClass| = R|/AbstractClass.StaticClass.StaticClass|()
}
}
@@ -27,9 +27,9 @@ FILE: multipleImplicitReceivers.kt
public final fun test(fooImpl: R|IFoo|, invokeImpl: R|IInvoke|): R|kotlin/Unit| {
R|kotlin/with|<R|A|, R|kotlin/Int|>(Q|A|, <L> = with@fun R|A|.<anonymous>(): R|kotlin/Int| <kind=EXACTLY_ONCE> {
R|kotlin/with|<R|IFoo|, R|kotlin/Int|>(R|<local>/fooImpl|, <L> = with@fun R|IFoo|.<anonymous>(): R|kotlin/Int| <kind=EXACTLY_ONCE> {
this@R|special/anonymous|.R|/IFoo.foo|
(this@R|special/anonymous|, this@R|special/anonymous|).R|/IFoo.foo|
R|kotlin/with|<R|IInvoke|, R|kotlin/Int|>(R|<local>/invokeImpl|, <L> = with@fun R|IInvoke|.<anonymous>(): R|kotlin/Int| <kind=EXACTLY_ONCE> {
(this@R|special/anonymous|, this@R|special/anonymous|.R|/IFoo.foo|).R|/IInvoke.invoke|()
(this@R|special/anonymous|, (this@R|special/anonymous|, this@R|special/anonymous|).R|/IFoo.foo|).R|/IInvoke.invoke|()
}
)
}
@@ -434,11 +434,21 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
runTest("compiler/fir/resolve/testData/resolve/expresssions/baseQualifier.kt");
}
@TestMetadata("CallBasedInExpressionGenerator.kt")
public void testCallBasedInExpressionGenerator() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/CallBasedInExpressionGenerator.kt");
}
@TestMetadata("checkArguments.kt")
public void testCheckArguments() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/checkArguments.kt");
}
@TestMetadata("classifierAccessFromCompanion.kt")
public void testClassifierAccessFromCompanion() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/classifierAccessFromCompanion.kt");
}
@TestMetadata("companion.kt")
public void testCompanion() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/companion.kt");
@@ -514,6 +524,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
runTest("compiler/fir/resolve/testData/resolve/expresssions/innerQualifier.kt");
}
@TestMetadata("innerWithSuperCompanion.kt")
public void testInnerWithSuperCompanion() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/innerWithSuperCompanion.kt");
}
@TestMetadata("javaFieldCallable.kt")
public void testJavaFieldCallable() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/javaFieldCallable.kt");
@@ -529,6 +544,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
runTest("compiler/fir/resolve/testData/resolve/expresssions/lambdaWithReceiver.kt");
}
@TestMetadata("localClassAccessesContainingClass.kt")
public void testLocalClassAccessesContainingClass() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/localClassAccessesContainingClass.kt");
}
@TestMetadata("localConstructor.kt")
public void testLocalConstructor() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/localConstructor.kt");
@@ -574,6 +594,16 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
runTest("compiler/fir/resolve/testData/resolve/expresssions/memberExtension.kt");
}
@TestMetadata("nestedConstructorCallable.kt")
public void testNestedConstructorCallable() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/nestedConstructorCallable.kt");
}
@TestMetadata("nestedObjects.kt")
public void testNestedObjects() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/nestedObjects.kt");
}
@TestMetadata("nestedVisibility.kt")
public void testNestedVisibility() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/nestedVisibility.kt");
@@ -594,6 +624,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
runTest("compiler/fir/resolve/testData/resolve/expresssions/objects.kt");
}
@TestMetadata("outerMemberAccesses.kt")
public void testOuterMemberAccesses() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/outerMemberAccesses.kt");
}
@TestMetadata("outerObject.kt")
public void testOuterObject() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/outerObject.kt");
@@ -724,6 +759,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/extension.kt");
}
@TestMetadata("extensionOnObject.kt")
public void testExtensionOnObject() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/extensionOnObject.kt");
}
@TestMetadata("farInvokeExtension.kt")
public void testFarInvokeExtension() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/farInvokeExtension.kt");
@@ -763,6 +803,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
public void testThreeReceivers() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/threeReceivers.kt");
}
@TestMetadata("threeReceiversCorrect.kt")
public void testThreeReceiversCorrect() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/threeReceiversCorrect.kt");
}
}
@TestMetadata("compiler/fir/resolve/testData/resolve/expresssions/operators")
@@ -434,11 +434,21 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/resolve/testData/resolve/expresssions/baseQualifier.kt");
}
@TestMetadata("CallBasedInExpressionGenerator.kt")
public void testCallBasedInExpressionGenerator() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/CallBasedInExpressionGenerator.kt");
}
@TestMetadata("checkArguments.kt")
public void testCheckArguments() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/checkArguments.kt");
}
@TestMetadata("classifierAccessFromCompanion.kt")
public void testClassifierAccessFromCompanion() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/classifierAccessFromCompanion.kt");
}
@TestMetadata("companion.kt")
public void testCompanion() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/companion.kt");
@@ -514,6 +524,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/resolve/testData/resolve/expresssions/innerQualifier.kt");
}
@TestMetadata("innerWithSuperCompanion.kt")
public void testInnerWithSuperCompanion() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/innerWithSuperCompanion.kt");
}
@TestMetadata("javaFieldCallable.kt")
public void testJavaFieldCallable() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/javaFieldCallable.kt");
@@ -529,6 +544,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/resolve/testData/resolve/expresssions/lambdaWithReceiver.kt");
}
@TestMetadata("localClassAccessesContainingClass.kt")
public void testLocalClassAccessesContainingClass() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/localClassAccessesContainingClass.kt");
}
@TestMetadata("localConstructor.kt")
public void testLocalConstructor() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/localConstructor.kt");
@@ -574,6 +594,16 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/resolve/testData/resolve/expresssions/memberExtension.kt");
}
@TestMetadata("nestedConstructorCallable.kt")
public void testNestedConstructorCallable() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/nestedConstructorCallable.kt");
}
@TestMetadata("nestedObjects.kt")
public void testNestedObjects() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/nestedObjects.kt");
}
@TestMetadata("nestedVisibility.kt")
public void testNestedVisibility() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/nestedVisibility.kt");
@@ -594,6 +624,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/resolve/testData/resolve/expresssions/objects.kt");
}
@TestMetadata("outerMemberAccesses.kt")
public void testOuterMemberAccesses() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/outerMemberAccesses.kt");
}
@TestMetadata("outerObject.kt")
public void testOuterObject() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/outerObject.kt");
@@ -724,6 +759,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/extension.kt");
}
@TestMetadata("extensionOnObject.kt")
public void testExtensionOnObject() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/extensionOnObject.kt");
}
@TestMetadata("farInvokeExtension.kt")
public void testFarInvokeExtension() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/farInvokeExtension.kt");
@@ -763,6 +803,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
public void testThreeReceivers() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/threeReceivers.kt");
}
@TestMetadata("threeReceiversCorrect.kt")
public void testThreeReceiversCorrect() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/threeReceiversCorrect.kt");
}
}
@TestMetadata("compiler/fir/resolve/testData/resolve/expresssions/operators")
@@ -43,4 +43,9 @@ enum class ProcessorAction {
fun stop() = this == STOP
fun next() = this != STOP
operator fun plus(other: ProcessorAction): ProcessorAction {
if (this == NEXT || other == NEXT) return NEXT
return this
}
}
@@ -2,6 +2,6 @@ fun bar(doIt: Int.() -> Int) {
1.doIt()
1?.doIt()
val i: Int? = 1
i.<!UNRESOLVED_REFERENCE!>doIt<!>()
i.doIt()
i?.doIt()
}
@@ -5,7 +5,7 @@ class X {}
val s = java
val ss = System
val sss = X
val x = "${System}"
val x = "${<!UNRESOLVED_REFERENCE!>System<!>}"
val xs = java.lang
val xss = java.lang.System
val xsss = foo.X
@@ -5,5 +5,5 @@ class Outer {
fun test() {
Outer()::Inner
Outer()::Nested
<!UNRESOLVED_REFERENCE!>Outer()::Nested<!>
}
@@ -9,6 +9,6 @@ public class A {
enum class E { EN }
fun test() {
A()::test
E.EN::valueOf
<!UNRESOLVED_REFERENCE!>A()::test<!>
<!UNRESOLVED_REFERENCE!>E.EN::valueOf<!>
}
@@ -16,6 +16,6 @@ fun test() {
Outer.Companion::Wrapper
(Outer.Companion)::Wrapper
Outer::Wrapper
(Outer)::Wrapper
<!UNRESOLVED_REFERENCE!>Outer::Wrapper<!>
<!UNRESOLVED_REFERENCE!>(Outer)::Wrapper<!>
}
@@ -15,5 +15,5 @@ fun take(f: () -> Unit) {}
fun test() {
B::foo checkType { <!UNRESOLVED_REFERENCE!>_<!><KFunction1<B, Unit>>() }
take(B::foo)
<!INAPPLICABLE_CANDIDATE!>take<!>(B::foo)
}
@@ -18,7 +18,7 @@ import test.A
fun foo(args: Array<String>) {
val main2 = A::main
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><KFunction1<Array<String>, Unit>>(main2)
<!INAPPLICABLE_CANDIDATE!>main2<!>(args)
<!INAPPLICABLE_CANDIDATE!>(A::main)(args)<!>
checkSubtype<KFunction1<Array<String>, Unit>>(main2)
main2(args)
(A::main)(args)
}
@@ -10,7 +10,7 @@ class A {
val y = A::Nested
checkSubtype<KFunction0<Nested>>(x)
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><KFunction0<Nested>>(y)
checkSubtype<KFunction0<Nested>>(y)
}
companion object {
@@ -18,7 +18,7 @@ class A {
::Nested
val y = A::Nested
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><KFunction0<A.Nested>>(y)
checkSubtype<KFunction0<A.Nested>>(y)
}
}
}
@@ -28,6 +28,6 @@ class B {
<!UNRESOLVED_REFERENCE!>::Nested<!>
val y = A::Nested
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><KFunction0<A.Nested>>(y)
checkSubtype<KFunction0<A.Nested>>(y)
}
}
@@ -7,15 +7,15 @@ class A {
}
fun A.main() {
::Nested
<!UNRESOLVED_REFERENCE!>::Nested<!>
val y = A::Nested
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><KFunction0<A.Nested>>(y)
checkSubtype<KFunction0<A.Nested>>(y)
}
fun Int.main() {
<!UNRESOLVED_REFERENCE!>::Nested<!>
val y = A::Nested
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><KFunction0<A.Nested>>(y)
checkSubtype<KFunction0<A.Nested>>(y)
}
@@ -9,5 +9,5 @@ class A {
fun main() {
val x = A::Nested
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><KFunction0<A.Nested>>(x)
checkSubtype<KFunction0<A.Nested>>(x)
}
@@ -4,7 +4,7 @@
package foo
fun test() {
<!UNRESOLVED_REFERENCE!>foo::test<!>
foo::test
}
// FILE: qualifiedName.kt
@@ -12,5 +12,5 @@ fun test() {
package foo.bar
fun test() {
<!UNRESOLVED_REFERENCE!>foo.bar::test<!>
foo.bar::test
}
@@ -14,14 +14,14 @@ class A {
fun A.foo(): String = "A"
val x0 = A::foo
val x0 = <!UNRESOLVED_REFERENCE!>A::foo<!>
val x1 = ofType<(A) -> Unit>(A::foo)
val x2 = ofType<KProperty1<A, Int>>(A::foo)
val x3: KProperty1<A, Int> = A::foo
val x4: (A) -> String = A::foo
val y0 = A::bar
val y0 = <!UNRESOLVED_REFERENCE!>A::bar<!>
val y1 = ofType<(A) -> Unit>(A::bar)
val y2 = ofType<KProperty1<A, Int>>(A::bar)
val y3: KProperty1<A, Int> = A::bar
@@ -4,6 +4,6 @@ class A() {
val x = 1
companion object {
val y = x
val y = <!UNRESOLVED_REFERENCE!>x<!>
}
}
@@ -21,7 +21,7 @@ enum class C {
C.A()
A()
//TODO: should be resolved with error
this.A()
this.<!UNRESOLVED_REFERENCE!>A<!>()
}
};
@@ -34,7 +34,7 @@ enum class C {
fun f() {
C.E1.A
C.E1.A()
C.E1.<!UNRESOLVED_REFERENCE!>A<!>()
C.E2.B()
C.E2.O
@@ -21,7 +21,7 @@ enum class C {
C.A()
A()
//TODO: should be resolved with error
this.A()
this.<!UNRESOLVED_REFERENCE!>A<!>()
}
};
@@ -34,7 +34,7 @@ enum class C {
fun f() {
C.E1.A
C.E1.A()
C.E1.<!UNRESOLVED_REFERENCE!>A<!>()
C.E2.B()
C.E2.O
@@ -4,6 +4,6 @@ class Test {
fun test(): Int = 12
companion object {
val a = test() // Check if resolver will be able to infer type of a variable
val a = <!UNRESOLVED_REFERENCE!>test<!>() // Check if resolver will be able to infer type of a variable
}
}
@@ -8,7 +8,7 @@ class My {
companion object {
val y = foo()
val y = <!UNRESOLVED_REFERENCE!>foo<!>()
val u = bar()
@@ -14,5 +14,5 @@ class TopLevel {
fun useNested() {
val d = TopLevel.Nested.use()
TopLevel.Nested.Nested2()
TopLevel.Nested.CompanionNested2()
TopLevel.Nested.<!UNRESOLVED_REFERENCE!>CompanionNested2<!>()
}
@@ -2,7 +2,7 @@ enum class A {
A1,
A2;
fun valueOf(s: String): A = <!AMBIGUITY!>valueOf<!>(s)
fun valueOf(s: String): A = valueOf(s)
fun valueOf() = "OK"
@@ -10,6 +10,6 @@ public enum A {
fun main() {
val c: A = A.ENTRY
val c2: String? = c.<!AMBIGUITY!>ENTRY<!>
val c3: String? = A.ANOTHER.<!AMBIGUITY!>ENTRY<!>
val c2: String? = c.ENTRY
val c3: String? = A.ANOTHER.ENTRY
}
@@ -7,5 +7,5 @@ public class A {
// FILE: B.kt
fun Any?.bar() = 42
fun f1() = A.bar()
fun f2() = A.Nested.bar()
fun f1() = A.<!UNRESOLVED_REFERENCE!>bar<!>()
fun f2() = A.Nested.<!UNRESOLVED_REFERENCE!>bar<!>()
@@ -12,5 +12,5 @@ fun <V, T : V?> G<T>.foo(vararg values: V2<V?>) = build()
fun forReference(ref: Any?) {}
fun test() {
forReference(<!UNRESOLVED_REFERENCE!>G<Int?>::foo<!>)
<!INAPPLICABLE_CANDIDATE!>forReference<!>(<!UNRESOLVED_REFERENCE!>G<Int?>::foo<!>)
}
@@ -23,6 +23,6 @@ class Outer {
fun Outer.foo() {
Outer()
Nested()
<!UNRESOLVED_REFERENCE!>Nested<!>()
Inner()
}
@@ -12,8 +12,8 @@ class Test {
fun more(): InnerClass {
val b = InnerClass()
val testVal = inClass
foo()
val testVal = <!UNRESOLVED_REFERENCE!>inClass<!>
<!UNRESOLVED_REFERENCE!>foo<!>()
return b
}
@@ -12,8 +12,8 @@ class Test {
fun more(): InnerClass {
val b = InnerClass()
val testVal = inClass
foo()
val testVal = <!UNRESOLVED_REFERENCE!>inClass<!>
<!UNRESOLVED_REFERENCE!>foo<!>()
return b
}
@@ -2,7 +2,7 @@ class Outer {
class Nested {
fun foo() {
class Local {
val state = outerState
val state = <!UNRESOLVED_REFERENCE!>outerState<!>
}
}
}
@@ -24,30 +24,30 @@ object Obj {
}
fun test(with: WithClassObject, without: WithoutClassObject, obj: Obj) {
with.Nested()
with.<!UNRESOLVED_REFERENCE!>Nested<!>()
with.NestedWithClassObject
with.NestedWithClassObject()
with.<!UNRESOLVED_REFERENCE!>NestedWithClassObject<!>()
with.NestedWithClassObject.foo()
with.NestedEnum.A
with.NestedObj
with.<!INAPPLICABLE_CANDIDATE!>NestedObj<!>()
with.<!UNRESOLVED_REFERENCE!>NestedObj<!>()
with.NestedObj.foo()
without.Nested()
without.<!UNRESOLVED_REFERENCE!>Nested<!>()
without.NestedWithClassObject
without.NestedWithClassObject()
without.<!UNRESOLVED_REFERENCE!>NestedWithClassObject<!>()
without.NestedWithClassObject.foo()
without.NestedEnum.A
without.NestedObj
without.<!INAPPLICABLE_CANDIDATE!>NestedObj<!>()
without.<!UNRESOLVED_REFERENCE!>NestedObj<!>()
without.NestedObj.foo()
obj.Nested()
obj.<!UNRESOLVED_REFERENCE!>Nested<!>()
obj.NestedWithClassObject
obj.NestedWithClassObject()
obj.<!UNRESOLVED_REFERENCE!>NestedWithClassObject<!>()
obj.NestedWithClassObject.foo()
obj.NestedEnum.A
obj.NestedObj
obj.<!INAPPLICABLE_CANDIDATE!>NestedObj<!>()
obj.<!UNRESOLVED_REFERENCE!>NestedObj<!>()
obj.NestedObj.foo()
}
@@ -5,8 +5,8 @@ class Outer {
val property = ""
class Nested {
fun f() = function()
fun g() = property
fun f() = <!UNRESOLVED_REFERENCE!>function<!>()
fun g() = <!UNRESOLVED_REFERENCE!>property<!>
fun h() = this@Outer.function()
fun i() = this@Outer.property
}
@@ -4,6 +4,6 @@ open class Base {
class Derived : Base() {
class Nested {
fun bar() = foo()
fun bar() = <!UNRESOLVED_REFERENCE!>foo<!>()
}
}
@@ -119,8 +119,8 @@ class C : O.B() {
val b = O.A::foo
// DEPRECATED: Classifiers from companions of direct superclasses
val e = <!UNRESOLVED_REFERENCE!>O.A.<!AMBIGUITY!>Companion<!>.<!UNRESOLVED_REFERENCE!>FromCompanionA<!>::foo<!>
val f = <!UNRESOLVED_REFERENCE!>O.B.<!AMBIGUITY!>Companion<!>.<!UNRESOLVED_REFERENCE!>FromCompanionB<!>::foo<!>
val e = O.A.Companion.FromCompanionA::foo
val f = O.B.Companion.FromCompanionB::foo
// INVISIBLE: "cousin" supertypes themselves
val g = O.Alpha::foo

Some files were not shown because too many files have changed in this diff Show More