From 383de7a9c5d55f52a9a8681788f764eab647d112 Mon Sep 17 00:00:00 2001 From: Jinseong Jeon Date: Wed, 23 Dec 2020 14:44:57 -0800 Subject: [PATCH] FIR Java: Fix Java override ambiguity with vararg value type #KT-44066 Fixed --- .../fir/java/scopes/JavaOverrideChecker.kt | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaOverrideChecker.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaOverrideChecker.kt index 3c5e543a48d..695154b9c85 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaOverrideChecker.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaOverrideChecker.kt @@ -11,6 +11,7 @@ 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.fullyExpandedType import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap 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 (baseType is ConeFlexibleType) return isEqualTypes(candidateType, baseType.lowerBound, substitutor, mayBeSpecialBuiltIn) if (candidateType is ConeClassLikeType && baseType is ConeClassLikeType) { - return candidateType.lookupTag.classId.let { it.readOnlyToMutable() ?: it } == - baseType.lookupTag.classId.let { it.readOnlyToMutable() ?: it } + val candidateTypeClassId = candidateType.fullyExpandedType(session).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 // Typical case: class EnumMap implements Map @@ -68,6 +85,20 @@ class JavaOverrideChecker internal constructor( 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.buildErasure() = associate { val symbol = it.symbol val firstBound = symbol.fir.bounds.first() // Note that in Java type parameter typed arguments always erased to first bound