[FIR] Make overriding generic callables independent of TP bounds order

This commit is contained in:
simon.ogorodnik
2020-06-01 21:34:43 +03:00
parent 2287435740
commit ab02381a83
7 changed files with 167 additions and 33 deletions
@@ -7,14 +7,12 @@ package org.jetbrains.kotlin.fir.java.scopes
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirCallableMemberDeclaration
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.declarations.modality
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack
import org.jetbrains.kotlin.fir.java.enhancement.readOnlyToMutable
import org.jetbrains.kotlin.fir.java.toConeKotlinTypeProbablyFlexible
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.scopes.impl.FirAbstractOverrideChecker
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.*
@@ -54,13 +52,29 @@ class JavaOverrideChecker internal constructor(
substitutor
)
override fun buildTypeParametersSubstitutorIfCompatible(
overrideCandidate: FirCallableMemberDeclaration<*>,
baseDeclaration: FirCallableMemberDeclaration<*>
): ConeSubstitutor? {
if (overrideCandidate.typeParameters.isEmpty() && baseDeclaration.typeParameters.isEmpty()) return ConeSubstitutor.Empty
val typeParametersErasure =
(overrideCandidate.typeParameters + baseDeclaration.typeParameters).associate {
val symbol = it.symbol
val firstBound = symbol.fir.bounds.first() // Note that in Java type parameter typed arguments always erased to first bound
symbol to firstBound.toConeKotlinTypeProbablyFlexible(session, javaTypeParameterStack)
}
return substitutorByMap(typeParametersErasure)
}
override fun isOverriddenFunction(overrideCandidate: FirSimpleFunction, baseDeclaration: FirSimpleFunction): Boolean {
// NB: overrideCandidate is from Java and has no receiver
val receiverTypeRef = baseDeclaration.receiverTypeRef
val baseParameterTypes = listOfNotNull(receiverTypeRef) + baseDeclaration.valueParameters.map { it.returnTypeRef }
if (overrideCandidate.valueParameters.size != baseParameterTypes.size) return false
val substitutor = getSubstitutorIfTypeParametersAreCompatible(overrideCandidate, baseDeclaration) ?: return false
val substitutor = buildTypeParametersSubstitutorIfCompatible(overrideCandidate, baseDeclaration) ?: return false
return overrideCandidate.valueParameters.zip(baseParameterTypes).all { (paramFromJava, baseType) ->
isEqualTypes(paramFromJava.returnTypeRef, baseType, substitutor)