[FIR] KT-39033: Fix generic property override detection

#KT-39033 Fixed
This commit is contained in:
simon.ogorodnik
2020-06-01 17:17:16 +03:00
parent e4a1c8dcef
commit 2287435740
6 changed files with 86 additions and 17 deletions
@@ -5,8 +5,7 @@
package org.jetbrains.kotlin.fir.scopes.impl
import org.jetbrains.kotlin.fir.declarations.FirCallableMemberDeclaration
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.scopes.FirOverrideChecker
@@ -17,15 +16,24 @@ abstract class FirAbstractOverrideChecker : FirOverrideChecker {
protected abstract fun isEqualTypes(candidateTypeRef: FirTypeRef, baseTypeRef: FirTypeRef, substitutor: ConeSubstitutor): Boolean
private fun isCompatibleTypeParameters(
overrideCandidate: FirTypeParameterRef,
baseDeclaration: FirTypeParameterRef,
substitutor: ConeSubstitutor
): Boolean {
if (overrideCandidate.symbol == baseDeclaration.symbol) return true
if (overrideCandidate !is FirTypeParameter || baseDeclaration !is FirTypeParameter) return false
return overrideCandidate.bounds.zip(baseDeclaration.bounds).all { (aBound, bBound) -> isEqualTypes(aBound, bBound, substitutor) }
}
protected fun getSubstitutorIfTypeParametersAreCompatible(
overrideCandidate: FirSimpleFunction,
baseDeclaration: FirSimpleFunction
overrideCandidate: FirCallableMemberDeclaration<*>,
baseDeclaration: FirCallableMemberDeclaration<*>
): ConeSubstitutor? {
val substitutor = buildSubstitutorForOverridesCheck(overrideCandidate, baseDeclaration) ?: return null
if (!overrideCandidate.typeParameters.zip(baseDeclaration.typeParameters).all { (a, b) ->
a.bounds.size == b.bounds.size && a.bounds.zip(b.bounds).all { (aBound, bBound) ->
isEqualTypes(aBound, bBound, substitutor)
}
if (
overrideCandidate.typeParameters.zip(baseDeclaration.typeParameters).any { (override, base) ->
!isCompatibleTypeParameters(override, base, substitutor)
}
) return null
return substitutor
@@ -38,6 +46,7 @@ fun buildSubstitutorForOverridesCheck(
): ConeSubstitutor? {
if (overrideCandidate.typeParameters.size != baseDeclaration.typeParameters.size) return null
if (baseDeclaration.typeParameters.isEmpty()) return ConeSubstitutor.Empty
val types = baseDeclaration.typeParameters.map {
ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false)
}
@@ -11,11 +11,7 @@ import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.ConeTypeContext
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.types.AbstractStrictEqualityTypeChecker.strictEqualTypes
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
@@ -24,7 +20,7 @@ class FirStandardOverrideChecker(session: FirSession) : FirAbstractOverrideCheck
private val context: ConeTypeContext = session.typeContext
private fun isEqualTypes(candidateType: ConeKotlinType, baseType: ConeKotlinType, substitutor: ConeSubstitutor): Boolean{
private fun isEqualTypes(candidateType: ConeKotlinType, baseType: ConeKotlinType, substitutor: ConeSubstitutor): Boolean {
val substitutedCandidateType = substitutor.substituteOrSelf(candidateType)
val substitutedBaseType = substitutor.substituteOrSelf(baseType)
return with(context) {
@@ -76,8 +72,8 @@ class FirStandardOverrideChecker(session: FirSession) : FirAbstractOverrideCheck
overrideCandidate: FirCallableMemberDeclaration<*>,
baseDeclaration: FirProperty
): Boolean {
// TODO: substitutor
return overrideCandidate is FirProperty &&
isEqualReceiverTypes(overrideCandidate.receiverTypeRef, baseDeclaration.receiverTypeRef, ConeSubstitutor.Empty)
if (overrideCandidate !is FirProperty) return false
val substitutor = getSubstitutorIfTypeParametersAreCompatible(overrideCandidate, baseDeclaration) ?: return false
return isEqualReceiverTypes(overrideCandidate.receiverTypeRef, baseDeclaration.receiverTypeRef, substitutor)
}
}