K2 resolve: prefer derived class property to base class field
#KT-50082 Fixed
This commit is contained in:
committed by
teamcity
parent
642bbd38ba
commit
59bafedd8a
+53
-14
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user