K2 resolve: prefer derived class property to base class field

#KT-50082 Fixed
This commit is contained in:
Mikhail Glukhikh
2022-11-16 17:14:56 +01:00
committed by teamcity
parent 642bbd38ba
commit 59bafedd8a
15 changed files with 407 additions and 41 deletions
@@ -10,11 +10,12 @@ import org.jetbrains.kotlin.fir.containingClassLookupTag
import org.jetbrains.kotlin.fir.declarations.FirField
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.languageVersionSettings
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.calls.AbstractConeCallConflictResolver
import org.jetbrains.kotlin.fir.resolve.calls.Candidate
import org.jetbrains.kotlin.fir.resolve.inference.InferenceComponents
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirAbstractBodyResolveTransformer
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.unwrapFakeOverrides
import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator
class JvmPlatformOverloadsConflictResolver(
@@ -31,21 +32,59 @@ class JvmPlatformOverloadsConflictResolver(
return candidates
}
val result = mutableSetOf<Candidate>()
outerLoop@ for (myCandidate in candidates) {
val me = myCandidate.symbol.fir
if (me is FirProperty && me.symbol.containingClassLookupTag() != null) {
for (otherCandidate in candidates) {
val other = otherCandidate.symbol.fir
if (other is FirField && other.symbol.containingClassLookupTag() != null) {
// NB: FE 1.0 does class equivalence check here
// However, in FIR container classes aren't the same for our samples (see fieldPropertyOverloads.kt)
// E.g. we can have SomeConcreteJavaEnum for field and kotlin.Enum for static property 'name'
continue@outerLoop
}
for (myCandidate in candidates) {
when (val me = myCandidate.symbol.fir) {
is FirProperty -> if (!me.isShadowedByFieldCandidate(candidates)) {
result += myCandidate
}
is FirField -> if (!me.isShadowedByPropertyCandidate(candidates)) {
result += myCandidate
}
else -> result += myCandidate
}
result += myCandidate
}
return result
}
private fun FirProperty.isShadowedByFieldCandidate(candidates: Set<Candidate>): Boolean {
val propertyContainingClassLookupTag = unwrapFakeOverrides().symbol.containingClassLookupTag() ?: return false
for (otherCandidate in candidates) {
val field = otherCandidate.symbol.fir as? FirField ?: continue
val fieldContainingClassLookupTag = field.unwrapFakeOverrides().symbol.containingClassLookupTag()
if (fieldContainingClassLookupTag != null &&
!propertyContainingClassLookupTag.strictlyDerivedFrom(fieldContainingClassLookupTag)
) {
// NB: FE 1.0 does class equivalence check here ^^^
// However, in FIR container classes aren't the same for our samples (see fieldPropertyOverloads.kt)
// E.g. we can have SomeConcreteJavaEnum for field and kotlin.Enum for static property 'name'
return true
}
}
return false
}
private fun FirField.isShadowedByPropertyCandidate(candidates: Set<Candidate>): Boolean {
val fieldContainingClassLookupTag = unwrapFakeOverrides().symbol.containingClassLookupTag() ?: return false
for (otherCandidate in candidates) {
val property = otherCandidate.symbol.fir as? FirProperty ?: continue
val propertyContainingClassLookupTag = property.unwrapFakeOverrides().symbol.containingClassLookupTag()
if (propertyContainingClassLookupTag != null &&
propertyContainingClassLookupTag.strictlyDerivedFrom(fieldContainingClassLookupTag)
) {
// NB: FE 1.0 does class equivalence check here ^^^
// However, in FIR container classes aren't the same for our samples (see fieldPropertyOverloads.kt)
// E.g. we can have SomeConcreteJavaEnum for field and kotlin.Enum for static property 'name'
return true
}
}
return false
}
private fun ConeClassLikeLookupTag.strictlyDerivedFrom(other: ConeClassLikeLookupTag): Boolean {
if (this == other) return false
val session = inferenceComponents.session
val thisClass = this.toFirRegularClassSymbol(session)?.fir ?: return false
return thisClass.isSubclassOf(other, session, isStrict = true)
}
}