FIR: Merge both synthetic type alias constructor kinds
This commit is contained in:
+87
-100
@@ -142,72 +142,6 @@ private fun FirTypeAliasSymbol.findSAMConstructorForTypeAlias(
|
|||||||
).fir
|
).fir
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun processConstructors(
|
|
||||||
matchedSymbol: FirClassLikeSymbol<*>?,
|
|
||||||
substitutor: ConeSubstitutor,
|
|
||||||
processor: (FirFunctionSymbol<*>) -> Unit,
|
|
||||||
session: FirSession,
|
|
||||||
bodyResolveComponents: BodyResolveComponents,
|
|
||||||
includeInnerConstructors: Boolean
|
|
||||||
) {
|
|
||||||
try {
|
|
||||||
if (matchedSymbol != null) {
|
|
||||||
val scope = when (matchedSymbol) {
|
|
||||||
is FirTypeAliasSymbol -> {
|
|
||||||
matchedSymbol.ensureResolved(FirResolvePhase.TYPES, session)
|
|
||||||
val type = matchedSymbol.fir.expandedTypeRef.coneTypeUnsafe<ConeClassLikeType>().fullyExpandedType(session)
|
|
||||||
val basicScope = type.scope(session, bodyResolveComponents.scopeSession, FakeOverrideTypeCalculator.DoNothing)
|
|
||||||
|
|
||||||
if (basicScope != null && type.typeArguments.isNotEmpty()) {
|
|
||||||
TypeAliasConstructorsSubstitutingScope(
|
|
||||||
matchedSymbol,
|
|
||||||
basicScope
|
|
||||||
)
|
|
||||||
} else basicScope
|
|
||||||
}
|
|
||||||
is FirClassSymbol ->
|
|
||||||
(matchedSymbol.fir as FirClass<*>).scopeForClass(
|
|
||||||
substitutor, session, bodyResolveComponents.scopeSession
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: why don't we use declared member scope at this point?
|
|
||||||
scope?.processDeclaredConstructors {
|
|
||||||
if (includeInnerConstructors || !it.fir.isInner) {
|
|
||||||
val constructorSymbolToProcess =
|
|
||||||
prepareCopyConstructorForTypealiasNestedClass(matchedSymbol, it, session, bodyResolveComponents) ?: it
|
|
||||||
processor(constructorSymbolToProcess)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e: Throwable) {
|
|
||||||
throw RuntimeException("While processing constructors", e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class TypeAliasConstructorsSubstitutingScope(
|
|
||||||
private val typeAliasSymbol: FirTypeAliasSymbol,
|
|
||||||
private val delegatingScope: FirScope
|
|
||||||
) : FirScope() {
|
|
||||||
|
|
||||||
override fun processDeclaredConstructors(processor: (FirConstructorSymbol) -> Unit) {
|
|
||||||
delegatingScope.processDeclaredConstructors { originalConstructorSymbol ->
|
|
||||||
|
|
||||||
val typeParameters = typeAliasSymbol.fir.typeParameters
|
|
||||||
if (typeParameters.isEmpty()) processor(originalConstructorSymbol)
|
|
||||||
else {
|
|
||||||
processor(
|
|
||||||
buildConstructorCopy(originalConstructorSymbol.fir) {
|
|
||||||
symbol = FirConstructorSymbol(originalConstructorSymbol.callableId, overriddenSymbol = originalConstructorSymbol)
|
|
||||||
origin = FirDeclarationOrigin.SubstitutionOverride
|
|
||||||
this.typeParameters += typeParameters.map { buildConstructedClassTypeParameterRef { symbol = it.symbol } }
|
|
||||||
}.symbol
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun prepareSubstitutorForTypeAliasConstructors(
|
private fun prepareSubstitutorForTypeAliasConstructors(
|
||||||
expandedType: ConeClassLikeType,
|
expandedType: ConeClassLikeType,
|
||||||
session: FirSession
|
session: FirSession
|
||||||
@@ -224,46 +158,99 @@ private fun prepareSubstitutorForTypeAliasConstructors(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun prepareCopyConstructorForTypealiasNestedClass(
|
private fun processConstructors(
|
||||||
matchedSymbol: FirClassLikeSymbol<*>,
|
matchedSymbol: FirClassLikeSymbol<*>?,
|
||||||
originalSymbol: FirConstructorSymbol,
|
substitutor: ConeSubstitutor,
|
||||||
|
processor: (FirFunctionSymbol<*>) -> Unit,
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
bodyResolveComponents: BodyResolveComponents,
|
bodyResolveComponents: BodyResolveComponents,
|
||||||
): FirConstructorSymbol? {
|
includeInnerConstructors: Boolean
|
||||||
// If the matched symbol is a type alias, and the expanded type is a nested class, e.g.,
|
) {
|
||||||
//
|
try {
|
||||||
// class Outer {
|
if (matchedSymbol != null) {
|
||||||
// inner class Inner
|
val scope = when (matchedSymbol) {
|
||||||
// }
|
is FirTypeAliasSymbol -> {
|
||||||
// typealias OI = Outer.Inner
|
matchedSymbol.ensureResolved(FirResolvePhase.TYPES, session)
|
||||||
// fun foo() { Outer().OI() }
|
val type = matchedSymbol.fir.expandedTypeRef.coneTypeUnsafe<ConeClassLikeType>().fullyExpandedType(session)
|
||||||
//
|
val basicScope = type.scope(session, bodyResolveComponents.scopeSession, FakeOverrideTypeCalculator.DoNothing)
|
||||||
// the chances are that `processor` belongs to [ScopeTowerLevel] (to resolve type aliases at top-level), which treats
|
|
||||||
// the explicit receiver (`Outer()`) as an extension receiver, whereas the constructor of the nested class may regard
|
val outerType = bodyResolveComponents.outerClassManager.outerType(type)
|
||||||
// the same explicit receiver as a dispatch receiver (hence inconsistent receiver).
|
|
||||||
// Here, we add a copy of the nested class constructor, along with the outer type as an extension receiver, so that it
|
if (basicScope != null && (matchedSymbol.fir.typeParameters.isNotEmpty() || outerType != null)) {
|
||||||
// can be seen as if resolving:
|
TypeAliasConstructorsSubstitutingScope(
|
||||||
//
|
matchedSymbol,
|
||||||
// fun Outer.OI(): OI = ...
|
basicScope,
|
||||||
//
|
outerType
|
||||||
if (originalSymbol.callableId.classId?.isNestedClass == true && matchedSymbol is FirTypeAliasSymbol) {
|
)
|
||||||
val innerTypeRef = originalSymbol.fir.returnTypeRef
|
} else basicScope
|
||||||
val innerType = innerTypeRef.coneType.fullyExpandedType(session) as? ConeClassLikeType
|
}
|
||||||
if (innerType != null) {
|
is FirClassSymbol ->
|
||||||
val outerType = bodyResolveComponents.outerClassManager.outerType(innerType)
|
(matchedSymbol.fir as FirClass<*>).scopeForClass(
|
||||||
if (outerType != null) {
|
substitutor, session, bodyResolveComponents.scopeSession
|
||||||
val extCopy = buildConstructorCopy(originalSymbol.fir) {
|
)
|
||||||
origin = FirDeclarationOrigin.Synthetic
|
}
|
||||||
receiverTypeRef = innerTypeRef.withReplacedConeType(outerType)
|
|
||||||
symbol = FirConstructorSymbol(originalSymbol.callableId)
|
//TODO: why don't we use declared member scope at this point?
|
||||||
}.apply {
|
scope?.processDeclaredConstructors {
|
||||||
originalConstructorIfTypeAlias = originalSymbol.fir
|
if (includeInnerConstructors || !it.fir.isInner) {
|
||||||
|
processor(it)
|
||||||
}
|
}
|
||||||
return extCopy.symbol
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
throw RuntimeException("While processing constructors", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TypeAliasConstructorsSubstitutingScope(
|
||||||
|
private val typeAliasSymbol: FirTypeAliasSymbol,
|
||||||
|
private val delegatingScope: FirScope,
|
||||||
|
private val outerType: ConeClassLikeType?,
|
||||||
|
) : FirScope() {
|
||||||
|
|
||||||
|
init {
|
||||||
|
require(outerType != null || typeAliasSymbol.fir.typeParameters.isNotEmpty())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun processDeclaredConstructors(processor: (FirConstructorSymbol) -> Unit) {
|
||||||
|
delegatingScope.processDeclaredConstructors wrapper@{ originalConstructorSymbol ->
|
||||||
|
val typeParameters = typeAliasSymbol.fir.typeParameters
|
||||||
|
|
||||||
|
processor(
|
||||||
|
buildConstructorCopy(originalConstructorSymbol.fir) {
|
||||||
|
symbol = FirConstructorSymbol(originalConstructorSymbol.callableId)
|
||||||
|
origin = FirDeclarationOrigin.Synthetic
|
||||||
|
|
||||||
|
this.typeParameters.clear()
|
||||||
|
this.typeParameters += typeParameters.map { buildConstructedClassTypeParameterRef { symbol = it.symbol } }
|
||||||
|
|
||||||
|
if (outerType != null) {
|
||||||
|
// If the matched symbol is a type alias, and the expanded type is a nested class, e.g.,
|
||||||
|
//
|
||||||
|
// class Outer {
|
||||||
|
// inner class Inner
|
||||||
|
// }
|
||||||
|
// typealias OI = Outer.Inner
|
||||||
|
// fun foo() { Outer().OI() }
|
||||||
|
//
|
||||||
|
// the chances are that `processor` belongs to [ScopeTowerLevel] (to resolve type aliases at top-level), which treats
|
||||||
|
// the explicit receiver (`Outer()`) as an extension receiver, whereas the constructor of the nested class may regard
|
||||||
|
// the same explicit receiver as a dispatch receiver (hence inconsistent receiver).
|
||||||
|
// Here, we add a copy of the nested class constructor, along with the outer type as an extension receiver, so that it
|
||||||
|
// can be seen as if resolving:
|
||||||
|
//
|
||||||
|
// fun Outer.OI(): OI = ...
|
||||||
|
//
|
||||||
|
//
|
||||||
|
receiverTypeRef = originalConstructorSymbol.fir.returnTypeRef.withReplacedConeType(outerType)
|
||||||
|
}
|
||||||
|
|
||||||
|
}.apply {
|
||||||
|
originalConstructorIfTypeAlias = originalConstructorSymbol.fir
|
||||||
|
}.symbol
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private object TypeAliasConstructorKey : FirDeclarationDataKey()
|
private object TypeAliasConstructorKey : FirDeclarationDataKey()
|
||||||
|
|||||||
Reference in New Issue
Block a user