[FIR] KT-54220: Don't crash on unsigned integers when no stdlib present
^KT-54220 Fixed
This commit is contained in:
+6
@@ -203,6 +203,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.UNSIGNED_LITERAL_WITHOUT_DECLARATIONS_ON_CLASSPATH) { firDiagnostic ->
|
||||
UnsignedLiteralWithoutDeclarationsOnClasspathImpl(
|
||||
firDiagnostic as KtPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.DIVISION_BY_ZERO) { firDiagnostic ->
|
||||
DivisionByZeroImpl(
|
||||
firDiagnostic as KtPsiDiagnostic,
|
||||
|
||||
+4
@@ -179,6 +179,10 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
override val diagnosticClass get() = WrongLongSuffix::class
|
||||
}
|
||||
|
||||
abstract class UnsignedLiteralWithoutDeclarationsOnClasspath : KtFirDiagnostic<KtElement>() {
|
||||
override val diagnosticClass get() = UnsignedLiteralWithoutDeclarationsOnClasspath::class
|
||||
}
|
||||
|
||||
abstract class DivisionByZero : KtFirDiagnostic<KtExpression>() {
|
||||
override val diagnosticClass get() = DivisionByZero::class
|
||||
}
|
||||
|
||||
+5
@@ -201,6 +201,11 @@ internal class WrongLongSuffixImpl(
|
||||
override val token: KtLifetimeToken,
|
||||
) : KtFirDiagnostic.WrongLongSuffix(), KtAbstractFirDiagnostic<KtElement>
|
||||
|
||||
internal class UnsignedLiteralWithoutDeclarationsOnClasspathImpl(
|
||||
override val firDiagnostic: KtPsiDiagnostic,
|
||||
override val token: KtLifetimeToken,
|
||||
) : KtFirDiagnostic.UnsignedLiteralWithoutDeclarationsOnClasspath(), KtAbstractFirDiagnostic<KtElement>
|
||||
|
||||
internal class DivisionByZeroImpl(
|
||||
override val firDiagnostic: KtPsiDiagnostic,
|
||||
override val token: KtLifetimeToken,
|
||||
|
||||
+1
@@ -368,6 +368,7 @@ internal object FirCompileTimeConstantEvaluator {
|
||||
ConstantValueKind.UnsignedShort -> value.toLong().toUShort()
|
||||
ConstantValueKind.UnsignedInt -> value.toLong().toUInt()
|
||||
ConstantValueKind.UnsignedLong -> value.toLong().toULong()
|
||||
ConstantValueKind.UnsignedIntegerLiteral -> value.toLong().toULong()
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
+12
@@ -362,6 +362,12 @@ public class DiagnosisCompilerFirTestdataTestGenerated extends AbstractDiagnosis
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/kt41990.kt");
|
||||
}
|
||||
|
||||
@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 {
|
||||
@@ -4664,6 +4670,12 @@ public class DiagnosisCompilerFirTestdataTestGenerated extends AbstractDiagnosis
|
||||
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/kotlinComparatorAlias.kt");
|
||||
}
|
||||
|
||||
@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 {
|
||||
|
||||
+5
@@ -309,6 +309,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
|
||||
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");
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
FILE: kt54220.kt
|
||||
public final const val c: R|kotlin/String| = ERROR_EXPR(Unsigned integers need stdlib).R|kotlin/plus|(ERROR_EXPR(Unsigned integers need stdlib))
|
||||
public get(): R|kotlin/String|
|
||||
public final fun box(): R|kotlin/String| {
|
||||
^box when () {
|
||||
!=(R|/c|, ERROR_EXPR(Unsigned integers need stdlib)) -> {
|
||||
String(fail)
|
||||
}
|
||||
else -> {
|
||||
String(OK)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
const val c = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!><!UNSIGNED_LITERAL_WITHOUT_DECLARATIONS_ON_CLASSPATH!>1u<!> + <!UNSIGNED_LITERAL_WITHOUT_DECLARATIONS_ON_CLASSPATH!>2u<!><!>
|
||||
|
||||
fun box() = when {
|
||||
c != <!UNSIGNED_LITERAL_WITHOUT_DECLARATIONS_ON_CLASSPATH!>3u<!> -> "fail"
|
||||
else -> "OK"
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
FILE: kt54220.kt
|
||||
public final const val c: R|kotlin/UInt| = UInt(1).R|kotlin/UInt.plus|(UInt(2))
|
||||
public get(): R|kotlin/UInt|
|
||||
public final fun box(): R|kotlin/String| {
|
||||
^box when () {
|
||||
!=(R|/c|, UInt(3)) -> {
|
||||
String(fail)
|
||||
}
|
||||
else -> {
|
||||
String(OK)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
const val c = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>1u + 2u<!>
|
||||
|
||||
fun box() = when {
|
||||
c != 3u -> "fail"
|
||||
else -> "OK"
|
||||
}
|
||||
+12
@@ -362,6 +362,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/kt41990.kt");
|
||||
}
|
||||
|
||||
@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 {
|
||||
@@ -4664,6 +4670,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/kotlinComparatorAlias.kt");
|
||||
}
|
||||
|
||||
@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 {
|
||||
|
||||
+12
@@ -362,6 +362,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/kt41990.kt");
|
||||
}
|
||||
|
||||
@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 {
|
||||
@@ -4664,6 +4670,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
||||
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/kotlinComparatorAlias.kt");
|
||||
}
|
||||
|
||||
@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 {
|
||||
|
||||
+1
@@ -76,6 +76,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
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_LITERAL_WITHOUT_DECLARATIONS_ON_CLASSPATH 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")
|
||||
|
||||
@@ -133,6 +133,7 @@ object FirErrors {
|
||||
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_LITERAL_WITHOUT_DECLARATIONS_ON_CLASSPATH 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)
|
||||
|
||||
+5
@@ -532,6 +532,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSAFE_CALL
|
||||
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_LITERAL_WITHOUT_DECLARATIONS_ON_CLASSPATH
|
||||
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,10 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
||||
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_LITERAL_WITHOUT_DECLARATIONS_ON_CLASSPATH,
|
||||
"Type of the constant expression cannot be resolved. Please make sure you have the required dependencies for unsigned types in the classpath"
|
||||
)
|
||||
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")
|
||||
|
||||
+1
@@ -499,6 +499,7 @@ private fun ConeSimpleDiagnostic.getFactory(source: KtSourceElement): KtDiagnost
|
||||
DiagnosticKind.IntLiteralOutOfRange -> FirErrors.INT_LITERAL_OUT_OF_RANGE
|
||||
DiagnosticKind.FloatLiteralOutOfRange -> FirErrors.FLOAT_LITERAL_OUT_OF_RANGE
|
||||
DiagnosticKind.WrongLongSuffix -> FirErrors.WRONG_LONG_SUFFIX
|
||||
DiagnosticKind.UnsignedNumbersAreNotPresent -> FirErrors.UNSIGNED_LITERAL_WITHOUT_DECLARATIONS_ON_CLASSPATH
|
||||
DiagnosticKind.IncorrectCharacterLiteral -> FirErrors.INCORRECT_CHARACTER_LITERAL
|
||||
DiagnosticKind.EmptyCharacterLiteral -> FirErrors.EMPTY_CHARACTER_LITERAL
|
||||
DiagnosticKind.TooManyCharactersInCharacterLiteral -> FirErrors.TOO_MANY_CHARACTERS_IN_CHARACTER_LITERAL
|
||||
|
||||
+14
-1
@@ -1010,11 +1010,15 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
|
||||
ConstantValueKind.IntegerLiteral, ConstantValueKind.UnsignedIntegerLiteral -> {
|
||||
val expressionType = ConeIntegerLiteralConstantTypeImpl.create(
|
||||
constExpression.value as Long,
|
||||
isTypePresent = { it.lookupTag.toSymbol(session) != null },
|
||||
isUnsigned = kind == ConstantValueKind.UnsignedIntegerLiteral
|
||||
)
|
||||
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 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
|
||||
|
||||
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 {
|
||||
|
||||
@@ -87,6 +87,7 @@ enum class DiagnosticKind {
|
||||
IntLiteralOutOfRange,
|
||||
FloatLiteralOutOfRange,
|
||||
WrongLongSuffix,
|
||||
UnsignedNumbersAreNotPresent,
|
||||
|
||||
IsEnumEntry,
|
||||
EnumEntryAsType,
|
||||
|
||||
@@ -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,6 +40,7 @@ class ConeIntegerLiteralConstantTypeImpl(
|
||||
fun create(
|
||||
value: Long,
|
||||
isUnsigned: Boolean,
|
||||
isTypePresent: (ConeClassLikeType) -> Boolean,
|
||||
nullability: ConeNullability = ConeNullability.NOT_NULL
|
||||
): ConeSimpleKotlinType {
|
||||
val possibleTypes = mutableListOf<ConeClassLikeType>()
|
||||
@@ -64,6 +67,9 @@ class ConeIntegerLiteralConstantTypeImpl(
|
||||
|
||||
if (isUnsigned) {
|
||||
addUnsignedPossibleType()
|
||||
if (possibleTypes.any { !isTypePresent(it) }) {
|
||||
return ConeErrorType(ConeSimpleDiagnostic("Unsigned integers need stdlib", DiagnosticKind.UnsignedNumbersAreNotPresent))
|
||||
}
|
||||
} else {
|
||||
addSignedPossibleTypes()
|
||||
}
|
||||
|
||||
Vendored
-3
@@ -1,3 +0,0 @@
|
||||
val u1 = 1u
|
||||
val u2 = 0xFu
|
||||
val u3 = 0b1u
|
||||
Vendored
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
val u1 = <!UNSIGNED_LITERAL_WITHOUT_DECLARATIONS_ON_CLASSPATH!>1u<!>
|
||||
val u2 = <!UNSIGNED_LITERAL_WITHOUT_DECLARATIONS_ON_CLASSPATH!>0xFu<!>
|
||||
val u3 = <!UNSIGNED_LITERAL_WITHOUT_DECLARATIONS_ON_CLASSPATH!>0b1u<!>
|
||||
Vendored
-3
@@ -1,3 +0,0 @@
|
||||
val u1 = 1u
|
||||
val u2 = 0xFu
|
||||
val u3 = 0b1u
|
||||
Vendored
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
val u1 = <!UNSIGNED_LITERAL_WITHOUT_DECLARATIONS_ON_CLASSPATH!>1u<!>
|
||||
val u2 = <!UNSIGNED_LITERAL_WITHOUT_DECLARATIONS_ON_CLASSPATH!>0xFu<!>
|
||||
val u3 = <!UNSIGNED_LITERAL_WITHOUT_DECLARATIONS_ON_CLASSPATH!>0b1u<!>
|
||||
Reference in New Issue
Block a user