[FIR] Implement replacing Object with type parameters for specials builtins

#KT-42601 Fixed
This commit is contained in:
Mikhail Glukhikh
2020-10-12 12:45:03 +03:00
parent d40248cb53
commit d3e85dbce0
19 changed files with 410 additions and 27 deletions
@@ -5,19 +5,29 @@
package org.jetbrains.kotlin.fir.java.scopes
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirCallableMemberDeclaration
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.java.enhancement.FirSignatureEnhancement
import org.jetbrains.kotlin.fir.resolve.lookupSuperTypes
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.impl.FirFakeOverrideGenerator
import org.jetbrains.kotlin.fir.scopes.jvm.computeJvmDescriptorReplacingKotlinToJava
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.load.java.SpecialGenericSignatures
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class JavaClassMembersEnhancementScope(
session: FirSession,
owner: FirRegularClassSymbol,
private val owner: FirRegularClassSymbol,
private val useSiteMemberScope: JavaClassUseSiteMemberScope,
) : FirTypeScope() {
private val overriddenFunctions = mutableMapOf<FirFunctionSymbol<*>, Collection<FirFunctionSymbol<*>>>()
@@ -46,10 +56,66 @@ class JavaClassMembersEnhancementScope(
return super.processPropertiesByName(name, processor)
}
private fun FirSimpleFunction.changeSignatureIfErasedValueParameter(): FirSimpleFunction {
val typeParameters = owner.fir.typeParameters
if (typeParameters.isEmpty() || name !in SpecialGenericSignatures.ERASED_VALUE_PARAMETERS_SHORT_NAMES) {
return this
}
val jvmDescriptor = this.computeJvmDescriptorReplacingKotlinToJava()
if (SpecialGenericSignatures.ERASED_VALUE_PARAMETERS_SIGNATURES.none { it.endsWith(jvmDescriptor) }) {
return this
}
val superClassIds = listOfNotNull(symbol.callableId.classId) +
lookupSuperTypes(owner, lookupInterfaces = true, deep = true, useSiteSession = session).map { it.lookupTag.classId }
for (superClassId in superClassIds) {
val javaClassId = JavaToKotlinClassMap.mapKotlinToJava(superClassId.asSingleFqName().toUnsafe()) ?: superClassId
val fqJvmDescriptor = "${javaClassId.asString()}.$jvmDescriptor"
if (fqJvmDescriptor in SpecialGenericSignatures.ERASED_VALUE_PARAMETERS_SIGNATURES) {
val specialSignatureInfo = SpecialGenericSignatures.getSpecialSignatureInfo(fqJvmDescriptor)
if (!specialSignatureInfo.isObjectReplacedWithTypeParameter) {
return this
}
val newParameterTypes = valueParameters.mapIndexed { i, valueParameter ->
val classLikeType =
valueParameter.returnTypeRef.coneTypeSafe<ConeKotlinType>()?.lowerBoundIfFlexible().safeAs<ConeClassLikeType>()
if (classLikeType?.lookupTag?.classId == StandardClassIds.Any) {
val typeParameterIndex = if (name.asString() == "containsValue") 1 else i
val typeParameter = typeParameters.getOrNull(typeParameterIndex) ?: typeParameters.first()
val type = ConeTypeParameterLookupTag(typeParameter.symbol).constructType(
emptyArray(), valueParameter.returnTypeRef.isMarkedNullable == true
)
if (valueParameter.returnTypeRef.coneType is ConeFlexibleType) {
ConeFlexibleType(type, type.withNullability(ConeNullability.NULLABLE))
} else {
type
}
} else {
null
}
}
if (newParameterTypes.none { it != null }) {
return this
}
return FirFakeOverrideGenerator.createCopyForFirFunction(
FirNamedFunctionSymbol(symbol.callableId),
this,
session,
FirDeclarationOrigin.Enhancement,
newParameterTypes = valueParameters.zip(newParameterTypes).map { (valueParameter, newType) ->
newType ?: valueParameter.returnTypeRef.coneType
}
)
}
}
return this
}
override fun processFunctionsByName(name: Name, processor: (FirFunctionSymbol<*>) -> Unit) {
useSiteMemberScope.processFunctionsByName(name) process@{ original ->
val enhancedFunctionSymbol = signatureEnhancement.enhancedFunction(original, name)
val enhancedFunction = enhancedFunctionSymbol.fir as? FirSimpleFunction
val symbol = signatureEnhancement.enhancedFunction(original, name)
val enhancedFunction = (symbol.fir as? FirSimpleFunction)?.changeSignatureIfErasedValueParameter()
val enhancedFunctionSymbol = enhancedFunction?.symbol ?: symbol
overriddenFunctions[enhancedFunctionSymbol] =
enhancedFunction