[FIR] KT-54220: Don't crash on unsigned integers when no stdlib present
diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt
index d89a655..bae65c2 100644
--- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt
+++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt
@@ -203,6 +203,12 @@
token,
)
}
+ add(FirErrors.UNSIGNED_LITERALS_NOT_PRESENT) { firDiagnostic ->
+ UnsignedLiteralsNotPresentImpl(
+ firDiagnostic as KtPsiDiagnostic,
+ token,
+ )
+ }
add(FirErrors.DIVISION_BY_ZERO) { firDiagnostic ->
DivisionByZeroImpl(
firDiagnostic as KtPsiDiagnostic,
diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt
index de0746f..4bfc3c7 100644
--- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt
+++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt
@@ -179,6 +179,10 @@
override val diagnosticClass get() = WrongLongSuffix::class
}
+ abstract class UnsignedLiteralsNotPresent : KtFirDiagnostic<KtElement>() {
+ override val diagnosticClass get() = UnsignedLiteralsNotPresent::class
+ }
+
abstract class DivisionByZero : KtFirDiagnostic<KtExpression>() {
override val diagnosticClass get() = DivisionByZero::class
}
diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt
index c02ece3..daf02c0 100644
--- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt
+++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt
@@ -201,6 +201,11 @@
override val token: KtLifetimeToken,
) : KtFirDiagnostic.WrongLongSuffix(), KtAbstractFirDiagnostic<KtElement>
+internal class UnsignedLiteralsNotPresentImpl(
+ override val firDiagnostic: KtPsiDiagnostic,
+ override val token: KtLifetimeToken,
+) : KtFirDiagnostic.UnsignedLiteralsNotPresent(), KtAbstractFirDiagnostic<KtElement>
+
internal class DivisionByZeroImpl(
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerFirTestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerFirTestdataTestGenerated.java
index b1b4a8c..6aeadf0 100644
--- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerFirTestdataTestGenerated.java
+++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerFirTestdataTestGenerated.java
@@ -363,6 +363,12 @@
}
@Test
+ @TestMetadata("kt54220.kt")
+ public void testKt54220() throws Exception {
+ runTest("compiler/fir/analysis-tests/testData/resolve/kt54220.kt");
+ }
+
+ @Test
@TestMetadata("labelAndReceiverForInfix.kt")
public void testLabelAndReceiverForInfix() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/labelAndReceiverForInfix.kt");
@@ -4659,6 +4665,12 @@
}
@Test
+ @TestMetadata("kt54220.kt")
+ public void testKt54220() throws Exception {
+ runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/kt54220.kt");
+ }
+
+ @Test
@TestMetadata("listPlusAssign.kt")
public void testListPlusAssign() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/listPlusAssign.kt");
diff --git a/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java b/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java
index 8ad6776..97f40e9 100644
--- a/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java
+++ b/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java
@@ -309,6 +309,11 @@
runTest("compiler/fir/analysis-tests/testData/resolve/kt41990.kt");
}
+ @TestMetadata("kt54220.kt")
+ public void testKt54220() throws Exception {
+ runTest("compiler/fir/analysis-tests/testData/resolve/kt54220.kt");
+ }
+
@TestMetadata("labelAndReceiverForInfix.kt")
public void testLabelAndReceiverForInfix() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/labelAndReceiverForInfix.kt");
diff --git a/compiler/fir/analysis-tests/testData/resolve/kt54220.kt b/compiler/fir/analysis-tests/testData/resolve/kt54220.kt
new file mode 100644
index 0000000..378817f
--- /dev/null
+++ b/compiler/fir/analysis-tests/testData/resolve/kt54220.kt
@@ -0,0 +1,6 @@
+const val c = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!><!UNSIGNED_LITERALS_NOT_PRESENT!>1u<!> + <!UNSIGNED_LITERALS_NOT_PRESENT!>2u<!><!>
+
+fun box() = when {
+ c != <!UNSIGNED_LITERALS_NOT_PRESENT!>3u<!> -> "fail"
+ else -> "OK"
+}
diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/kt54220.kt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/kt54220.kt
new file mode 100644
index 0000000..3176462
--- /dev/null
+++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/kt54220.kt
@@ -0,0 +1,6 @@
+const val c = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>1u + 2u<!>
+
+fun box() = when {
+ c != 3u -> "fail"
+ else -> "OK"
+}
diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java
index d84a389..fb768f0 100644
--- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java
+++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java
@@ -363,6 +363,12 @@
}
@Test
+ @TestMetadata("kt54220.kt")
+ public void testKt54220() throws Exception {
+ runTest("compiler/fir/analysis-tests/testData/resolve/kt54220.kt");
+ }
+
+ @Test
@TestMetadata("labelAndReceiverForInfix.kt")
public void testLabelAndReceiverForInfix() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/labelAndReceiverForInfix.kt");
@@ -4659,6 +4665,12 @@
}
@Test
+ @TestMetadata("kt54220.kt")
+ public void testKt54220() throws Exception {
+ runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/kt54220.kt");
+ }
+
+ @Test
@TestMetadata("listPlusAssign.kt")
public void testListPlusAssign() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/listPlusAssign.kt");
diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java
index 2591b4b..0d4c712 100644
--- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java
+++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java
@@ -363,6 +363,12 @@
}
@Test
+ @TestMetadata("kt54220.kt")
+ public void testKt54220() throws Exception {
+ runTest("compiler/fir/analysis-tests/testData/resolve/kt54220.kt");
+ }
+
+ @Test
@TestMetadata("labelAndReceiverForInfix.kt")
public void testLabelAndReceiverForInfix() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/labelAndReceiverForInfix.kt");
@@ -4659,6 +4665,12 @@
}
@Test
+ @TestMetadata("kt54220.kt")
+ public void testKt54220() throws Exception {
+ runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/kt54220.kt");
+ }
+
+ @Test
@TestMetadata("listPlusAssign.kt")
public void testListPlusAssign() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/listPlusAssign.kt");
diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt
index 0337343..34dbfc6 100644
--- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt
+++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt
@@ -76,6 +76,7 @@
val INT_LITERAL_OUT_OF_RANGE by error<PsiElement>()
val FLOAT_LITERAL_OUT_OF_RANGE by error<PsiElement>()
val WRONG_LONG_SUFFIX by error<KtElement>(PositioningStrategy.LONG_LITERAL_SUFFIX)
+ val UNSIGNED_LITERALS_NOT_PRESENT by error<KtElement>()
val DIVISION_BY_ZERO by warning<KtExpression>()
val VAL_OR_VAR_ON_LOOP_PARAMETER by error<KtParameter>(PositioningStrategy.VAL_OR_VAR_NODE) {
parameter<KtKeywordToken>("valOrVar")
diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt
index 1cf57d6..8fe5bd5 100644
--- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt
+++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt
@@ -133,6 +133,7 @@
val INT_LITERAL_OUT_OF_RANGE by error0<PsiElement>()
val FLOAT_LITERAL_OUT_OF_RANGE by error0<PsiElement>()
val WRONG_LONG_SUFFIX by error0<KtElement>(SourceElementPositioningStrategies.LONG_LITERAL_SUFFIX)
+ val UNSIGNED_LITERALS_NOT_PRESENT by error0<KtElement>()
val DIVISION_BY_ZERO by warning0<KtExpression>()
val VAL_OR_VAR_ON_LOOP_PARAMETER by error1<KtParameter, KtKeywordToken>(SourceElementPositioningStrategies.VAL_OR_VAR_NODE)
val VAL_OR_VAR_ON_FUN_PARAMETER by error1<KtParameter, KtKeywordToken>(SourceElementPositioningStrategies.VAL_OR_VAR_NODE)
diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt
index 54e2219..8ec3593 100644
--- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt
+++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt
@@ -532,6 +532,7 @@
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSAFE_IMPLICIT_INVOKE_CALL
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSAFE_INFIX_CALL
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSAFE_OPERATOR_CALL
+import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSIGNED_LITERALS_NOT_PRESENT
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSUPPORTED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSUPPORTED_CONTEXTUAL_DECLARATION_CALL
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSUPPORTED_FEATURE
@@ -633,6 +634,7 @@
map.put(WRONG_LONG_SUFFIX, "Use 'L' instead of 'l'")
map.put(EMPTY_CHARACTER_LITERAL, "Empty character literal")
map.put(FLOAT_LITERAL_OUT_OF_RANGE, "The value is out of range")
+ map.put(UNSIGNED_LITERALS_NOT_PRESENT, "The standard library is required when using unsigned integers")
map.put(INCORRECT_CHARACTER_LITERAL, "Incorrect character literal")
map.put(TOO_MANY_CHARACTERS_IN_CHARACTER_LITERAL, "Too many characters in a character literal")
map.put(ILLEGAL_ESCAPE, "Illegal escape")
diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt
index a0155d6..1f6bab4 100644
--- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt
+++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt
@@ -498,6 +498,7 @@
DiagnosticKind.IntLiteralOutOfRange -> FirErrors.INT_LITERAL_OUT_OF_RANGE
DiagnosticKind.FloatLiteralOutOfRange -> FirErrors.FLOAT_LITERAL_OUT_OF_RANGE
DiagnosticKind.WrongLongSuffix -> FirErrors.WRONG_LONG_SUFFIX
+ DiagnosticKind.UnsignedLiteralsNotPresent -> FirErrors.UNSIGNED_LITERALS_NOT_PRESENT
DiagnosticKind.IncorrectCharacterLiteral -> FirErrors.INCORRECT_CHARACTER_LITERAL
DiagnosticKind.EmptyCharacterLiteral -> FirErrors.EMPTY_CHARACTER_LITERAL
DiagnosticKind.TooManyCharactersInCharacterLiteral -> FirErrors.TOO_MANY_CHARACTERS_IN_CHARACTER_LITERAL
diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt
index 68886691..2c56cf1 100644
--- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt
+++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt
@@ -1010,11 +1010,15 @@
ConstantValueKind.IntegerLiteral, ConstantValueKind.UnsignedIntegerLiteral -> {
val expressionType = ConeIntegerLiteralConstantTypeImpl.create(
constExpression.value as Long,
- isUnsigned = kind == ConstantValueKind.UnsignedIntegerLiteral
+ isUnsigned = kind == ConstantValueKind.UnsignedIntegerLiteral,
+ isTypePresent = { it.lookupTag.toSymbol(session) != null }
)
val expectedTypeRef = data.expectedType
@Suppress("UNCHECKED_CAST")
when {
+ expressionType is ConeErrorType -> {
+ expressionType
+ }
expressionType is ConeClassLikeType -> {
constExpression.replaceKind(expressionType.toConstKind() as ConstantValueKind<T>)
expressionType
@@ -1040,7 +1044,16 @@
dataFlowAnalyzer.exitConstExpression(constExpression as FirConstExpression<*>)
constExpression.resultType = constExpression.resultType.resolvedTypeFromPrototype(type)
- return constExpression
+
+ return when (val resolvedType = constExpression.resultType.coneType) {
+ is ConeErrorType -> buildErrorExpression {
+ expression = constExpression
+ diagnostic = resolvedType.diagnostic
+ source = constExpression.source
+ }
+
+ else -> constExpression
+ }
}
override fun transformAnnotation(annotation: FirAnnotation, data: ResolutionMode): FirStatement {
diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/diagnostics/ConeSimpleDiagnostic.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/diagnostics/ConeSimpleDiagnostic.kt
index 21b8d53..3ab471b 100644
--- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/diagnostics/ConeSimpleDiagnostic.kt
+++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/diagnostics/ConeSimpleDiagnostic.kt
@@ -84,6 +84,7 @@
IntLiteralOutOfRange,
FloatLiteralOutOfRange,
WrongLongSuffix,
+ UnsignedLiteralsNotPresent,
IsEnumEntry,
EnumEntryAsType,
diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/ConeIntegerLiteralTypeImpl.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/ConeIntegerLiteralTypeImpl.kt
index 69e2c89..cfa489c 100644
--- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/ConeIntegerLiteralTypeImpl.kt
+++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/ConeIntegerLiteralTypeImpl.kt
@@ -5,6 +5,8 @@
package org.jetbrains.kotlin.fir.types
+import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
+import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.isLong
import org.jetbrains.kotlin.fir.isULong
import org.jetbrains.kotlin.name.StandardClassIds
@@ -38,7 +40,8 @@
fun create(
value: Long,
isUnsigned: Boolean,
- nullability: ConeNullability = ConeNullability.NOT_NULL
+ nullability: ConeNullability = ConeNullability.NOT_NULL,
+ isTypePresent: (ConeClassLikeType) -> Boolean = { true },
): ConeSimpleKotlinType {
val possibleTypes = mutableListOf<ConeClassLikeType>()
@@ -64,6 +67,9 @@
if (isUnsigned) {
addUnsignedPossibleType()
+ if (!possibleTypes.all { isTypePresent(it) }) {
+ return ConeErrorType(ConeSimpleDiagnostic("Unsigned integers need stdlib", DiagnosticKind.UnsignedLiteralsNotPresent))
+ }
} else {
addSignedPossibleTypes()
}