Fix bogus smartcast on enum entry members

Previously, enum entries were treated by the data-flow subsystem similar
to other class/singletons. As a consequence, calls like
'Enum.ENTRY.property' had IdentifierInfo of 'property'.

However, specially for enum entries, descriptor of 'property' is one and
the same for all entries. It means that from the data-flow point of
view, 'Enum.ONE.property' and 'Enum.TWO.property' are *one and the same
data-flow values*.

It could obviously lead to some bogus smartcasts, so this commit
introduces separate IdentifierInfo.EnumEntry and uses it to build proper
qualified values.

^KT-20772 Fixed
This commit is contained in:
Dmitry Savvinov
2018-05-04 16:13:51 +03:00
committed by Dmitry Savvinov
parent ce6543b1cb
commit 952f67dafc
6 changed files with 72 additions and 1 deletions
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.resolve.calls.smartcasts
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.lexer.KtToken
@@ -77,6 +78,10 @@ interface IdentifierInfo {
override fun toString() = descriptor.toString()
}
data class EnumEntry(val descriptor: ClassDescriptor) : IdentifierInfo {
override val kind: DataFlowValue.Kind = STABLE_VALUE
}
class Qualified(
val receiverInfo: IdentifierInfo,
val selectorInfo: IdentifierInfo,
@@ -229,7 +234,14 @@ private fun getIdForSimpleNameExpression(
}
}
is PackageViewDescriptor, is ClassDescriptor -> IdentifierInfo.PackageOrClass(declarationDescriptor)
is ClassDescriptor -> {
if (declarationDescriptor.kind == ClassKind.ENUM_ENTRY && languageVersionSettings.supportsFeature(LanguageFeature.SoundSmartcastForEnumEntries))
IdentifierInfo.EnumEntry(declarationDescriptor)
else
IdentifierInfo.PackageOrClass(declarationDescriptor)
}
is PackageViewDescriptor -> IdentifierInfo.PackageOrClass(declarationDescriptor)
else -> IdentifierInfo.NO
}