FIR Java: Fix Java override ambiguity with vararg value type

#KT-44066 Fixed
This commit is contained in:
Jinseong Jeon
2020-12-23 14:44:57 -08:00
committed by Denis.Zharkov
parent d663f204e5
commit 383de7a9c5
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack
import org.jetbrains.kotlin.fir.java.enhancement.readOnlyToMutable import org.jetbrains.kotlin.fir.java.enhancement.readOnlyToMutable
import org.jetbrains.kotlin.fir.java.toConeKotlinTypeProbablyFlexible import org.jetbrains.kotlin.fir.java.toConeKotlinTypeProbablyFlexible
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.scopes.impl.FirAbstractOverrideChecker import org.jetbrains.kotlin.fir.scopes.impl.FirAbstractOverrideChecker
@@ -35,8 +36,24 @@ class JavaOverrideChecker internal constructor(
if (candidateType is ConeFlexibleType) return isEqualTypes(candidateType.lowerBound, baseType, substitutor, mayBeSpecialBuiltIn) if (candidateType is ConeFlexibleType) return isEqualTypes(candidateType.lowerBound, baseType, substitutor, mayBeSpecialBuiltIn)
if (baseType is ConeFlexibleType) return isEqualTypes(candidateType, baseType.lowerBound, substitutor, mayBeSpecialBuiltIn) if (baseType is ConeFlexibleType) return isEqualTypes(candidateType, baseType.lowerBound, substitutor, mayBeSpecialBuiltIn)
if (candidateType is ConeClassLikeType && baseType is ConeClassLikeType) { if (candidateType is ConeClassLikeType && baseType is ConeClassLikeType) {
return candidateType.lookupTag.classId.let { it.readOnlyToMutable() ?: it } == val candidateTypeClassId = candidateType.fullyExpandedType(session).lookupTag.classId.let { it.readOnlyToMutable() ?: it }
baseType.lookupTag.classId.let { it.readOnlyToMutable() ?: it } val baseTypeClassId = baseType.fullyExpandedType(session).lookupTag.classId.let { it.readOnlyToMutable() ?: it }
if (candidateTypeClassId != baseTypeClassId) return false
if (!candidateTypeClassId.shortClassName.isSpecial && candidateTypeClassId.shortClassName.identifier == "Array") {
assert(candidateType.typeArguments.size == 1) {
"Array type with unexpected number of type arguments: $candidateType"
}
assert(baseType.typeArguments.size == 1) {
"Array type with unexpected number of type arguments: $baseType"
}
return isEqualArrayElementTypeProjections(
candidateType.typeArguments.single(),
baseType.typeArguments.single(),
substitutor,
mayBeSpecialBuiltIn
)
}
return true
} }
// TODO: handle the situation in more proper way // TODO: handle the situation in more proper way
// Typical case: class EnumMap<K extends Enum, V> implements Map<K, V> // Typical case: class EnumMap<K extends Enum, V> implements Map<K, V>
@@ -68,6 +85,20 @@ class JavaOverrideChecker internal constructor(
mayBeSpecialBuiltIn mayBeSpecialBuiltIn
) )
private fun isEqualArrayElementTypeProjections(
candidateTypeProjection: ConeTypeProjection,
baseTypeProjection: ConeTypeProjection,
substitutor: ConeSubstitutor,
mayBeSpecialBuiltIn: Boolean
): Boolean =
when {
candidateTypeProjection is ConeKotlinTypeProjection && baseTypeProjection is ConeKotlinTypeProjection ->
candidateTypeProjection.kind == baseTypeProjection.kind &&
isEqualTypes(candidateTypeProjection.type, baseTypeProjection.type, substitutor, mayBeSpecialBuiltIn)
candidateTypeProjection is ConeStarProjection && baseTypeProjection is ConeStarProjection -> true
else -> false
}
private fun Collection<FirTypeParameterRef>.buildErasure() = associate { private fun Collection<FirTypeParameterRef>.buildErasure() = associate {
val symbol = it.symbol val symbol = it.symbol
val firstBound = symbol.fir.bounds.first() // Note that in Java type parameter typed arguments always erased to first bound val firstBound = symbol.fir.bounds.first() // Note that in Java type parameter typed arguments always erased to first bound