[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()
             }