FIR: more accurate handling of dispatch receiver values
This commit fixes resolve priorities (see changed test data), e.g. top-levels now have less priority than implicit receiver members
This commit is contained in:
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.fir.resolve.transformers.resultType
|
|||||||
import org.jetbrains.kotlin.fir.resolve.typeForQualifier
|
import org.jetbrains.kotlin.fir.resolve.typeForQualifier
|
||||||
import org.jetbrains.kotlin.fir.resolve.typeFromCallee
|
import org.jetbrains.kotlin.fir.resolve.typeFromCallee
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
|
||||||
import org.jetbrains.kotlin.fir.symbols.ConeCallableSymbol
|
import org.jetbrains.kotlin.fir.symbols.ConeCallableSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeSymbol
|
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.ConeSymbol
|
import org.jetbrains.kotlin.fir.symbols.ConeSymbol
|
||||||
@@ -36,8 +37,8 @@ import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator
|
|||||||
|
|
||||||
class FirCallResolver(
|
class FirCallResolver(
|
||||||
private val transformer: FirBodyResolveTransformer,
|
private val transformer: FirBodyResolveTransformer,
|
||||||
private val scopes: List<FirScope>,
|
private val topLevelScopes: List<FirScope>,
|
||||||
private val localScopes: List<FirScope>,
|
private val localScopes: List<FirLocalScope>,
|
||||||
private val implicitReceiverStack: List<ImplicitReceiverValue>,
|
private val implicitReceiverStack: List<ImplicitReceiverValue>,
|
||||||
private val qualifiedResolver: FirQualifiedNameResolver
|
private val qualifiedResolver: FirQualifiedNameResolver
|
||||||
) : BodyResolveComponents by transformer {
|
) : BodyResolveComponents by transformer {
|
||||||
@@ -64,9 +65,11 @@ class FirCallResolver(
|
|||||||
file,
|
file,
|
||||||
transformer.container
|
transformer.container
|
||||||
) { it.resultType }
|
) { it.resultType }
|
||||||
val resolver = CallResolver(returnTypeCalculator, inferenceComponents, resolutionStageRunner)
|
val resolver = CallResolver(
|
||||||
resolver.callInfo = info
|
returnTypeCalculator, inferenceComponents, resolutionStageRunner,
|
||||||
resolver.scopes = (scopes + localScopes).asReversed()
|
topLevelScopes = topLevelScopes.asReversed(),
|
||||||
|
localScopes = localScopes.asReversed()
|
||||||
|
)
|
||||||
|
|
||||||
val consumer = createFunctionConsumer(session, name, info, inferenceComponents, resolver.collector, resolver)
|
val consumer = createFunctionConsumer(session, name, info, inferenceComponents, resolver.collector, resolver)
|
||||||
val result = resolver.runTowerResolver(consumer, implicitReceiverStack.asReversed())
|
val result = resolver.runTowerResolver(consumer, implicitReceiverStack.asReversed())
|
||||||
@@ -154,9 +157,11 @@ class FirCallResolver(
|
|||||||
file,
|
file,
|
||||||
transformer.container
|
transformer.container
|
||||||
) { it.resultType }
|
) { it.resultType }
|
||||||
val resolver = CallResolver(returnTypeCalculator, inferenceComponents, resolutionStageRunner)
|
val resolver = CallResolver(
|
||||||
resolver.callInfo = info
|
returnTypeCalculator, inferenceComponents, resolutionStageRunner,
|
||||||
resolver.scopes = (scopes + localScopes).asReversed()
|
topLevelScopes = topLevelScopes.asReversed(),
|
||||||
|
localScopes = localScopes.asReversed()
|
||||||
|
)
|
||||||
|
|
||||||
val consumer = createVariableAndObjectConsumer(
|
val consumer = createVariableAndObjectConsumer(
|
||||||
session,
|
session,
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.resolve.calls
|
|||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator
|
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
|
||||||
|
|
||||||
enum class TowerDataKind {
|
enum class TowerDataKind {
|
||||||
EMPTY,
|
EMPTY,
|
||||||
@@ -17,10 +18,10 @@ enum class TowerDataKind {
|
|||||||
class CallResolver(
|
class CallResolver(
|
||||||
val typeCalculator: ReturnTypeCalculator,
|
val typeCalculator: ReturnTypeCalculator,
|
||||||
val components: InferenceComponents,
|
val components: InferenceComponents,
|
||||||
val resolutionStageRunner: ResolutionStageRunner
|
val resolutionStageRunner: ResolutionStageRunner,
|
||||||
|
val topLevelScopes: List<FirScope>,
|
||||||
|
val localScopes: List<FirLocalScope>
|
||||||
) {
|
) {
|
||||||
var callInfo: CallInfo? = null
|
|
||||||
var scopes: List<FirScope>? = null
|
|
||||||
|
|
||||||
val session: FirSession get() = components.session
|
val session: FirSession get() = components.session
|
||||||
|
|
||||||
@@ -44,10 +45,39 @@ class CallResolver(
|
|||||||
group++
|
group++
|
||||||
)
|
)
|
||||||
|
|
||||||
for (scope in scopes!!) {
|
for (scope in localScopes) {
|
||||||
towerDataConsumer.consume(
|
towerDataConsumer.consume(
|
||||||
TowerDataKind.TOWER_LEVEL,
|
TowerDataKind.TOWER_LEVEL,
|
||||||
ScopeTowerLevel(session, scope, implicitReceiverValue),
|
ScopeTowerLevel(session, scope, implicitExtensionReceiver = implicitReceiverValue),
|
||||||
|
group++
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (implicitDispatchReceiverValue in implicitReceiverValues) {
|
||||||
|
val implicitScope = implicitDispatchReceiverValue.implicitScope
|
||||||
|
if (implicitScope != null) {
|
||||||
|
towerDataConsumer.consume(
|
||||||
|
TowerDataKind.TOWER_LEVEL,
|
||||||
|
ScopeTowerLevel(session, implicitScope, implicitExtensionReceiver = implicitReceiverValue),
|
||||||
|
group++
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (implicitDispatchReceiverValue is ImplicitDispatchReceiverValue) {
|
||||||
|
val implicitCompanionScope = implicitDispatchReceiverValue.implicitCompanionScope
|
||||||
|
if (implicitCompanionScope != null) {
|
||||||
|
towerDataConsumer.consume(
|
||||||
|
TowerDataKind.TOWER_LEVEL,
|
||||||
|
ScopeTowerLevel(session, implicitCompanionScope, implicitExtensionReceiver = implicitReceiverValue),
|
||||||
|
group++
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (scope in topLevelScopes) {
|
||||||
|
towerDataConsumer.consume(
|
||||||
|
TowerDataKind.TOWER_LEVEL,
|
||||||
|
ScopeTowerLevel(session, scope, implicitExtensionReceiver = implicitReceiverValue),
|
||||||
group++
|
group++
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -64,15 +94,27 @@ class CallResolver(
|
|||||||
towerDataConsumer = consumer
|
towerDataConsumer = consumer
|
||||||
|
|
||||||
var group = 0
|
var group = 0
|
||||||
|
// Member of explicit receiver' type
|
||||||
towerDataConsumer.consume(TowerDataKind.EMPTY, TowerScopeLevel.Empty, group++)
|
towerDataConsumer.consume(TowerDataKind.EMPTY, TowerScopeLevel.Empty, group++)
|
||||||
|
|
||||||
for (scope in scopes!!) {
|
// Member of local scope
|
||||||
|
for (scope in localScopes) {
|
||||||
towerDataConsumer.consume(TowerDataKind.TOWER_LEVEL, ScopeTowerLevel(session, scope), group++)
|
towerDataConsumer.consume(TowerDataKind.TOWER_LEVEL, ScopeTowerLevel(session, scope), group++)
|
||||||
}
|
}
|
||||||
|
|
||||||
var blockDispatchReceivers = false
|
var blockDispatchReceivers = false
|
||||||
|
|
||||||
|
// Member of implicit receiver' type
|
||||||
for (implicitReceiverValue in implicitReceiverValues) {
|
for (implicitReceiverValue in implicitReceiverValues) {
|
||||||
|
val implicitScope = implicitReceiverValue.implicitScope
|
||||||
|
if (implicitScope != null) {
|
||||||
|
towerDataConsumer.consume(TowerDataKind.TOWER_LEVEL, ScopeTowerLevel(session, implicitScope), group++)
|
||||||
|
}
|
||||||
if (implicitReceiverValue is ImplicitDispatchReceiverValue) {
|
if (implicitReceiverValue is ImplicitDispatchReceiverValue) {
|
||||||
|
val implicitCompanionScope = implicitReceiverValue.implicitCompanionScope
|
||||||
|
if (implicitCompanionScope != null) {
|
||||||
|
towerDataConsumer.consume(TowerDataKind.TOWER_LEVEL, ScopeTowerLevel(session, implicitCompanionScope), group++)
|
||||||
|
}
|
||||||
if (blockDispatchReceivers) {
|
if (blockDispatchReceivers) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -83,6 +125,11 @@ class CallResolver(
|
|||||||
group = processImplicitReceiver(towerDataConsumer, implicitReceiverValue, collector, group)
|
group = processImplicitReceiver(towerDataConsumer, implicitReceiverValue, collector, group)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Member of top-level scope
|
||||||
|
for (scope in topLevelScopes) {
|
||||||
|
towerDataConsumer.consume(TowerDataKind.TOWER_LEVEL, ScopeTowerLevel(session, scope), group++)
|
||||||
|
}
|
||||||
|
|
||||||
return collector
|
return collector
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,8 +5,14 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.resolve.calls
|
package org.jetbrains.kotlin.fir.resolve.calls
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.classId
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
import org.jetbrains.kotlin.fir.renderWithType
|
import org.jetbrains.kotlin.fir.renderWithType
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.scope
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassTypeImpl
|
import org.jetbrains.kotlin.fir.types.impl.ConeClassTypeImpl
|
||||||
@@ -32,14 +38,28 @@ class ExpressionReceiverValue(
|
|||||||
?: ConeKotlinErrorType("No type calculated for: ${explicitReceiverExpression.renderWithType()}") // TODO: assert here
|
?: ConeKotlinErrorType("No type calculated for: ${explicitReceiverExpression.renderWithType()}") // TODO: assert here
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ImplicitReceiverValue : ReceiverValue {
|
abstract class ImplicitReceiverValue(
|
||||||
|
final override val type: ConeKotlinType,
|
||||||
|
useSiteSession: FirSession,
|
||||||
|
scopeSession: ScopeSession
|
||||||
|
) : ReceiverValue {
|
||||||
|
val implicitScope: FirScope? = type.scope(useSiteSession, scopeSession)
|
||||||
}
|
}
|
||||||
|
|
||||||
class ImplicitDispatchReceiverValue(
|
class ImplicitDispatchReceiverValue(
|
||||||
val boundSymbol: FirClassSymbol,
|
val boundSymbol: FirClassSymbol,
|
||||||
override val type: ConeKotlinType
|
type: ConeKotlinType,
|
||||||
) : ImplicitReceiverValue
|
symbolProvider: FirSymbolProvider,
|
||||||
|
useSiteSession: FirSession,
|
||||||
|
scopeSession: ScopeSession
|
||||||
|
) : ImplicitReceiverValue(type, useSiteSession, scopeSession) {
|
||||||
|
val implicitCompanionScope: FirScope? = boundSymbol.fir.companionObject?.let { companionObject ->
|
||||||
|
symbolProvider.getClassUseSiteMemberScope(companionObject.classId, useSiteSession, scopeSession)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class ImplicitExtensionReceiverValue(
|
class ImplicitExtensionReceiverValue(
|
||||||
override val type: ConeKotlinType
|
type: ConeKotlinType,
|
||||||
) : ImplicitReceiverValue
|
useSiteSession: FirSession,
|
||||||
|
scopeSession: ScopeSession
|
||||||
|
) : ImplicitReceiverValue(type, useSiteSession, scopeSession)
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ abstract class SessionBasedTowerLevel(val session: FirSession) : TowerScopeLevel
|
|||||||
protected fun AbstractFirBasedSymbol<*>.dispatchReceiverValue(): ClassDispatchReceiverValue? {
|
protected fun AbstractFirBasedSymbol<*>.dispatchReceiverValue(): ClassDispatchReceiverValue? {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
is FirNamedFunctionSymbol -> fir.dispatchReceiverValue(session)
|
is FirNamedFunctionSymbol -> fir.dispatchReceiverValue(session)
|
||||||
|
is FirPropertySymbol -> fir.dispatchReceiverValue(session)
|
||||||
is FirClassSymbol -> ClassDispatchReceiverValue(fir.symbol)
|
is FirClassSymbol -> ClassDispatchReceiverValue(fir.symbol)
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|||||||
+42
-49
@@ -53,7 +53,6 @@ open class FirBodyResolveTransformer(
|
|||||||
private val booleanType = FirImplicitBooleanTypeRef(null)
|
private val booleanType = FirImplicitBooleanTypeRef(null)
|
||||||
|
|
||||||
final override val symbolProvider = session.service<FirSymbolProvider>()
|
final override val symbolProvider = session.service<FirSymbolProvider>()
|
||||||
val scopes = mutableListOf<FirScope>()
|
|
||||||
|
|
||||||
private var packageFqName = FqName.ROOT
|
private var packageFqName = FqName.ROOT
|
||||||
final override lateinit var file: FirFile
|
final override lateinit var file: FirFile
|
||||||
@@ -67,6 +66,7 @@ open class FirBodyResolveTransformer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val localScopes = mutableListOf<FirLocalScope>()
|
private val localScopes = mutableListOf<FirLocalScope>()
|
||||||
|
private val topLevelScopes = mutableListOf<FirScope>()
|
||||||
private val implicitReceiverStack = mutableListOf<ImplicitReceiverValue>()
|
private val implicitReceiverStack = mutableListOf<ImplicitReceiverValue>()
|
||||||
final override val inferenceComponents = inferenceComponents(session, returnTypeCalculator, scopeSession)
|
final override val inferenceComponents = inferenceComponents(session, returnTypeCalculator, scopeSession)
|
||||||
|
|
||||||
@@ -77,7 +77,7 @@ open class FirBodyResolveTransformer(
|
|||||||
final override val resolutionStageRunner: ResolutionStageRunner = ResolutionStageRunner(inferenceComponents)
|
final override val resolutionStageRunner: ResolutionStageRunner = ResolutionStageRunner(inferenceComponents)
|
||||||
private val callResolver: FirCallResolver = FirCallResolver(
|
private val callResolver: FirCallResolver = FirCallResolver(
|
||||||
this,
|
this,
|
||||||
scopes,
|
topLevelScopes,
|
||||||
localScopes,
|
localScopes,
|
||||||
implicitReceiverStack,
|
implicitReceiverStack,
|
||||||
qualifiedResolver
|
qualifiedResolver
|
||||||
@@ -94,9 +94,9 @@ open class FirBodyResolveTransformer(
|
|||||||
override fun transformFile(file: FirFile, data: Any?): CompositeTransformResult<FirFile> {
|
override fun transformFile(file: FirFile, data: Any?): CompositeTransformResult<FirFile> {
|
||||||
packageFqName = file.packageFqName
|
packageFqName = file.packageFqName
|
||||||
this.file = file
|
this.file = file
|
||||||
return withScopeCleanup(scopes) {
|
return withScopeCleanup(topLevelScopes) {
|
||||||
scopes.addImportingScopes(file, session)
|
topLevelScopes.addImportingScopes(file, session)
|
||||||
scopes += FirTopLevelDeclaredMemberScope(file, session)
|
topLevelScopes += FirTopLevelDeclaredMemberScope(file, session)
|
||||||
super.transformFile(file, data)
|
super.transformFile(file, data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -139,27 +139,20 @@ open class FirBodyResolveTransformer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun transformRegularClass(regularClass: FirRegularClass, data: Any?): CompositeTransformResult<FirDeclaration> {
|
override fun transformRegularClass(regularClass: FirRegularClass, data: Any?): CompositeTransformResult<FirDeclaration> {
|
||||||
return withScopeCleanup(scopes) {
|
val oldConstructorScope = primaryConstructorParametersScope
|
||||||
val oldConstructorScope = primaryConstructorParametersScope
|
primaryConstructorParametersScope = null
|
||||||
primaryConstructorParametersScope = null
|
val type = regularClass.defaultType()
|
||||||
val type = regularClass.defaultType()
|
val result = withLabelAndReceiverType(regularClass.name, regularClass, type) {
|
||||||
scopes.addIfNotNull(type.scope(session, scopeSession))
|
val constructor = regularClass.declarations.firstOrNull() as? FirConstructor
|
||||||
val companionObject = regularClass.companionObject
|
if (constructor?.isPrimary == true) {
|
||||||
if (companionObject != null) {
|
primaryConstructorParametersScope = FirLocalScope().apply {
|
||||||
scopes.addIfNotNull(symbolProvider.getClassUseSiteMemberScope(companionObject.classId, session, scopeSession))
|
constructor.valueParameters.forEach { this.storeDeclaration(it) }
|
||||||
}
|
|
||||||
val result = withLabelAndReceiverType(regularClass.name, regularClass, type) {
|
|
||||||
val constructor = regularClass.declarations.firstOrNull() as? FirConstructor
|
|
||||||
if (constructor?.isPrimary == true) {
|
|
||||||
primaryConstructorParametersScope = FirLocalScope().apply {
|
|
||||||
constructor.valueParameters.forEach { this.storeDeclaration(it) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
super.transformRegularClass(regularClass, data)
|
|
||||||
}
|
}
|
||||||
primaryConstructorParametersScope = oldConstructorScope
|
super.transformRegularClass(regularClass, data)
|
||||||
result
|
|
||||||
}
|
}
|
||||||
|
primaryConstructorParametersScope = oldConstructorScope
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun transformUncheckedNotNullCast(
|
override fun transformUncheckedNotNullCast(
|
||||||
@@ -359,17 +352,15 @@ open class FirBodyResolveTransformer(
|
|||||||
): FirAnonymousFunction {
|
): FirAnonymousFunction {
|
||||||
val receiverTypeRef = anonymousFunction.receiverTypeRef
|
val receiverTypeRef = anonymousFunction.receiverTypeRef
|
||||||
fun transform(): FirAnonymousFunction {
|
fun transform(): FirAnonymousFunction {
|
||||||
return withScopeCleanup(scopes) {
|
val expectedReturnType =
|
||||||
scopes.addIfNotNull(receiverTypeRef?.coneTypeSafe<ConeKotlinType>()?.scope(session, scopeSession))
|
lambdaResolution.expectedReturnTypeRef ?: anonymousFunction.returnTypeRef.takeUnless { it is FirImplicitTypeRef }
|
||||||
val expectedReturnType = lambdaResolution.expectedReturnTypeRef ?: anonymousFunction.returnTypeRef.takeUnless { it is FirImplicitTypeRef }
|
|
||||||
val result = super.transformAnonymousFunction(anonymousFunction, expectedReturnType).single as FirAnonymousFunction
|
val result = super.transformAnonymousFunction(anonymousFunction, expectedReturnType).single as FirAnonymousFunction
|
||||||
val body = result.body
|
val body = result.body
|
||||||
if (result.returnTypeRef is FirImplicitTypeRef && body != null) {
|
return if (result.returnTypeRef is FirImplicitTypeRef && body != null) {
|
||||||
result.transformReturnTypeRef(this, body.resultType)
|
result.transformReturnTypeRef(this, body.resultType)
|
||||||
result
|
result
|
||||||
} else {
|
} else {
|
||||||
result
|
result
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -563,18 +554,14 @@ open class FirBodyResolveTransformer(
|
|||||||
if (function is FirNamedFunction) {
|
if (function is FirNamedFunction) {
|
||||||
localScopes.lastOrNull()?.storeDeclaration(function)
|
localScopes.lastOrNull()?.storeDeclaration(function)
|
||||||
}
|
}
|
||||||
return withScopeCleanup(scopes) {
|
val result = transformFunction(function, returnTypeRef).single as FirFunction<*>
|
||||||
scopes.addIfNotNull(receiverTypeRef?.coneTypeSafe<ConeKotlinType>()?.scope(session, scopeSession))
|
val body = result.body
|
||||||
|
return if (result is FirTypedDeclaration && result.returnTypeRef is FirImplicitTypeRef && body != null) {
|
||||||
val result = transformFunction(function, returnTypeRef).single as FirFunction<*>
|
result.transformReturnTypeRef(this, body.resultType)
|
||||||
val body = result.body
|
result
|
||||||
if (result is FirTypedDeclaration && result.returnTypeRef is FirImplicitTypeRef && body != null) {
|
} else {
|
||||||
result.transformReturnTypeRef(this, body.resultType)
|
result
|
||||||
result
|
}.compose()
|
||||||
} else {
|
|
||||||
result
|
|
||||||
}.compose()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun transformNamedFunction(namedFunction: FirNamedFunction, data: Any?): CompositeTransformResult<FirDeclaration> {
|
override fun transformNamedFunction(namedFunction: FirNamedFunction, data: Any?): CompositeTransformResult<FirDeclaration> {
|
||||||
@@ -783,10 +770,16 @@ open class FirBodyResolveTransformer(
|
|||||||
|
|
||||||
private inline fun <T> withLabelAndReceiverType(labelName: Name, owner: FirElement, type: ConeKotlinType, block: () -> T): T {
|
private inline fun <T> withLabelAndReceiverType(labelName: Name, owner: FirElement, type: ConeKotlinType, block: () -> T): T {
|
||||||
labels.put(labelName, type)
|
labels.put(labelName, type)
|
||||||
when (owner) {
|
implicitReceiverStack += when (owner) {
|
||||||
is FirRegularClass -> implicitReceiverStack += ImplicitDispatchReceiverValue(owner.symbol, type)
|
is FirRegularClass -> {
|
||||||
is FirFunction<*> -> implicitReceiverStack += ImplicitExtensionReceiverValue(type)
|
ImplicitDispatchReceiverValue(owner.symbol, type, symbolProvider, session, scopeSession)
|
||||||
else -> throw IllegalArgumentException("Incorrect label & receiver owner: ${owner.javaClass}")
|
}
|
||||||
|
is FirFunction<*> -> {
|
||||||
|
ImplicitExtensionReceiverValue(type, session, scopeSession)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
throw IllegalArgumentException("Incorrect label & receiver owner: ${owner.javaClass}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
val result = block()
|
val result = block()
|
||||||
implicitReceiverStack.removeAt(implicitReceiverStack.size - 1)
|
implicitReceiverStack.removeAt(implicitReceiverStack.size - 1)
|
||||||
|
|||||||
@@ -37,11 +37,11 @@ FILE: access.kt
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final fun R|Foo|.check(): <ERROR TYPE REF: Inapplicable(INAPPLICABLE): [kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus]> {
|
public final fun R|Foo|.check(): <ERROR TYPE REF: Inapplicable(INAPPLICABLE): [kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus]> {
|
||||||
^check R|/Foo.abc|().<Inapplicable(INAPPLICABLE): [kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus]>#(R|/bar|())
|
^check R|/Foo.abc|().<Inapplicable(INAPPLICABLE): [kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus]>#(R|/Bar.bar|())
|
||||||
}
|
}
|
||||||
|
|
||||||
public final fun R|Foo|.check2(): R|kotlin/String| {
|
public final fun R|Foo|.check2(): R|kotlin/String| {
|
||||||
^check2 String().R|kotlin/String.plus|(R|/bar|())
|
^check2 String().R|kotlin/String.plus|(R|/Bar.bar|())
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+12
@@ -10,4 +10,16 @@ class Foo {
|
|||||||
operator fun invoke(): Foo { return this }
|
operator fun invoke(): Foo { return this }
|
||||||
|
|
||||||
fun bar() = x() // Should resolve to invoke
|
fun bar() = x() // Should resolve to invoke
|
||||||
|
}
|
||||||
|
|
||||||
|
class Bar {
|
||||||
|
fun x() {}
|
||||||
|
|
||||||
|
val x: Bar = Bar()
|
||||||
|
|
||||||
|
operator fun invoke(): Bar { return this }
|
||||||
|
|
||||||
|
fun baz() {
|
||||||
|
x() // Should resolve to fun x()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+20
@@ -18,3 +18,23 @@ FILE: explicitReceiver.kt
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
public final class Bar : R|kotlin/Any| {
|
||||||
|
public constructor(): R|Bar| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
public final fun x(): R|kotlin/Unit| {
|
||||||
|
}
|
||||||
|
|
||||||
|
public final val x: R|Bar| = R|/Bar.Bar|()
|
||||||
|
public get(): R|Bar|
|
||||||
|
|
||||||
|
public final operator fun invoke(): R|Bar| {
|
||||||
|
^invoke this#
|
||||||
|
}
|
||||||
|
|
||||||
|
public final fun baz(): R|kotlin/Unit| {
|
||||||
|
R|/Bar.x|()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ FILE: extension.kt
|
|||||||
public final val x: R|kotlin/Int| = Int(0)
|
public final val x: R|kotlin/Int| = Int(0)
|
||||||
public get(): R|kotlin/Int|
|
public get(): R|kotlin/Int|
|
||||||
|
|
||||||
public final fun foo(): R|kotlin/Unit| {
|
public final fun foo(): R|Foo| {
|
||||||
^foo R|/x|()
|
^foo R|/Foo.x|.R|/Foo.invoke|()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ FILE: recursiveBug.kt
|
|||||||
super<R|kotlin/Any|>()
|
super<R|kotlin/Any|>()
|
||||||
}
|
}
|
||||||
|
|
||||||
public final val result: R|kotlin/String| = R|kotlin/run|<R|kotlin/String|>(<L> = run@fun <anonymous>(): R|kotlin/String| {
|
public final val result: R|kotlin/String| = R|kotlin/run|<R|Foo|, R|kotlin/String|>(<L> = run@fun R|Foo|.<anonymous>(it: R|Foo|): R|kotlin/String| {
|
||||||
R|<local>/name|.R|FakeOverride<kotlin/Function0.invoke: R|kotlin/String|>|()
|
R|<local>/name|.R|FakeOverride<kotlin/Function0.invoke: R|kotlin/String|>|()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
FILE fqName:<root> fileName:/implicitCastToNonNull.kt
|
FILE fqName:<root> fileName:/implicitCastToNonNull.kt
|
||||||
FUN name:test1 visibility:public modality:FINAL <> (x:kotlin.String?) returnType:kotlin.Int
|
FUN name:test1 visibility:public modality:FINAL <> (x:kotlin.String?) returnType:IrErrorType
|
||||||
VALUE_PARAMETER name:x index:0 type:kotlin.String?
|
VALUE_PARAMETER name:x index:0 type:kotlin.String?
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
RETURN type=kotlin.Nothing from='public final fun test1 (x: kotlin.String?): kotlin.Int declared in <root>'
|
RETURN type=kotlin.Nothing from='public final fun test1 (x: kotlin.String?): IrErrorType declared in <root>'
|
||||||
WHEN type=kotlin.Int origin=IF
|
WHEN type=IrErrorType origin=IF
|
||||||
BRANCH
|
BRANCH
|
||||||
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
|
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
|
||||||
arg0: GET_VAR 'x: kotlin.String? declared in <root>.test1' type=kotlin.String? origin=null
|
arg0: GET_VAR 'x: kotlin.String? declared in <root>.test1' type=kotlin.String? origin=null
|
||||||
@@ -11,13 +11,13 @@ FILE fqName:<root> fileName:/implicitCastToNonNull.kt
|
|||||||
then: CONST Int type=kotlin.Int value=0
|
then: CONST Int type=kotlin.Int value=0
|
||||||
BRANCH
|
BRANCH
|
||||||
if: CONST Boolean type=kotlin.Boolean value=true
|
if: CONST Boolean type=kotlin.Boolean value=true
|
||||||
then: ERROR_CALL 'No getter found for R|kotlin/String.length|' type=kotlin.Int
|
then: ERROR_CALL 'Unresolved reference: <Inapplicable(WRONG_RECEIVER): [kotlin/String.length]>#' type=IrErrorType
|
||||||
FUN name:test2 visibility:public modality:FINAL <T> (x:T of <root>.test2) returnType:kotlin.Int
|
FUN name:test2 visibility:public modality:FINAL <T> (x:T of <root>.test2) returnType:IrErrorType
|
||||||
TYPE_PARAMETER name:T index:0 variance: superTypes:[]
|
TYPE_PARAMETER name:T index:0 variance: superTypes:[]
|
||||||
VALUE_PARAMETER name:x index:0 type:T of <root>.test2
|
VALUE_PARAMETER name:x index:0 type:T of <root>.test2
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
RETURN type=kotlin.Nothing from='public final fun test2 <T> (x: T of <root>.test2): kotlin.Int declared in <root>'
|
RETURN type=kotlin.Nothing from='public final fun test2 <T> (x: T of <root>.test2): IrErrorType declared in <root>'
|
||||||
WHEN type=kotlin.Int origin=IF
|
WHEN type=IrErrorType origin=IF
|
||||||
BRANCH
|
BRANCH
|
||||||
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
|
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
|
||||||
arg0: GET_VAR 'x: T of <root>.test2 declared in <root>.test2' type=T of <root>.test2 origin=null
|
arg0: GET_VAR 'x: T of <root>.test2 declared in <root>.test2' type=T of <root>.test2 origin=null
|
||||||
@@ -25,7 +25,7 @@ FILE fqName:<root> fileName:/implicitCastToNonNull.kt
|
|||||||
then: CONST Int type=kotlin.Int value=0
|
then: CONST Int type=kotlin.Int value=0
|
||||||
BRANCH
|
BRANCH
|
||||||
if: CONST Boolean type=kotlin.Boolean value=true
|
if: CONST Boolean type=kotlin.Boolean value=true
|
||||||
then: ERROR_CALL 'No getter found for R|kotlin/CharSequence.length|' type=kotlin.Int
|
then: ERROR_CALL 'Unresolved reference: <Inapplicable(WRONG_RECEIVER): [kotlin/CharSequence.length]>#' type=IrErrorType
|
||||||
FUN name:test3 visibility:public modality:FINAL <T> (x:kotlin.Any) returnType:IrErrorType [inline]
|
FUN name:test3 visibility:public modality:FINAL <T> (x:kotlin.Any) returnType:IrErrorType [inline]
|
||||||
TYPE_PARAMETER name:T index:0 variance: superTypes:[]
|
TYPE_PARAMETER name:T index:0 variance: superTypes:[]
|
||||||
VALUE_PARAMETER name:x index:0 type:kotlin.Any
|
VALUE_PARAMETER name:x index:0 type:kotlin.Any
|
||||||
|
|||||||
Reference in New Issue
Block a user