[FIR] Fix false positive CONST_VAL_WITH_NON_CONST_INITIALIZER

... in presence of typealiases.

#KT-61499 Fixed
This commit is contained in:
Kirill Rakhman
2023-09-13 17:37:12 +02:00
committed by Space Team
parent b72ac4f560
commit 373ffbc779
4 changed files with 18 additions and 146 deletions
@@ -90,7 +90,7 @@ internal fun checkConstantArguments(
if (coneType is ConeErrorType)
return ConstantArgumentKind.NOT_CONST
while (coneType?.classId == StandardClassIds.Array)
while (coneType?.fullyExpandedClassId(session) == StandardClassIds.Array)
coneType = (coneType.lowerBoundIfFlexible().typeArguments.first() as? ConeKotlinTypeProjection)?.type ?: break
return when {
@@ -122,7 +122,7 @@ internal fun checkConstantArguments(
if (calleeReference is FirErrorNamedReference) {
return null
}
if (expression.resolvedType.classId == StandardClassIds.KClass) {
if (expression.resolvedType.fullyExpandedClassId(session) == StandardClassIds.KClass) {
return ConstantArgumentKind.NOT_KCLASS_LITERAL
}
@@ -134,13 +134,13 @@ internal fun checkConstantArguments(
if (calleeReference !is FirResolvedNamedReference) return ConstantArgumentKind.NOT_CONST
val symbol = calleeReference.resolvedSymbol as? FirNamedFunctionSymbol ?: return ConstantArgumentKind.NOT_CONST
if (!symbol.canBeEvaluated() && !expression.isCompileTimeBuiltinCall() || expression.isForbiddenComplexConstant(session)) {
if (!symbol.canBeEvaluated() && !expression.isCompileTimeBuiltinCall(session) || expression.isForbiddenComplexConstant(session)) {
return ConstantArgumentKind.NOT_CONST
}
for (exp in expression.arguments.plus(expression.dispatchReceiver).plus(expression.extensionReceiver)) {
if (exp == null) continue
val expClassId = exp.resolvedType.lowerBoundIfFlexible().classId
val expClassId = exp.resolvedType.fullyExpandedClassId(session)
// TODO, KT-59823: add annotation for allowed constant types
if (expClassId !in StandardClassIds.constantAllowedTypes) {
return ConstantArgumentKind.NOT_CONST
@@ -165,12 +165,12 @@ internal fun checkConstantArguments(
@OptIn(SymbolInternals::class)
val property = propertySymbol.fir
when {
property.unwrapFakeOverrides().symbol.canBeEvaluated() || property.isCompileTimeBuiltinProperty() -> {
property.unwrapFakeOverrides().symbol.canBeEvaluated() || property.isCompileTimeBuiltinProperty(session) -> {
val receiver = listOf(expression.dispatchReceiver, expression.extensionReceiver).single { it != null }!!
return checkConstantArguments(receiver, session)
}
propertySymbol.isLocal || propertySymbol.callableId.className?.isRoot == false -> return ConstantArgumentKind.NOT_CONST
expressionType.classId == StandardClassIds.KClass -> return ConstantArgumentKind.NOT_KCLASS_LITERAL
expressionType.fullyExpandedClassId(session) == StandardClassIds.KClass -> return ConstantArgumentKind.NOT_KCLASS_LITERAL
//TODO, KT-59822: UNRESOLVED REFERENCE
expression.dispatchReceiver is FirThisReceiverExpression -> return null
@@ -229,7 +229,7 @@ private val compileTimeConversionFunctions = listOf(
"toInt", "toLong", "toShort", "toByte", "toFloat", "toDouble", "toChar", "toBoolean"
).mapTo(hashSetOf()) { Name.identifier(it) }
private fun FirFunctionCall.isCompileTimeBuiltinCall(): Boolean {
private fun FirFunctionCall.isCompileTimeBuiltinCall(session: FirSession): Boolean {
val calleeReference = this.calleeReference
if (calleeReference !is FirResolvedNamedReference) return false
@@ -238,7 +238,7 @@ private fun FirFunctionCall.isCompileTimeBuiltinCall(): Boolean {
if (!symbol.fromKotlin()) return false
val coneType = this.dispatchReceiver?.resolvedType
val receiverClassId = coneType?.lowerBoundIfFlexible()?.classId
val receiverClassId = coneType?.fullyExpandedClassId(session)
if (receiverClassId in StandardClassIds.unsignedTypes) return false
@@ -254,9 +254,9 @@ private fun FirFunctionCall.isCompileTimeBuiltinCall(): Boolean {
return false
}
private fun FirProperty.isCompileTimeBuiltinProperty(): Boolean {
private fun FirProperty.isCompileTimeBuiltinProperty(session: FirSession): Boolean {
val receiverType = dispatchReceiverType ?: receiverParameter?.typeRef?.coneTypeSafe<ConeKotlinType>() ?: return false
val receiverClassId = receiverType.lowerBoundIfFlexible().classId ?: return false
val receiverClassId = receiverType.fullyExpandedClassId(session) ?: return false
return when (name.asString()) {
"length" -> receiverClassId == StandardClassIds.String
"code" -> receiverClassId == StandardClassIds.Char
@@ -100,6 +100,10 @@ const val constInitializer12 = (-1.0) % 0
const val constInitializer13 = 1.0.rem(0)
const val constInitializer15 = 1.0.div(0)
typealias IntAlias = Int
const val constInitializer16: IntAlias = 1
const val constInitializer17 = constInitializer16 + 0
// ------------------
class Delegate {
operator fun getValue(thisRef: Any?, prop: KProperty<*>): Int = 1
@@ -100,6 +100,10 @@ const val constInitializer12 = (-1.0) % 0
const val constInitializer13 = 1.0.rem(0)
const val constInitializer15 = 1.0.div(0)
typealias IntAlias = Int
const val constInitializer16: IntAlias = 1
const val constInitializer17 = constInitializer16 + 0
// ------------------
class Delegate {
operator fun getValue(thisRef: Any?, prop: KProperty<*>): Int = 1
@@ -1,136 +0,0 @@
package
public const val constInitializer1: kotlin.Double = Infinity.toDouble()
public const val constInitializer10: kotlin.Double = NaN.toDouble()
public const val constInitializer11: kotlin.Double = NaN.toDouble()
public const val constInitializer12: kotlin.Double = NaN.toDouble()
public const val constInitializer13: kotlin.Double = NaN.toDouble()
public const val constInitializer15: kotlin.Double = Infinity.toDouble()
public const val constInitializer2: kotlin.Double = Infinity.toDouble()
public const val constInitializer3: kotlin.Double = Infinity.toDouble()
public const val constInitializer4: kotlin.Double = -Infinity.toDouble()
public const val constInitializer5: kotlin.Double = NaN.toDouble()
public const val constInitializer6: kotlin.Double = Infinity.toDouble()
public const val constInitializer7: kotlin.Double = -Infinity.toDouble()
public const val constInitializer8: kotlin.Double = NaN.toDouble()
public const val constInitializer9: kotlin.Double = NaN.toDouble()
public const val defaultGetter: kotlin.Int = 19
public const val delegated: kotlin.Int
public const val nonConstInitializer1: kotlin.Int
public const val nonConstInitializer10: kotlin.Int
public const val nonConstInitializer11: kotlin.Int
public const val nonConstInitializer12: kotlin.Int
public const val nonConstInitializer14: kotlin.Int
public const val nonConstInitializer15: kotlin.Int
public const val nonConstInitializer2: kotlin.String
public const val nonConstInitializer3: kotlin.String
public const val nonConstInitializer4: kotlin.Double
public const val nonConstInitializer5: kotlin.Int
public const val nonConstInitializer6: kotlin.Int
public const val nonConstInitializer7: kotlin.Int
public const val nonConstInitializer8: kotlin.Int
public const val nonConstInitializer9: kotlin.Double
private val privateTopLevel: kotlin.Int = 3
public const var topLeveLVar: kotlin.Int
public const val topLevel: kotlin.Int = 0
public const val topLevelInferred: kotlin.Int = 1
public const val withExplicitDefaultGetter: kotlin.Int = 1
public const val withGetter: kotlin.Int
public fun foo(): kotlin.Int
public object A {
private constructor A()
public const final val inObject: kotlin.Int = 4
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class B {
public constructor B(/*0*/ constructor: kotlin.Int = ...)
public final val constructor: kotlin.Int
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public abstract class C {
public constructor C()
public const open val x: kotlin.Int = 6
public const abstract val y: kotlin.Int = 7
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public companion object Companion {
private constructor Companion()
public const final val inCompaionObject: kotlin.Int = 8
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
}
public object D : C {
private constructor D()
public const final val final: kotlin.Int = 11
public const final val inObject: kotlin.Int = 10
public const final val withoutInitializer: kotlin.Int
public const open override /*1*/ val x: kotlin.Int = 9
public const abstract override /*1*/ /*fake_override*/ val y: kotlin.Int = 7
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class Delegate {
public constructor Delegate()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final operator fun getValue(/*0*/ thisRef: kotlin.Any?, /*1*/ prop: kotlin.reflect.KProperty<*>): kotlin.Int
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public final operator fun setValue(/*0*/ thisRef: kotlin.Any?, /*1*/ prop: kotlin.reflect.KProperty<*>, /*2*/ value: kotlin.Int): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final enum class MyEnum : kotlin.Enum<MyEnum> {
enum entry A
private constructor MyEnum()
public const final val inEnum: kotlin.Int = 17
@kotlin.internal.IntrinsicConstEvaluation public final override /*1*/ /*fake_override*/ val name: kotlin.String
public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int
protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: MyEnum): kotlin.Int
public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
protected/*protected and package*/ final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit
public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class<MyEnum!>!
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
// Static members
public final /*synthesized*/ val entries: kotlin.enums.EnumEntries<MyEnum>
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): MyEnum
public final /*synthesized*/ fun values(): kotlin.Array<MyEnum>
}
public final class Outer {
public constructor Outer()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public final inner class Inner {
public constructor Inner()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public object C {
private constructor C()
public const final val a: kotlin.Int = 18
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
}
}