FIR: Rework delegation constructor calls resolution

Make it work independently of being called for inner class (as in FE 1.0)
This commit is contained in:
Denis Zharkov
2020-07-30 15:35:35 +03:00
parent db93b9052b
commit a5a93d00a7
27 changed files with 181 additions and 169 deletions
@@ -50,4 +50,4 @@ fun test_4() {
fun test_5() { fun test_5() {
val map = LinkedHashMap<Int, Int>() // should be foo.LinkedHashMap val map = LinkedHashMap<Int, Int>() // should be foo.LinkedHashMap
} }
@@ -25,7 +25,7 @@ class E<T> {
// selection of the proper constructor // selection of the proper constructor
// but a type mismatch for the first // but a type mismatch for the first
// argument // argument
constructor(e: T, i: Int) : <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(i, 10) {} constructor(e: T, i: Int) : <!INAPPLICABLE_CANDIDATE!>this<!>(i, 10) {}
} }
class I<T> { class I<T> {
@@ -33,7 +33,7 @@ class I<T> {
// selection of the proper constructor // selection of the proper constructor
// but a type mismatch for the first // but a type mismatch for the first
// argument // argument
constructor(e: T, i: Int) : <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(i, 10) constructor(e: T, i: Int) : <!INAPPLICABLE_CANDIDATE!>this<!>(i, 10)
} }
class J<T> { class J<T> {
@@ -64,4 +64,4 @@ class M {
class U : M { class U : M {
<!INAPPLICABLE_CANDIDATE!>constructor()<!> <!INAPPLICABLE_CANDIDATE!>constructor()<!>
} }
@@ -7,6 +7,8 @@ package org.jetbrains.kotlin.fir
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
import org.jetbrains.kotlin.fir.declarations.isInner import org.jetbrains.kotlin.fir.declarations.isInner
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.*
@@ -32,10 +34,13 @@ import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildStarProjection
import org.jetbrains.kotlin.fir.types.builder.buildTypeProjectionWithVariance
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.types.Variance
class FirCallResolver( class FirCallResolver(
private val components: BodyResolveComponents, private val components: BodyResolveComponents,
@@ -291,10 +296,16 @@ class FirCallResolver(
fun resolveDelegatingConstructorCall( fun resolveDelegatingConstructorCall(
delegatedConstructorCall: FirDelegatedConstructorCall, delegatedConstructorCall: FirDelegatedConstructorCall,
constructorClassSymbol: FirClassSymbol<*>, constructedType: ConeClassLikeType
typeArguments: List<FirTypeProjection>,
): FirDelegatedConstructorCall? { ): FirDelegatedConstructorCall? {
val name = Name.special("<init>") val name = Name.special("<init>")
val symbol = constructedType.lookupTag.toSymbol(components.session)
val typeArguments =
constructedType.typeArguments.take((symbol?.fir as? FirRegularClass)?.typeParameters?.count { it is FirTypeParameter } ?: 0)
.map {
it.toFirTypeProjection()
}
val callInfo = CallInfo( val callInfo = CallInfo(
CallKind.DelegatingConstructorCall, CallKind.DelegatingConstructorCall,
name, name,
@@ -307,14 +318,36 @@ class FirCallResolver(
containingDeclarations, containingDeclarations,
) )
towerResolver.reset() towerResolver.reset()
val result = towerResolver.runResolverForDelegatingConstructor( val result = towerResolver.runResolverForDelegatingConstructor(
callInfo, callInfo,
constructorClassSymbol, constructedType
) )
return callResolver.selectDelegatingConstructorCall(delegatedConstructorCall, name, result, callInfo) return callResolver.selectDelegatingConstructorCall(delegatedConstructorCall, name, result, callInfo)
} }
private fun ConeTypeProjection.toFirTypeProjection(): FirTypeProjection = when (this) {
is ConeStarProjection -> buildStarProjection()
else -> {
val type = when (this) {
is ConeKotlinTypeProjectionIn -> type
is ConeKotlinTypeProjectionOut -> type
is ConeStarProjection -> throw IllegalStateException()
else -> this as ConeKotlinType
}
buildTypeProjectionWithVariance {
typeRef = buildResolvedTypeRef { this.type = type }
variance = when (kind) {
ProjectionKind.IN -> Variance.IN_VARIANCE
ProjectionKind.OUT -> Variance.OUT_VARIANCE
ProjectionKind.INVARIANT -> Variance.INVARIANT
ProjectionKind.STAR -> throw IllegalStateException()
}
}
}
}
fun resolveAnnotationCall(annotationCall: FirAnnotationCall): FirAnnotationCall? { fun resolveAnnotationCall(annotationCall: FirAnnotationCall): FirAnnotationCall? {
val reference = annotationCall.calleeReference as? FirSimpleNamedReference ?: return null val reference = annotationCall.calleeReference as? FirSimpleNamedReference ?: return null
annotationCall.argumentList.transformArguments(transformer, ResolutionMode.ContextDependent) annotationCall.argumentList.transformArguments(transformer, ResolutionMode.ContextDependent)
@@ -57,6 +57,7 @@ interface BodyResolveComponents : SessionHolder {
val dataFlowAnalyzer: FirDataFlowAnalyzer<*> val dataFlowAnalyzer: FirDataFlowAnalyzer<*>
val integerLiteralTypeApproximator: IntegerLiteralTypeApproximationTransformer val integerLiteralTypeApproximator: IntegerLiteralTypeApproximationTransformer
val integerOperatorsTypeUpdater: IntegerOperatorsTypeUpdater val integerOperatorsTypeUpdater: IntegerOperatorsTypeUpdater
val outerClassManager: FirOuterClassManager
val <D> AbstractFirBasedSymbol<D>.phasedFir: D where D : FirDeclaration, D : FirSymbolOwner<D> val <D> AbstractFirBasedSymbol<D>.phasedFir: D where D : FirDeclaration, D : FirSymbolOwner<D>
get() = phasedFir(FirResolvePhase.DECLARATIONS) get() = phasedFir(FirResolvePhase.DECLARATIONS)
@@ -0,0 +1,45 @@
/*
* 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
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
import org.jetbrains.kotlin.fir.declarations.isInner
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
class FirOuterClassManager(
private val session: FirSession,
private val outerLocalClassForNested: Map<FirClassLikeSymbol<*>, FirClassLikeSymbol<*>>,
) {
private val symbolProvider = session.firSymbolProvider
fun outerClass(classSymbol: FirClassLikeSymbol<*>): FirClassLikeSymbol<*>? {
if (classSymbol !is FirClassSymbol<*>) return null
val classId = classSymbol.classId
if (classId.isLocal) return outerLocalClassForNested[classSymbol]
val outerClassId = classId.outerClassId ?: return null
return symbolProvider.getClassLikeSymbolByFqName(outerClassId)
}
fun outerType(classLikeType: ConeClassLikeType): ConeClassLikeType? {
val fullyExpandedType = classLikeType.fullyExpandedType(session)
val symbol = fullyExpandedType.lookupTag.toSymbol(session) ?: return null
if (symbol is FirRegularClassSymbol && !symbol.fir.isInner) return null
val containingSymbol = outerClass(symbol) ?: return null
val currentTypeArgumentsNumber = (symbol as? FirRegularClassSymbol)?.fir?.typeParameters?.count { it is FirTypeParameter } ?: 0
return containingSymbol.constructType(
fullyExpandedType.typeArguments.drop(currentTypeArgumentsNumber).toTypedArray(),
isNullable = false
) as ConeClassLikeType
}
}
@@ -21,8 +21,8 @@ import org.jetbrains.kotlin.fir.scopes.scope
import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.ConeClassLikeType import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.coneTypeUnsafe
import org.jetbrains.kotlin.fir.types.coneType import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.coneTypeUnsafe
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
private operator fun <T> Pair<T, *>?.component1() = this?.first private operator fun <T> Pair<T, *>?.component1() = this?.first
@@ -32,7 +32,6 @@ internal fun FirScope.processConstructorsByName(
name: Name, name: Name,
session: FirSession, session: FirSession,
bodyResolveComponents: BodyResolveComponents, bodyResolveComponents: BodyResolveComponents,
includeSyntheticConstructors: Boolean,
includeInnerConstructors: Boolean, includeInnerConstructors: Boolean,
processor: (FirCallableSymbol<*>) -> Unit processor: (FirCallableSymbol<*>) -> Unit
) { ) {
@@ -51,13 +50,11 @@ internal fun FirScope.processConstructorsByName(
includeInnerConstructors includeInnerConstructors
) )
if (includeSyntheticConstructors) { processSyntheticConstructors(
processSyntheticConstructors( matchedClassSymbol,
matchedClassSymbol, processor,
processor, bodyResolveComponents
bodyResolveComponents )
)
}
} }
} }
@@ -70,7 +67,6 @@ internal fun FirScope.processFunctionsAndConstructorsByName(
) { ) {
processConstructorsByName( processConstructorsByName(
name, session, bodyResolveComponents, name, session, bodyResolveComponents,
includeSyntheticConstructors = true,
includeInnerConstructors = includeInnerConstructors, includeInnerConstructors = includeInnerConstructors,
processor = processor processor = processor
) )
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.fir.resolve.calls.tower
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
import org.jetbrains.kotlin.fir.resolve.calls.* import org.jetbrains.kotlin.fir.resolve.calls.*
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol import org.jetbrains.kotlin.fir.types.ConeClassLikeType
class FirTowerResolver( class FirTowerResolver(
private val components: BodyResolveComponents, private val components: BodyResolveComponents,
@@ -32,12 +32,12 @@ class FirTowerResolver(
fun runResolverForDelegatingConstructor( fun runResolverForDelegatingConstructor(
info: CallInfo, info: CallInfo,
constructorClassSymbol: FirClassSymbol<*>, constructedType: ConeClassLikeType,
): CandidateCollector { ): CandidateCollector {
val candidateFactoriesAndCollectors = buildCandidateFactoriesAndCollectors(info, collector) val candidateFactoriesAndCollectors = buildCandidateFactoriesAndCollectors(info, collector)
val towerResolverSession = FirTowerResolverSession(components, manager, candidateFactoriesAndCollectors, info) val towerResolverSession = FirTowerResolverSession(components, manager, candidateFactoriesAndCollectors, info)
towerResolverSession.runResolutionForDelegatingConstructor(info, constructorClassSymbol) towerResolverSession.runResolutionForDelegatingConstructor(info, constructedType)
manager.runTasks() manager.runTasks()
return collector return collector
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.fir.resolve.calls.tower
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.asReversedFrozen import org.jetbrains.kotlin.fir.asReversedFrozen
import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.isInner
import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
@@ -20,15 +19,15 @@ import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe
import org.jetbrains.kotlin.fir.scopes.FirCompositeScope import org.jetbrains.kotlin.fir.scopes.FirCompositeScope
import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.ProcessorAction import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.descriptorUtil.HIDES_MEMBERS_NAME_LIST import org.jetbrains.kotlin.resolve.descriptorUtil.HIDES_MEMBERS_NAME_LIST
import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
class FirTowerResolverSession internal constructor( class FirTowerResolverSession internal constructor(
@@ -67,8 +66,11 @@ class FirTowerResolverSession internal constructor(
} }
} }
fun runResolutionForDelegatingConstructor(info: CallInfo, constructorClassSymbol: FirClassSymbol<*>) { fun runResolutionForDelegatingConstructor(
manager.enqueueResolverTask { runResolverForDelegatingConstructorCall(info, constructorClassSymbol) } info: CallInfo,
constructedType: ConeClassLikeType
) {
manager.enqueueResolverTask { runResolverForDelegatingConstructorCall(info, constructedType) }
} }
fun runResolution(info: CallInfo) { fun runResolution(info: CallInfo) {
@@ -138,8 +140,8 @@ class FirTowerResolverSession internal constructor(
extensionReceiver, extensionsOnly, includeInnerConstructors extensionReceiver, extensionsOnly, includeInnerConstructors
) )
private fun FirScope.toConstructorScopeTowerLevel(): ConstructorScopeTowerLevel = private fun FirScope.toConstructorScopeTowerLevel(dispatchReceiver: ImplicitReceiver?): ConstructorScopeTowerLevel =
ConstructorScopeTowerLevel(session, this) ConstructorScopeTowerLevel(session, this, dispatchReceiver?.receiver)
private fun ReceiverValue.toMemberScopeTowerLevel( private fun ReceiverValue.toMemberScopeTowerLevel(
extensionReceiver: ReceiverValue? = null, extensionReceiver: ReceiverValue? = null,
@@ -211,23 +213,25 @@ class FirTowerResolverSession internal constructor(
} }
} }
private suspend fun runResolverForDelegatingConstructorCall(info: CallInfo, constructorClassSymbol: FirClassSymbol<*>) { private suspend fun runResolverForDelegatingConstructorCall(
val scope = constructorClassSymbol.fir.unsubstitutedScope(session, components.scopeSession) info: CallInfo,
if (constructorClassSymbol is FirRegularClassSymbol && constructorClassSymbol.fir.isInner) { constructedType: ConeClassLikeType
// Search for inner constructors only ) {
for ((implicitReceiverValue, depth) in implicitReceivers.drop(1)) { val outerType = components.outerClassManager.outerType(constructedType)
processLevel( val scope = constructedType.scope(session, components.scopeSession) ?: return
implicitReceiverValue.toMemberScopeTowerLevel(),
info.copy(name = constructorClassSymbol.fir.name), TowerGroup.Implicit(depth) val dispatchReceiver =
) if (outerType != null)
} implicitReceivers.drop(1).firstOrNull {
} else { AbstractTypeChecker.isSubtypeOf(components.session.typeContext, it.receiver.type, outerType)
// Search for non-inner constructors only } ?: return // TODO: report diagnostic about not-found receiver
processLevel( else
scope.toConstructorScopeTowerLevel(), null
info, TowerGroup.Member
) processLevel(
} scope.toConstructorScopeTowerLevel(dispatchReceiver),
info, TowerGroup.Member
)
} }
private suspend fun runResolverForNoReceiver( private suspend fun runResolverForNoReceiver(
@@ -123,7 +123,7 @@ internal class TowerLevelHandler {
} }
} }
CallKind.DelegatingConstructorCall -> { CallKind.DelegatingConstructorCall -> {
towerLevel.processConstructors(info.name, processor) towerLevel.processElementsByNameAndStoreResult(TowerScopeLevel.Token.ConstructorsForDelegationCall, info.name, processor)
} }
else -> { else -> {
throw AssertionError("Unsupported call kind in tower resolver: ${info.callKind}") throw AssertionError("Unsupported call kind in tower resolver: ${info.callKind}")
@@ -153,12 +153,6 @@ internal class TowerLevelHandler {
processProperties(name, processor) processProperties(name, processor)
} }
private fun TowerScopeLevel.processConstructors(
name: Name, processor: TowerScopeLevel.TowerScopeLevelProcessor<AbstractFirBasedSymbol<*>>
) {
processElementsByNameAndStoreResult(TowerScopeLevel.Token.Constructors, name, processor)
}
private fun TowerScopeLevel.processObjectsAsVariables( private fun TowerScopeLevel.processObjectsAsVariables(
name: Name, processor: TowerScopeLevel.TowerScopeLevelProcessor<AbstractFirBasedSymbol<*>> name: Name, processor: TowerScopeLevel.TowerScopeLevelProcessor<AbstractFirBasedSymbol<*>>
) { ) {
@@ -35,7 +35,7 @@ interface TowerScopeLevel {
sealed class Token<out T : AbstractFirBasedSymbol<*>> { sealed class Token<out T : AbstractFirBasedSymbol<*>> {
object Properties : Token<FirVariableSymbol<*>>() object Properties : Token<FirVariableSymbol<*>>()
object Functions : Token<FirFunctionSymbol<*>>() object Functions : Token<FirFunctionSymbol<*>>()
object Constructors : Token<FirConstructorSymbol>() object ConstructorsForDelegationCall : Token<FirConstructorSymbol>()
object Objects : Token<AbstractFirBasedSymbol<*>>() object Objects : Token<AbstractFirBasedSymbol<*>>()
} }
@@ -79,7 +79,6 @@ class MemberScopeTowerLevel(
) : SessionBasedTowerLevel(session) { ) : SessionBasedTowerLevel(session) {
private fun <T : AbstractFirBasedSymbol<*>> processMembers( private fun <T : AbstractFirBasedSymbol<*>> processMembers(
output: TowerScopeLevel.TowerScopeLevelProcessor<T>, output: TowerScopeLevel.TowerScopeLevelProcessor<T>,
forInnerConstructorDelegationCalls: Boolean = false,
processScopeMembers: FirScope.(processor: (T) -> Unit) -> Unit processScopeMembers: FirScope.(processor: (T) -> Unit) -> Unit
): ProcessorAction { ): ProcessorAction {
var empty = true var empty = true
@@ -90,9 +89,7 @@ class MemberScopeTowerLevel(
(implicitExtensionInvokeMode || candidate.hasConsistentExtensionReceiver(extensionReceiver)) (implicitExtensionInvokeMode || candidate.hasConsistentExtensionReceiver(extensionReceiver))
) { ) {
val fir = candidate.fir val fir = candidate.fir
if (forInnerConstructorDelegationCalls && candidate !is FirConstructorSymbol) { if ((fir as? FirConstructor)?.isInner == false) {
return@processScopeMembers
} else if ((fir as? FirConstructor)?.isInner == false) {
return@processScopeMembers return@processScopeMembers
} }
val dispatchReceiverValue = NotNullableReceiverValue(dispatchReceiver) val dispatchReceiverValue = NotNullableReceiverValue(dispatchReceiver)
@@ -114,7 +111,7 @@ class MemberScopeTowerLevel(
} }
} }
if (!forInnerConstructorDelegationCalls && extensionReceiver == null) { if (extensionReceiver == null) {
val withSynthetic = FirSyntheticPropertiesScope(session, scope) val withSynthetic = FirSyntheticPropertiesScope(session, scope)
withSynthetic.processScopeMembers { symbol -> withSynthetic.processScopeMembers { symbol ->
empty = false empty = false
@@ -159,17 +156,7 @@ class MemberScopeTowerLevel(
consumer(it as T) consumer(it as T)
} }
} }
TowerScopeLevel.Token.Constructors -> processMembers(processor, forInnerConstructorDelegationCalls = true) { consumer -> TowerScopeLevel.Token.ConstructorsForDelegationCall -> error("ConstructorsForDelegationCall should be handled via ConstructorScopeTowerLevel")
this.processConstructorsByName(
name, session, bodyResolveComponents,
includeSyntheticConstructors = false,
includeInnerConstructors = true,
processor = {
@Suppress("UNCHECKED_CAST")
consumer(it as T)
}
)
}
} }
} }
@@ -276,7 +263,7 @@ class ScopeTowerLevel(
implicitExtensionReceiverValue = null implicitExtensionReceiverValue = null
) )
} }
TowerScopeLevel.Token.Constructors -> { TowerScopeLevel.Token.ConstructorsForDelegationCall -> {
throw AssertionError("Should not be here") throw AssertionError("Should not be here")
} }
} }
@@ -286,7 +273,8 @@ class ScopeTowerLevel(
class ConstructorScopeTowerLevel( class ConstructorScopeTowerLevel(
session: FirSession, session: FirSession,
val scope: FirScope private val scope: FirScope,
private val dispatchReceiver: ImplicitReceiverValue<*>?,
) : SessionBasedTowerLevel(session) { ) : SessionBasedTowerLevel(session) {
override fun <T : AbstractFirBasedSymbol<*>> processElementsByName( override fun <T : AbstractFirBasedSymbol<*>> processElementsByName(
token: TowerScopeLevel.Token<T>, token: TowerScopeLevel.Token<T>,
@@ -295,17 +283,14 @@ class ConstructorScopeTowerLevel(
): ProcessorAction { ): ProcessorAction {
var empty = true var empty = true
when (token) { when (token) {
TowerScopeLevel.Token.Constructors -> scope.processDeclaredConstructors { candidate -> TowerScopeLevel.Token.ConstructorsForDelegationCall -> scope.processDeclaredConstructors { candidate ->
// NB: here we cannot resolve inner constructors, because they should have dispatch receiver empty = false
if (!candidate.fir.isInner) { @Suppress("UNCHECKED_CAST")
empty = false processor.consumeCandidate(
@Suppress("UNCHECKED_CAST") candidate as T,
processor.consumeCandidate( dispatchReceiverValue = dispatchReceiver,
candidate as T, implicitExtensionReceiverValue = null
dispatchReceiverValue = null, )
implicitExtensionReceiverValue = null
)
}
} }
else -> { else -> {
throw AssertionError("Should not be here: token = $token") throw AssertionError("Should not be here: token = $token")
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildImplicitTypeRef import org.jetbrains.kotlin.fir.types.builder.buildImplicitTypeRef
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
@@ -104,7 +105,8 @@ abstract class FirAbstractBodyResolveTransformer(phase: FirResolvePhase) : FirAb
class BodyResolveContext( class BodyResolveContext(
val returnTypeCalculator: ReturnTypeCalculator, val returnTypeCalculator: ReturnTypeCalculator,
val dataFlowAnalyzerContext: DataFlowAnalyzerContext<PersistentFlow>, val dataFlowAnalyzerContext: DataFlowAnalyzerContext<PersistentFlow>,
val targetedLocalClasses: Set<FirClass<*>> = emptySet() val targetedLocalClasses: Set<FirClass<*>> = emptySet(),
val outerLocalClassForNested: MutableMap<FirClassLikeSymbol<*>, FirClassLikeSymbol<*>> = mutableMapOf()
) { ) {
val fileImportsScope: MutableList<FirScope> = mutableListOf() val fileImportsScope: MutableList<FirScope> = mutableListOf()
@@ -241,7 +243,7 @@ abstract class FirAbstractBodyResolveTransformer(phase: FirResolvePhase) : FirAb
fun createSnapshotForLocalClasses( fun createSnapshotForLocalClasses(
returnTypeCalculator: ReturnTypeCalculator, returnTypeCalculator: ReturnTypeCalculator,
targetedLocalClasses: Set<FirClass<*>> targetedLocalClasses: Set<FirClass<*>>
) = BodyResolveContext(returnTypeCalculator, dataFlowAnalyzerContext, targetedLocalClasses).apply { ) = BodyResolveContext(returnTypeCalculator, dataFlowAnalyzerContext, targetedLocalClasses, outerLocalClassForNested).apply {
file = this@BodyResolveContext.file file = this@BodyResolveContext.file
towerDataContextForAnonymousFunctions.putAll(this@BodyResolveContext.towerDataContextForAnonymousFunctions) towerDataContextForAnonymousFunctions.putAll(this@BodyResolveContext.towerDataContextForAnonymousFunctions)
containers = this@BodyResolveContext.containers containers = this@BodyResolveContext.containers
@@ -291,5 +293,6 @@ abstract class FirAbstractBodyResolveTransformer(phase: FirResolvePhase) : FirAb
override val doubleColonExpressionResolver: FirDoubleColonExpressionResolver = override val doubleColonExpressionResolver: FirDoubleColonExpressionResolver =
FirDoubleColonExpressionResolver(session, integerLiteralTypeApproximator) FirDoubleColonExpressionResolver(session, integerLiteralTypeApproximator)
override val integerOperatorsTypeUpdater: IntegerOperatorsTypeUpdater = IntegerOperatorsTypeUpdater(integerLiteralTypeApproximator) override val integerOperatorsTypeUpdater: IntegerOperatorsTypeUpdater = IntegerOperatorsTypeUpdater(integerLiteralTypeApproximator)
override val outerClassManager: FirOuterClassManager = FirOuterClassManager(session, context.outerLocalClassForNested)
} }
} }
@@ -11,7 +11,6 @@ import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.ConeStubDiagnostic import org.jetbrains.kotlin.fir.diagnostics.ConeStubDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.ConeIntermediateDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.buildErrorExpression import org.jetbrains.kotlin.fir.expressions.builder.buildErrorExpression
@@ -31,14 +30,12 @@ import org.jetbrains.kotlin.fir.resolve.transformers.StoreReceiver
import org.jetbrains.kotlin.fir.resolve.transformers.firClassLike import org.jetbrains.kotlin.fir.resolve.transformers.firClassLike
import org.jetbrains.kotlin.fir.scopes.impl.withReplacedConeType import org.jetbrains.kotlin.fir.scopes.impl.withReplacedConeType
import org.jetbrains.kotlin.fir.symbols.StandardClassIds import org.jetbrains.kotlin.fir.symbols.StandardClassIds
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.* import org.jetbrains.kotlin.fir.types.builder.*
import org.jetbrains.kotlin.fir.visitors.* import org.jetbrains.kotlin.fir.visitors.*
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.Variance
open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) : FirPartialBodyResolveTransformer(transformer) { open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) : FirPartialBodyResolveTransformer(transformer) {
private inline val builtinTypes: BuiltinTypes get() = session.builtinTypes private inline val builtinTypes: BuiltinTypes get() = session.builtinTypes
@@ -757,27 +754,6 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
} }
} }
private fun ConeTypeProjection.toFirTypeProjection(): FirTypeProjection = when (this) {
is ConeStarProjection -> buildStarProjection()
else -> {
val type = when (this) {
is ConeKotlinTypeProjectionIn -> type
is ConeKotlinTypeProjectionOut -> type
is ConeStarProjection -> throw IllegalStateException()
else -> this as ConeKotlinType
}
buildTypeProjectionWithVariance {
typeRef = buildResolvedTypeRef { this.type = type }
variance = when (kind) {
ProjectionKind.IN -> Variance.IN_VARIANCE
ProjectionKind.OUT -> Variance.OUT_VARIANCE
ProjectionKind.INVARIANT -> Variance.INVARIANT
ProjectionKind.STAR -> throw IllegalStateException()
}
}
}
}
override fun transformDelegatedConstructorCall( override fun transformDelegatedConstructorCall(
delegatedConstructorCall: FirDelegatedConstructorCall, delegatedConstructorCall: FirDelegatedConstructorCall,
data: ResolutionMode, data: ResolutionMode,
@@ -814,38 +790,23 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
delegatedConstructorCall.transformChildren(transformer, ResolutionMode.ContextDependent) delegatedConstructorCall.transformChildren(transformer, ResolutionMode.ContextDependent)
} }
val typeArguments: List<FirTypeProjection>
val reference = delegatedConstructorCall.calleeReference val reference = delegatedConstructorCall.calleeReference
val symbol: FirClassSymbol<*> = when (reference) { val constructorType: ConeClassLikeType = when (reference) {
is FirThisReference -> { is FirThisReference -> {
typeArguments = emptyList() lastDispatchReceiver?.type as? ConeClassLikeType ?: return delegatedConstructorCall.compose()
if (reference.boundSymbol == null) {
lastDispatchReceiver?.boundSymbol?.also {
reference.replaceBoundSymbol(it)
} ?: return delegatedConstructorCall.compose()
} else {
reference.boundSymbol!! as FirClassSymbol<*>
}
} }
is FirSuperReference -> { is FirSuperReference -> {
// TODO: unresolved supertype // TODO: unresolved supertype
val supertype = reference.superTypeRef.coneTypeSafe<ConeClassLikeType>() ?: return delegatedConstructorCall.compose() val supertype = reference.superTypeRef.coneTypeSafe<ConeClassLikeType>()
val expandedSupertype = supertype.fullyExpandedType(session) ?.takeIf { it !is ConeClassErrorType } ?: return delegatedConstructorCall.compose()
val symbol = supertype.fullyExpandedType(session)
expandedSupertype.lookupTag.toSymbol(session) as? FirClassSymbol<*> ?: return delegatedConstructorCall.compose()
val classTypeParametersCount =
(symbol.fir as? FirTypeParameterRefsOwner)?.typeParameters?.count { it is FirTypeParameter } ?: 0
typeArguments = expandedSupertype.typeArguments
.takeLast(classTypeParametersCount) // Hack for KT-37525
.takeIf { it.isNotEmpty() }
?.map { it.toFirTypeProjection() }
?: emptyList()
symbol
} }
else -> return delegatedConstructorCall.compose() else -> return delegatedConstructorCall.compose()
} }
val resolvedCall = callResolver.resolveDelegatingConstructorCall(delegatedConstructorCall, symbol, typeArguments)
?: return delegatedConstructorCall.compose() val resolvedCall =
callResolver.resolveDelegatingConstructorCall(delegatedConstructorCall, constructorType)
?: return delegatedConstructorCall.compose()
if (reference is FirThisReference && reference.boundSymbol == null) { if (reference is FirThisReference && reference.boundSymbol == null) {
resolvedCall.dispatchReceiver.typeRef.coneTypeSafe<ConeClassLikeType>()?.lookupTag?.toSymbol(session)?.let { resolvedCall.dispatchReceiver.typeRef.coneTypeSafe<ConeClassLikeType>()?.lookupTag?.toSymbol(session)?.let {
reference.replaceBoundSymbol(it) reference.replaceBoundSymbol(it)
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.fir.resolve.transformers.body.resolve
import org.jetbrains.kotlin.fir.declarations.FirClass import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.resolve.ResolutionMode import org.jetbrains.kotlin.fir.resolve.ResolutionMode
import org.jetbrains.kotlin.fir.resolve.transformers.contracts.runContractResolveForLocalClass
import org.jetbrains.kotlin.fir.resolve.transformers.runStatusResolveForLocalClass import org.jetbrains.kotlin.fir.resolve.transformers.runStatusResolveForLocalClass
import org.jetbrains.kotlin.fir.resolve.transformers.runSupertypeResolvePhaseForLocalClass import org.jetbrains.kotlin.fir.resolve.transformers.runSupertypeResolvePhaseForLocalClass
import org.jetbrains.kotlin.fir.resolve.transformers.runTypeResolvePhaseForLocalClass import org.jetbrains.kotlin.fir.resolve.transformers.runTypeResolvePhaseForLocalClass
@@ -22,6 +21,12 @@ fun <F : FirClass<F>> F.runAllPhasesForLocalClass(
if (this.resolvePhase > FirResolvePhase.RAW_FIR) return this if (this.resolvePhase > FirResolvePhase.RAW_FIR) return this
this.transformAnnotations(transformer, ResolutionMode.ContextIndependent) this.transformAnnotations(transformer, ResolutionMode.ContextIndependent)
val localClassesNavigationInfo = collectLocalClassesNavigationInfo() val localClassesNavigationInfo = collectLocalClassesNavigationInfo()
for ((nested, outer) in localClassesNavigationInfo.parentForClass) {
if (outer == null) continue
components.context.outerLocalClassForNested[nested.symbol] = outer.symbol
}
runSupertypeResolvePhaseForLocalClass( runSupertypeResolvePhaseForLocalClass(
components.session, components.session,
components.scopeSession, components.scopeSession,
@@ -12,4 +12,4 @@ public class C {
class Foo : <!UNRESOLVED_REFERENCE!>Data<!>() class Foo : <!UNRESOLVED_REFERENCE!>Data<!>()
companion object : DerivedAbstract() companion object : DerivedAbstract()
} }
@@ -12,4 +12,4 @@ public class C {
class Foo : <!UNRESOLVED_REFERENCE!>Data<!>() class Foo : <!UNRESOLVED_REFERENCE!>Data<!>()
companion object : DerivedAbstract() companion object : DerivedAbstract()
} }
@@ -79,4 +79,4 @@ object MessageManager15 : Manager<Int> {
var <T : Int> T.y var <T : Int> T.y
get() = 10 get() = 10
set(value) {} set(value) {}
} }
+1 -1
View File
@@ -6,7 +6,7 @@ abstract class A<T> {
public abstract fun bar(x: T) public abstract fun bar(x: T)
public inner abstract class B<S> : A<B<S>>() { public inner abstract class B<S> : A<B<S>>() {
public inner class C<U> : B<C<U>>() public inner class C<U> : <!UNRESOLVED_REFERENCE!>B<C<U>><!>()
{ {
// Here B<C<U>> means A<A<A<T>.B<S>>.B<A<T>.B<S>.C<U>>>.B<A<A<T>.B<S>>.B<A<T>.B<S>.C<U>>.C<U>> // Here B<C<U>> means A<A<A<T>.B<S>>.B<A<T>.B<S>.C<U>>>.B<A<A<T>.B<S>>.B<A<T>.B<S>.C<U>>.C<U>>
// while for being a correct override it should be A<A<T>.B<S>>.B<A<T>.B<S>.C<U>> // while for being a correct override it should be A<A<T>.B<S>>.B<A<T>.B<S>.C<U>>
@@ -97,4 +97,4 @@ open class C : O.B() {
// DEPRECATED: Classifiers from supertypes of our own companion // DEPRECATED: Classifiers from supertypes of our own companion
open class r : <!UNRESOLVED_REFERENCE!>FromDelta<!>() open class r : <!UNRESOLVED_REFERENCE!>FromDelta<!>()
} }
+1 -1
View File
@@ -16,4 +16,4 @@ class Some: <!UNRESOLVED_REFERENCE!>Test<!>()
package b.d package b.d
public open class Test public open class Test
@@ -17,5 +17,5 @@ class A1<R> : B<R> {
} }
class A2<R> { class A2<R> {
constructor(t: R, i: Int) : <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(i, 1) constructor(t: R, i: Int) : <!INAPPLICABLE_CANDIDATE!>this<!>(i, 1)
} }
@@ -5,11 +5,11 @@ open class B<R1, R2>(x: R1, y: R2)
class A0<T1, T2> { class A0<T1, T2> {
constructor(x: T1, y: T2): <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(x, y) constructor(x: T1, y: T2): <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(x, y)
constructor(x: T1, y: T2, z: T2): <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(x, 1) // ok, delegates to constructor(x: T1, y: Int) constructor(x: T1, y: T2, z: T2): this(x, 1) // ok, delegates to constructor(x: T1, y: Int)
constructor(x: T1, y: Int): <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(x, "") constructor(x: T1, y: Int): <!NONE_APPLICABLE!>this<!>(x, "")
constructor(x: T1): <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(x, 1) constructor(x: T1): this(x, 1)
constructor(x: T1, y: T2, z: String): <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(y, x) constructor(x: T1, y: T2, z: String): <!NONE_APPLICABLE!>this<!>(y, x)
} }
class A1<T1, T2> : B<T1, T2> { class A1<T1, T2> : B<T1, T2> {
@@ -1,16 +0,0 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
open class B<X, Y : X> {
constructor(x: X, y: Y)
constructor(x: X, s: String)
constructor(y: Y, i: Int) : this(y, "")
}
class A<T1, T2 : T1> : B<T1, T2> {
constructor(x: T1, y: T2): super(x, y)
constructor(x: T2, y: T2, z: String): super(x, y)
constructor(x: T2, z: String, z1: String): super(x, "")
constructor(x: T2, z: String, z1: String, z2: String): super(x, 1)
constructor(x: T1, z: String, z1: String, z2: String, z3: String): super(x, "")
constructor(x: T1, z: String, z1: String, z2: String, z3: String, z4: String): super(x, 1)
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER // !DIAGNOSTICS: -UNUSED_PARAMETER
open class B<X, Y : X> { open class B<X, Y : X> {
constructor(x: X, y: Y) constructor(x: X, y: Y)
@@ -1,5 +1,5 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER // !DIAGNOSTICS: -UNUSED_PARAMETER
// !WITH_NEW_INFERENCE // !WITH_NEW_INFERENCE
class X<T>(val t: T) { class X<T>(val t: T) {
constructor(t: T, i: Int) : this(i) constructor(t: T, i: Int) : <!INAPPLICABLE_CANDIDATE!>this<!>(i)
} }
@@ -1,4 +1,4 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER // !DIAGNOSTICS: -UNUSED_PARAMETER
class X<T> { class X<T> {
constructor(t: T, i: Int): <!CYCLIC_CONSTRUCTOR_DELEGATION_CALL!>this<!>(i, 1) constructor(t: T, i: Int): <!INAPPLICABLE_CANDIDATE!>this<!>(i, 1)
} }
@@ -22,16 +22,16 @@ class Generic<T1> {
open inner class Generic<T2> open inner class Generic<T2>
inner class Test1 : GI<T1>() inner class Test1 : GI<T1>()
inner class Test2 : GIInt() inner class Test2 : <!UNRESOLVED_REFERENCE!>GIInt<!>()
inner class Test3 : GIStar() inner class Test3 : GIStar()
inner class Test3a : test.Generic<*>.Inner() inner class Test3a : test.Generic<*>.Inner()
inner class Test4<T2> : GG<T1, T2>() inner class Test4<T2> : GG<T1, T2>()
inner class Test5 : GG<T1, Int>() inner class Test5 : GG<T1, Int>()
inner class Test6 : GG<Int, T1>() inner class Test6 : <!UNRESOLVED_REFERENCE!>GG<Int, T1><!>()
inner class Test7 : GG<Int, Int>() inner class Test7 : <!UNRESOLVED_REFERENCE!>GG<Int, Int><!>()
inner class Test8 : GIntG<Int>() inner class Test8 : <!UNRESOLVED_REFERENCE!>GIntG<Int><!>()
inner class Test9 : GGInt<Int>() inner class Test9 : <!UNRESOLVED_REFERENCE!>GGInt<Int><!>()
inner class Test10 : GGInt<T1>() inner class Test10 : GGInt<T1>()
inner class Test11 : GG<T1, Int> { inner class Test11 : GG<T1, Int> {
@@ -3,5 +3,5 @@ open class Ref<T>(var x: T)
typealias R<T> = Ref<T> typealias R<T> = Ref<T>
// Type inference SHOULD NOT work for type alias constructor in supertypes list // Type inference SHOULD NOT work for type alias constructor in supertypes list
class Test1 : R(0) class Test1 : <!INAPPLICABLE_CANDIDATE!>R<!>(0)
class Test2 : R<Int>(0) class Test2 : R<Int>(0)