From b1bcbaf48fd58f660bbbe5e0a315cfbc8a4f3eac Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Tue, 10 Aug 2021 11:00:51 +0300 Subject: [PATCH] FirConstChecks: support "Some string".length case properly #KT-48165 Fixed --- .../testData/resolve/constVal/const.fir.txt | 10 ++++++++++ .../testData/resolve/constVal/const.kt | 5 +++++ .../fir/analysis/checkers/FirConstChecks.kt | 18 ++++++++++++++---- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/compiler/fir/analysis-tests/testData/resolve/constVal/const.fir.txt b/compiler/fir/analysis-tests/testData/resolve/constVal/const.fir.txt index 31f4487af2a..ee7f160de56 100644 --- a/compiler/fir/analysis-tests/testData/resolve/constVal/const.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/constVal/const.fir.txt @@ -23,6 +23,16 @@ FILE: const.kt public get(): R|kotlin/Int| public final const val l: R|kotlin/Int| = R|/k| public get(): R|kotlin/Int| + public final const val m: R|kotlin/String| = String(123).R|kotlin/Any.toString|() + public get(): R|kotlin/String| + public final const val n: R|kotlin/Int| = String(456).R|kotlin/String.length| + public get(): R|kotlin/Int| + public final val o: R|kotlin/String| = String(789) + public get(): R|kotlin/String| + public final const val p: R|kotlin/String| = R|/o|.R|kotlin/Any.toString|() + public get(): R|kotlin/String| + public final const val q: R|kotlin/Int| = R|/o|.R|kotlin/String.length| + public get(): R|kotlin/Int| public final class ForConst : R|kotlin/Any| { public constructor(): R|ForConst| { super() diff --git a/compiler/fir/analysis-tests/testData/resolve/constVal/const.kt b/compiler/fir/analysis-tests/testData/resolve/constVal/const.kt index 21cf60e5466..157a7af37b2 100644 --- a/compiler/fir/analysis-tests/testData/resolve/constVal/const.kt +++ b/compiler/fir/analysis-tests/testData/resolve/constVal/const.kt @@ -18,6 +18,11 @@ const val i = ForConst.one() + "one" const val j = 4 * ForConst.two() val k = 3 - ForConst.two() const val l = k +const val m = "123".toString() +const val n = "456".length +val o = "789" +const val p = o.toString() +const val q = o.length class ForConst{ companion object { diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirConstChecks.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirConstChecks.kt index 51650fcae0a..fcfb389bdac 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirConstChecks.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirConstChecks.kt @@ -160,8 +160,20 @@ internal fun checkConstantArguments( } } expression is FirQualifiedAccessExpression -> { + val propertySymbol = expressionSymbol as? FirPropertySymbol ?: return ConstantArgumentKind.NOT_CONST + + @OptIn(SymbolInternals::class) + val property = propertySymbol.fir when { - (expressionSymbol as FirPropertySymbol).isLocal || expressionSymbol.callableId.className?.isRoot == false -> + property.name.asString() == "length" -> { + val coneType = + expression.dispatchReceiver.typeRef.coneTypeSafe() ?: return ConstantArgumentKind.NOT_CONST + val receiverClassId = coneType.lowerBoundIfFlexible().classId + if (receiverClassId == StandardClassIds.String) { + return checkConstantArguments(expression.dispatchReceiver, session) + } + } + propertySymbol.isLocal || propertySymbol.callableId.className?.isRoot == false -> return ConstantArgumentKind.NOT_CONST expression.typeRef.coneType.classId == StandardClassIds.KClass -> return ConstantArgumentKind.NOT_KCLASS_LITERAL @@ -170,9 +182,7 @@ internal fun checkConstantArguments( expression.dispatchReceiver is FirThisReceiverExpression -> return null } - @OptIn(SymbolInternals::class) - val property = expressionSymbol.fir as? FirProperty - return when (property?.initializer) { + return when (property.initializer) { is FirConstExpression<*> -> { if (property.isVal) ConstantArgumentKind.NOT_CONST_VAL_IN_CONST_EXPRESSION