FIR: refactor delegate unwrapping

Not implemented override checker will use those to pretend to make
delegeted members (before checking similarly pretended fake overrides)
This commit is contained in:
Jinseong Jeon
2021-02-12 22:25:58 -08:00
committed by TeamCityServer
parent ef890464d8
commit 856838f82c
3 changed files with 42 additions and 46 deletions
@@ -5,18 +5,12 @@
package org.jetbrains.kotlin.fir.backend.generators
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.backend.*
import org.jetbrains.kotlin.fir.baseForIntersectionOverride
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.isIntersectionOverride
import org.jetbrains.kotlin.fir.isSubstitutionOverride
import org.jetbrains.kotlin.fir.originalForSubstitutionOverride
import org.jetbrains.kotlin.fir.scopes.*
import org.jetbrains.kotlin.fir.scopes.impl.delegatedWrapperData
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.scopes.impl.unwrapDelegateTarget
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrBlockBody
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
@@ -51,7 +45,7 @@ internal class DelegatedMemberGenerator(
declarationStorage.getIrFunctionSymbol(unwrapped.symbol).owner as? IrSimpleFunction
?: return@processAllFunctions
if (isJavaDefault(unwrapped)) {
if (unwrapped.isJavaDefault) {
return@processAllFunctions
}
@@ -83,42 +77,6 @@ internal class DelegatedMemberGenerator(
}
}
private inline fun <reified S : FirCallableSymbol<D>, reified D : FirCallableMemberDeclaration<D>> S.unwrapDelegateTarget(
subClassLookupTag: ConeClassLikeLookupTag,
noinline directOverridden: S.() -> List<S>,
firField: FirField,
firSubClass: FirClass<*>,
): D? {
val unwrappedIntersectionSymbol =
this.unwrapIntersectionOverride(directOverridden) ?: return null
val callable = unwrappedIntersectionSymbol.fir as? D ?: return null
val delegatedWrapperData = callable.delegatedWrapperData ?: return null
if (delegatedWrapperData.containingClass != subClassLookupTag) return null
if (delegatedWrapperData.delegateField != firField) return null
val wrapped = delegatedWrapperData.wrapped as? D ?: return null
val wrappedSymbol = wrapped.symbol as? S ?: return null
return when {
wrappedSymbol.fir.isSubstitutionOverride &&
(wrappedSymbol.fir.dispatchReceiverType as? ConeClassLikeType)?.lookupTag == firSubClass.symbol.toLookupTag() ->
wrapped.originalForSubstitutionOverride
else -> wrapped
}
}
private fun isJavaDefault(function: FirSimpleFunction): Boolean {
if (function.isIntersectionOverride) return isJavaDefault(function.baseForIntersectionOverride!!)
return function.origin == FirDeclarationOrigin.Enhancement && function.modality == Modality.OPEN
}
private fun <S : FirCallableSymbol<*>> S.unwrapIntersectionOverride(directOverridden: S.() -> List<S>): S? {
if (this.fir.isIntersectionOverride) return directOverridden().firstOrNull { it.fir.delegatedWrapperData != null }
return this
}
private fun generateDelegatedFunction(
subClass: IrClass,
firSubClass: FirClass<*>,
@@ -9,6 +9,9 @@ import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.isIntersectionOverride
import org.jetbrains.kotlin.fir.isSubstitutionOverride
import org.jetbrains.kotlin.fir.originalForSubstitutionOverride
import org.jetbrains.kotlin.fir.resolve.defaultType
import org.jetbrains.kotlin.fir.scopes.*
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
@@ -162,6 +165,35 @@ class DelegatedWrapperData<D : FirCallableDeclaration<*>>(
var <D : FirCallableDeclaration<*>>
D.delegatedWrapperData: DelegatedWrapperData<D>? by FirDeclarationDataRegistry.data(DelegatedWrapperDataKey)
inline fun <reified S : FirCallableSymbol<D>, reified D : FirCallableMemberDeclaration<D>> S.unwrapDelegateTarget(
subClassLookupTag: ConeClassLikeLookupTag,
noinline directOverridden: S.() -> List<S>,
firField: FirField,
firSubClass: FirClass<*>,
): D? {
val unwrappedIntersectionSymbol = this.unwrapIntersectionOverride(directOverridden) ?: return null
val callable = unwrappedIntersectionSymbol.fir as? D ?: return null
val delegatedWrapperData = callable.delegatedWrapperData ?: return null
if (delegatedWrapperData.containingClass != subClassLookupTag) return null
if (delegatedWrapperData.delegateField != firField) return null
val wrapped = delegatedWrapperData.wrapped as? D ?: return null
val wrappedSymbol = wrapped.symbol as? S ?: return null
return when {
wrappedSymbol.fir.isSubstitutionOverride &&
(wrappedSymbol.fir.dispatchReceiverType as? ConeClassLikeType)?.lookupTag == firSubClass.symbol.toLookupTag() ->
wrapped.originalForSubstitutionOverride
else -> wrapped
}
}
fun <S : FirCallableSymbol<*>> S.unwrapIntersectionOverride(directOverridden: S.() -> List<S>): S? {
if (this.fir.isIntersectionOverride) return directOverridden().firstOrNull { it.fir.delegatedWrapperData != null }
return this
}
// From the definition of function interfaces in the Java specification (pt. 9.8):
// "methods that are members of I that do not have the same signature as any public instance method of the class Object"
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.fir
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
@@ -29,7 +30,6 @@ fun FirCallableDeclaration<*>.containingClass(): ConeClassLikeLookupTag? {
private object ContainingClassKey : FirDeclarationDataKey()
var FirCallableDeclaration<*>.containingClassAttr: ConeClassLikeLookupTag? by FirDeclarationDataRegistry.data(ContainingClassKey)
val FirCallableDeclaration<*>.isIntersectionOverride get() = origin == FirDeclarationOrigin.IntersectionOverride
val FirCallableDeclaration<*>.isSubstitutionOverride get() = origin == FirDeclarationOrigin.SubstitutionOverride
val FirCallableDeclaration<*>.isSubstitutionOrIntersectionOverride get() = isSubstitutionOverride || isIntersectionOverride
@@ -46,6 +46,12 @@ inline val <reified D : FirCallableDeclaration<*>> D.baseForIntersectionOverride
inline val <reified S : FirCallableSymbol<*>> S.baseForIntersectionOverride: S?
get() = fir.baseForIntersectionOverride?.symbol as S?
val FirSimpleFunction.isJavaDefault: Boolean
get() {
if (isIntersectionOverride) return baseForIntersectionOverride!!.isJavaDefault
return origin == FirDeclarationOrigin.Enhancement && modality == Modality.OPEN
}
inline fun <reified D : FirCallableDeclaration<*>> D.originalIfFakeOverride(): D? =
originalForSubstitutionOverride ?: baseForIntersectionOverride